aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-09-01 20:46:03 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-09-01 20:46:03 +0000
commit6c684b3367b9f21ea46b0565b6e4aac8daf85f51 (patch)
treea95c4b548e49a2e750ff0b5b14e2353050d24082 /src
parent9839451a4a8344322d6a1578540e2eb1919427d7 (diff)
- more barrier stuff
Diffstat (limited to 'src')
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.c123
1 files changed, 121 insertions, 2 deletions
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c
index f82e38c969..c12075d66d 100644
--- a/src/testbed/gnunet-service-testbed_barriers.c
+++ b/src/testbed/gnunet-service-testbed_barriers.c
@@ -34,6 +34,13 @@
/**
+ * Test to see if local peers have reached the required quorum of a barrier
+ */
+#define LOCAL_QUORUM_REACHED(barrier) \
+ ((barrier->quorum * GST_num_local_peers) <= (barrier->nreached * 100))
+
+
+/**
* Barrier
*/
struct Barrier;
@@ -60,6 +67,7 @@ struct MessageQueue
struct GNUNET_MessageHeader *msg;
};
+
/**
* Context to be associated with each client
*/
@@ -103,6 +111,38 @@ struct ClientCtx
/**
+ * Wrapper around Barrier handle
+ */
+struct WBarrier
+{
+ /**
+ * DLL next pointer
+ */
+ struct WBarrier *next;
+
+ /**
+ * DLL prev pointer
+ */
+ struct WBarrier *prev;
+
+ /**
+ * The local barrier associated with the creation of this wrapper
+ */
+ struct Barrier *barrier;
+
+ /**
+ * The barrier handle from API
+ */
+ struct GNUNET_TESTBED_Barrier *hbarrier;
+
+ /**
+ * Has this barrier been crossed?
+ */
+ uint8_t reached;
+};
+
+
+/**
* Barrier
*/
struct Barrier
@@ -128,6 +168,26 @@ struct Barrier
struct ClientCtx *tail;
/**
+ * DLL head for the list of barrier handles
+ */
+ struct WBarrier *whead;
+
+ /**
+ * DLL tail for the list of barrier handles
+ */
+ struct WBarrier *wtail;
+
+ /**
+ * Number of barriers wrapped in the above DLL
+ */
+ unsigned int num_wbarriers;
+
+ /**
+ * Number of wrapped barriers reached so far
+ */
+ unsigned int num_wbarriers_reached;
+
+ /**
* Number of peers which have reached this barrier
*/
unsigned int nreached;
@@ -364,7 +424,7 @@ handle_barrier_wait (void *cls, struct GNUNET_SERVER_Client *client,
client_ctx->barrier = barrier;
GNUNET_CONTAINER_DLL_insert_tail (barrier->head, barrier->tail, client_ctx);
barrier->nreached++;
- if ((barrier->quorum * GST_num_local_peers) <= (barrier->nreached * 100))
+ if (LOCAL_QUORUM_REACHED (barrier))
notify_task_cb (barrier, NULL);
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -423,12 +483,64 @@ GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg)
void
GST_barriers_stop ()
{
+ GNUNET_assert (NULL != barrier_map);
+ GNUNET_CONTAINER_multihashmap_destroy (barrier_map);
GNUNET_assert (NULL != ctx);
GNUNET_SERVICE_stop (ctx);
}
/**
+ * Functions of this type are to be given as callback argument to
+ * GNUNET_TESTBED_barrier_init(). The callback will be called when status
+ * information is available for the barrier.
+ *
+ * @param cls the closure given to GNUNET_TESTBED_barrier_init()
+ * @param name the name of the barrier
+ * @param barrier the barrier handle
+ * @param status status of the barrier; GNUNET_OK if the barrier is crossed;
+ * GNUNET_SYSERR upon error
+ * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the
+ * error messsage
+ */
+static void
+wbarrier_status_cb (void *cls, const char *name,
+ struct GNUNET_TESTBED_Barrier *b_,
+ int status, const char *emsg)
+{
+ struct WBarrier *wrapper = cls;
+ struct Barrier *barrier = wrapper->barrier;
+
+ GNUNET_assert (b_ == wrapper->hbarrier);
+ wrapper->hbarrier = NULL;
+ GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper);
+ GNUNET_free (wrapper);
+ if (GNUNET_SYSERR == status)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Initialising barrier (%s) failed at a sub-controller: %s\n",
+ barrier->name, (NULL != emsg) ? emsg : "NULL");
+ while (NULL != (wrapper = barrier->whead))
+ {
+ GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier);
+ GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper);
+ GNUNET_free (wrapper);
+ }
+ /* Send parent controller failure message */
+ GNUNET_break (0);
+ }
+ barrier->num_wbarriers_reached++;
+ if ((barrier->num_wbarriers_reached == barrier->num_wbarriers)
+ && (LOCAL_QUORUM_REACHED (barrier)))
+ {
+ /* Send parent controller success status message */
+ GNUNET_break (0);
+ }
+ return;
+}
+
+
+/**
* Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This
* message should always come from a parent controller or the testbed API if we
* are the root controller.
@@ -448,6 +560,7 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client,
const char *name;
struct Barrier *barrier;
struct Slave *slave;
+ struct WBarrier *wrapper;
struct GNUNET_HashCode hash;
size_t name_len;
uint64_t op_id;
@@ -506,6 +619,12 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_break (0);/* May happen when we are connecting to the controller */
continue;
}
- GNUNET_break (0); /* FIXME */
+ wrapper = GNUNET_malloc (sizeof (struct WBarrier));
+ wrapper->barrier = barrier;
+ wrapper->hbarrier = GNUNET_TESTBED_barrier_init (slave->controller,
+ barrier->name,
+ barrier->quorum,
+ &wbarrier_status_cb,
+ wrapper);
}
}