OpenDNSSEC-signer  1.3.4
/build/buildd/opendnssec-1.3.4/signer/src/scheduler/fifoq.c
Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (c) 2011 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00034 #include "config.h"
00035 #include "daemon/worker.h"
00036 #include "scheduler/fifoq.h"
00037 #include "shared/allocator.h"
00038 #include "shared/log.h"
00039 
00040 #include <ldns/ldns.h>
00041 
00042 static const char* fifoq_str = "fifo";
00043 
00044 
00049 fifoq_type*
00050 fifoq_create(allocator_type* allocator)
00051 {
00052     fifoq_type* fifoq;
00053     if (!allocator) {
00054         ods_log_error("[%s] unable to create: no allocator available",
00055             fifoq_str);
00056         return NULL;
00057     }
00058     ods_log_assert(allocator);
00059 
00060     fifoq = (fifoq_type*) allocator_alloc(allocator, sizeof(fifoq_type));
00061     if (!fifoq) {
00062         ods_log_error("[%s] unable to create: allocator failed", fifoq_str);
00063         return NULL;
00064     }
00065     ods_log_assert(fifoq);
00066 
00067     fifoq->allocator = allocator;
00068     fifoq_wipe(fifoq);
00069     lock_basic_init(&fifoq->q_lock);
00070     lock_basic_set(&fifoq->q_threshold);
00071     return fifoq;
00072 }
00073 
00074 
00079 void
00080 fifoq_wipe(fifoq_type* q)
00081 {
00082     size_t i = 0;
00083 
00084     for (i=0; i < FIFOQ_MAX_COUNT; i++) {
00085         q->blob[i] = NULL;
00086         q->owner[i] = NULL;
00087     }
00088     q->count = 0;
00089     return;
00090 }
00091 
00092 
00097 void*
00098 fifoq_pop(fifoq_type* q, worker_type** worker)
00099 {
00100     void* pop = NULL;
00101     size_t i = 0;
00102 
00103     if (!q) {
00104         return NULL;
00105     }
00106     if (q->count <= 0) {
00107         return NULL;
00108     }
00109 
00110     pop = q->blob[0];
00111     *worker = q->owner[0];
00112     for (i = 0; i < q->count-1; i++) {
00113         q->blob[i] = q->blob[i+1];
00114         q->owner[i] = q->owner[i+1];
00115     }
00116     q->count -= 1;
00117     ods_log_deeebug("[%s] popped item, count=%u", fifoq_str, q->count);
00118     return pop;
00119 }
00120 
00121 
00126 ods_status
00127 fifoq_push(fifoq_type* q, void* item, worker_type* worker, int* tries)
00128 {
00129     size_t count = 0;
00130 
00131     if (!item) {
00132         ods_log_error("[%s] unable to push item: no item", fifoq_str);
00133         return ODS_STATUS_ASSERT_ERR;
00134     }
00135     ods_log_assert(item);
00136     if (!q) {
00137         ods_log_error("[%s] unable to push item: no queue", fifoq_str);
00138         return ODS_STATUS_ASSERT_ERR;
00139     }
00140     ods_log_assert(q);
00141 
00142     if (q->count >= FIFOQ_MAX_COUNT) {
00143         ods_log_deeebug("[%s] unable to push item: max cap reached",
00144             fifoq_str);
00145         /* #262 if drudgers remain on hold, do additional broadcast */
00146         if (*tries > FIFOQ_TRIES_COUNT) {
00147             lock_basic_broadcast(&q->q_threshold);
00148             ods_log_debug("[%s] max cap reached, but drudgers seem to be "
00149                 "on hold, notify drudgers again", fifoq_str);
00150             /* reset tries */
00151             *tries = 0;
00152         }
00153         return ODS_STATUS_UNCHANGED;
00154     }
00155     count = q->count;
00156 
00157     q->blob[q->count] = item;
00158     q->owner[q->count] = worker;
00159     q->count += 1;
00160 
00161     if (count == 0 && q->count == 1) {
00162         lock_basic_broadcast(&q->q_threshold);
00163         ods_log_deeebug("[%s] threshold %u reached, notify drudgers",
00164             fifoq_str, q->count);
00165     }
00166     return ODS_STATUS_OK;
00167 }
00168 
00169 
00174 void
00175 fifoq_cleanup(fifoq_type* q)
00176 {
00177     allocator_type* allocator;
00178     lock_basic_type q_lock;
00179     cond_basic_type q_cond;
00180 
00181     if (!q) {
00182         return;
00183     }
00184     ods_log_assert(q);
00185     allocator = q->allocator;
00186     q_lock = q->q_lock;
00187     q_cond = q->q_threshold;
00188 
00189     allocator_deallocate(allocator, (void*) q);
00190     lock_basic_off(&q_cond);
00191     lock_basic_destroy(&q_lock);
00192     return;
00193 }