]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rq.c
bafb12166d62aa8ae70ed4ce7d859217089c0a08
[openldap] / libraries / libldap_r / rq.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003-2005 The OpenLDAP Foundation.
5  * Portions Copyright 2003 IBM Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* This work was initially developed by Jong Hyuk Choi for inclusion
17  * in OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdarg.h>
25 #include <ac/stdlib.h>
26 #include <ac/errno.h>
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30
31 #include "ldap-int.h"
32 #include "ldap_pvt_thread.h"
33 #include "ldap_queue.h"
34 #include "ldap_rq.h"
35
36 void
37 ldap_pvt_runqueue_insert(
38         struct runqueue_s* rq,
39         time_t interval,
40         ldap_pvt_thread_start_t *routine,
41         void *arg
42 )
43 {
44         struct re_s* entry;
45
46         entry = (struct re_s *) LDAP_CALLOC( 1, sizeof( struct re_s ));
47         entry->interval.tv_sec = interval;
48         entry->interval.tv_usec = 0;
49         entry->next_sched.tv_sec = time( NULL );
50         entry->next_sched.tv_usec = 0;
51         entry->routine = routine;
52         entry->arg = arg;
53         LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
54 }
55
56 struct re_s *
57 ldap_pvt_runqueue_find(
58         struct runqueue_s *rq,
59         ldap_pvt_thread_start_t *routine,
60         void *arg
61 )
62 {
63         struct re_s* e;
64
65         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
66                 if ( e->routine == routine && e->arg == arg )
67                         return e;
68         }
69         return NULL;
70 }
71
72 void
73 ldap_pvt_runqueue_remove(
74         struct runqueue_s* rq,
75         struct re_s* entry
76 )
77 {
78         struct re_s* e;
79
80         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
81                 if ( e == entry)
82                         break;
83         }
84
85         assert( e == entry );
86
87         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
88
89         LDAP_FREE( entry );
90 }
91
92 struct re_s*
93 ldap_pvt_runqueue_next_sched(
94         struct runqueue_s* rq,
95         struct timeval** next_run
96 )
97 {
98         struct re_s* entry;
99
100         entry = LDAP_STAILQ_FIRST( &rq->task_list );
101         if ( entry == NULL ) {
102                 *next_run = NULL;
103                 return NULL;
104         } else if ( entry->next_sched.tv_sec == 0 ) {
105                 *next_run = NULL;
106                 return NULL;
107         } else {
108                 *next_run = &entry->next_sched;
109                 return entry;
110         }
111 }
112
113 void
114 ldap_pvt_runqueue_runtask(
115         struct runqueue_s* rq,
116         struct re_s* entry
117 )
118 {
119         LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext );
120 }
121
122 void
123 ldap_pvt_runqueue_stoptask(
124         struct runqueue_s* rq,
125         struct re_s* entry
126 )
127 {
128         LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext );
129 }
130
131 int
132 ldap_pvt_runqueue_isrunning(
133         struct runqueue_s* rq,
134         struct re_s* entry
135 )
136 {
137         struct re_s* e;
138
139         LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) {
140                 if ( e == entry ) {
141                         return 1;
142                 }
143         }
144         return 0;
145 }
146
147 void 
148 ldap_pvt_runqueue_resched(
149         struct runqueue_s* rq,
150         struct re_s* entry,
151         int defer
152 )
153 {
154         struct re_s* prev;
155         struct re_s* e;
156
157         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
158                 if ( e == entry )
159                         break;
160         }
161
162         assert ( e == entry );
163
164         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
165
166         if ( !defer ) {
167                 entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
168         } else {
169                 entry->next_sched.tv_sec = 0;
170         }
171
172         if ( LDAP_STAILQ_EMPTY( &rq->task_list )) {
173                 LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
174         } else if ( entry->next_sched.tv_sec == 0 ) {
175                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
176         } else {
177                 prev = NULL;
178                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
179                         if ( e->next_sched.tv_sec == 0 ) {
180                                 if ( prev == NULL ) {
181                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
182                                 } else {
183                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
184                                 }
185                                 return;
186                         } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) {
187                                 if ( prev == NULL ) {
188                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
189                                 } else {
190                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
191                                 }
192                                 return;
193                         }
194                         prev = e;
195                 }
196                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
197         }
198 }
199
200 int
201 ldap_pvt_runqueue_persistent_backload(
202         struct runqueue_s* rq
203 )
204 {
205         struct re_s* e;
206         int count = 0;
207
208         ldap_pvt_thread_mutex_lock( &rq->rq_mutex );
209         if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) {
210                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
211                         if ( e->next_sched.tv_sec == 0 )
212                                 count++;
213                 }
214         }
215         ldap_pvt_thread_mutex_unlock( &rq->rq_mutex );
216         return count;
217 }
218