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