Line data Source code
1 : /*
2 : START OF LICENSE STUB
3 : DeDOS: Declarative Dispersion-Oriented Software
4 : Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : END OF LICENSE STUB
19 : */
20 : /**
21 : * @file msu_state.c
22 : *
23 : * State storage that is tied to a specific MSU message
24 : */
25 : #include "msu_message.h"
26 : #include "rt_stats.h"
27 : #include "logging.h"
28 : #include "uthash.h"
29 : #include "local_msu.h"
30 :
31 : /** Explicitly check whether a state is being replaced on a call to msu_init_state */
32 : #define CHECK_STATE_REPLACEMENT 1
33 :
34 : /** The structure contining msu state */
35 : struct msu_state {
36 : /** The key with which the state is stored */
37 : struct composite_key key;
38 : /** The size of the data being stored */
39 : size_t size;
40 : /** An ID to facilitate the transferring of state between msus (not implemented yet) */
41 : int group_id;
42 : /** A unique identifier for the state
43 : * (not used at the moment, will be utilized in state transfer) */
44 : int32_t id;
45 : /** The payload of the state */
46 : void *data;
47 : /** For use with the UT hash structure */
48 : UT_hash_handle hh;
49 : };
50 :
51 0 : int msu_num_states(struct local_msu *msu) {
52 0 : return HASH_COUNT(msu->item_state);
53 : }
54 :
55 6 : void *msu_init_state(struct local_msu *msu, struct msu_msg_key *key, size_t size) {
56 6 : struct msu_state *state = malloc(sizeof(*state));
57 6 : memcpy(&state->key, &key->key, key->key_len);
58 6 : state->group_id = key->group_id;
59 6 : state->data = malloc(size);
60 6 : state->size = size;
61 6 : state->id = key->id;
62 :
63 6 : log(LOG_STATE_MANAGEMENT, "Allocating new state of size %d for msu %d, key %d",
64 : (int)size, msu->id, (int)key->id);
65 :
66 : #if CHECK_STATE_REPLACEMENT
67 6 : struct msu_state *old_state = NULL;
68 6 : HASH_REPLACE(hh, msu->item_state, key, key->key_len, state, old_state);
69 6 : if (old_state != NULL) {
70 0 : log_warn("Replacing old state! Not freeing! Bad!");
71 : }
72 : #else
73 : HASH_ADD(hh, msu->item_state, key, key->key_len, state);
74 : #endif
75 :
76 6 : increment_stat(MSU_MEM_ALLOC, msu->id, (double)(sizeof(*state) + size));
77 6 : increment_stat(MSU_NUM_STATES, msu->id, 1);
78 :
79 6 : return state->data;
80 : }
81 :
82 5 : void *msu_get_state(struct local_msu *msu, struct msu_msg_key *key, size_t *size) {
83 : struct msu_state *state;
84 5 : HASH_FIND(hh, msu->item_state, &key->key, key->key_len, state);
85 5 : log(LOG_STATE_MANAGEMENT, "Accessing state for MSU %d, key %d",
86 : msu->id, (int)key->id);
87 5 : if (state == NULL) {
88 2 : log(LOG_STATE_MANAGEMENT, "State does not exist");
89 2 : return NULL;
90 : }
91 3 : if (size != NULL) {
92 1 : *size = state->size;
93 : }
94 3 : return state->data;
95 : }
96 :
97 2 : int msu_free_state(struct local_msu *msu, struct msu_msg_key *key) {
98 : struct msu_state *state;
99 2 : HASH_FIND(hh, msu->item_state, &key->key, key->key_len, state);
100 2 : log(LOG_STATE_MANAGEMENT, "Freeing state for MSU %d, key %d",
101 : msu->id, (int)key->id);
102 2 : if (state == NULL) {
103 1 : log_warn("State for MSU %d, key %d does not exist",
104 : msu->id, (int)key->id);
105 1 : return -1;
106 : }
107 1 : HASH_DEL(msu->item_state, state);
108 :
109 1 : increment_stat(MSU_MEM_ALLOC, msu->id,
110 1 : (double)(-1 * (int)(sizeof(*state) + state->size)));
111 1 : increment_stat(MSU_NUM_STATES, msu->id, -1);
112 1 : free(state->data);
113 1 : free(state);
114 1 : return 0;
115 : }
116 :
117 0 : void msu_free_all_state(struct local_msu *msu) {
118 : struct msu_state *state, *tmp;
119 0 : HASH_ITER(hh, msu->item_state, state, tmp) {
120 0 : HASH_DEL(msu->item_state, state);
121 0 : free(state->data);
122 0 : free(state);
123 : }
124 0 : }
|