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 #include <cx/hash_map.h>
30 #include <cx/linked_list.h>
31 #include "../util/atomic.h"
32
33 #include "event.h"
34
35 static CxMap *event_handler_map =
NULL;
36 int numevhandlers =
0;
37
38 EVHandler *default_event_handler =
NULL;
39
40 EVHandler *last_handler_c =
NULL;
41
42 int create_event_handler(EventHandlerConfig *cfg) {
43 if(event_handler_map ==
NULL) {
44 event_handler_map = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
16);
45 }
46
47 CxHashKey key = cx_hash_key_bytes((
const unsigned char*)cfg->name.ptr, cfg->name.length);
48
49
50 if(cxMapGet(event_handler_map, key)) {
51
52
53 log_ereport(
LOG_DEBUG,
"event handler %s already exists", cfg->name.ptr);
54 return 0;
55 }
56
57
58 EVHandler *e = evhandler_create(cfg);
59 if(e ==
NULL) {
60 log_ereport(
LOG_FAILURE,
"evhandler_create failed");
61 return 1;
62 }
63
64 if(cfg->isdefault) {
65 if(default_event_handler) {
66
67
68 }
69 default_event_handler = e;
70 }
71
72 int ret = cxMapPut(event_handler_map, key, e);
73 if(ret ==
0) {
74 last_handler_c = e;
75 numevhandlers++;
76 }
77
78 return ret;
79 }
80
81 void shutdown_eventhandlers_wait(
void) {
82 log_ereport(
LOG_INFORM,
"shutdown eventhandlers");
83
84 CxIterator i = cxMapIteratorValues(event_handler_map);
85 cx_foreach(EVHandler *, e, i) {
86 evhandler_shutdown(e);
87 }
88
89 i = cxMapIteratorValues(event_handler_map);
90 cx_foreach(EVHandler *, e, i) {
91 evhandler_wait_and_destroy(e);
92 }
93
94 cxMapDestroy(event_handler_map);
95
96 log_ereport(
LOG_INFORM,
"all eventhandlers closed");
97 }
98
99 void evhandler_shutdown(EVHandler *h) {
100 for(
int i=
0;i<h->numins;i++) {
101 ev_instance_shutdown(h->instances[i]);
102 }
103 }
104
105 void evhandler_close(EVHandler *h) {
106 for(
int i=
0;i<h->numins;i++) {
107 ev_instance_close(h->instances[i]);
108 }
109 }
110
111 void evhandler_wait_and_destroy(EVHandler *h) {
112 for(
int i=
0;i<h->numins;i++) {
113 ev_instance_wait(h->instances[i]);
114 }
115
116 free(h->instances);
117 free(h);
118 }
119
120
121
122
123
124 int check_event_handler_cfg() {
125 if(numevhandlers >
0 ) {
126 if(default_event_handler) {
127 return 0;
128 }
else {
129 default_event_handler = last_handler_c;
130 return 0;
131 }
132 }
133
134 EventHandlerConfig cfg;
135 cfg.name = cx_str(
"default");
136 cfg.nthreads =
1;
137 cfg.isdefault =
1;
138
139 return create_event_handler(&cfg);
140 }
141
142
143 EVHandler* get_default_event_handler() {
144 return default_event_handler;
145 }
146
147 EVHandler* get_event_handler(
const char *name) {
148 return cxMapGet(event_handler_map, cx_hash_key_str(name));
149 }
150
151 EventHandler* ev_instance(EVHandler *ev) {
152 int nev = ev->numins;
153 if(nev ==
1) {
154 return ev->instances[
0];
155 }
156
157 int ins = ev->current & nev;
158 ws_atomic_inc32(&ev->current);
159 return ev->instances[ins];
160 }
161
162 int ev_free_event(EventHandler *h, Event *event) {
163 free(event);
164 return 0;
165 }
166
167
168 void ev_watchlist_add(EventHandler *h, EVWatchList *elm) {
169 watchlist_add(&h->watchlist_begin, &h->watchlist_end, elm);
170 }
171
172 void ev_watchlist_remove(EventHandler *h, EVWatchList *elm) {
173 watchlist_remove(&h->watchlist_begin, &h->watchlist_end, elm);
174 }
175
176 void ev_saf_return(EventHandler *h, Session *sn, Request *rq,
int ret) {
177 h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret };
178 }
179
180 void watchlist_add(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) {
181 cx_linked_list_add(
182 (
void**)begin,
183 (
void**)end,
184 offsetof(EVWatchList, prev),
185 offsetof(EVWatchList, next),
186 elm);
187 }
188
189 void watchlist_remove(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) {
190 cx_linked_list_remove(
191 (
void**)begin,
192 (
void**)end,
193 offsetof(EVWatchList, prev),
194 offsetof(EVWatchList, next),
195 elm);
196 }
197
198 void watchlist_check(EventHandler *h,
time_t t) {
199 if(t ==
0) {
200 t = time(
NULL);
201 }
202
203 log_ereport(
LOG_DEBUG,
"eventhandler: check watchlist");
204
205 EVWatchList *elm = h->watchlist_begin;
206 while(elm) {
207 EVWatchList *next = elm->next;
208
209 if(elm->expire < t) {
210 ev_watchlist_remove(h, elm);
211
212 if(elm->destroy) {
213 elm->destroy(h, elm);
214 }
215 }
216
217 elm = next;
218 }
219
220
221 }
222