From 47a9a3c95de2dfadc431d34c1dc079d35d3d6d18 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Apr 2018 20:45:44 +0200 Subject: [PATCH] add transactions to namestore plugin API --- src/include/gnunet_namestore_plugin.h | 31 +++++++- src/namestore/plugin_namestore_flat.c | 93 +++++++++++++++++------ src/namestore/plugin_namestore_postgres.c | 79 ++++++++++++++++++- src/namestore/plugin_namestore_sqlite.c | 44 +++++++++++ src/pq/pq_exec.c | 1 - 5 files changed, 220 insertions(+), 28 deletions(-) diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h index 11f16b97a..d1c68cd23 100644 --- a/src/include/gnunet_namestore_plugin.h +++ b/src/include/gnunet_namestore_plugin.h @@ -88,7 +88,7 @@ struct GNUNET_NAMESTORE_PluginFunctions const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); - + /** * Lookup records in the datastore for which we are the authority. * @@ -145,6 +145,35 @@ struct GNUNET_NAMESTORE_PluginFunctions void *iter_cls); + /** + * Start a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_NO if transactions are not supported, + * #GNUNET_SYSERR on internal errors + */ + int + (*begin_transaction) (void *cls); + + + /** + * Try to commit a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ + int + (*commit_transaction) (void *cls); + + + /** + * Rollback a transaction. + * + * @param cls closure + */ + void + (*rollback_transaction) (void *cls); + }; diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c index 024fc34f2..170adb49e 100644 --- a/src/namestore/plugin_namestore_flat.c +++ b/src/namestore/plugin_namestore_flat.c @@ -383,7 +383,7 @@ static void database_shutdown (struct Plugin *plugin) { struct GNUNET_DISK_FileHandle *fh; - + fh = GNUNET_DISK_file_open (plugin->fn, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE | @@ -418,11 +418,11 @@ database_shutdown (struct Plugin *plugin) * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int -namestore_store_records (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) +namestore_flat_store_records (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) { struct Plugin *plugin = cls; uint64_t rvalue; @@ -488,11 +488,11 @@ namestore_store_records (void *cls, * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int -namestore_lookup_records (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - GNUNET_NAMESTORE_RecordIterator iter, - void *iter_cls) +namestore_flat_lookup_records (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + GNUNET_NAMESTORE_RecordIterator iter, + void *iter_cls) { struct Plugin *plugin = cls; struct FlatFileEntry *entry; @@ -571,11 +571,11 @@ iterate_zones (void *cls, * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int -namestore_iterate_records (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - uint64_t offset, - GNUNET_NAMESTORE_RecordIterator iter, - void *iter_cls) +namestore_flat_iterate_records (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + uint64_t offset, + GNUNET_NAMESTORE_RecordIterator iter, + void *iter_cls) { struct Plugin *plugin = cls; @@ -641,11 +641,11 @@ zone_to_name (void *cls, * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int -namestore_zone_to_name (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, - GNUNET_NAMESTORE_RecordIterator iter, - void *iter_cls) +namestore_flat_zone_to_name (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, + GNUNET_NAMESTORE_RecordIterator iter, + void *iter_cls) { struct Plugin *plugin = cls; @@ -666,6 +666,46 @@ namestore_zone_to_name (void *cls, } +/** + * Start a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_NO if transactions are not supported, + * #GNUNET_SYSERR on internal errors + */ +static int +namestore_flat_begin_transaction (void *cls) +{ + return GNUNET_NO; +} + + +/** + * Try to commit a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +static int +namestore_flat_commit_transaction (void *cls) +{ + GNUNET_break (0); + return GNUNET_SYSERR; +} + + +/** + * Rollback a transaction. + * + * @param cls closure + */ +static void +namestore_flat_rollback_transaction (void *cls) +{ + GNUNET_break (0); +} + + /** * Entry point for the plugin. * @@ -692,10 +732,13 @@ libgnunet_plugin_namestore_flat_init (void *cls) } api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); api->cls = &plugin; - api->store_records = &namestore_store_records; - api->iterate_records = &namestore_iterate_records; - api->zone_to_name = &namestore_zone_to_name; - api->lookup_records = &namestore_lookup_records; + api->store_records = &namestore_flat_store_records; + api->iterate_records = &namestore_flat_iterate_records; + api->zone_to_name = &namestore_flat_zone_to_name; + api->lookup_records = &namestore_flat_lookup_records; + api->begin_transaction = &namestore_flat_begin_transaction; + api->commit_transaction = &namestore_flat_commit_transaction; + api->rollback_transaction = &namestore_flat_rollback_transaction; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("flat file database running\n")); return api; diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c index 4828cb190..378a88f51 100644 --- a/src/namestore/plugin_namestore_postgres.c +++ b/src/namestore/plugin_namestore_postgres.c @@ -243,7 +243,7 @@ namestore_postgres_store_records (void *cls, data_size, data); if ( (ret < 0) || - (data_size != (size_t) ret) ) + (data_size != (size_t) ret) ) { GNUNET_break (0); return GNUNET_SYSERR; @@ -517,6 +517,80 @@ database_shutdown (struct Plugin *plugin) } +/** + * Start a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_NO if transactions are not supported, + * #GNUNET_SYSERR on internal errors + */ +static int +namestore_postgres_begin_transaction (void *cls) +{ + struct Plugin *plugin = cls; + PGresult *result; + ExecStatusType ex; + + result = PQexec (plugin->dbh, + "START TRANSACTION ISOLATION LEVEL SERIALIZABLE"); + if (PGRES_COMMAND_OK != + (ex = PQresultStatus (result))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start transaction (%s): %s\n", + PQresStatus (ex), + PQerrorMessage (plugin->dbh)); + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Try to commit a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +static int +namestore_postgres_commit_transaction (void *cls) +{ + struct Plugin *plugin = cls; + PGresult *result; + ExecStatusType status; + int ret; + + result = PQexec (plugin->dbh, + "COMMIT"); + status = PQresultStatus (result); + ret = (PGRES_COMMAND_OK == status) ? GNUNET_OK : GNUNET_SYSERR; + PQclear (result); + return ret; +} + + +/** + * Rollback a transaction. + * + * @param cls closure + */ +static void +namestore_postgres_rollback_transaction (void *cls) +{ + struct Plugin *plugin = cls; + PGresult *result; + + result = PQexec (plugin->dbh, + "ROLLBACK"); + GNUNET_break (PGRES_COMMAND_OK == + PQresultStatus (result)); + PQclear (result); +} + + /** * Entry point for the plugin. * @@ -545,6 +619,9 @@ libgnunet_plugin_namestore_postgres_init (void *cls) api->iterate_records = &namestore_postgres_iterate_records; api->zone_to_name = &namestore_postgres_zone_to_name; api->lookup_records = &namestore_postgres_lookup_records; + api->begin_transaction = &namestore_postgres_begin_transaction; + api->commit_transaction = &namestore_postgres_commit_transaction; + api->rollback_transaction = &namestore_postgres_rollback_transaction; LOG (GNUNET_ERROR_TYPE_INFO, "Postgres namestore plugin running\n"); return api; diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index 5ad84688c..1ebb6bfc7 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c @@ -772,6 +772,47 @@ namestore_sqlite_zone_to_name (void *cls, } +/** + * Start a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_NO if transactions are not supported, + * #GNUNET_SYSERR on internal errors + */ +static int +namestore_sqlite_begin_transaction (void *cls) +{ + return GNUNET_NO; +} + + +/** + * Try to commit a transaction. + * + * @param cls closure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +static int +namestore_sqlite_commit_transaction (void *cls) +{ + GNUNET_break (0); + return GNUNET_SYSERR; +} + + +/** + * Rollback a transaction. + * + * @param cls closure + */ +static void +namestore_sqlite_rollback_transaction (void *cls) +{ + GNUNET_break (0); +} + + + /** * Entry point for the plugin. * @@ -800,6 +841,9 @@ libgnunet_plugin_namestore_sqlite_init (void *cls) api->iterate_records = &namestore_sqlite_iterate_records; api->zone_to_name = &namestore_sqlite_zone_to_name; api->lookup_records = &namestore_sqlite_lookup_records; + api->begin_transaction = &namestore_sqlite_begin_transaction; + api->commit_transaction = &namestore_sqlite_commit_transaction; + api->rollback_transaction = &namestore_sqlite_rollback_transaction; LOG (GNUNET_ERROR_TYPE_INFO, _("Sqlite database running\n")); return api; diff --git a/src/pq/pq_exec.c b/src/pq/pq_exec.c index 1e5e4eb76..eacc1f2b3 100644 --- a/src/pq/pq_exec.c +++ b/src/pq/pq_exec.c @@ -79,7 +79,6 @@ GNUNET_PQ_exec_statements (PGconn *connection, result = PQexec (connection, es[i].sql); - if ( (GNUNET_NO == es[i].ignore_errors) && (PGRES_COMMAND_OK != PQresultStatus (result)) ) { -- 2.25.1