2 Copyright (c) 2003-2006 by Juliusz Chroboczek
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 static volatile sig_atomic_t exitFlag
= 0;
28 static int exitFlag
= 0;
30 static int in_signalCondition
= 0;
32 static TimeEventHandlerPtr timeEventQueue
;
33 static TimeEventHandlerPtr timeEventQueueLast
;
35 struct timeval current_time
;
36 struct timeval null_time
= {0,0};
38 static int fdEventSize
= 0;
39 static int fdEventNum
= 0;
40 static struct pollfd
*poll_fds
= NULL
;
41 static FdEventHandlerPtr
*fdEvents
= NULL
, *fdEventsLast
= NULL
;
44 static int fds_invalid
= 0;
47 timeval_cmp(struct timeval
*t1
, struct timeval
*t2
)
49 if(t1
->tv_sec
< t2
->tv_sec
)
51 else if(t1
->tv_sec
> t2
->tv_sec
)
53 else if(t1
->tv_usec
< t2
->tv_usec
)
55 else if(t1
->tv_usec
> t2
->tv_usec
)
62 timeval_minus(struct timeval
*d
,
63 const struct timeval
*s1
, const struct timeval
*s2
)
65 if(s1
->tv_usec
> s2
->tv_usec
) {
66 d
->tv_usec
= s1
->tv_usec
- s2
->tv_usec
;
67 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
;
69 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
70 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
75 timeval_minus_usec(const struct timeval
*s1
, const struct timeval
*s2
)
77 return (s1
->tv_sec
- s2
->tv_sec
) * 1000000 + s1
->tv_usec
- s2
->tv_usec
;
86 else if(signo
== SIGUSR2
)
101 sa
.sa_handler
= SIG_IGN
;
104 sigaction(SIGPIPE
, &sa
, NULL
);
107 sa
.sa_handler
= sigexit
;
110 sigaction(SIGTERM
, &sa
, NULL
);
113 sa
.sa_handler
= sigexit
;
116 sigaction(SIGHUP
, &sa
, NULL
);
119 sa
.sa_handler
= sigexit
;
122 sigaction(SIGINT
, &sa
, NULL
);
125 sa
.sa_handler
= sigexit
;
128 sigaction(SIGUSR1
, &sa
, NULL
);
131 sa
.sa_handler
= sigexit
;
134 sigaction(SIGUSR2
, &sa
, NULL
);
137 timeEventQueue
= NULL
;
138 timeEventQueueLast
= NULL
;
154 sa
.sa_handler
= SIG_DFL
;
157 sigaction(SIGTERM
, &sa
, NULL
);
160 sa
.sa_handler
= SIG_DFL
;
163 sigaction(SIGHUP
, &sa
, NULL
);
166 sa
.sa_handler
= SIG_DFL
;
169 sigaction(SIGINT
, &sa
, NULL
);
172 sa
.sa_handler
= SIG_DFL
;
175 sigaction(SIGUSR1
, &sa
, NULL
);
178 sa
.sa_handler
= SIG_DFL
;
181 sigaction(SIGUSR2
, &sa
, NULL
);
187 interestingSignals(sigset_t
*ss
)
190 sigaddset(ss
, SIGTERM
);
191 sigaddset(ss
, SIGHUP
);
192 sigaddset(ss
, SIGINT
);
193 sigaddset(ss
, SIGUSR1
);
194 sigaddset(ss
, SIGUSR2
);
199 timeToSleep(struct timeval
*time
)
201 if(!timeEventQueue
) {
205 *time
= timeEventQueue
->time
;
209 static TimeEventHandlerPtr
210 enqueueTimeEvent(TimeEventHandlerPtr event
)
212 TimeEventHandlerPtr otherevent
;
214 /* We try to optimise two cases -- the event happens very soon, or
215 it happens after most of the other events. */
216 if(timeEventQueue
== NULL
||
217 timeval_cmp(&event
->time
, &timeEventQueue
->time
) < 0) {
218 /* It's the first event */
219 event
->next
= timeEventQueue
;
220 event
->previous
= NULL
;
222 timeEventQueue
->previous
= event
;
224 timeEventQueueLast
= event
;
226 timeEventQueue
= event
;
227 } else if(timeval_cmp(&event
->time
, &timeEventQueueLast
->time
) >= 0) {
228 /* It's the last one */
230 event
->previous
= timeEventQueueLast
;
231 timeEventQueueLast
->next
= event
;
232 timeEventQueueLast
= event
;
234 /* Walk from the end */
235 otherevent
= timeEventQueueLast
;
236 while(otherevent
->previous
&&
237 timeval_cmp(&event
->time
, &otherevent
->previous
->time
) < 0) {
238 otherevent
= otherevent
->previous
;
240 event
->next
= otherevent
;
241 event
->previous
= otherevent
->previous
;
242 if(otherevent
->previous
) {
243 otherevent
->previous
->next
= event
;
245 timeEventQueue
= event
;
247 otherevent
->previous
= event
;
253 scheduleTimeEvent(int seconds
,
254 int (*handler
)(TimeEventHandlerPtr
), int dsize
, void *data
)
257 TimeEventHandlerPtr event
;
261 when
.tv_sec
+= seconds
;
267 event
= malloc(sizeof(TimeEventHandlerRec
) - 1 + dsize
);
269 do_log(L_ERROR
, "Couldn't allocate time event handler -- "
270 "discarding all objects.\n");
276 event
->handler
= handler
;
277 /* Let the compiler optimise the common case */
278 if(dsize
== sizeof(void*))
279 memcpy(event
->data
, data
, sizeof(void*));
281 memcpy(event
->data
, data
, dsize
);
283 return enqueueTimeEvent(event
);
287 cancelTimeEvent(TimeEventHandlerPtr event
)
289 if(event
== timeEventQueue
)
290 timeEventQueue
= event
->next
;
291 if(event
== timeEventQueueLast
)
292 timeEventQueueLast
= event
->previous
;
294 event
->next
->previous
= event
->previous
;
296 event
->previous
->next
= event
->next
;
301 allocateFdEventNum(int fd
)
304 if(fdEventNum
< fdEventSize
) {
308 struct pollfd
*new_poll_fds
;
309 FdEventHandlerPtr
*new_fdEvents
, *new_fdEventsLast
;
310 int new_size
= 3 * fdEventSize
/ 2 + 1;
312 new_poll_fds
= realloc(poll_fds
, new_size
* sizeof(struct pollfd
));
315 new_fdEvents
= realloc(fdEvents
, new_size
* sizeof(FdEventHandlerPtr
));
318 new_fdEventsLast
= realloc(fdEventsLast
,
319 new_size
* sizeof(FdEventHandlerPtr
));
320 if(!new_fdEventsLast
)
323 poll_fds
= new_poll_fds
;
324 fdEvents
= new_fdEvents
;
325 fdEventsLast
= new_fdEventsLast
;
326 fdEventSize
= new_size
;
332 poll_fds
[i
].events
= POLLERR
| POLLHUP
| POLLNVAL
;
333 poll_fds
[i
].revents
= 0;
335 fdEventsLast
[i
] = NULL
;
341 deallocateFdEventNum(int i
)
343 if(i
< fdEventNum
- 1) {
344 memmove(&poll_fds
[i
], &poll_fds
[i
+ 1],
345 (fdEventNum
- i
- 1) * sizeof(struct pollfd
));
346 memmove(&fdEvents
[i
], &fdEvents
[i
+ 1],
347 (fdEventNum
- i
- 1) * sizeof(FdEventHandlerPtr
));
348 memmove(&fdEventsLast
[i
], &fdEventsLast
[i
+ 1],
349 (fdEventNum
- i
- 1) * sizeof(FdEventHandlerPtr
));
356 makeFdEvent(int fd
, int poll_events
,
357 int (*handler
)(int, FdEventHandlerPtr
), int dsize
, void *data
)
359 FdEventHandlerPtr event
;
361 event
= malloc(sizeof(FdEventHandlerRec
) - 1 + dsize
);
363 do_log(L_ERROR
, "Couldn't allocate fd event handler -- "
364 "discarding all objects.\n");
369 event
->poll_events
= poll_events
;
370 event
->handler
= handler
;
371 /* Let the compiler optimise the common cases */
372 if(dsize
== sizeof(void*))
373 memcpy(event
->data
, data
, sizeof(void*));
374 else if(dsize
== sizeof(StreamRequestRec
))
375 memcpy(event
->data
, data
, sizeof(StreamRequestRec
));
377 memcpy(event
->data
, data
, dsize
);
382 registerFdEventHelper(FdEventHandlerPtr event
)
387 for(i
= 0; i
< fdEventNum
; i
++)
388 if(poll_fds
[i
].fd
== fd
)
392 i
= allocateFdEventNum(fd
);
399 event
->previous
= fdEventsLast
[i
];
400 if(fdEvents
[i
] == NULL
) {
403 fdEventsLast
[i
]->next
= event
;
405 fdEventsLast
[i
] = event
;
406 poll_fds
[i
].events
|= event
->poll_events
;
412 registerFdEvent(int fd
, int poll_events
,
413 int (*handler
)(int, FdEventHandlerPtr
), int dsize
, void *data
)
415 FdEventHandlerPtr event
;
417 event
= makeFdEvent(fd
, poll_events
, handler
, dsize
, data
);
421 return registerFdEventHelper(event
);
425 recomputePollEvents(FdEventHandlerPtr event
)
429 pe
|= event
->poll_events
;
432 return pe
| POLLERR
| POLLHUP
| POLLNVAL
;
436 unregisterFdEventI(FdEventHandlerPtr event
, int i
)
438 assert(i
< fdEventNum
&& poll_fds
[i
].fd
== event
->fd
);
440 if(fdEvents
[i
] == event
) {
441 assert(!event
->previous
);
442 fdEvents
[i
] = event
->next
;
444 event
->previous
->next
= event
->next
;
447 if(fdEventsLast
[i
] == event
) {
448 assert(!event
->next
);
449 fdEventsLast
[i
] = event
->previous
;
451 event
->next
->previous
= event
->previous
;
456 if(fdEvents
[i
] == NULL
) {
457 deallocateFdEventNum(i
);
459 poll_fds
[i
].events
= recomputePollEvents(fdEvents
[i
]) |
460 POLLERR
| POLLHUP
| POLLNVAL
;
465 unregisterFdEvent(FdEventHandlerPtr event
)
469 for(i
= 0; i
< fdEventNum
; i
++) {
470 if(poll_fds
[i
].fd
== event
->fd
) {
471 unregisterFdEventI(event
, i
);
481 TimeEventHandlerPtr event
;
484 while(timeEventQueue
&&
485 timeval_cmp(&timeEventQueue
->time
, ¤t_time
) <= 0) {
486 event
= timeEventQueue
;
487 timeEventQueue
= event
->next
;
489 timeEventQueue
->previous
= NULL
;
491 timeEventQueueLast
= NULL
;
492 done
= event
->handler(event
);
498 static FdEventHandlerPtr
499 findEventHelper(int revents
, FdEventHandlerPtr events
)
501 FdEventHandlerPtr event
= events
;
503 if(revents
& event
->poll_events
)
512 static FdEventHandlerPtr
513 findEvent(int revents
, FdEventHandlerPtr events
)
515 FdEventHandlerPtr event
;
517 assert(!(revents
& POLLNVAL
));
519 if((revents
& POLLHUP
) || (revents
& POLLERR
)) {
520 event
= findEventHelper(POLLOUT
, events
);
521 if(event
) return event
;
523 event
= findEventHelper(POLLIN
, events
);
524 if(event
) return event
;
528 if(revents
& POLLOUT
) {
529 event
= findEventHelper(POLLOUT
, events
);
530 if(event
) return event
;
533 if(revents
& POLLIN
) {
534 event
= findEventHelper(POLLIN
, events
);
535 if(event
) return event
;
540 typedef struct _FdEventHandlerPoke
{
544 } FdEventHandlerPokeRec
, *FdEventHandlerPokePtr
;
547 pokeFdEventHandler(TimeEventHandlerPtr tevent
)
549 FdEventHandlerPokePtr poke
= (FdEventHandlerPokePtr
)tevent
->data
;
551 int what
= poke
->what
;
552 int status
= poke
->status
;
554 FdEventHandlerPtr event
, next
;
557 for(i
= 0; i
< fdEventNum
; i
++) {
558 if(poll_fds
[i
].fd
== fd
)
568 if(event
->poll_events
& what
) {
569 done
= event
->handler(status
, event
);
572 unregisterFdEvent(event
);
574 unregisterFdEventI(event
, i
);
585 pokeFdEvent(int fd
, int status
, int what
)
587 TimeEventHandlerPtr handler
;
588 FdEventHandlerPokeRec poke
;
591 poke
.status
= status
;
594 handler
= scheduleTimeEvent(0, pokeFdEventHandler
,
595 sizeof(poke
), &poke
);
597 do_log(L_ERROR
, "Couldn't allocate handler.\n");
604 struct timeval sleep_time
;
610 timeToSleep(&sleep_time
);
611 gettimeofday(¤t_time
, NULL
);
612 if(timeval_cmp(&sleep_time
, ¤t_time
) <= 0)
614 rc
= poll(poll_fds
, fdEventNum
, 0);
616 do_log_error(L_ERROR
, errno
, "Couldn't poll");
625 struct timeval sleep_time
, timeout
;
627 FdEventHandlerPtr event
;
630 gettimeofday(¤t_time
, NULL
);
638 discardObjects(1, 0);
649 timeToSleep(&sleep_time
);
650 if(sleep_time
.tv_sec
== -1) {
651 rc
= poll(poll_fds
, fdEventNum
,
652 diskIsClean
? -1 : idleTime
* 1000);
653 } else if(timeval_cmp(&sleep_time
, ¤t_time
) <= 0) {
657 gettimeofday(¤t_time
, NULL
);
658 if(timeval_cmp(&sleep_time
, ¤t_time
) <= 0) {
663 timeval_minus(&timeout
, &sleep_time
, ¤t_time
);
664 t
= timeout
.tv_sec
* 1000 + (timeout
.tv_usec
+ 999) / 1000;
665 rc
= poll(poll_fds
, fdEventNum
,
666 diskIsClean
? t
: MIN(idleTime
* 1000, t
));
670 gettimeofday(¤t_time
, NULL
);
675 } else if(errno
== ENOMEM
) {
678 "Couldn't poll: out of memory. "
679 "Sleeping for one second.\n");
682 do_log_error(L_ERROR
, errno
, "Couldn't poll");
690 timeToSleep(&sleep_time
);
691 if(timeval_cmp(&sleep_time
, ¤t_time
) > 0)
697 /* Rather than tracking all changes to the in-memory cache, we
698 assume that something changed whenever we see any activity. */
702 (current_time
.tv_usec
^ (current_time
.tv_usec
>> 16)) % fdEventNum
;
704 for(i
= 0; i
< fdEventNum
; i
++) {
705 int j
= (i
+ fd0
) % fdEventNum
;
708 if(poll_fds
[j
].revents
) {
710 event
= findEvent(poll_fds
[j
].revents
, fdEvents
[j
]);
713 done
= event
->handler(0, event
);
716 unregisterFdEvent(event
);
718 unregisterFdEventI(event
, j
);
730 initCondition(ConditionPtr condition
)
732 condition
->handlers
= NULL
;
738 ConditionPtr condition
;
739 condition
= malloc(sizeof(ConditionRec
));
740 if(condition
== NULL
)
742 initCondition(condition
);
747 conditionWait(ConditionPtr condition
,
748 int (*handler
)(int, ConditionHandlerPtr
),
749 int dsize
, void *data
)
751 ConditionHandlerPtr chandler
;
753 assert(!in_signalCondition
);
755 chandler
= malloc(sizeof(ConditionHandlerRec
) - 1 + dsize
);
759 chandler
->condition
= condition
;
760 chandler
->handler
= handler
;
761 /* Let the compiler optimise the common case */
762 if(dsize
== sizeof(void*))
763 memcpy(chandler
->data
, data
, sizeof(void*));
765 memcpy(chandler
->data
, data
, dsize
);
767 if(condition
->handlers
)
768 condition
->handlers
->previous
= chandler
;
769 chandler
->next
= condition
->handlers
;
770 chandler
->previous
= NULL
;
771 condition
->handlers
= chandler
;
776 unregisterConditionHandler(ConditionHandlerPtr handler
)
778 ConditionPtr condition
= handler
->condition
;
780 assert(!in_signalCondition
);
782 if(condition
->handlers
== handler
)
783 condition
->handlers
= condition
->handlers
->next
;
785 handler
->next
->previous
= handler
->previous
;
786 if(handler
->previous
)
787 handler
->previous
->next
= handler
->next
;
793 abortConditionHandler(ConditionHandlerPtr handler
)
796 done
= handler
->handler(-1, handler
);
798 unregisterConditionHandler(handler
);
802 signalCondition(ConditionPtr condition
)
804 ConditionHandlerPtr handler
;
807 assert(!in_signalCondition
);
808 in_signalCondition
++;
810 handler
= condition
->handlers
;
812 ConditionHandlerPtr next
= handler
->next
;
813 done
= handler
->handler(0, handler
);
815 if(handler
== condition
->handlers
)
816 condition
->handlers
= next
;
818 next
->previous
= handler
->previous
;
819 if(handler
->previous
)
820 handler
->previous
->next
= next
;
822 condition
->handlers
= next
;
827 in_signalCondition
--;