-do not run test without sqlite
[oweals/gnunet.git] / src / psycstore / psycstore_api.c
index 7b71c9d3ad5d630ac30972763b97c2c090190a3c..214d8ba5d2b1b3a6d67dead6e1e2b4bb5cf86511 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of GNUnet
- * (C) 2013 Christian Grothoff (and other contributing authors)
+ * Copyright (C) 2013 Christian Grothoff (and other contributing authors)
  *
  * GNUnet is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with GNUnet; see the file COPYING.  If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 /**
@@ -283,7 +283,7 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
       return;
     }
     if (size == sizeof (struct OperationResult))
-      str = NULL;
+      str = "";
 
     op = find_op_by_id (h, GNUNET_ntohll (opres->op_id));
     if (NULL == op)
@@ -302,16 +302,9 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
       GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
       if (NULL != op->res_cb)
       {
-        const struct StateModifyRequest *smreq;
         const struct StateSyncRequest *ssreq;
         switch (ntohs (op->msg->type))
         {
-        case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY:
-          smreq = (const struct StateModifyRequest *) op->msg;
-          if (!(smreq->flags & STATE_OP_LAST
-                || GNUNET_OK != result_code))
-            op->res_cb = NULL;
-          break;
         case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC:
           ssreq = (const struct StateSyncRequest *) op->msg;
           if (!(ssreq->flags & STATE_OP_LAST
@@ -321,7 +314,7 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
         }
       }
       if (NULL != op->res_cb)
-        op->res_cb (op->cls, result_code, str);
+        op->res_cb (op->cls, result_code, str, size - sizeof (*opres));
       GNUNET_free (op);
     }
     break;
@@ -965,18 +958,19 @@ GNUNET_PSYCSTORE_fragment_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
  * @param channel_key
  *        The channel we are interested in.
  * @param slave_key
- *        The slave requesting the message.  If not NULL, a membership test is
- *        performed first and the message is only returned if the slave has
- *        access to it.
+ *        The slave requesting the message.
+ *        If not NULL, a membership test is performed first
+ *        and the message is only returned if the slave has access to it.
  * @param first_message_id
  *        First message ID to retrieve.
- *        Use 0 to get the latest message.
  * @param last_message_id
  *        Last consecutive message ID to retrieve.
- *        Use 0 to get the latest message.
+ * @param method_prefix
+ *        Retrieve only messages with a matching method prefix.
+ * @todo Implement method_prefix query.
  * @param fragment_cb
  *        Callback to call with the retrieved fragments.
- * @param rcb
+ * @param result_cb
  *        Callback to call with the result of the operation.
  * @param cls
  *        Closure for the callbacks.
@@ -989,11 +983,18 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
                               const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
                               uint64_t first_message_id,
                               uint64_t last_message_id,
+                              const char *method_prefix,
                               GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
                               GNUNET_PSYCSTORE_ResultCallback rcb,
                               void *cls)
 {
   struct MessageGetRequest *req;
+  if (NULL == method_prefix)
+    method_prefix = "";
+  uint16_t method_size = strnlen (method_prefix,
+                                  GNUNET_SERVER_MAX_MESSAGE_SIZE
+                                  - sizeof (*req)) + 1;
+
   struct GNUNET_PSYCSTORE_OperationHandle *
     op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
   op->h = h;
@@ -1004,7 +1005,7 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
   req = (struct MessageGetRequest *) &op[1];
   op->msg = (struct GNUNET_MessageHeader *) req;
   req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET);
-  req->header.size = htons (sizeof (*req));
+  req->header.size = htons (sizeof (*req) + method_size);
   req->channel_key = *channel_key;
   req->first_message_id = GNUNET_htonll (first_message_id);
   req->last_message_id = GNUNET_htonll (last_message_id);
@@ -1013,6 +1014,8 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
     req->slave_key = *slave_key;
     req->do_membership_test = GNUNET_YES;
   }
+  memcpy (&req[1], method_prefix, method_size);
+  ((char *) &req[1])[method_size - 1] = '\0';
 
   op->op_id = get_next_op_id (h);
   req->op_id = GNUNET_htonll (op->op_id);
@@ -1032,14 +1035,17 @@ GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
  * @param channel_key
  *        The channel we are interested in.
  * @param slave_key
- *        The slave requesting the message.  If not NULL, a membership test is
- *        performed first and the message is only returned if the slave has
- *        access to it.
+ *        The slave requesting the message.
+ *        If not NULL, a membership test is performed first
+ *        and the message is only returned if the slave has access to it.
  * @param message_limit
  *        Maximum number of messages to retrieve.
+ * @param method_prefix
+ *        Retrieve only messages with a matching method prefix.
+ * @todo Implement method_prefix query.
  * @param fragment_cb
  *        Callback to call with the retrieved fragments.
- * @param rcb
+ * @param result_cb
  *        Callback to call with the result of the operation.
  * @param cls
  *        Closure for the callbacks.
@@ -1051,13 +1057,22 @@ GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
                                      const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                      const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
                                      uint64_t message_limit,
+                                     const char *method_prefix,
                                      GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
                                      GNUNET_PSYCSTORE_ResultCallback rcb,
                                      void *cls)
 {
   struct MessageGetRequest *req;
+
+  if (NULL == method_prefix)
+    method_prefix = "";
+  uint16_t method_size = strnlen (method_prefix,
+                                  GNUNET_SERVER_MAX_MESSAGE_SIZE
+                                  - sizeof (*req)) + 1;
+  GNUNET_assert ('\0' == method_prefix[method_size - 1]);
+
   struct GNUNET_PSYCSTORE_OperationHandle *
-    op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
+    op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + method_size);
   op->h = h;
   op->data_cb = (DataCallback) fragment_cb;
   op->res_cb = rcb;
@@ -1066,7 +1081,7 @@ GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
   req = (struct MessageGetRequest *) &op[1];
   op->msg = (struct GNUNET_MessageHeader *) req;
   req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET);
-  req->header.size = htons (sizeof (*req));
+  req->header.size = htons (sizeof (*req) + method_size);
   req->channel_key = *channel_key;
   req->message_limit = GNUNET_ntohll (message_limit);
   if (NULL != slave_key)
@@ -1077,6 +1092,7 @@ GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
 
   op->op_id = get_next_op_id (h);
   req->op_id = GNUNET_htonll (op->op_id);
+  memcpy (&req[1], method_prefix, method_size);
 
   GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
   transmit_next (h);
@@ -1157,10 +1173,14 @@ GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
  * The current value of counters are needed when a channel master is restarted,
  * so that it can continue incrementing the counters from their last value.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key Public key that identifies the channel.
- * @param ccb Callback to call with the result.
- * @param ccb_cls Closure for the @a ccb callback.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        Public key that identifies the channel.
+ * @param ccb
+ *        Callback to call with the result.
+ * @param ccb_cls
+ *        Closure for the @a ccb callback.
  *
  * @return Handle that can be used to cancel the operation.
  */
@@ -1199,14 +1219,18 @@ GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
  * An error is returned if there are missing messages containing state
  * operations before the current one.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param message_id ID of the message that contains the @a modifiers.
- * @param state_delta Value of the _state_delta PSYC header variable of the message.
- * @param modifier_count Number of elements in the @a modifiers array.
- * @param modifiers List of modifiers to apply.
- * @param rcb Callback to call with the result of the operation.
- * @param rcb_cls Closure for the @a rcb callback.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param message_id
+ *        ID of the message that contains the @a modifiers.
+ * @param state_delta
+ *        Value of the _state_delta PSYC header variable of the message.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param rcb_cls
+ *        Closure for the @a rcb callback.
  *
  * @return Handle that can be used to cancel the operation.
  */
@@ -1215,50 +1239,31 @@ GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h,
                                const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                uint64_t message_id,
                                uint64_t state_delta,
-                               size_t modifier_count,
-                               const struct GNUNET_ENV_Modifier *modifiers,
                                GNUNET_PSYCSTORE_ResultCallback rcb,
                                void *rcb_cls)
 {
   struct GNUNET_PSYCSTORE_OperationHandle *op = NULL;
-  size_t i;
+  struct StateModifyRequest *req;
 
-  for (i = 0; i < modifier_count; i++) {
-    struct StateModifyRequest *req;
-    uint16_t name_size = strlen (modifiers[i].name) + 1;
-
-    op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size +
-                        modifiers[i].value_size);
-    op->h = h;
-    op->res_cb = rcb;
-    op->cls = rcb_cls;
+  op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
+  op->h = h;
+  op->res_cb = rcb;
+  op->cls = rcb_cls;
 
-    req = (struct StateModifyRequest *) &op[1];
-    op->msg = (struct GNUNET_MessageHeader *) req;
-    req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY);
-    req->header.size = htons (sizeof (*req) + name_size
-                              + modifiers[i].value_size);
-    req->channel_key = *channel_key;
-    req->message_id = GNUNET_htonll (message_id);
-    req->state_delta = GNUNET_htonll (state_delta);
-    req->oper = modifiers[i].oper;
-    req->name_size = htons (name_size);
-    req->flags
-      = 0 == i
-      ? STATE_OP_FIRST
-      : modifier_count - 1 == i
-      ? STATE_OP_LAST
-      : 0;
+  req = (struct StateModifyRequest *) &op[1];
+  op->msg = (struct GNUNET_MessageHeader *) req;
+  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY);
+  req->header.size = htons (sizeof (*req));
+  req->channel_key = *channel_key;
+  req->message_id = GNUNET_htonll (message_id);
+  req->state_delta = GNUNET_htonll (state_delta);
 
-    memcpy (&req[1], modifiers[i].name, name_size);
-    memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size);
+  op->op_id = get_next_op_id (h);
+  req->op_id = GNUNET_htonll (op->op_id);
 
-    op->op_id = get_next_op_id (h);
-    req->op_id = GNUNET_htonll (op->op_id);
+  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
+  transmit_next (h);
 
-    GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
-    transmit_next (h);
-  }
   return op;
   /* FIXME: only the last operation is returned,
    *        operation_cancel() should be able to cancel all of them.
@@ -1269,20 +1274,30 @@ GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h,
 /**
  * Store synchronized state.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param message_id ID of the message that contains the state_hash PSYC header variable.
- * @param modifier_count Number of elements in the @a modifiers array.
- * @param modifiers Full state to store.
- * @param rcb Callback to call with the result of the operation.
- * @param rcb_cls Closure for the callback.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param max_state_message_id
+ *        ID of the last stateful message before @a state_hash_message_id.
+ * @param state_hash_message_id
+ *        ID of the message that contains the state_hash PSYC header variable.
+ * @param modifier_count
+ *        Number of elements in the @a modifiers array.
+ * @param modifiers
+ *        Full state to store.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param rcb_cls
+ *        Closure for the callback.
  *
  * @return Handle that can be used to cancel the operation.
  */
 struct GNUNET_PSYCSTORE_OperationHandle *
 GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h,
                              const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
-                             uint64_t message_id,
+                             uint64_t max_state_message_id,
+                             uint64_t state_hash_message_id,
                              size_t modifier_count,
                              const struct GNUNET_ENV_Modifier *modifiers,
                              GNUNET_PSYCSTORE_ResultCallback rcb,
@@ -1307,7 +1322,8 @@ GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h,
     req->header.size = htons (sizeof (*req) + name_size
                               + modifiers[i].value_size);
     req->channel_key = *channel_key;
-    req->message_id = GNUNET_htonll (message_id);
+    req->max_state_message_id = GNUNET_htonll (max_state_message_id);
+    req->state_hash_message_id = GNUNET_htonll (state_hash_message_id);
     req->name_size = htons (name_size);
     req->flags
       = (0 == i)
@@ -1334,10 +1350,14 @@ GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h,
  *
  * Delete all state variables stored for the given channel.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param rcb Callback to call with the result of the operation.
- * @param rcb_cls Closure for the callback.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param rcb_cls
+ *        Closure for the callback.
  *
  * @return Handle that can be used to cancel the operation.
  */
@@ -1375,13 +1395,18 @@ GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h,
 /**
  * Update signed values of state variables in the state store.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param message_id Message ID that contained the state @a hash.
- * @param hash Hash of the serialized full state.
- * @param rcb Callback to call with the result of the operation.
- * @param rcb_cls Closure for the callback.
- *
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param message_id
+ *        Message ID that contained the state @a hash.
+ * @param hash
+ *        Hash of the serialized full state.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param rcb_cls
+ *        Closure for the callback.
  */
 struct GNUNET_PSYCSTORE_OperationHandle *
 GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
@@ -1418,12 +1443,18 @@ GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
 /**
  * Retrieve the best matching state variable.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param name Name of variable to match, the returned variable might be less specific.
- * @param scb Callback to return the matching state variable.
- * @param rcb Callback to call with the result of the operation.
- * @param cls Closure for the callbacks.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param name
+ *        Name of variable to match, the returned variable might be less specific.
+ * @param scb
+ *        Callback to return the matching state variable.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param cls
+ *        Closure for the callbacks.
  *
  * @return Handle that can be used to cancel the operation.
  */
@@ -1465,12 +1496,18 @@ GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h,
 /**
  * Retrieve all state variables for a channel with the given prefix.
  *
- * @param h Handle for the PSYCstore.
- * @param channel_key The channel we are interested in.
- * @param name_prefix Prefix of state variable names to match.
- * @param scb Callback to return matching state variables.
- * @param rcb Callback to call with the result of the operation.
- * @param cls Closure for the callbacks.
+ * @param h
+ *        Handle for the PSYCstore.
+ * @param channel_key
+ *        The channel we are interested in.
+ * @param name_prefix
+ *        Prefix of state variable names to match.
+ * @param scb
+ *        Callback to return matching state variables.
+ * @param rcb
+ *        Callback to call with the result of the operation.
+ * @param cls
+ *        Closure for the callbacks.
  *
  * @return Handle that can be used to cancel the operation.
  */