Back to index

openldap  2.4.31
rq.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 2003-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 2003 IBM Corporation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* This work was initially developed by Jong Hyuk Choi for inclusion
00017  * in OpenLDAP Software.
00018  */
00019 
00020 #include "portable.h"
00021 
00022 #include <stdio.h>
00023 
00024 #include <ac/stdarg.h>
00025 #include <ac/stdlib.h>
00026 #include <ac/errno.h>
00027 #include <ac/socket.h>
00028 #include <ac/string.h>
00029 #include <ac/time.h>
00030 
00031 #include "ldap-int.h"
00032 #include "ldap_pvt_thread.h"
00033 #include "ldap_queue.h"
00034 #include "ldap_rq.h"
00035 
00036 struct re_s *
00037 ldap_pvt_runqueue_insert(
00038        struct runqueue_s* rq,
00039        time_t interval,
00040        ldap_pvt_thread_start_t *routine,
00041        void *arg,
00042        char *tname,
00043        char *tspec
00044 )
00045 {
00046        struct re_s* entry;
00047 
00048        entry = (struct re_s *) LDAP_CALLOC( 1, sizeof( struct re_s ));
00049        if ( entry ) {
00050               entry->interval.tv_sec = interval;
00051               entry->interval.tv_usec = 0;
00052               entry->next_sched.tv_sec = time( NULL );
00053               entry->next_sched.tv_usec = 0;
00054               entry->routine = routine;
00055               entry->arg = arg;
00056               entry->tname = tname;
00057               entry->tspec = tspec;
00058               LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
00059        }
00060        return entry;
00061 }
00062 
00063 struct re_s *
00064 ldap_pvt_runqueue_find(
00065        struct runqueue_s *rq,
00066        ldap_pvt_thread_start_t *routine,
00067        void *arg
00068 )
00069 {
00070        struct re_s* e;
00071 
00072        LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
00073               if ( e->routine == routine && e->arg == arg )
00074                      return e;
00075        }
00076        return NULL;
00077 }
00078 
00079 void
00080 ldap_pvt_runqueue_remove(
00081        struct runqueue_s* rq,
00082        struct re_s* entry
00083 )
00084 {
00085        struct re_s* e;
00086 
00087        LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
00088               if ( e == entry)
00089                      break;
00090        }
00091 
00092        assert( e == entry );
00093 
00094        LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
00095 
00096        LDAP_FREE( entry );
00097 }
00098 
00099 struct re_s*
00100 ldap_pvt_runqueue_next_sched(
00101        struct runqueue_s* rq,
00102        struct timeval* next_run
00103 )
00104 {
00105        struct re_s* entry;
00106 
00107        entry = LDAP_STAILQ_FIRST( &rq->task_list );
00108        if ( entry == NULL || entry->next_sched.tv_sec == 0 ) {
00109               return NULL;
00110        } else {
00111               *next_run = entry->next_sched;
00112               return entry;
00113        }
00114 }
00115 
00116 void
00117 ldap_pvt_runqueue_runtask(
00118        struct runqueue_s* rq,
00119        struct re_s* entry
00120 )
00121 {
00122        LDAP_STAILQ_INSERT_TAIL( &rq->run_list, entry, rnext );
00123 }
00124 
00125 void
00126 ldap_pvt_runqueue_stoptask(
00127        struct runqueue_s* rq,
00128        struct re_s* entry
00129 )
00130 {
00131        LDAP_STAILQ_REMOVE( &rq->run_list, entry, re_s, rnext );
00132 }
00133 
00134 int
00135 ldap_pvt_runqueue_isrunning(
00136        struct runqueue_s* rq,
00137        struct re_s* entry
00138 )
00139 {
00140        struct re_s* e;
00141 
00142        LDAP_STAILQ_FOREACH( e, &rq->run_list, rnext ) {
00143               if ( e == entry ) {
00144                      return 1;
00145               }
00146        }
00147        return 0;
00148 }
00149 
00150 void 
00151 ldap_pvt_runqueue_resched(
00152        struct runqueue_s* rq,
00153        struct re_s* entry,
00154        int defer
00155 )
00156 {
00157        struct re_s* prev;
00158        struct re_s* e;
00159 
00160        LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
00161               if ( e == entry )
00162                      break;
00163        }
00164 
00165        assert ( e == entry );
00166 
00167        LDAP_STAILQ_REMOVE( &rq->task_list, entry, re_s, tnext );
00168 
00169        if ( !defer ) {
00170               entry->next_sched.tv_sec = time( NULL ) + entry->interval.tv_sec;
00171        } else {
00172               entry->next_sched.tv_sec = 0;
00173        }
00174 
00175        if ( LDAP_STAILQ_EMPTY( &rq->task_list )) {
00176               LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
00177        } else if ( entry->next_sched.tv_sec == 0 ) {
00178               LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
00179        } else {
00180               prev = NULL;
00181               LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
00182                      if ( e->next_sched.tv_sec == 0 ) {
00183                             if ( prev == NULL ) {
00184                                    LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
00185                             } else {
00186                                    LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
00187                             }
00188                             return;
00189                      } else if ( e->next_sched.tv_sec > entry->next_sched.tv_sec ) {
00190                             if ( prev == NULL ) {
00191                                    LDAP_STAILQ_INSERT_HEAD( &rq->task_list, entry, tnext );
00192                             } else {
00193                                    LDAP_STAILQ_INSERT_AFTER( &rq->task_list, prev, entry, tnext );
00194                             }
00195                             return;
00196                      }
00197                      prev = e;
00198               }
00199               LDAP_STAILQ_INSERT_TAIL( &rq->task_list, entry, tnext );
00200        }
00201 }
00202 
00203 int
00204 ldap_pvt_runqueue_persistent_backload(
00205        struct runqueue_s* rq
00206 )
00207 {
00208        struct re_s* e;
00209        int count = 0;
00210 
00211        ldap_pvt_thread_mutex_lock( &rq->rq_mutex );
00212        if ( !LDAP_STAILQ_EMPTY( &rq->task_list )) {
00213               LDAP_STAILQ_FOREACH( e, &rq->task_list, tnext ) {
00214                      if ( e->next_sched.tv_sec == 0 )
00215                             count++;
00216               }
00217        }
00218        ldap_pvt_thread_mutex_unlock( &rq->rq_mutex );
00219        return count;
00220 }
00221