]>
Commit | Line | Data |
---|---|---|
2c5db955 CP |
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 | /* | |
55 | * checkindex(): | |
56 | * Given the number of a new file descriptor, makes sure that the arrays | |
57 | * will be big enough to deal with it. | |
58 | */ | |
59 | ||
60 | void checkindex(unsigned index) { | |
61 | int oldmax=maxfds; | |
62 | ||
63 | if (index<maxfds) { | |
64 | return; | |
65 | } | |
66 | ||
67 | while (maxfds<=index) { | |
68 | maxfds+=GROWFDS; | |
69 | } | |
70 | ||
71 | eventfds=(struct pollfd *)realloc((void *)eventfds,maxfds*sizeof(struct pollfd)); | |
da846057 | 72 | memset(&eventfds[oldmax],0,(maxfds-oldmax)*sizeof(struct pollfd)); |
2c5db955 | 73 | eventhandlers=(reghandler *)realloc((void *)eventhandlers,maxfds*sizeof(reghandler)); |
da846057 | 74 | memset(&eventhandlers[oldmax],0,(maxfds-oldmax)*sizeof(reghandler)); |
2c5db955 CP |
75 | } |
76 | ||
77 | /* | |
78 | * registerhandler(): | |
79 | * Add an fd to the poll() array. | |
80 | * | |
81 | * Now O(1) | |
82 | */ | |
83 | ||
84 | int registerhandler(int fd, short events, FDHandler handler) { | |
85 | checkindex(fd); | |
86 | ||
87 | /* Check that it's not already registered */ | |
88 | if (eventhandlers[fd].handler!=NULL) { | |
89 | return 1; | |
90 | } | |
91 | ||
92 | eventhandlers[fd].handler=handler; | |
93 | eventhandlers[fd].fdarraypos=regfds; | |
94 | ||
95 | eventfds[regfds].fd=fd; | |
96 | eventfds[regfds].events=events; | |
97 | eventfds[regfds].revents=0; | |
98 | ||
99 | eventadds++; | |
100 | regfds++; | |
101 | return 0; | |
102 | } | |
103 | ||
104 | /* | |
105 | * deregisterhandler(): | |
106 | * Remove an fd from the poll() array. | |
107 | * | |
108 | * The poll() version can't save any time if doclose is set, so | |
109 | * we just do the same work and then close the socket if it's set. | |
110 | * | |
111 | * Now O(1) | |
112 | */ | |
113 | ||
114 | ||
115 | int deregisterhandler(int fd, int doclose) { | |
116 | int oldfdpos; | |
117 | int lastreggedfd; | |
118 | ||
119 | /* Check that the handler exists */ | |
120 | if (eventhandlers[fd].handler==NULL) | |
121 | return 1; | |
122 | ||
123 | /* We need to rearrange the fds array slightly to handle the delete */ | |
124 | eventdels++; | |
125 | regfds--; | |
126 | if (regfds>0) { | |
127 | oldfdpos=eventhandlers[fd].fdarraypos; | |
128 | lastreggedfd=eventfds[regfds].fd; | |
129 | if (lastreggedfd!=fd) { | |
130 | /* We need to move the "lastreggedfd" into "oldfdpos" */ | |
131 | memcpy(&eventfds[oldfdpos],&eventfds[regfds],sizeof(struct pollfd)); | |
132 | eventhandlers[lastreggedfd].fdarraypos=oldfdpos; | |
133 | } | |
134 | } | |
135 | ||
136 | eventhandlers[fd].handler=NULL; | |
137 | eventhandlers[fd].fdarraypos=-1; | |
138 | ||
139 | if (doclose) { | |
140 | close(fd); | |
141 | } | |
142 | ||
143 | return 0; | |
144 | } | |
145 | ||
146 | /* | |
147 | * handleevents(): | |
148 | * Call poll() and handle and call appropiate handlers | |
149 | * for any sockets that come up. | |
150 | * | |
151 | * Unavoidably O(n) | |
152 | */ | |
153 | ||
154 | int handleevents(int timeout) { | |
155 | int i,res; | |
156 | ||
157 | for (i=0;i<regfds;i++) { | |
158 | eventfds[i].revents=0; | |
159 | } | |
160 | ||
161 | res=poll(eventfds,regfds,timeout); | |
162 | if (res<0) { | |
163 | return 1; | |
164 | } | |
165 | ||
166 | for (i=0;i<regfds;i++) { | |
167 | if(eventfds[i].revents>0) { | |
168 | (eventhandlers[eventfds[i].fd].handler)(eventfds[i].fd, eventfds[i].revents); | |
169 | eventexes++; | |
170 | } | |
171 | } | |
172 | return 0; | |
173 | } | |
174 | ||
175 | void eventstats(int hooknum, void *arg) { | |
176 | char buf[512]; | |
c3db6f7e | 177 | long level=(long) arg; |
2c5db955 CP |
178 | |
179 | if (level>5) { | |
180 | sprintf(buf,"Events :%7d fds registered, %7d fds deregistered",eventadds,eventdels); | |
181 | triggerhook(HOOK_CORE_STATSREPLY,(void *)buf); | |
182 | sprintf(buf,"Events :%7d events triggered, %6d fds active",eventexes,regfds); | |
183 | triggerhook(HOOK_CORE_STATSREPLY,(void *)buf); | |
184 | } | |
185 | } | |
186 |