gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] branch master updated: namestore: Add transaction handling to n


From: gnunet
Subject: [gnunet] branch master updated: namestore: Add transaction handling to namestore API and plugins
Date: Tue, 02 Jul 2024 10:49:49 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 891d29d72 namestore: Add transaction handling to namestore API and 
plugins
891d29d72 is described below

commit 891d29d727b09b5e5d0d8bcb170a770b0c30972f
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Tue Jul 2 10:48:59 2024 +0200

    namestore: Add transaction handling to namestore API and plugins
    
    NEWS: Namestore records can not be inserted in a single transaction (if 
plugin supports this)
---
 src/include/gnunet_namestore_plugin.h            | 33 +++++++++++
 src/plugin/namestore/plugin_namestore_postgres.c | 70 ++++++++++++++++++++++++
 src/plugin/namestore/plugin_namestore_sqlite.c   | 69 +++++++++++++++++++++++
 src/service/namestore/gnunet-service-namestore.c |  6 ++
 src/service/namestore/namestore.h                | 11 ++++
 5 files changed, 189 insertions(+)

diff --git a/src/include/gnunet_namestore_plugin.h 
b/src/include/gnunet_namestore_plugin.h
index 88e5e4be1..c354cb2cd 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -202,6 +202,39 @@ struct GNUNET_NAMESTORE_PluginFunctions
                   const struct GNUNET_CRYPTO_PrivateKey *zone,
                        const char *label);
 
+  /**
+   * Tell plugin that a set of procedures are coming that
+   * are ideally handled within a single TX (BEGIN/COMMIT).
+   * This may be implemented as a NOP, but can speed up
+   * store calls in some cases (e.g. SQL databases)
+   *
+   * @param cls closure (internal context for the plugin)
+   * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
+   */
+  enum GNUNET_GenericReturnValue
+  (*begin_tx)(void *cls);
+
+  /**
+   * Tell plugin the we finished what we started with
+   * #begin_tx
+   *
+   * @param cls closure (internal context for the plugin)
+   * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
+   */
+  enum GNUNET_GenericReturnValue
+  (*commit_tx)(void *cls);
+
+  /**
+   * Tell plugin to rollback what we started with
+   * #begin_tx
+   * This may be a NOP (and thus NOT roll anything back!)
+   *
+   * @param cls closure (internal context for the plugin)
+   * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
+   */
+  enum GNUNET_GenericReturnValue
+  (*rollback_tx)(void *cls);
+
   /**
    * Setup the database.
    *
diff --git a/src/plugin/namestore/plugin_namestore_postgres.c 
b/src/plugin/namestore/plugin_namestore_postgres.c
index ccf84dfa6..e19ac410f 100644
--- a/src/plugin/namestore/plugin_namestore_postgres.c
+++ b/src/plugin/namestore/plugin_namestore_postgres.c
@@ -119,6 +119,17 @@ database_prepare (struct Plugin *plugin)
     return GNUNET_OK;
   {
     struct GNUNET_PQ_PreparedStatement ps[] = {
+      GNUNET_PQ_make_prepare ("store_records_bulk",
+                              "FOR i IN 1..cardinality($1) LOOP "
+                              "INSERT INTO namestore.ns098records"
+                              " (zone_private_key, pkey, rvalue, record_count, 
record_data, label, editor_hint)"
+                              " VALUES ($1, $2, $3, $4, $5, $6, '')"
+                              " ON CONFLICT ON CONSTRAINT zl"
+                              " DO UPDATE"
+                              "    SET 
pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
+                              "    WHERE ns098records.zone_private_key = $1"
+                              "          AND ns098records.label = $6"
+                              " END LOOP"),
       GNUNET_PQ_make_prepare ("store_records",
                               "INSERT INTO namestore.ns098records"
                               " (zone_private_key, pkey, rvalue, record_count, 
record_data, label, editor_hint)"
@@ -709,6 +720,62 @@ namestore_postgres_zone_to_name (void *cls,
   return GNUNET_OK;
 }
 
+/**
+ *
+ * @param cls closure (internal context for the plugin)
+ * @return #GNUNET_OK on success, #GNUNET_NO for no results, else 
#GNUNET_SYSERR
+ */
+static int
+namestore_postgres_begin_tx (void *cls)
+{
+
+  struct Plugin *plugin = cls;
+
+  struct GNUNET_PQ_ExecuteStatement ess[] = {
+    GNUNET_PQ_make_try_execute ("BEGIN"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
+  return GNUNET_PQ_exec_statements(plugin->dbh, ess);
+}
+
+/**
+ *
+ * @param cls closure (internal context for the plugin)
+ * @return #GNUNET_OK on success, #GNUNET_NO for no results, else 
#GNUNET_SYSERR
+ */
+static int
+namestore_postgres_commit_tx (void *cls)
+{
+
+  struct Plugin *plugin = cls;
+
+  struct GNUNET_PQ_ExecuteStatement ess[] = {
+    GNUNET_PQ_make_try_execute ("COMMIT"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
+  return GNUNET_PQ_exec_statements(plugin->dbh, ess);
+}
+
+/**
+ *
+ * @param cls closure (internal context for the plugin)
+ * @return #GNUNET_OK on success, #GNUNET_NO for no results, else 
#GNUNET_SYSERR
+ */
+static int
+namestore_postgres_rollback_tx (void *cls)
+{
+
+  struct Plugin *plugin = cls;
+
+  struct GNUNET_PQ_ExecuteStatement ess[] = {
+    GNUNET_PQ_make_try_execute ("ROLLBACK"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
+  return GNUNET_PQ_exec_statements(plugin->dbh, ess);
+}
 
 /**
  * Shutdown database connection and associate data
@@ -755,6 +822,9 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
   api->lookup_records = &namestore_postgres_lookup_records;
   api->edit_records = &namestore_postgres_edit_records;
   api->clear_editor_hint = &namestore_postgres_clear_editor_hint;
+  api->begin_tx = &namestore_postgres_begin_tx;
+  api->commit_tx = &namestore_postgres_commit_tx;
+  api->rollback_tx = &namestore_postgres_rollback_tx;
   LOG (GNUNET_ERROR_TYPE_INFO,
        "Postgres namestore plugin running\n");
   return api;
diff --git a/src/plugin/namestore/plugin_namestore_sqlite.c 
b/src/plugin/namestore/plugin_namestore_sqlite.c
index 50c2f5728..6a416f332 100644
--- a/src/plugin/namestore/plugin_namestore_sqlite.c
+++ b/src/plugin/namestore/plugin_namestore_sqlite.c
@@ -903,6 +903,72 @@ namestore_sqlite_drop_tables (void *cls)
 }
 
 
+static enum GNUNET_GenericReturnValue
+namestore_sqlite_begin_tx (void *cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_ExecuteStatement es_drop[] = {
+    GNUNET_SQ_make_execute ("BEGIN"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_exec_statements (plugin->dbh,
+                                 es_drop))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to drop database with: `%s'\n",
+                sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+static enum GNUNET_GenericReturnValue
+namestore_sqlite_commit_tx (void *cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_ExecuteStatement es_drop[] = {
+    GNUNET_SQ_make_execute ("COMMIT"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_exec_statements (plugin->dbh,
+                                 es_drop))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to drop database with: `%s'\n",
+                sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+static enum GNUNET_GenericReturnValue
+namestore_sqlite_rollback_tx (void *cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_ExecuteStatement es_drop[] = {
+    GNUNET_SQ_make_execute ("ROLLBACK"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_exec_statements (plugin->dbh,
+                                 es_drop))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to drop database with: `%s'\n",
+                sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
 /**
  * Initialize the database connections and associated
  * data structures (create tables and indices
@@ -999,6 +1065,9 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
   api->drop_tables = &namestore_sqlite_drop_tables;
   api->edit_records = &namestore_sqlite_edit_records;
   api->clear_editor_hint = &namestore_sqlite_editor_hint_clear;
+  api->begin_tx = &namestore_sqlite_begin_tx;
+  api->commit_tx = &namestore_sqlite_commit_tx;
+  api->rollback_tx = &namestore_sqlite_rollback_tx;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        _ ("SQlite database running\n"));
   return api;
diff --git a/src/service/namestore/gnunet-service-namestore.c 
b/src/service/namestore/gnunet-service-namestore.c
index 4d8c41d05..0c5747f52 100644
--- a/src/service/namestore/gnunet-service-namestore.c
+++ b/src/service/namestore/gnunet-service-namestore.c
@@ -1946,6 +1946,8 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
   rid = ntohl (rp_msg->gns_header.r_id);
   rd_set_count = ntohs (rp_msg->rd_set_count);
   buf = (const char *) rp_msg + rs_off;
+  if (GNUNET_YES == ntohs (rp_msg->single_tx))
+    GSN_database->begin_tx (GSN_database->cls);
   for (int i = 0; i < rd_set_count; i++)
   {
     rs = (struct RecordSet *) buf;
@@ -1953,12 +1955,16 @@ handle_record_store (void *cls, const struct 
RecordStoreMessage *rp_msg)
                             rs, &read);
     if (GNUNET_EC_NONE != res)
     {
+      if (GNUNET_YES == ntohs (rp_msg->single_tx))
+        GSN_database->rollback_tx (GSN_database->cls);
       send_store_response (nc, res, rid);
       GNUNET_SERVICE_client_continue (nc->client);
       return;
     }
     buf += read;
   }
+  if (GNUNET_YES == ntohs (rp_msg->single_tx))
+    GSN_database->commit_tx (GSN_database->cls);
   sa = GNUNET_malloc (sizeof(struct StoreActivity) + rs_len);
   GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
   sa->nc = nc;
diff --git a/src/service/namestore/namestore.h 
b/src/service/namestore/namestore.h
index 171eb6ee3..5866bc1d6 100644
--- a/src/service/namestore/namestore.h
+++ b/src/service/namestore/namestore.h
@@ -90,6 +90,17 @@ struct RecordStoreMessage
    */
   struct GNUNET_NAMESTORE_Header gns_header;
 
+  /**
+   * Reserved
+   */
+  uint16_t reserved;
+
+  /**
+   * GNUNET_YES if all sets should be stored
+   * in a single transaction (e.g. BEGIN/COMMIT).
+   */
+  uint16_t single_tx GNUNET_PACKED;
+
   /**
    * Number of record sets
    */

-- 
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]