OpenDNSSEC-signer  1.3.9
fifoq.c
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2011 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "daemon/worker.h"
36 #include "scheduler/fifoq.h"
37 #include "shared/allocator.h"
38 #include "shared/log.h"
39 
40 #include <ldns/ldns.h>
41 
42 static const char* fifoq_str = "fifo";
43 
44 
51 {
52  fifoq_type* fifoq;
53  if (!allocator) {
54  ods_log_error("[%s] unable to create: no allocator available",
55  fifoq_str);
56  return NULL;
57  }
58  ods_log_assert(allocator);
59 
60  fifoq = (fifoq_type*) allocator_alloc(allocator, sizeof(fifoq_type));
61  if (!fifoq) {
62  ods_log_error("[%s] unable to create: allocator failed", fifoq_str);
63  return NULL;
64  }
65  ods_log_assert(fifoq);
66 
67  fifoq->allocator = allocator;
68  fifoq_wipe(fifoq);
69  lock_basic_init(&fifoq->q_lock);
70  lock_basic_set(&fifoq->q_threshold);
71  lock_basic_set(&fifoq->q_nonfull);
72  return fifoq;
73 }
74 
75 
80 void
82 {
83  size_t i = 0;
84 
85  for (i=0; i < FIFOQ_MAX_COUNT; i++) {
86  q->blob[i] = NULL;
87  q->owner[i] = NULL;
88  }
89  q->count = 0;
90  return;
91 }
92 
93 
98 void*
100 {
101  void* pop = NULL;
102  size_t i = 0;
103 
104  if (!q) {
105  return NULL;
106  }
107  if (q->count <= 0) {
108  return NULL;
109  }
110 
111  pop = q->blob[0];
112  *worker = q->owner[0];
113  for (i = 0; i < q->count-1; i++) {
114  q->blob[i] = q->blob[i+1];
115  q->owner[i] = q->owner[i+1];
116  }
117  q->count -= 1;
118 
119  if (q->count <= (size_t) FIFOQ_MAX_COUNT * 0.1) {
120  /* notify waiting workers that they can start queuing again */
122  }
123  return pop;
124 }
125 
126 
132 fifoq_push(fifoq_type* q, void* item, worker_type* worker, int* tries)
133 {
134  if (!item) {
135  ods_log_error("[%s] unable to push item: no item", fifoq_str);
136  return ODS_STATUS_ASSERT_ERR;
137  }
138  ods_log_assert(item);
139  if (!q) {
140  ods_log_error("[%s] unable to push item: no queue", fifoq_str);
141  return ODS_STATUS_ASSERT_ERR;
142  }
143  ods_log_assert(q);
144 
145  if (q->count >= FIFOQ_MAX_COUNT) {
146  /* #262 if drudgers remain on hold, do additional broadcast */
147  if (*tries > FIFOQ_TRIES_COUNT) {
149  ods_log_debug("[%s] queue full, notify drudgers again", fifoq_str);
150  /* reset tries */
151  *tries = 0;
152  }
153  return ODS_STATUS_UNCHANGED;
154  }
155 
156  q->blob[q->count] = item;
157  q->owner[q->count] = worker;
158  q->count += 1;
159  if (q->count == 1) {
161  ods_log_deeebug("[%s] threshold %u reached, notify drudgers",
162  fifoq_str, q->count);
163  }
164  return ODS_STATUS_OK;
165 }
166 
167 
172 void
174 {
176  lock_basic_type q_lock;
177  cond_basic_type q_threshold;
178  cond_basic_type q_nonfull;
179 
180  if (!q) {
181  return;
182  }
183  ods_log_assert(q);
184  allocator = q->allocator;
185  q_lock = q->q_lock;
186  q_threshold = q->q_threshold;
187  q_nonfull = q->q_nonfull;
188 
189  allocator_deallocate(allocator, (void*) q);
190  lock_basic_off(&q_threshold);
191  lock_basic_off(&q_nonfull);
192  lock_basic_destroy(&q_lock);
193  return;
194 }