do not filter access levels if not wanted (show database errors)
[NeonServV5.git] / src / timeq.c
1 /* timeq.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "timeq.h"
19 #include "IOHandler.h"
20 #include "tools.h"
21 #include "log.h"
22
23 static struct timeq_entry *timeq_events;
24 #ifdef HAVE_THREADS
25 static int pthread_mutex_initialized = 0;
26 static pthread_mutex_t synchronized;
27 #endif
28
29 static IOHANDLER_CALLBACK(timeq_callback) {
30     struct timeq_entry *entry = event->iofd->data;
31     switch(event->type) {
32     case IOEVENT_TIMEOUT:
33         entry->callback(entry->data);
34         entry->iofd = NULL;
35         timeq_del(entry);
36         break;
37     default:
38         break;
39     }
40 }
41
42 struct timeq_entry* timeq_add(int seconds, int module_id, timeq_callback_t *callback, void *data) {
43     return timeq_uadd(seconds * 1000, module_id, callback, data);
44 }
45
46 struct timeq_entry* timeq_uadd(int useconds, int module_id, timeq_callback_t *callback, void *data) {
47     struct timeval timeout;
48     struct timeq_entry *entry = malloc(sizeof(*entry));
49     if (!entry)
50     {
51         printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
52         return NULL;
53     }
54     #ifdef HAVE_THREADS
55     if(!pthread_mutex_initialized) {
56         THREAD_MUTEX_INIT(synchronized);
57         pthread_mutex_initialized = 1;
58     }
59     #endif
60     gettimeofday(&timeout, NULL);
61     SYNCHRONIZE(synchronized);
62     timeout.tv_usec += (useconds % 1000);
63     timeout.tv_sec += (useconds / 1000);
64     entry->iofd = iohandler_timer(timeout, timeq_callback);
65     entry->iofd->data = entry;
66     entry->module_id = module_id;
67     entry->callback = callback;
68     entry->data = data;
69     entry->name = NULL;
70     entry->next = timeq_events;
71     entry->prev = NULL;
72     if(timeq_events)
73         timeq_events->prev = entry;
74     timeq_events = entry;
75     DESYNCHRONIZE(synchronized);
76     return entry;
77 }
78
79 struct timeq_entry* timeq_add_name(char *name, int seconds, int module_id, timeq_callback_t *callback, void *data) {
80     return timeq_uadd_name(name, seconds * 1000, module_id, callback, data);
81 }
82
83 struct timeq_entry* timeq_uadd_name(char *name, int useconds, int module_id, timeq_callback_t *callback, void *data) {
84     struct timeq_entry *entry = timeq_uadd(useconds, module_id, callback, data);
85     entry->name = strdup(name);
86     return entry;
87 }
88
89 int timeq_del(struct timeq_entry* entry) {
90     #ifdef HAVE_THREADS
91     if(!pthread_mutex_initialized) return 0;
92     #endif
93     SYNCHRONIZE(synchronized);
94     if(entry->next)
95         entry->next->prev = entry->prev;
96     if(entry->prev)
97         entry->prev->next = entry->next;
98     else
99         timeq_events = entry->next;
100     if(entry->name)
101         free(entry->name);
102     if(entry->iofd)
103         iohandler_close(entry->iofd);
104     free(entry);
105     DESYNCHRONIZE(synchronized);
106     return 1;
107 }
108
109 int timeq_del_name(char *name) {
110     SYNCHRONIZE(synchronized);
111     struct timeq_entry *entry;
112     int removed = 0;
113     for(entry = timeq_events; entry; entry = entry->next) {
114         if(entry->name && !stricmp(entry->name, name)) {
115             removed = timeq_del(entry);
116             break;
117         }
118     }
119     DESYNCHRONIZE(synchronized);
120     return removed;
121 }
122
123 int timeq_name_exists(char *name) {
124     SYNCHRONIZE(synchronized);
125     struct timeq_entry *centry;
126     for(centry = timeq_events; centry; centry = centry->next) {
127         if(centry->name && !stricmp(centry->name, name)) {
128             DESYNCHRONIZE(synchronized);
129             return 1;
130         }
131     }
132     DESYNCHRONIZE(synchronized);
133     return 0;
134 }
135
136 void unregister_module_timers(int module_id) {
137     SYNCHRONIZE(synchronized);
138     struct timeq_entry *entry, *next_entry;
139     for(entry = timeq_events; entry; entry = next_entry) {
140         next_entry = entry->next;
141         if(entry->module_id == module_id)
142             timeq_del(entry);
143     }
144     DESYNCHRONIZE(synchronized);
145 }