UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 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 // if the event handler already exists, we don't modify it 50 if(cxMapGet(event_handler_map, key)) { 51 /* TODO: log message */ 52 /* TODO: set reload status */ 53 log_ereport(LOG_DEBUG, "event handler %s already exists", cfg->name.ptr); 54 return 0; 55 } 56 57 // create new handler 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 /* there can be only one default event handler */ 67 /* TODO: log warning */ 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 * checks if there is at least one event handler and a default handler 122 * if necessary, check_event_handler_cfg() creates a default event handler 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