]> jfr.im git - irc/quakenet/newserv.git/blob - core/events-poll.c
fix some format string errors and dergister some hooks, also do some (pointless)...
[irc/quakenet/newserv.git] / core / events-poll.c
1 /*
2 * events.c: the event handling core, poll() version
3 */
4
5 #include <stdio.h>
6 #include <sys/poll.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10
11 #include "../lib/array.h"
12 #include "events.h"
13 #include "error.h"
14 #include "hooks.h"
15
16 typedef struct {
17 FDHandler handler;
18 int fdarraypos;
19 } reghandler;
20
21 /*
22 * OK, new data structure format for here to make everything
23 * faster. Two fixed static arrays, one of struct pollfds
24 * (for feeding to poll) in no particular order. Second array
25 * has an array of reghandler structs; this is indexed by FD for
26 * quick reference...
27 */
28
29 struct pollfd *eventfds;
30 reghandler *eventhandlers;
31
32 unsigned int maxfds;
33
34 int eventadds;
35 int eventdels;
36 int eventexes;
37
38 /* How many fds are currently registered */
39 int regfds;
40
41 void eventstats(int hooknum, void *arg);
42
43 void inithandlers() {
44 regfds=0;
45 eventadds=eventdels=eventexes=0;
46 maxfds=STARTFDS;
47 eventfds=(struct pollfd *)malloc(maxfds*sizeof(struct pollfd));
48 memset(eventfds,0,maxfds*sizeof(struct pollfd));
49 eventhandlers=(reghandler *)malloc(maxfds*sizeof(reghandler));
50 memset(eventhandlers,0,maxfds*sizeof(reghandler));
51 registerhook(HOOK_CORE_STATSREQUEST, &eventstats);
52 }
53
54 void finihandlers() {
55 deregisterhook(HOOK_CORE_STATSREQUEST, &eventstats);
56 free(eventfds);
57 free(eventhandlers);
58 }
59
60 /*
61 * checkindex():
62 * Given the number of a new file descriptor, makes sure that the arrays
63 * will be big enough to deal with it.
64 */
65
66 void checkindex(unsigned index) {
67 int oldmax=maxfds;
68
69 if (index<maxfds) {
70 return;
71 }
72
73 while (maxfds<=index) {
74 maxfds+=GROWFDS;
75 }
76
77 eventfds=(struct pollfd *)realloc((void *)eventfds,maxfds*sizeof(struct pollfd));
78 memset(&eventfds[oldmax],0,(maxfds-oldmax)*sizeof(struct pollfd));
79 eventhandlers=(reghandler *)realloc((void *)eventhandlers,maxfds*sizeof(reghandler));
80 memset(&eventhandlers[oldmax],0,(maxfds-oldmax)*sizeof(reghandler));
81 }
82
83 /*
84 * registerhandler():
85 * Add an fd to the poll() array.
86 *
87 * Now O(1)
88 */
89
90 int registerhandler(int fd, short events, FDHandler handler) {
91 checkindex(fd);
92
93 /* Check that it's not already registered */
94 if (eventhandlers[fd].handler!=NULL) {
95 return 1;
96 }
97
98 eventhandlers[fd].handler=handler;
99 eventhandlers[fd].fdarraypos=regfds;
100
101 eventfds[regfds].fd=fd;
102 eventfds[regfds].events=events;
103 eventfds[regfds].revents=0;
104
105 eventadds++;
106 regfds++;
107 return 0;
108 }
109
110 /*
111 * deregisterhandler():
112 * Remove an fd from the poll() array.
113 *
114 * The poll() version can't save any time if doclose is set, so
115 * we just do the same work and then close the socket if it's set.
116 *
117 * Now O(1)
118 */
119
120
121 int deregisterhandler(int fd, int doclose) {
122 int oldfdpos;
123 int lastreggedfd;
124
125 /* Check that the handler exists */
126 if (eventhandlers[fd].handler==NULL)
127 return 1;
128
129 /* We need to rearrange the fds array slightly to handle the delete */
130 eventdels++;
131 regfds--;
132 if (regfds>0) {
133 oldfdpos=eventhandlers[fd].fdarraypos;
134 lastreggedfd=eventfds[regfds].fd;
135 if (lastreggedfd!=fd) {
136 /* We need to move the "lastreggedfd" into "oldfdpos" */
137 memcpy(&eventfds[oldfdpos],&eventfds[regfds],sizeof(struct pollfd));
138 eventhandlers[lastreggedfd].fdarraypos=oldfdpos;
139 }
140 }
141
142 eventhandlers[fd].handler=NULL;
143 eventhandlers[fd].fdarraypos=-1;
144
145 if (doclose) {
146 close(fd);
147 }
148
149 return 0;
150 }
151
152 /*
153 * handleevents():
154 * Call poll() and handle and call appropiate handlers
155 * for any sockets that come up.
156 *
157 * Unavoidably O(n)
158 */
159
160 int handleevents(int timeout) {
161 int i,res;
162
163 for (i=0;i<regfds;i++) {
164 eventfds[i].revents=0;
165 }
166
167 res=poll(eventfds,regfds,timeout);
168 if (res<0) {
169 return 1;
170 }
171
172 for (i=0;i<regfds;i++) {
173 if(eventfds[i].revents>0) {
174 (eventhandlers[eventfds[i].fd].handler)(eventfds[i].fd, eventfds[i].revents);
175 eventexes++;
176 }
177 }
178 return 0;
179 }
180
181 void eventstats(int hooknum, void *arg) {
182 char buf[512];
183 long level=(long) arg;
184
185 if (level>5) {
186 sprintf(buf,"Events :%7d fds registered, %7d fds deregistered",eventadds,eventdels);
187 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
188 sprintf(buf,"Events :%7d events triggered, %6d fds active",eventexes,regfds);
189 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
190 }
191 }
192