gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 05/08: NAMESTORE: Add begin, commit and rollback API messages


From: gnunet
Subject: [gnunet] 05/08: NAMESTORE: Add begin, commit and rollback API messages
Date: Fri, 23 Sep 2022 06:01:09 +0200

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

commit 52babbd648cd8b9ab7f49f26641f8ccf7d2fc4e8
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Fri Sep 23 12:44:45 2022 +0900

    NAMESTORE: Add begin, commit and rollback API messages
    
    Namestore service can now handle begin commit and rollback.
    A test for rollback exists and works for sqlite.
---
 src/include/gnunet_namestore_service.h   |  40 ++++++----
 src/include/gnunet_protocols.h           |  22 ++++++
 src/namestore/Makefile.am                |  13 +++-
 src/namestore/gnunet-service-namestore.c |  55 +++++++++++++
 src/namestore/namestore.h                |  48 ++++++++++++
 src/namestore/namestore_api.c            | 128 +++++++++++++++++++++++++------
 src/namestore/plugin_namestore_sqlite.c  |  12 +--
 7 files changed, 272 insertions(+), 46 deletions(-)

diff --git a/src/include/gnunet_namestore_service.h 
b/src/include/gnunet_namestore_service.h
index 8b42945e1..68aeebef8 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -70,6 +70,16 @@ struct GNUNET_NAMESTORE_Handle;
  */
 struct GNUNET_NAMESTORE_ZoneIterator;
 
+/**
+ * Transaction control types.
+ * They roughly correspond to DB transaction controls
+ */
+enum GNUNET_NAMESTORE_TxControl
+{
+  GNUNET_NAMESTORE_TX_BEGIN = 0,
+  GNUNET_NAMESTORE_TX_COMMIT = 1,
+  GNUNET_NAMESTORE_TX_ROLLBACK = 2,
+};
 
 /**
  * Connect to the namestore service.
@@ -404,44 +414,44 @@ GNUNET_NAMESTORE_zone_monitor_stop (struct 
GNUNET_NAMESTORE_ZoneMonitor *zm);
  * Begin a namestore transaction.
  *
  * @param h handle to the namestore
- * @param error_cb function to call on error (i.e. disconnect or unable to get 
lock)
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
+ * @param cont function to call on result
+ * @param cont_cls closure for @a cont
  * @return handle to abort the request
  */
 struct GNUNET_NAMESTORE_QueueEntry *
 GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
-                                    GNUNET_SCHEDULER_TaskCallback error_cb,
-                                    void *error_cb_cls);
+                                    GNUNET_NAMESTORE_ContinuationWithStatus
+                                    cont,
+                                    void *cont_cls);
 
 /**
  * Begin rollback all actions in a transaction.
  * Reverts all actions performed since #GNUNET_NAMESTORE_transaction_begin
  *
  * @param h handle to the namestore
- * @param error_cb function to call on error (i.e. disconnect or unable to get 
lock)
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
+ * @param cont function to call on result
+ * @param cont_cls closure for @a cont
  * @return handle to abort the request
  */
 struct GNUNET_NAMESTORE_QueueEntry *
 GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h,
-                                       GNUNET_SCHEDULER_TaskCallback error_cb,
-                                       void *error_cb_cls);
+                                     GNUNET_NAMESTORE_ContinuationWithStatus
+                                     cont,
+                                     void *cont_cls);
 /**
  * Commit a namestore transaction.
  * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
  *
  * @param h handle to the namestore
- * @param error_cb function to call on error (i.e. disconnect or unable to get 
lock)
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
+ * @param cont function to call on result
+ * @param cont_cls closure for @a cont
  * @return handle to abort the request
  */
 struct GNUNET_NAMESTORE_QueueEntry *
 GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
-                                     GNUNET_SCHEDULER_TaskCallback error_cb,
-                                     void *error_cb_cls);
+                                     GNUNET_NAMESTORE_ContinuationWithStatus
+                                     cont,
+                                     void *cont_cls);
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index dc66a0401..509c97fb2 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -3603,6 +3603,28 @@ extern "C" {
 
 
/*********************************************************************************/
 
+/*********************************************************************************/
+/**********************************  NAMESTORE (cont.)  
**************************/
+/*********************************************************************************/
+/* NAMESTORE: message types 1750-1800
+ */
+
+/**
+ * Message type for Begin, Commit or Rollback
+ */
+#define GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL 1750
+
+/**
+ * Return status message for control message
+ */
+#define GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT 1751
+
+/**
+ * Open and lock records for editing message
+ */
+#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_EDIT 1752
+
+
 /**
  * Type used to match 'all' message types.
  */
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 51708dd67..58e3c49f0 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -54,7 +54,8 @@ SQLITE_TESTS = test_plugin_namestore_sqlite \
  test_namestore_api_zone_iteration_stop_sqlite \
  test_namestore_api_monitoring_existing_sqlite \
  test_namestore_api_zone_to_name_sqlite \
- perf_namestore_api_zone_iteration_sqlite
+ perf_namestore_api_zone_iteration_sqlite \
+ test_namestore_api_tx_rollback_sqlite
 endif
 
 if HAVE_POSTGRESQL
@@ -569,6 +570,16 @@ test_namestore_api_monitoring_existing_postgres_LDADD = \
   $(top_builddir)/src/identity/libgnunetidentity.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
+test_namestore_api_tx_rollback_sqlite_SOURCES = \
+ test_namestore_api_tx_rollback.c
+test_namestore_api_tx_rollback_sqlite_LDADD = \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  libgnunetnamestore.la \
+  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+  $(top_builddir)/src/util/libgnunetutil.la
+
+
 test_namestore_api_zone_iteration_flat_SOURCES = \
  test_namestore_api_zone_iteration.c
 test_namestore_api_zone_iteration_flat_LDADD = \
diff --git a/src/namestore/gnunet-service-namestore.c 
b/src/namestore/gnunet-service-namestore.c
index a173e8927..1f621c5f0 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1728,6 +1728,57 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
   }
 }
 
+/**
+ * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message
+ *
+ * @param cls client sending the message
+ * @param tx_msg message of type `struct TxControlMessage`
+ */
+static void
+handle_tx_control (void *cls, const struct TxControlMessage *tx_msg)
+{
+  struct NamestoreClient *nc = cls;
+  struct TxControlResultMessage *txr_msg;
+  struct GNUNET_MQ_Envelope *env;
+  enum GNUNET_GenericReturnValue ret;
+  char *emsg;
+  char *err_tmp;
+  size_t err_len;
+
+  switch (ntohs (tx_msg->control))
+  {
+  case GNUNET_NAMESTORE_TX_BEGIN:
+    ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls,
+                                               &emsg);
+    break;
+  case GNUNET_NAMESTORE_TX_COMMIT:
+    ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls,
+                                                &emsg);
+    break;
+  case GNUNET_NAMESTORE_TX_ROLLBACK:
+    ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls,
+                                                  &emsg);
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unknown control type %u\n", ntohs (tx_msg->control));
+    GNUNET_break (0);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "TX status is %u\n", ret);
+  err_len = (GNUNET_YES == ret) ? 0 : strlen (emsg) + 1;
+  env =
+    GNUNET_MQ_msg_extra (txr_msg,
+                         err_len,
+                         GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT);
+  txr_msg->gns_header.header.size = htons (sizeof (struct 
TxControlResultMessage) + err_len);
+  txr_msg->gns_header.r_id = tx_msg->gns_header.r_id;
+  txr_msg->success = htons (ret);
+  err_tmp = (char *) &txr_msg[1];
+  GNUNET_memcpy (err_tmp, emsg, err_len);
+  GNUNET_MQ_send (nc->mq, env);
+  GNUNET_SERVICE_client_continue (nc->client);
+}
 
 /**
  * Context for record remove operations passed from #handle_zone_to_name to
@@ -2371,6 +2422,10 @@ GNUNET_SERVICE_MAIN (
   &client_connect_cb,
   &client_disconnect_cb,
   NULL,
+  GNUNET_MQ_hd_fixed_size (tx_control,
+                           GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL,
+                           struct TxControlMessage,
+                           NULL),
   GNUNET_MQ_hd_var_size (record_store,
                          GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
                          struct RecordStoreMessage,
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 583ec1e68..06feee13a 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -305,6 +305,54 @@ struct RecordResultMessage
    */
 };
 
+/**
+ * Send a transaction control message.
+ */
+struct TxControlMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL
+   */
+  struct GNUNET_NAMESTORE_Header gns_header;
+
+  /**
+   * The type of control message to send
+   */
+  uint16_t control GNUNET_PACKED;
+
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+};
+
+/**
+ * Result of a transaction control message.
+ */
+struct TxControlResultMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT
+   */
+  struct GNUNET_NAMESTORE_Header gns_header;
+
+  /**
+   * The type of control message to send
+   */
+  uint16_t control GNUNET_PACKED;
+
+  /**
+   * Of type GNUNET_GenericReturnValue
+   */
+  uint16_t success GNUNET_PACKED;
+
+  /* followed by:
+   * an error message if status != ntohs(GNUNET_OK)
+   */
+};
+
+
 
 /**
  * Start monitoring a zone.
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 67541b45a..26e1477f4 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -674,6 +674,60 @@ handle_record_result_end (void *cls, const struct 
GNUNET_NAMESTORE_Header *msg)
   free_ze (ze);
 }
 
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT.
+ *
+ * @param qe the respective entry in the message queue
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
+ */
+static int
+check_tx_control_result (void *cls,
+                         const struct TxControlResultMessage *msg)
+{
+  const char *err_tmp;
+  size_t err_len;
+
+  (void) cls;
+  err_len = ntohs (msg->gns_header.header.size)
+            - sizeof (struct TxControlResultMessage);
+  if ((GNUNET_YES == ntohs (msg->success)) && (err_len > 0))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  err_tmp = (const char *) &msg[1];
+  if ((err_len > 0) && ('\0' != err_tmp[err_len - 1]))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+static void
+handle_tx_control_result (void *cls,
+                          const struct TxControlResultMessage *msg)
+{
+  struct GNUNET_NAMESTORE_Handle *h = cls;
+  struct GNUNET_NAMESTORE_QueueEntry *qe;
+  int res;
+  const char *emsg;
+
+  qe = find_qe (h, ntohl (msg->gns_header.r_id));
+  emsg = (const char *) &msg[1];
+  res = ntohs (msg->success);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received TX_CONTROL_RESULT with result %d\n",
+       res);
+  if (NULL == qe)
+    return;
+  if (NULL != qe->cont)
+    qe->cont (qe->cont_cls, res,
+              (GNUNET_YES == res) ? NULL : emsg);
+  free_qe (qe);
+}
 
 /**
  * Handle an incoming message of type
@@ -839,6 +893,10 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
                            
GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
                            struct LabelLookupResponseMessage,
                            h),
+    GNUNET_MQ_hd_var_size (tx_control_result,
+                           GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT,
+                           struct TxControlResultMessage,
+                           h),
     GNUNET_MQ_handler_end () };
   struct GNUNET_NAMESTORE_ZoneIterator *it;
   struct GNUNET_NAMESTORE_QueueEntry *qe;
@@ -1344,43 +1402,65 @@ GNUNET_NAMESTORE_cancel (struct 
GNUNET_NAMESTORE_QueueEntry *qe)
  * New API draft. Experimental
  */
 
-struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
-                                    GNUNET_SCHEDULER_TaskCallback error_cb,
-                                    void *error_cb_cls)
+static struct GNUNET_NAMESTORE_QueueEntry *
+send_transaction_control_msg (struct GNUNET_NAMESTORE_Handle *h,
+                              GNUNET_NAMESTORE_ContinuationWithStatus cont,
+                              void *cont_cls,
+                              enum GNUNET_NAMESTORE_TxControl ctrl)
 {
+  struct GNUNET_NAMESTORE_QueueEntry *qe;
+  struct GNUNET_MQ_Envelope *env;
+  struct TxControlMessage *msg;
+  uint32_t rid;
+
+  rid = get_op_id (h);
+  qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
+  qe->h = h;
+  qe->cont = cont;
+  qe->cont_cls = cont_cls;
+  qe->op_id = rid;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
+
+  env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL);
+  msg->gns_header.r_id = htonl (rid);
+  msg->control = htons (ctrl);
+  if (NULL == h->mq)
+    qe->env = env;
+  else
+    GNUNET_MQ_send (h->mq, env);
+  return qe;
   GNUNET_break (0);
   return NULL;
 }
 
+struct GNUNET_NAMESTORE_QueueEntry *
+GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
+                                    GNUNET_NAMESTORE_ContinuationWithStatus 
cont,
+                                    void *cont_cls)
+{
+  return send_transaction_control_msg (h, cont, cont_cls,
+                                       GNUNET_NAMESTORE_TX_BEGIN);
+}
 
 struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h,
-                                       GNUNET_SCHEDULER_TaskCallback error_cb,
-                                       void *error_cb_cls)
+GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
+                                     GNUNET_NAMESTORE_ContinuationWithStatus
+                                     cont,
+                                     void *cont_cls)
 {
-  GNUNET_break (0);
-  return NULL;
+  return send_transaction_control_msg (h, cont, cont_cls,
+                                       GNUNET_NAMESTORE_TX_COMMIT);
 }
 
 
-/**
- * Commit a namestore transaction.
- * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
- *
- * @param h handle to the namestore
- * @param error_cb function to call on error (i.e. disconnect or unable to get 
lock)
- *        the handle is afterwards invalid
- * @param error_cb_cls closure for @a error_cb
- * @return handle to abort the request
- */
 struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
-                                     GNUNET_SCHEDULER_TaskCallback error_cb,
-                                     void *error_cb_cls)
+GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h,
+                                       GNUNET_NAMESTORE_ContinuationWithStatus
+                                       cont,
+                                       void *cont_cls)
 {
-  GNUNET_break (0);
-  return NULL;
+  return send_transaction_control_msg (h, cont, cont_cls,
+                                       GNUNET_NAMESTORE_TX_ROLLBACK);
 }
 
 
diff --git a/src/namestore/plugin_namestore_sqlite.c 
b/src/namestore/plugin_namestore_sqlite.c
index fd81780fb..d434abd94 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -748,7 +748,7 @@ namestore_sqlite_zone_to_name (void *cls,
  *
  * @param cls closure (internal context for the plugin)
  * @param emsg error message set of return code is #GNUNET_SYSERR
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if transaction cannot be 
started.
+ * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be 
started.
  */
 static enum GNUNET_GenericReturnValue
 namestore_sqlite_transaction_begin (void *cls,
@@ -756,7 +756,7 @@ namestore_sqlite_transaction_begin (void *cls,
 {
   struct Plugin *plugin = cls;
   return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN TRANSACTION;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_OK;
+                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
 }
 
 /**
@@ -765,7 +765,7 @@ namestore_sqlite_transaction_begin (void *cls,
  *
  * @param cls closure (internal context for the plugin)
  * @param emsg error message set of return code is #GNUNET_SYSERR
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if transaction cannot be 
started.
+ * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be 
started.
  */
 static enum GNUNET_GenericReturnValue
 namestore_sqlite_transaction_rollback (void *cls,
@@ -773,7 +773,7 @@ namestore_sqlite_transaction_rollback (void *cls,
 {
   struct Plugin *plugin = cls;
   return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_OK;
+                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
 }
 
 /**
@@ -782,7 +782,7 @@ namestore_sqlite_transaction_rollback (void *cls,
  *
  * @param cls closure (internal context for the plugin)
  * @param emsg error message set of return code is #GNUNET_SYSERR
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if transaction cannot be 
started.
+ * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be 
started.
  */
 static enum GNUNET_GenericReturnValue
 namestore_sqlite_transaction_commit (void *cls,
@@ -790,7 +790,7 @@ namestore_sqlite_transaction_commit (void *cls,
 {
   struct Plugin *plugin = cls;
   return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_OK;
+                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
 }
 
 /**

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]