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