gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit e1d8213bb3264ef384af84d01b0ad05f7911f829
parent c50fba92d14a20c4321768c26b3dd6e417c46f23
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Thu, 22 Sep 2022 00:13:52 +0900

NAMESTORE: Start transactional API

Diffstat:
Msrc/include/gnunet_namestore_plugin.h | 52++++++++++------------------------------------------
Msrc/namestore/plugin_namestore_sqlite.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h @@ -160,63 +160,31 @@ struct GNUNET_NAMESTORE_PluginFunctions * Start a transaction in the database * * @param cls closure (internal context for the plugin) - * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error + * @param emsg message. On error, string will be allocated and must be freed. + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ enum GNUNET_GenericReturnValue - (*transaction_begin) (void *cls); + (*transaction_begin) (void *cls, char **emsg); /** - * Abort a transaction in the database + * Abort and roll back a transaction in the database * * @param cls closure (internal context for the plugin) - * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error + * @param emsg message. On error, string will be allocated and must be freed. + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ enum GNUNET_GenericReturnValue - (*transaction_abort) (void *cls); + (*transaction_rollback) (void *cls, char **emsg); /** * Commit a transaction in the database * * @param cls closure (internal context for the plugin) - * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error + * @param emsg message. On error, string will be allocated and must be freed. + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ enum GNUNET_GenericReturnValue - (*transaction_commit) (void *cls); - - /** - * Replace a record in the datastore for which we are the authority. - * Removes any existing record in the same zone with the same name. - * - * @param cls closure (internal context for the plugin) - * @param zone private key of the zone - * @param label name of the record in the zone - * @param rd_count number of entries in @a rd array, 0 to delete all records - * @param rd array of records with data to store - * @return #GNUNET_OK on success, else #GNUNET_SYSERR - */ - int - (*replace_records) (void *cls, - const struct GNUNET_IDENTITY_PrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd); - - /** - * Lookup records in the datastore for which we are the authority. - * - * @param cls closure (internal context for the plugin) - * @param zone private key of the zone - * @param label name of the record in the zone - * @param iter function to call with the result - * @param iter_cls closure for @a iter - * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR - */ - int - (*select_records) (void *cls, - const struct GNUNET_IDENTITY_PrivateKey *zone, - const char *label, - GNUNET_NAMESTORE_RecordIterator iter, - void *iter_cls); + (*transaction_commit) (void *cls, char **emsg); }; diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c @@ -331,8 +331,8 @@ namestore_sqlite_store_records (void *cls, for (unsigned int i = 0; i < rd_count; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "Checking if `%d' is zonekey type\n", - rd[i].record_type); + "Checking if `%d' is zonekey type\n", + rd[i].record_type); if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) { @@ -342,8 +342,8 @@ namestore_sqlite_store_records (void *cls, rd[i].record_type, &pkey)); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Storing delegation zone record value `%s'\n", - GNUNET_GNSRECORD_z2s (&pkey)); + "Storing delegation zone record value `%s'\n", + GNUNET_GNSRECORD_z2s (&pkey)); break; } @@ -740,6 +740,58 @@ namestore_sqlite_zone_to_name (void *cls, iter_cls); } +/** + * Begin a transaction for a client. + * This locks the database. SQLite is unable to discern between different + * rows with a specific zone key but the API looks like this anyway. + * https://www.sqlite.org/lang_transaction.html + * + * @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. + */ +static enum GNUNET_GenericReturnValue +namestore_sqlite_transaction_begin (void *cls, + char **emsg) +{ + struct Plugin *plugin = cls; + return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN TRANSACTION;", NULL, + NULL, emsg)) ? GNUNET_SYSERR : GNUNET_OK; +} + +/** + * Commit a transaction for a client. + * This releases the lock on the database. + * + * @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. + */ +static enum GNUNET_GenericReturnValue +namestore_sqlite_transaction_rollback (void *cls, + char **emsg) +{ + struct Plugin *plugin = cls; + return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL, + NULL, emsg)) ? GNUNET_SYSERR : GNUNET_OK; +} + +/** + * Roll back a transaction for a client. + * This releases the lock on the database. + * + * @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. + */ +static enum GNUNET_GenericReturnValue +namestore_sqlite_transaction_commit (void *cls, + char **emsg) +{ + struct Plugin *plugin = cls; + return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL, + NULL, emsg)) ? GNUNET_SYSERR : GNUNET_OK; +} /** * Entry point for the plugin. @@ -771,6 +823,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->transaction_begin = &namestore_sqlite_transaction_begin; + api->transaction_commit = &namestore_sqlite_transaction_commit; + api->transaction_rollback = &namestore_sqlite_transaction_rollback; LOG (GNUNET_ERROR_TYPE_INFO, _ ("Sqlite database running\n")); return api;