/
bang-module-registry.c
182 lines (131 loc) · 4.52 KB
/
bang-module-registry.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include"bang-module.h"
#include"bang-module-api.h"
#include"bang-utils.h"
#include"string.h"
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<uuid/uuid.h>
#define STARTED 1
#define STOPPED 0
typedef struct {
BANG_module *module;
char started;
pthread_mutex_t lck;
} module_wrapper_t;
typedef struct {
char *name;
unsigned char *version;
} module_wrapper_key_t;
static BANG_hashmap *modules = NULL;
static module_wrapper_t* new_module_wrapper(BANG_module *module) {
module_wrapper_t *new = malloc(sizeof(module_wrapper_t));
pthread_mutex_init(&new->lck,NULL);
new->module = module;
new->started = STOPPED;
return new;
}
static module_wrapper_key_t create_key(char *module_name, unsigned char *module_version) {
module_wrapper_key_t module_key;
module_key.name = module_name;
module_key.version = module_version;
return module_key;
}
static BANG_module* get_module_if_started_with_wrapper(module_wrapper_t *module_wrapper) {
BANG_module *ret = NULL;
if (module_wrapper != NULL) {
pthread_mutex_lock(&module_wrapper->lck);
ret = (module_wrapper->started == STARTED) ? module_wrapper->module : NULL;
pthread_mutex_unlock(&module_wrapper->lck);
}
return ret;
}
static BANG_module* get_module_if_started(char *module_name, unsigned char *module_version) {
module_wrapper_key_t module_key = create_key(module_name, module_version);
module_wrapper_t *module_wrapper = BANG_hashmap_get(modules,&module_key);
return get_module_if_started_with_wrapper(module_wrapper);
}
static unsigned int hash_module_wrapper_key_t(const void *data) {
const module_wrapper_key_t *module_key = data;
unsigned int hashcode;
hashcode = strlen(module_key->name);
hashcode |= module_key->name[hashcode/4] << 8;
hashcode |= module_key->version[0] << 16;
hashcode |= module_key->version[1] << 24;
return hashcode;
}
static int compare_module_wrapper_key_t(const void *d1, const void *d2) {
const module_wrapper_key_t *mk1 = d1;
const module_wrapper_key_t *mk2 = d2;
int ret = BANG_version_cmp(mk1->version, mk2->version) +
strcmp(mk1->name, mk2->name);
#ifdef BDEBUG_1
fprintf(stderr,"Found that %s and %s matched at %d.\n",mk1->name, mk2->name, ret);
#endif
return ret;
}
void BANG_new_module(char *path, char **module_name, unsigned char **module_version) {
#ifdef BDEBUG_2
fprintf(stderr,"Putting a new module in the registry.\n");
#endif
BANG_module *module = BANG_load_module(path);
if (module) {
if (module_name) {
*module_name = module->info->module_name;
}
if (module_version) {
*module_version = module->info->module_version;
}
module_wrapper_t *module_wrapper = new_module_wrapper(module);
module_wrapper_key_t module_key = create_key(module->info->module_name, module->info->module_version);
#ifdef BDEBUG_1
fprintf(stderr,"Trying to put the %s module into a hashmap.\n",module_wrapper->module->info->module_name);
#endif
BANG_hashmap_set(modules,&module_key,module_wrapper);
}
}
BANG_module* BANG_get_module(char *module_name, unsigned char *module_version) {
#ifdef BDEBUG_1
fprintf(stderr,"Trying to get the %s module.\n", module_name);
#endif
module_wrapper_key_t module_key = create_key(module_name, module_version);
module_wrapper_t *module_wrapper = BANG_hashmap_get(modules,&module_key);
if (module_wrapper)
return module_wrapper->module;
else
return NULL;
}
int BANG_run_module_in_registry(char *module_name, unsigned char *module_version) {
int ret = -1;
module_wrapper_key_t module_key = create_key(module_name, module_version);
module_wrapper_t *module_wrapper = BANG_hashmap_get(modules,&module_key);
pthread_mutex_lock(&module_wrapper->lck);
if (module_wrapper->started == STOPPED) {
BANG_run_module(module_wrapper->module);
module_wrapper->started = STARTED;
ret = 0;
}
pthread_mutex_unlock(&module_wrapper->lck);
return ret;
}
void BANG_module_inform_new_peer(char *module_name, unsigned char *module_version, uuid_t new_peer) {
BANG_module *module = get_module_if_started(module_name, module_version);
if (module) {
int module_id = BANG_get_my_id(module->info);
uuid_t this_module_uuid;
BANG_get_uuid_from_local_id(this_module_uuid, module_id, module->info);
BANG_module_new_peer(module, this_module_uuid, new_peer);
}
}
void BANG_module_registry_init() {
#ifdef BDEBUG_1
fprintf(stderr,"BANG module registry starting.\n");
#endif
modules = new_BANG_hashmap(&hash_module_wrapper_key_t,&compare_module_wrapper_key_t);
}
void BANG_module_registry_close() {
#ifdef BDEBUG_1
fprintf(stderr,"BANG module registry closing.\n");
#endif
free_BANG_hashmap(modules);
}