OpenDNSSEC-signer
1.3.8
|
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 lock_basic_set(&fifoq->q_nonfull); 00072 return fifoq; 00073 } 00074 00075 00080 void 00081 fifoq_wipe(fifoq_type* q) 00082 { 00083 size_t i = 0; 00084 00085 for (i=0; i < FIFOQ_MAX_COUNT; i++) { 00086 q->blob[i] = NULL; 00087 q->owner[i] = NULL; 00088 } 00089 q->count = 0; 00090 return; 00091 } 00092 00093 00098 void* 00099 fifoq_pop(fifoq_type* q, worker_type** worker) 00100 { 00101 void* pop = NULL; 00102 size_t i = 0; 00103 00104 if (!q) { 00105 return NULL; 00106 } 00107 if (q->count <= 0) { 00108 return NULL; 00109 } 00110 00111 pop = q->blob[0]; 00112 *worker = q->owner[0]; 00113 for (i = 0; i < q->count-1; i++) { 00114 q->blob[i] = q->blob[i+1]; 00115 q->owner[i] = q->owner[i+1]; 00116 } 00117 q->count -= 1; 00118 00119 if (q->count <= (size_t) FIFOQ_MAX_COUNT * 0.1) { 00120 /* notify waiting workers that they can start queuing again */ 00121 lock_basic_broadcast(&q->q_nonfull); 00122 } 00123 return pop; 00124 } 00125 00126 00131 ods_status 00132 fifoq_push(fifoq_type* q, void* item, worker_type* worker, int* tries) 00133 { 00134 if (!item) { 00135 ods_log_error("[%s] unable to push item: no item", fifoq_str); 00136 return ODS_STATUS_ASSERT_ERR; 00137 } 00138 ods_log_assert(item); 00139 if (!q) { 00140 ods_log_error("[%s] unable to push item: no queue", fifoq_str); 00141 return ODS_STATUS_ASSERT_ERR; 00142 } 00143 ods_log_assert(q); 00144 00145 if (q->count >= FIFOQ_MAX_COUNT) { 00146 /* #262 if drudgers remain on hold, do additional broadcast */ 00147 if (*tries > FIFOQ_TRIES_COUNT) { 00148 lock_basic_broadcast(&q->q_threshold); 00149 ods_log_debug("[%s] queue full, notify drudgers again", fifoq_str); 00150 /* reset tries */ 00151 *tries = 0; 00152 } 00153 return ODS_STATUS_UNCHANGED; 00154 } 00155 00156 q->blob[q->count] = item; 00157 q->owner[q->count] = worker; 00158 q->count += 1; 00159 if (q->count == 1) { 00160 lock_basic_broadcast(&q->q_threshold); 00161 ods_log_deeebug("[%s] threshold %u reached, notify drudgers", 00162 fifoq_str, q->count); 00163 } 00164 return ODS_STATUS_OK; 00165 } 00166 00167 00172 void 00173 fifoq_cleanup(fifoq_type* q) 00174 { 00175 allocator_type* allocator; 00176 lock_basic_type q_lock; 00177 cond_basic_type q_threshold; 00178 cond_basic_type q_nonfull; 00179 00180 if (!q) { 00181 return; 00182 } 00183 ods_log_assert(q); 00184 allocator = q->allocator; 00185 q_lock = q->q_lock; 00186 q_threshold = q->q_threshold; 00187 q_nonfull = q->q_nonfull; 00188 00189 allocator_deallocate(allocator, (void*) q); 00190 lock_basic_off(&q_threshold); 00191 lock_basic_off(&q_nonfull); 00192 lock_basic_destroy(&q_lock); 00193 return; 00194 }