- struct QueueEntry *entry;
- struct QueueEntry *entry2;
-
- for (entry = queue->head; NULL != entry; entry = entry->next)
- if (entry->op == operation)
- break;
- GNUNET_assert (NULL != entry);
- if (OP_STATE_STARTED == operation->state)
- queue->active++;
- entry2 = entry->next;
- GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry);
- GNUNET_free (entry);
- for (; NULL != entry2; entry2 = entry2->next)
- if (OP_STATE_STARTED != entry2->op->state)
- break;
- if (NULL == entry2)
- return;
- check_readiness (entry2->op);
+ unsigned int qsize;
+
+ GNUNET_assert (0 < nres);
+ qsize = op->nqueues;
+ GNUNET_array_append (op->queues, op->nqueues, queue);
+ GNUNET_array_append (op->nres, qsize, nres);
+ GNUNET_assert (qsize == op->nqueues);
+}
+
+
+/**
+ * Add an operation to a queue. An operation can be in multiple queues at
+ * once. Once the operation is inserted into all the queues
+ * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start
+ * waiting for the operation to become active. The operation is assumed to take
+ * 1 queue resource. Use GNUNET_TESTBED_operation_queue_insert2_() if it
+ * requires more than 1
+ *
+ * @param queue queue to add the operation to
+ * @param op operation to add to the queue
+ */
+void
+GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue,
+ struct GNUNET_TESTBED_Operation *op)
+{
+ return GNUNET_TESTBED_operation_queue_insert2_ (queue, op, 1);
+}
+
+
+/**
+ * Marks the given operation as waiting on the queues. Once all queues permit
+ * the operation to become active, the operation will be activated. The actual
+ * activation will occur in a separate task (thus allowing multiple queue
+ * insertions to be made without having the first one instantly trigger the
+ * operation if the first queue has sufficient resources).
+ *
+ * @param op the operation to marks as waiting
+ */
+void
+GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op)
+{
+ GNUNET_assert (NULL == op->rq_entry);
+ change_state (op, OP_STATE_WAITING);
+ (void) check_readiness (op);
+}
+
+
+/**
+ * Marks an active operation as inactive - the operation will be kept in a
+ * ready-to-be-released state and continues to hold resources until another
+ * operation contents for them.
+ *
+ * @param op the operation to be marked as inactive. The operation start
+ * callback should have been called before for this operation to mark
+ * it as inactive.
+ */
+void
+GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op)
+{
+ struct OperationQueue **queues;
+ size_t ms;
+ unsigned int nqueues;
+ unsigned int i;
+
+ GNUNET_assert (OP_STATE_ACTIVE == op->state);
+ change_state (op, OP_STATE_INACTIVE);
+ nqueues = op->nqueues;
+ ms = sizeof (struct OperationQueue *) * nqueues;
+ queues = GNUNET_malloc (ms);
+ /* Cloning is needed as the operation be released by waiting operations and
+ hence its nqueues memory ptr will be freed */
+ GNUNET_assert (NULL != (queues = memcpy (queues, op->queues, ms)));
+ for (i = 0; i < nqueues; i++)
+ recheck_waiting (queues[i]);
+ GNUNET_free (queues);
+}
+
+
+/**
+ * Marks and inactive operation as active. This fuction should be called to
+ * ensure that the oprelease callback will not be called until it is either
+ * marked as inactive or released.
+ *
+ * @param op the operation to be marked as active
+ */
+void
+GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op)
+{
+
+ GNUNET_assert (OP_STATE_INACTIVE == op->state);
+ change_state (op, OP_STATE_ACTIVE);