]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rq.c
85ae1aa2db99e810132c88174e5e37ad83bdcac1
[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 void
57 ldap_pvt_runqueue_remove(
58         struct runqueue_s* rq,
59         struct re_s* entry
60 )
61 {
62         struct re_s* e;
63
64         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
65                 if ( e == entry)
66                         break;
67         }
68
69         assert( e == entry );
70
71         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
72
73         LDAP_FREE( entry );
74 }
75
76 struct re_s*
77 ldap_pvt_runqueue_next_sched(
78         struct runqueue_s* rq,
79         struct timeval** next_run
80 )
81 {
82         struct re_s* entry;
83
84         entry = LDAP_STAILQ_FIRST( &rq->task_list );
85         if ( entry == NULL ) {
86                 *next_run = NULL;
87                 return NULL;
88         } else if ( entry->next_sched.tv_sec == 0 ) {
89                 *next_run = NULL;
90                 return NULL;
91         } else {
92                 *next_run = &entry->next_sched;
93                 return entry;
94         }
95 }
96
97 void
98 ldap_pvt_runqueue_runtask(
99         struct runqueue_s* rq,
100         struct re_s* entry
101 )
102 {
103         LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext );
104 }
105
106 void
107 ldap_pvt_runqueue_stoptask(
108         struct runqueue_s* rq,
109         struct re_s* entry
110 )
111 {
112         LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext );
113 }
114
115 int
116 ldap_pvt_runqueue_isrunning(
117         struct runqueue_s* rq,
118         struct re_s* entry
119 )
120 {
121         struct re_s* e;
122
123         LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) {
124                 if ( e == entry ) {
125                         return 1;
126                 }
127         }
128         return 0;
129 }
130
131 void 
132 ldap_pvt_runqueue_resched(
133         struct runqueue_s* rq,
134         struct re_s* entry,
135         int defer
136 )
137 {
138         struct re_s* prev;
139         struct re_s* e;
140
141         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
142                 if ( e == entry )
143                         break;
144         }
145
146         assert ( e == entry );
147
148         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
149
150         if ( !defer ) {
151                 entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
152         } else {
153                 entry->next_sched.tv_sec = 0;
154         }
155
156         if ( LDAP_STAILQ_EMPTY( &rq->task_list )) {
157                 LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
158         } else if ( entry->next_sched.tv_sec == 0 ) {
159                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
160         } else {
161                 prev = NULL;
162                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
163                         if ( e->next_sched.tv_sec == 0 ) {
164                                 if ( prev == NULL ) {
165                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
166                                 } else {
167                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
168                                 }
169                                 return;
170                         } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) {
171                                 if ( prev == NULL ) {
172                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
173                                 } else {
174                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
175                                 }
176                                 return;
177                         }
178                         prev = e;
179                 }
180                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
181         }
182 }
183
184 int
185 ldap_pvt_runqueue_persistent_backload(
186         struct runqueue_s* rq
187 )
188 {
189         struct re_s* e;
190         int count = 0;
191
192         ldap_pvt_thread_mutex_lock( &rq->rq_mutex );
193         if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) {
194                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
195                         if ( e->next_sched.tv_sec == 0 )
196                                 count++;
197                 }
198         }
199         ldap_pvt_thread_mutex_unlock( &rq->rq_mutex );
200         return count;
201 }
202