aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2012-11-16 11:20:38 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2012-11-16 11:20:38 +0000
commit57dc1a4ec314043cfdbf6e5a0bcf3c4ca103ddec (patch)
tree33553c2e36c8db66de2df88ed144e5d46bda5b70 /src
parent27520ef39b732562a6c4ffa8640b44250ad72a4a (diff)
downloadgnunet-57dc1a4ec314043cfdbf6e5a0bcf3c4ca103ddec.tar.gz
gnunet-57dc1a4ec314043cfdbf6e5a0bcf3c4ca103ddec.zip
dynamically adjustable operation queues
Diffstat (limited to 'src')
-rw-r--r--src/testbed/test_testbed_api_operations.c110
-rw-r--r--src/testbed/testbed_api_operations.c54
-rw-r--r--src/testbed/testbed_api_operations.h13
3 files changed, 150 insertions, 27 deletions
diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c
index 45f2db103..92bf12983 100644
--- a/src/testbed/test_testbed_api_operations.c
+++ b/src/testbed/test_testbed_api_operations.c
@@ -35,12 +35,14 @@
35 GNUNET_log (kind, __VA_ARGS__) 35 GNUNET_log (kind, __VA_ARGS__)
36 36
37/** 37/**
38 * Queue A 38 * Queue A. Initially the max active is set to 2 and then reduced to 0 - this
39 * should block op2 even after op1 has finished. Later the max active is set to
40 * 1 and this should start op2
39 */ 41 */
40struct OperationQueue *q1; 42struct OperationQueue *q1;
41 43
42/** 44/**
43 * Queue B 45 * Queue B. Max active set to 1
44 */ 46 */
45struct OperationQueue *q2; 47struct OperationQueue *q2;
46 48
@@ -54,6 +56,17 @@ struct GNUNET_TESTBED_Operation *op1;
54 */ 56 */
55struct GNUNET_TESTBED_Operation *op2; 57struct GNUNET_TESTBED_Operation *op2;
56 58
59/**
60 * This operation should go into both queues and should be started after op2 has
61 * been released.
62 */
63struct GNUNET_TESTBED_Operation *op3;
64
65/**
66 * The delay task identifier
67 */
68GNUNET_SCHEDULER_TaskIdentifier step_task;
69
57 70
58/** 71/**
59 * Enumeration of test stages 72 * Enumeration of test stages
@@ -83,7 +96,23 @@ enum Test
83 /** 96 /**
84 * op2 released 97 * op2 released
85 */ 98 */
86 TEST_OP2_RELEASED 99 TEST_OP2_RELEASED,
100
101 /**
102 * Temporary pause where no operations should start as we set max active in q1
103 * to 0
104 */
105 TEST_PAUSE,
106
107 /**
108 * op3 has started
109 */
110 TEST_OP3_STARTED,
111
112 /**
113 * op3 has finished
114 */
115 TEST_OP3_RELEASED
87}; 116};
88 117
89/** 118/**
@@ -93,6 +122,28 @@ enum Test result;
93 122
94 123
95/** 124/**
125 * Function to call to start an operation once all
126 * queues the operation is part of declare that the
127 * operation can be activated.
128 */
129static void
130start_cb (void *cls);
131
132
133/**
134 * Function to cancel an operation (release all associated resources). This can
135 * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
136 * operation generated an event) or AFTER the operation generated an event due
137 * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that
138 * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
139 * Implementations of this function are expected to clean up whatever state is
140 * in 'cls' and release all resources associated with the operation.
141 */
142static void
143release_cb (void *cls);
144
145
146/**
96 * Task to simulate artificial delay and change the test stage 147 * Task to simulate artificial delay and change the test stage
97 * 148 *
98 * @param cls NULL 149 * @param cls NULL
@@ -101,14 +152,28 @@ enum Test result;
101static void 152static void
102step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 153step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
103{ 154{
155 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != step_task);
156 step_task = GNUNET_SCHEDULER_NO_TASK;
104 switch (result) 157 switch (result)
105 { 158 {
106 case TEST_OP1_STARTED: 159 case TEST_OP1_STARTED:
107 GNUNET_TESTBED_operation_release_ (op1); 160 GNUNET_TESTBED_operation_release_ (op1);
161 GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0);
162 op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb);
163 GNUNET_TESTBED_operation_queue_insert_ (q1, op3);
164 GNUNET_TESTBED_operation_queue_insert_ (q2, op3);
165 GNUNET_TESTBED_operation_begin_wait_ (op3);
108 break; 166 break;
109 case TEST_OP2_STARTED: 167 case TEST_OP2_STARTED:
110 GNUNET_TESTBED_operation_release_ (op2); 168 GNUNET_TESTBED_operation_release_ (op2);
111 break; 169 break;
170 case TEST_OP2_RELEASED:
171 result = TEST_PAUSE;
172 GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 1);
173 break;
174 case TEST_OP3_STARTED:
175 GNUNET_TESTBED_operation_release_ (op3);
176 break;
112 default: 177 default:
113 GNUNET_assert (0); 178 GNUNET_assert (0);
114 } 179 }
@@ -128,12 +193,20 @@ start_cb (void *cls)
128 case TEST_INIT: 193 case TEST_INIT:
129 GNUNET_assert (&op1 == cls); 194 GNUNET_assert (&op1 == cls);
130 result = TEST_OP1_STARTED; 195 result = TEST_OP1_STARTED;
131 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL); 196 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
197 step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
132 break; 198 break;
133 case TEST_OP1_RELEASED: 199 case TEST_OP1_RELEASED:
134 GNUNET_assert (&op2 == cls); 200 GNUNET_assert (&op2 == cls);
135 result = TEST_OP2_STARTED; 201 result = TEST_OP2_STARTED;
136 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL); 202 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
203 step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
204 break;
205 case TEST_PAUSE:
206 GNUNET_assert (&op3 == cls);
207 result = TEST_OP3_STARTED;
208 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
209 step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
137 break; 210 break;
138 default: 211 default:
139 GNUNET_assert (0); 212 GNUNET_assert (0);
@@ -142,15 +215,13 @@ start_cb (void *cls)
142 215
143 216
144/** 217/**
145 * Function to call to cancel an operation (release all associated 218 * Function to cancel an operation (release all associated resources). This can
146 * resources). This can be because of a call to 219 * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
147 * "GNUNET_TESTBED_operation_cancel" (before the operation generated 220 * operation generated an event) or AFTER the operation generated an event due
148 * an event) or AFTER the operation generated an event due to a call 221 * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that
149 * to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that 222 * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
150 * a callback to the 'OperationStart' preceeds the call to 223 * Implementations of this function are expected to clean up whatever state is
151 * 'OperationRelease'. Implementations of this function are expected 224 * in 'cls' and release all resources associated with the operation.
152 * to clean up whatever state is in 'cls' and release all resources
153 * associated with the operation.
154 */ 225 */
155static void 226static void
156release_cb (void *cls) 227release_cb (void *cls)
@@ -160,10 +231,18 @@ release_cb (void *cls)
160 case TEST_OP1_STARTED: 231 case TEST_OP1_STARTED:
161 GNUNET_assert (&op1 == cls); 232 GNUNET_assert (&op1 == cls);
162 result = TEST_OP1_RELEASED; 233 result = TEST_OP1_RELEASED;
234 op1 = NULL;
235 //GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
163 break; 236 break;
164 case TEST_OP2_STARTED: 237 case TEST_OP2_STARTED:
165 GNUNET_assert (&op2 == cls); 238 GNUNET_assert (&op2 == cls);
166 result = TEST_OP2_RELEASED; 239 result = TEST_OP2_RELEASED;
240 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
241 step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
242 break;
243 case TEST_OP3_STARTED:
244 GNUNET_assert (&op3 == cls);
245 result = TEST_OP3_RELEASED;
167 GNUNET_TESTBED_operation_queue_destroy_ (q1); 246 GNUNET_TESTBED_operation_queue_destroy_ (q1);
168 GNUNET_TESTBED_operation_queue_destroy_ (q2); 247 GNUNET_TESTBED_operation_queue_destroy_ (q2);
169 break; 248 break;
@@ -217,10 +296,11 @@ main (int argc, char **argv)
217 GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, 296 GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
218 "test_testbed_api_operations", "nohelp", options, 297 "test_testbed_api_operations", "nohelp", options,
219 &run, NULL); 298 &run, NULL);
220 if ((GNUNET_OK != ret) || (TEST_OP2_RELEASED != result)) 299 if ((GNUNET_OK != ret) || (TEST_OP3_RELEASED != result))
221 return 1; 300 return 1;
222 op1 = NULL; 301 op1 = NULL;
223 op2 = NULL; 302 op2 = NULL;
303 op3 = NULL;
224 q1 = NULL; 304 q1 = NULL;
225 q2 = NULL; 305 q2 = NULL;
226 return 0; 306 return 0;
diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c
index f609b1770..e657c8354 100644
--- a/src/testbed/testbed_api_operations.c
+++ b/src/testbed/testbed_api_operations.c
@@ -66,10 +66,15 @@ struct OperationQueue
66 struct QueueEntry *tail; 66 struct QueueEntry *tail;
67 67
68 /** 68 /**
69 * Number of operations that can be concurrently 69 * Number of operations that are currently active in this queue.
70 * active in this queue.
71 */ 70 */
72 unsigned int active; 71 unsigned int active;
72
73 /**
74 * Max number of operations which can be active at any time in this queue
75 */
76 unsigned int max_active;
77
73}; 78};
74 79
75 80
@@ -158,9 +163,7 @@ call_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
158 op->start_task_id = GNUNET_SCHEDULER_NO_TASK; 163 op->start_task_id = GNUNET_SCHEDULER_NO_TASK;
159 op->state = OP_STATE_STARTED; 164 op->state = OP_STATE_STARTED;
160 if (NULL != op->start) 165 if (NULL != op->start)
161 {
162 op->start (op->cb_cls); 166 op->start (op->cb_cls);
163 }
164} 167}
165 168
166 169
@@ -176,14 +179,10 @@ check_readiness (struct GNUNET_TESTBED_Operation *op)
176 179
177 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == op->start_task_id); 180 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == op->start_task_id);
178 for (i = 0; i < op->nqueues; i++) 181 for (i = 0; i < op->nqueues; i++)
179 { 182 if (op->queues[i]->active >= op->queues[i]->max_active)
180 if (0 == op->queues[i]->active)
181 return; 183 return;
182 }
183 for (i = 0; i < op->nqueues; i++) 184 for (i = 0; i < op->nqueues; i++)
184 { 185 op->queues[i]->active++;
185 op->queues[i]->active--;
186 }
187 op->state = OP_STATE_READY; 186 op->state = OP_STATE_READY;
188 op->start_task_id = GNUNET_SCHEDULER_add_now (&call_start, op); 187 op->start_task_id = GNUNET_SCHEDULER_add_now (&call_start, op);
189} 188}
@@ -226,7 +225,7 @@ GNUNET_TESTBED_operation_queue_create_ (unsigned int max_active)
226 struct OperationQueue *queue; 225 struct OperationQueue *queue;
227 226
228 queue = GNUNET_malloc (sizeof (struct OperationQueue)); 227 queue = GNUNET_malloc (sizeof (struct OperationQueue));
229 queue->active = max_active; 228 queue->max_active = max_active;
230 return queue; 229 return queue;
231} 230}
232 231
@@ -247,6 +246,34 @@ GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue)
247 246
248 247
249/** 248/**
249 * Function to reset the maximum number of operations in the given queue. If
250 * max_active is lesser than the number of currently active operations, the
251 * active operations are not stopped immediately.
252 *
253 * @param queue the operation queue which has to be modified
254 * @param max_active the new maximum number of active operations
255 */
256void
257GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue,
258 unsigned int max_active)
259{
260 struct QueueEntry *entry;
261
262 queue->max_active = max_active;
263 if (queue->active >= queue->max_active)
264 return;
265 entry = queue->head;
266 while ( (NULL != entry) &&
267 (queue->active < queue->max_active) )
268 {
269 if (OP_STATE_WAITING == entry->op->state)
270 check_readiness (entry->op);
271 entry = entry->next;
272 }
273}
274
275
276/**
250 * Add an operation to a queue. An operation can be in multiple queues at 277 * Add an operation to a queue. An operation can be in multiple queues at
251 * once. Once the operation is inserted into all the queues 278 * once. Once the operation is inserted into all the queues
252 * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start 279 * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start
@@ -314,7 +341,10 @@ GNUNET_TESTBED_operation_queue_remove_ (struct OperationQueue *queue,
314 break; 341 break;
315 GNUNET_assert (NULL != entry); 342 GNUNET_assert (NULL != entry);
316 if (OP_STATE_STARTED == operation->state) 343 if (OP_STATE_STARTED == operation->state)
317 queue->active++; 344 {
345 GNUNET_assert (0 != queue->active);
346 queue->active--;
347 }
318 entry2 = entry->next; 348 entry2 = entry->next;
319 GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry); 349 GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry);
320 GNUNET_free (entry); 350 GNUNET_free (entry);
diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h
index e78ed0fcc..d5a918f0e 100644
--- a/src/testbed/testbed_api_operations.h
+++ b/src/testbed/testbed_api_operations.h
@@ -59,6 +59,19 @@ GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue);
59 59
60 60
61/** 61/**
62 * Function to reset the maximum number of operations in the given queue. If
63 * max_active is lesser than the number of currently active operations, the
64 * active operations are not stopped immediately.
65 *
66 * @param queue the operation queue which has to be modified
67 * @param max_active the new maximum number of active operations
68 */
69void
70GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue,
71 unsigned int max_active);
72
73
74/**
62 * Add an operation to a queue. An operation can be in multiple queues at 75 * Add an operation to a queue. An operation can be in multiple queues at
63 * once. Once the operation is inserted into all the queues 76 * once. Once the operation is inserted into all the queues
64 * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start 77 * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start