]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rq.c
6cbddd61437dbed0bce455d28464af0a87119cf9
[openldap] / libraries / libldap_r / rq.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003 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
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/stdarg.h>
22 #include <ac/stdlib.h>
23 #include <ac/errno.h>
24 #include <ac/socket.h>
25 #include <ac/string.h>
26 #include <ac/time.h>
27
28 #include "ldap-int.h"
29 #include "ldap_pvt_thread.h"
30 #include "ldap_queue.h"
31 #include "ldap_rq.h"
32
33 void
34 ldap_pvt_runqueue_insert(
35         struct runqueue_s* rq,
36         time_t interval,
37         ldap_pvt_thread_start_t *routine,
38         void *arg
39 )
40 {
41         struct re_s* entry;
42
43         entry = (struct re_s *) LDAP_CALLOC( 1, sizeof( struct re_s ));
44         entry->interval.tv_sec = interval;
45         entry->interval.tv_usec = 0;
46         entry->next_sched.tv_sec = time( NULL );
47         entry->next_sched.tv_usec = 0;
48         entry->routine = routine;
49         entry->arg = arg;
50         LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
51 }
52
53 void
54 ldap_pvt_runqueue_remove(
55         struct runqueue_s* rq,
56         struct re_s* entry
57 )
58 {
59         struct re_s* e;
60
61         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
62                 if ( e == entry)
63                         break;
64         }
65
66         assert ( e == entry );
67
68         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
69
70         LDAP_FREE( entry );
71
72 }
73
74 struct re_s*
75 ldap_pvt_runqueue_next_sched(
76         struct runqueue_s* rq,
77         struct timeval** next_run
78 )
79 {
80         struct re_s* entry;
81
82         entry = LDAP_STAILQ_FIRST( &rq->task_list );
83         if ( entry == NULL ) {
84                 *next_run = NULL;
85                 return NULL;
86         } else if ( entry->next_sched.tv_sec == 0 ) {
87                 *next_run = NULL;
88                 return NULL;
89         } else {
90                 *next_run = &entry->next_sched;
91                 return entry;
92         }
93 }
94
95 void
96 ldap_pvt_runqueue_runtask(
97         struct runqueue_s* rq,
98         struct re_s* entry
99 )
100 {
101         LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext );
102 }
103
104 void
105 ldap_pvt_runqueue_stoptask(
106         struct runqueue_s* rq,
107         struct re_s* entry
108 )
109 {
110         LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext );
111 }
112
113 int
114 ldap_pvt_runqueue_isrunning(
115         struct runqueue_s* rq,
116         struct re_s* entry
117 )
118 {
119         struct re_s* e;
120
121         LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) {
122                 if ( e == entry ) {
123                         return 1;
124                 }
125         }
126         return 0;
127 }
128
129 void 
130 ldap_pvt_runqueue_resched(
131         struct runqueue_s* rq,
132         struct re_s* entry,
133         int defer
134 )
135 {
136         struct re_s* prev;
137         struct re_s* e;
138
139         LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
140                 if ( e == entry )
141                         break;
142         }
143
144         assert ( e == entry );
145
146         LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
147
148         if ( entry->interval.tv_sec && !defer ) {
149                 entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
150         } else {
151                 entry->next_sched.tv_sec = 0;
152         }
153
154         if ( LDAP_STAILQ_EMPTY( &rq->task_list )) {
155                 LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
156         } else if ( entry->next_sched.tv_sec == 0 ) {
157                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
158         } else {
159                 prev = NULL;
160                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
161                         if ( e->next_sched.tv_sec == 0 ) {
162                                 if ( prev == NULL ) {
163                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
164                                 } else {
165                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
166                                 }
167                                 return;
168                         } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) {
169                                 if ( prev == NULL ) {
170                                         LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
171                                 } else {
172                                         LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
173                                 }
174                                 return;
175                         }
176                         prev = e;
177                 }
178                 LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
179         }
180 }
181
182 int
183 ldap_pvt_runqueue_persistent_backload(
184         struct runqueue_s* rq
185 )
186 {
187         struct re_s* e;
188         int count = 0;
189
190         ldap_pvt_thread_mutex_lock( &rq->rq_mutex );
191         if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) {
192                 LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
193                         if ( e->next_sched.tv_sec == 0 )
194                                 count++;
195                 }
196         }
197         ldap_pvt_thread_mutex_unlock( &rq->rq_mutex );
198         return count;
199 }
200