]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rq.c
7b775f61f1898f646f4b4ffbbd30716a7bf57652
[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 struct re_s *
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         char *tname,
43         char *tspec
44 )
45 {
46         struct re_s* entry;
47
48         entry = (struct re_s *) LDAP_CALLOC( 1, sizeof( struct re_s ));
49         if ( entry ) {
50                 entry->interval.tv_sec = interval;
51                 entry->interval.tv_usec = 0;
52                 entry->next_sched.tv_sec = time( NULL );
53                 entry->next_sched.tv_usec = 0;
54                 entry->routine = routine;
55                 entry->arg = arg;
56                 entry->tname = tname;
57                 entry->tspec = tspec;
58                 LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
59         }
60         return entry;
61 }
62
63 struct re_s *
64 ldap_pvt_runqueue_find(
65         struct runqueue_s *rq,
66         ldap_pvt_thread_start_t *routine,
67         void *arg
68 )
69 {
70         struct re_s* e;
71
72         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
73                 if ( e->routine == routine && e->arg == arg )
74                         return e;
75         }
76         return NULL;
77 }
78
79 void
80 ldap_pvt_runqueue_remove(
81         struct runqueue_s* rq,
82         struct re_s* entry
83 )
84 {
85         struct re_s* e;
86
87         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
88                 if ( e == entry)
89                         break;
90         }
91
92         assert( e == entry );
93
94         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
95
96         LDAP_FREE( entry );
97 }
98
99 struct re_s*
100 ldap_pvt_runqueue_next_sched(
101         struct runqueue_s* rq,
102         struct timeval** next_run
103 )
104 {
105         struct re_s* entry;
106
107         entry = LDAP_STAILQ_FIRST( &rq->task_list );
108         if ( entry == NULL ) {
109                 *next_run = NULL;
110                 return NULL;
111         } else if ( entry->next_sched.tv_sec == 0 ) {
112                 *next_run = NULL;
113                 return NULL;
114         } else {
115                 *next_run = &entry->next_sched;
116                 return entry;
117         }
118 }
119
120 void
121 ldap_pvt_runqueue_runtask(
122         struct runqueue_s* rq,
123         struct re_s* entry
124 )
125 {
126         LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext );
127 }
128
129 void
130 ldap_pvt_runqueue_stoptask(
131         struct runqueue_s* rq,
132         struct re_s* entry
133 )
134 {
135         LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext );
136 }
137
138 int
139 ldap_pvt_runqueue_isrunning(
140         struct runqueue_s* rq,
141         struct re_s* entry
142 )
143 {
144         struct re_s* e;
145
146         LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) {
147                 if ( e == entry ) {
148                         return 1;
149                 }
150         }
151         return 0;
152 }
153
154 void 
155 ldap_pvt_runqueue_resched(
156         struct runqueue_s* rq,
157         struct re_s* entry,
158         int defer
159 )
160 {
161         struct re_s* prev;
162         struct re_s* e;
163
164         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
165                 if ( e == entry )
166                         break;
167         }
168
169         assert ( e == entry );
170
171         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
172
173         if ( !defer ) {
174                 entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
175         } else {
176                 entry->next_sched.tv_sec = 0;
177         }
178
179         if ( LDAP_STAILQ_EMPTY( &rq->task_list )) {
180                 LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
181         } else if ( entry->next_sched.tv_sec == 0 ) {
182                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
183         } else {
184                 prev = NULL;
185                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
186                         if ( e->next_sched.tv_sec == 0 ) {
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                         } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) {
194                                 if ( prev == NULL ) {
195                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
196                                 } else {
197                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
198                                 }
199                                 return;
200                         }
201                         prev = e;
202                 }
203                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
204         }
205 }
206
207 int
208 ldap_pvt_runqueue_persistent_backload(
209         struct runqueue_s* rq
210 )
211 {
212         struct re_s* e;
213         int count = 0;
214
215         ldap_pvt_thread_mutex_lock( &rq->rq_mutex );
216         if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) {
217                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
218                         if ( e->next_sched.tv_sec == 0 )
219                                 count++;
220                 }
221         }
222         ldap_pvt_thread_mutex_unlock( &rq->rq_mutex );
223         return count;
224 }
225