diff options
author | grothoff <grothoff@140774ce-b5e7-0310-ab8b-a85725594a96> | 2012-11-13 20:05:40 +0000 |
---|---|---|
committer | grothoff <grothoff@140774ce-b5e7-0310-ab8b-a85725594a96> | 2012-11-13 20:05:40 +0000 |
commit | 9e60dddece6bf27697e97363294b821b516e4795 (patch) | |
tree | df5c5a0d972f35d741b51c3a3fc8d2298ac8b4fd | |
parent | 200fc7133325e844371909fce57cd34b39ff23d9 (diff) |
changing datacache API to separate put-paths from data (so that plugins can test for duplicates), removing support for MySQL
git-svn-id: https://gnunet.org/svn/gnunet@24938 140774ce-b5e7-0310-ab8b-a85725594a96
-rw-r--r-- | src/datacache/Makefile.am | 48 | ||||
-rw-r--r-- | src/datacache/datacache.c | 24 | ||||
-rw-r--r-- | src/datacache/perf_datacache.c | 10 | ||||
-rw-r--r-- | src/datacache/perf_datacache_data_heap.conf | 5 | ||||
-rw-r--r-- | src/datacache/perf_datacache_data_mysql.conf | 13 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_heap.c | 73 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_mysql.c | 474 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_postgres.c | 69 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_sqlite.c | 53 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_template.c | 12 | ||||
-rw-r--r-- | src/datacache/test_datacache.c | 16 | ||||
-rw-r--r-- | src/datacache/test_datacache_data_heap.conf | 4 | ||||
-rw-r--r-- | src/datacache/test_datacache_data_mysql.conf | 13 | ||||
-rw-r--r-- | src/datacache/test_datacache_quota.c | 2 | ||||
-rw-r--r-- | src/dht/gnunet-service-dht_datacache.c | 80 | ||||
-rw-r--r-- | src/include/gnunet_datacache_lib.h | 20 | ||||
-rw-r--r-- | src/include/gnunet_datacache_plugin.h | 12 |
17 files changed, 253 insertions, 675 deletions
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am index 99e333dc95..c6c27b3275 100644 --- a/src/datacache/Makefile.am +++ b/src/datacache/Makefile.am @@ -19,9 +19,6 @@ endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_datacache_sqlite.la endif -if HAVE_MYSQL - MYSQL_PLUGIN = libgnunet_plugin_datacache_mysql.la -endif if HAVE_POSTGRES POSTGRES_PLUGIN = libgnunet_plugin_datacache_postgres.la endif @@ -42,7 +39,6 @@ libgnunetdatacache_la_LDFLAGS = \ plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ - $(MYSQL_PLUGIN) \ $(POSTGRES_PLUGIN) \ libgnunet_plugin_datacache_heap.la \ libgnunet_plugin_datacache_template.la @@ -66,18 +62,6 @@ libgnunet_plugin_datacache_heap_la_LIBADD = \ libgnunet_plugin_datacache_heap_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) -libgnunet_plugin_datacache_mysql_la_SOURCES = \ - plugin_datacache_mysql.c -libgnunet_plugin_datacache_mysql_la_LIBADD = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/mysql/libgnunetmysql.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient -libgnunet_plugin_datacache_mysql_la_CPPFLAGS = \ - $(MYSQL_CPPFLAGS) -libgnunet_plugin_datacache_mysql_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient - libgnunet_plugin_datacache_postgres_la_SOURCES = \ plugin_datacache_postgres.c libgnunet_plugin_datacache_postgres_la_LIBADD = \ @@ -110,16 +94,14 @@ SQLITE_TESTS = \ $(SQLITE_BENCHMARKS) endif -if HAVE_MYSQL if HAVE_BENCHMARKS - MYSQL_BENCHMARKS = \ - perf_datacache_mysql -endif -MYSQL_TESTS = \ - test_datacache_mysql \ - test_datacache_quota_mysql \ - $(MYSQL_BENCHMARKS) + HEAP_BENCHMARKS = \ + perf_datacache_heap endif +HEAP_TESTS = \ + test_datacache_heap \ + test_datacache_quota_heap \ + $(HEAP_BENCHMARKS) if HAVE_POSTGRES if HAVE_BENCHMARKS @@ -134,7 +116,7 @@ endif check_PROGRAMS = \ $(SQLITE_TESTS) \ - $(MYSQL_TESTS) \ + $(HEAP_TESTS) \ $(POSTGRES_TESTS) if ENABLE_TEST_RUN @@ -162,23 +144,23 @@ perf_datacache_sqlite_LDADD = \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la -test_datacache_mysql_SOURCES = \ +test_datacache_heap_SOURCES = \ test_datacache.c -test_datacache_mysql_LDADD = \ +test_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la -test_datacache_quota_mysql_SOURCES = \ +test_datacache_quota_heap_SOURCES = \ test_datacache_quota.c -test_datacache_quota_mysql_LDADD = \ +test_datacache_quota_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la -perf_datacache_mysql_SOURCES = \ +perf_datacache_heap_SOURCES = \ perf_datacache.c -perf_datacache_mysql_LDADD = \ +perf_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la @@ -207,7 +189,7 @@ perf_datacache_postgres_LDADD = \ EXTRA_DIST = \ test_datacache_data_sqlite.conf \ perf_datacache_data_sqlite.conf \ - test_datacache_data_mysql.conf \ - perf_datacache_data_mysql.conf \ + test_datacache_data_heap.conf \ + perf_datacache_data_heap.conf \ test_datacache_data_postgres.conf \ perf_datacache_data_postgres.conf diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c index e5dbfac161..0cd6f884b3 100644 --- a/src/datacache/datacache.c +++ b/src/datacache/datacache.c @@ -233,22 +233,34 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.) + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if duplicate */ int GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info) { - uint32_t used; + ssize_t used; - used = h->api->put (h->api->cls, key, size, data, type, discard_time); - if (0 == used) + used = h->api->put (h->api->cls, key, + size, data, + type, discard_time, + path_info_len, path_info); + if (-1 == used) { - /* error or duplicate */ + GNUNET_break (0); return GNUNET_SYSERR; } + if (0 == used) + { + /* duplicate */ + return GNUNET_NO; + } LOG (GNUNET_ERROR_TYPE_DEBUG, "Stored data under key `%s' in cache\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), size, diff --git a/src/datacache/perf_datacache.c b/src/datacache/perf_datacache.c index 10289ec68b..e30ae869d3 100644 --- a/src/datacache/perf_datacache.c +++ b/src/datacache/perf_datacache.c @@ -44,9 +44,12 @@ static const char *plugin_name; static int -checkIt (void *cls, struct GNUNET_TIME_Absolute exp, +checkIt (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, - enum GNUNET_BLOCK_Type type) + enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute exp, + unsigned int path_len, + const struct GNUNET_PeerIdentity *path) { if ((size == sizeof (struct GNUNET_HashCode)) && (0 == memcmp (data, cls, size))) found++; @@ -84,7 +87,8 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), - (const char *) &n, 1 + i % 16, exp)); + (const char *) &n, 1 + i % 16, exp, + 0, NULL)); k = n; } FPRINTF (stderr, "%s", "\n"); diff --git a/src/datacache/perf_datacache_data_heap.conf b/src/datacache/perf_datacache_data_heap.conf new file mode 100644 index 0000000000..3680c020b9 --- /dev/null +++ b/src/datacache/perf_datacache_data_heap.conf @@ -0,0 +1,5 @@ +[perfcache] +QUOTA = 500 KB +DATABASE = heap + + diff --git a/src/datacache/perf_datacache_data_mysql.conf b/src/datacache/perf_datacache_data_mysql.conf deleted file mode 100644 index 1760f7d08e..0000000000 --- a/src/datacache/perf_datacache_data_mysql.conf +++ /dev/null @@ -1,13 +0,0 @@ -[perfcache] -QUOTA = 500 KB -DATABASE = mysql - -[datacache-mysql] -DATABASE = gnunetcheck -# CONFIG = ~/.my.cnf -# USER = -# PASSWORD = -# HOST = -# PORT = - - diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c index 2f55bcf533..8bc9b29f65 100644 --- a/src/datacache/plugin_datacache_heap.c +++ b/src/datacache/plugin_datacache_heap.c @@ -32,6 +32,7 @@ #define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache-heap", op, fn) + /** * Context for all functions in this plugin. */ @@ -76,11 +77,21 @@ struct Value struct GNUNET_CONTAINER_HeapNode *hn; /** + * Path information. + */ + struct GNUNET_PeerIdentity *path_info; + + /** * Payload (actual payload follows this struct) */ size_t size; /** + * Number of entries in 'path_info'. + */ + unsigned int path_info_len; + + /** * Type of the block. */ enum GNUNET_BLOCK_Type type; @@ -88,6 +99,9 @@ struct Value }; +#define OVERHEAD (sizeof (struct Value) + 64) + + /** * Closure for 'put_cb'. */ @@ -109,6 +123,11 @@ struct PutContext struct GNUNET_CONTAINER_Heap *heap; /** + * Path information. + */ + const struct GNUNET_PeerIdentity *path_info; + + /** * Number of bytes in 'data'. */ size_t size; @@ -119,6 +138,11 @@ struct PutContext enum GNUNET_BLOCK_Type type; /** + * Number of entries in 'path_info'. + */ + unsigned int path_info_len; + + /** * Value to set to GNUNET_YES if an equivalent block was found. */ int found; @@ -149,13 +173,20 @@ put_cb (void *cls, put_ctx->found = GNUNET_YES; val->discard_time = GNUNET_TIME_absolute_max (val->discard_time, put_ctx->discard_time); + /* replace old path with new path */ + GNUNET_array_grow (val->path_info, + val->path_info_len, + put_ctx->path_info_len); + memcpy (val->path_info, + put_ctx->path_info, + put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity)); GNUNET_CONTAINER_heap_update_cost (put_ctx->heap, val->hn, val->discard_time.abs_value); return GNUNET_NO; } if (val->type == put_ctx->type) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got another value for key %s and type %d (size %u vs %u)\n", GNUNET_h2s (key), val->type, @@ -174,12 +205,16 @@ put_cb (void *cls, * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ -static size_t +static ssize_t heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, - const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) + const char *data, enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; struct Value *val; @@ -189,6 +224,8 @@ heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, put_ctx.heap = plugin->heap; put_ctx.data = data; put_ctx.size = size; + put_ctx.path_info = path_info; + put_ctx.path_info_len = path_info_len; put_ctx.discard_time = discard_time; put_ctx.type = type; GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map, @@ -203,6 +240,11 @@ heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, val->type = type; val->discard_time = discard_time; val->size = size; + GNUNET_array_grow (val->path_info, + val->path_info_len, + path_info_len); + memcpy (val->path_info, path_info, + path_info_len * sizeof (struct GNUNET_PeerIdentity)); (void) GNUNET_CONTAINER_multihashmap_put (plugin->map, &val->key, val, @@ -210,7 +252,7 @@ heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, val->hn = GNUNET_CONTAINER_heap_insert (plugin->heap, val, val->discard_time.abs_value); - return size; + return size + OVERHEAD; } @@ -263,13 +305,17 @@ get_cb (void *cls, if ( (get_ctx->type != val->type) && (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) ) return GNUNET_OK; - ret = get_ctx->iter (get_ctx->iter_cls, + if (NULL != get_ctx->iter) + ret = get_ctx->iter (get_ctx->iter_cls, + key, + val->size, + (const char *) &val[1], + val->type, val->discard_time, - key, - val->size, - (const char *) &val[1], - val->type); - + val->path_info_len, + val->path_info); + else + ret = GNUNET_YES; get_ctx->cnt++; return ret; } @@ -328,7 +374,8 @@ heap_plugin_del (void *cls) val)); plugin->env->delete_notify (plugin->env->cls, &val->key, - val->size); + val->size + OVERHEAD); + GNUNET_free_non_null (val->path_info); GNUNET_free (val); return GNUNET_OK; } diff --git a/src/datacache/plugin_datacache_mysql.c b/src/datacache/plugin_datacache_mysql.c deleted file mode 100644 index 1457eddfb7..0000000000 --- a/src/datacache/plugin_datacache_mysql.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - This file is part of GNUnet - (C) 2006, 2009, 2010 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 - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - 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. -*/ - -/** - * @file datacache/plugin_datacache_mysql.c - * @brief mysql for an implementation of a database backend for the datacache - * @author Christian Grothoff - * - * SETUP INSTRUCTIONS: - * - * 1) Access mysql as root, - * <pre> - * - * $ mysql -u root -p - * - * </pre> - * and do the following. [You should replace $USER with the username - * that will be running the gnunetd process]. - * @verbatim - CREATE DATABASE gnunet; - GRANT select,insert,update,delete,create,alter,drop,create temporary tables - ON gnunet.* TO $USER@localhost; - SET PASSWORD FOR $USER@localhost=PASSWORD('$the_password_you_like'); - FLUSH PRIVILEGES; - @endverbatim - * 2) In the $HOME directory of $USER, create a ".my.cnf" file - * with the following lines - * @verbatim - [client] - user=$USER - password=$the_password_you_like - @endverbatim - * - * Thats it -- now you can configure your datastores in GNUnet to - * use MySQL. Note that .my.cnf file is a security risk unless its on - * a safe partition etc. The $HOME/.my.cnf can of course be a symbolic - * link. Even greater security risk can be achieved by setting no - * password for $USER. Luckily $USER has only priviledges to mess - * up GNUnet's tables, nothing else (unless you give him more, - * of course).<p> - * - * 3) Still, perhaps you should briefly try if the DB connection - * works. First, login as $USER. Then use, - * @verbatim - $ mysql -u $USER -p $the_password_you_like - mysql> use gnunet; - @endverbatim - * - * If you get the message "Database changed" it probably works. - * - * [If you get "ERROR 2002: Can't connect to local MySQL server - * through socket '/tmp/mysql.sock' (2)" it may be resolvable by - * "ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock" - * so there may be some additional trouble depending on your mysql setup.] - * - * PROBLEMS? - * - * If you have problems related to the mysql module, your best - * friend is probably the mysql manual. The first thing to check - * is that mysql is basically operational, that you can connect - * to it, create tables, issue queries etc. - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_datacache_plugin.h" -#include "gnunet_mysql_lib.h" -#include <mysql/mysql.h> - - -/** - * Estimate of the per-entry overhead (including indices). - */ -#define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(struct GNUNET_HashCode)*5+8)) - -/** - * Die with an error message that indicates - * a failure of the command 'cmd' with the message given - * by strerror(errno). - */ -#define DIE_MYSQL(cmd, dbh) do { GNUNET_log(GNUNET_ERROR_TYPE__ERROR, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); GNUNET_abort(); } while(0); - -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' on file 'filename' - * with the message given by strerror(errno). - */ -#define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0); - - -/** - * Context for all functions in this plugin. - */ -struct Plugin -{ - /** - * Our execution environment. - */ - struct GNUNET_DATACACHE_PluginEnvironment *env; - - /** - * Handle to the mysql database. - */ - struct GNUNET_MYSQL_Context *mc; - -#define SELECT_VALUE_STMT "SELECT value,expire FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?" - struct GNUNET_MYSQL_StatementHandle *select_value; - -#define COUNT_VALUE_STMT "SELECT count(*) FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ?" - struct GNUNET_MYSQL_StatementHandle *count_value; - -#define SELECT_OLD_VALUE_STMT "SELECT hash, vhash, type, value FROM gn080dstore FORCE INDEX (expireidx) ORDER BY puttime ASC LIMIT 1" - struct GNUNET_MYSQL_StatementHandle *select_old_value; - -#define DELETE_VALUE_STMT "DELETE FROM gn080dstore WHERE hash = ? AND vhash = ? AND type = ? AND value = ?" - struct GNUNET_MYSQL_StatementHandle *delete_value; - -#define INSERT_VALUE_STMT "INSERT INTO gn080dstore (type, puttime, expire, hash, vhash, value) "\ - "VALUES (?, ?, ?, ?, ?, ?)" - struct GNUNET_MYSQL_StatementHandle *insert_value; - -#define UPDATE_VALUE_STMT "UPDATE gn080dstore FORCE INDEX (allidx) SET puttime=?, expire=? "\ - "WHERE hash=? AND vhash=? AND type=?" - struct GNUNET_MYSQL_StatementHandle *update_value; - -}; - - -/** - * Create temporary table and prepare statements. - * - * @param plugin plugin context - * @return GNUNET_OK on success - */ -static int -itable (struct Plugin *plugin) -{ -#define MRUNS(a) (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, a) ) - if (MRUNS - ("CREATE TEMPORARY TABLE gn080dstore (" - " type INT(11) UNSIGNED NOT NULL DEFAULT 0," - " puttime BIGINT UNSIGNED NOT NULL DEFAULT 0," - " expire BIGINT UNSIGNED NOT NULL DEFAULT 0," - " hash BINARY(64) NOT NULL DEFAULT ''," - " vhash BINARY(64) NOT NULL DEFAULT ''," - " value BLOB NOT NULL DEFAULT ''," - " INDEX hashidx (hash(64),type,expire)," - " INDEX allidx (hash(64),vhash(64),type)," " INDEX expireidx (puttime)" - ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1")) - return GNUNET_SYSERR; -#undef MRUNS -#define PINIT(a,b) (NULL == (a = GNUNET_MYSQL_statement_prepare (plugin->mc, b))) - if (PINIT (plugin->select_value, SELECT_VALUE_STMT) || - PINIT (plugin->count_value, COUNT_VALUE_STMT) || - PINIT (plugin->select_old_value, SELECT_OLD_VALUE_STMT) || - PINIT (plugin->delete_value, DELETE_VALUE_STMT) || - PINIT (plugin->insert_value, INSERT_VALUE_STMT) || - PINIT (plugin->update_value, UPDATE_VALUE_STMT)) - return GNUNET_SYSERR; -#undef PINIT - return GNUNET_OK; -} - - -/** - * Store an item in the datastore. - * - * @param cls closure (our "struct Plugin") - * @param key key to store data under - * @param size number of bytes in data - * @param data data to store - * @param type type of the value - * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise - */ -static size_t -mysql_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, - const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) -{ - struct Plugin *plugin = cls; - struct GNUNET_TIME_Absolute now; - unsigned long k_length; - unsigned long h_length; - unsigned long v_length; - unsigned long long v_now; - unsigned long long v_discard_time; - unsigned int v_type; - struct GNUNET_HashCode vhash; - int ret; - - if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE) - return GNUNET_SYSERR; - GNUNET_CRYPTO_hash (data, size, &vhash); - now = GNUNET_TIME_absolute_get (); - - /* first try UPDATE */ - h_length = sizeof (struct GNUNET_HashCode); - k_length = sizeof (struct GNUNET_HashCode); - v_length = size; - v_type = type; - v_now = (unsigned long long) now.abs_value; - v_discard_time = (unsigned long long) discard_time.abs_value; - if (GNUNET_OK == - GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->update_value, NULL, - MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, - MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, - MYSQL_TYPE_BLOB, key, sizeof (struct GNUNET_HashCode), - &k_length, MYSQL_TYPE_BLOB, &vhash, - sizeof (struct GNUNET_HashCode), &h_length, - MYSQL_TYPE_LONG, &v_type, GNUNET_YES, -1)) - return GNUNET_OK; - - /* now try INSERT */ - h_length = sizeof (struct GNUNET_HashCode); - k_length = sizeof (struct GNUNET_HashCode); - v_length = size; - if (GNUNET_OK != - (ret = - GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_value, NULL, - MYSQL_TYPE_LONG, &type, GNUNET_YES, - MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, - MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, - MYSQL_TYPE_BLOB, key, sizeof (struct GNUNET_HashCode), - &k_length, MYSQL_TYPE_BLOB, &vhash, - sizeof (struct GNUNET_HashCode), &h_length, - MYSQL_TYPE_BLOB, data, (unsigned long) size, - &v_length, -1))) - { - if (ret == GNUNET_SYSERR) - itable (plugin); - return GNUNET_SYSERR; - } - return size + OVERHEAD; -} - - -static int -return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values) -{ - return GNUNET_OK; -} - - -/** - * Iterate over the results for a particular key - * in the datastore. - * - * @param cls closure (our "struct Plugin") - * @param key - * @param type entries of which type are relevant? - * @param iter maybe NULL (to just count) - * @param iter_cls closure for iter - * @return the number of results found - */ -static unsigned int -mysql_plugin_get (void *cls, const struct GNUNET_HashCode * key, - enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, - void *iter_cls) -{ - struct Plugin *plugin = cls; - MYSQL_BIND rbind[3]; - unsigned long h_length; - unsigned long v_length; - unsigned long long v_expire; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Absolute expire; - unsigned int cnt; - unsigned long long total; - unsigned long long v_now; - unsigned int off; - unsigned int v_type; - int ret; - char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE]; - - now = GNUNET_TIME_absolute_get (); - h_length = sizeof (struct GNUNET_HashCode); - v_length = sizeof (buffer); - total = -1; - memset (rbind, 0, sizeof (rbind)); - rbind[0].buffer_type = MYSQL_TYPE_LONGLONG; - rbind[0].buffer = &total; - rbind[0].is_unsigned = GNUNET_YES; - v_type = type; - v_now = (unsigned long long) now.abs_value; - if ((GNUNET_OK != - (ret = - GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_value, 1, rbind, - return_ok, NULL, MYSQL_TYPE_BLOB, key, - sizeof (struct GNUNET_HashCode), &h_length, - MYSQL_TYPE_LONG, &v_type, GNUNET_YES, - MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, - -1))) || (-1 == total)) - { - if (ret == GNUNET_SYSERR) - itable (plugin); - return GNUNET_SYSERR; - } - if ((iter == NULL) || (total == 0)) - return (int) total; - - off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); - cnt = 0; - while (cnt < total) - { - memset (rbind, 0, sizeof (rbind)); - rbind[0].buffer_type = MYSQL_TYPE_BLOB; - rbind[0].buffer_length = sizeof (buffer); - rbind[0].length = &v_length; - rbind[0].buffer = buffer; - rbind[1].buffer_type = MYSQL_TYPE_LONGLONG; - rbind[1].is_unsigned = 1; - rbind[1].buffer = &v_expire; - off = (off + 1) % total; - if (GNUNET_OK != - (ret = - GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->select_value, 2, rbind, - return_ok, NULL, MYSQL_TYPE_BLOB, key, - sizeof (struct GNUNET_HashCode), &h_length, - MYSQL_TYPE_LONG, &v_type, GNUNET_YES, - MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, - MYSQL_TYPE_LONG, &off, GNUNET_YES, -1))) - { - if (ret == GNUNET_SYSERR) - itable (plugin); - return GNUNET_SYSERR; - } - cnt++; - expire.abs_value = v_expire; - if (GNUNET_OK != iter (iter_cls, expire, key, v_length, buffer, type)) - break; - } - return cnt; -} - - -/** - * Delete the entry with the lowest expiration value - * from the datacache right now. - * - * @param cls closure (our "struct Plugin") - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -static int -mysql_plugin_del (void *cls) -{ - struct Plugin *plugin = cls; - - MYSQL_BIND rbind[5]; - unsigned int v_type; - struct GNUNET_HashCode v_key; - struct GNUNET_HashCode vhash; - unsigned long k_length; - unsigned long h_length; - unsigned long v_length; - int ret; - char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE]; - - k_length = sizeof (struct GNUNET_HashCode); - h_length = sizeof (struct GNUNET_HashCode); - v_length = sizeof (buffer); - memset (rbind, 0, sizeof (rbind)); - rbind[0].buffer_type = MYSQL_TYPE_BLOB; - rbind[0].buffer_length = sizeof (struct GNUNET_HashCode); - rbind[0].length = &k_length; - rbind[0].buffer = &v_key; - rbind[1].buffer_type = MYSQL_TYPE_BLOB; - rbind[1].buffer_length = sizeof (struct GNUNET_HashCode); - rbind[1].length = &h_length; - rbind[1].buffer = &vhash; - rbind[2].buffer_type = MYSQL_TYPE_LONG; - rbind[2].is_unsigned = 1; - rbind[2].buffer = &v_type; - rbind[3].buffer_type = MYSQL_TYPE_BLOB; - rbind[3].buffer_length = sizeof (buffer); - rbind[3].length = &v_length; - rbind[3].buffer = buffer; - if ((GNUNET_OK != - (ret = - GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->select_old_value, 4, - rbind, return_ok, NULL, -1))) || - (GNUNET_OK != - (ret = - GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->delete_value, NULL, - MYSQL_TYPE_BLOB, &v_key, - sizeof (struct GNUNET_HashCode), &k_length, - MYSQL_TYPE_BLOB, &vhash, - sizeof (struct GNUNET_HashCode), &h_length, - MYSQL_TYPE_LONG, &v_type, GNUNET_YES, - MYSQL_TYPE_BLOB, buffer, - (unsigned long) sizeof (buffer), &v_length, - -1)))) - { - if (ret == GNUNET_SYSERR) - itable (plugin); - return GNUNET_SYSERR; - } - plugin->env->delete_notify (plugin->env->cls, &v_key, v_length + OVERHEAD); - - return GNUNET_OK; -} - - -/** - * Entry point for the plugin. - * - * @param cls closure (the "struct GNUNET_DATACACHE_PluginEnvironmnet") - * @return the plugin's closure (our "struct Plugin") - */ -void * -libgnunet_plugin_datacache_mysql_init (void *cls) -{ - struct GNUNET_DATACACHE_PluginEnvironment *env = cls; - struct GNUNET_DATACACHE_PluginFunctions *api; - struct Plugin *plugin; - - plugin = GNUNET_malloc (sizeof (struct Plugin)); - plugin->env = env; - plugin->mc = GNUNET_MYSQL_context_create (env->cfg, "datacache-mysql"); - if ( (NULL == plugin->mc) || - (GNUNET_OK != itable (plugin)) ) - { - if (NULL != plugin->mc) - GNUNET_MYSQL_context_destroy (plugin->mc); - GNUNET_free (plugin); - return NULL; - } - api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); - api->cls = plugin; - api->get = &mysql_plugin_get; - api->put = &mysql_plugin_put; - api->del = &mysql_plugin_del; - GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", - _("MySQL datacache running\n")); - return api; -} - - -/** - * Exit point from the plugin. - * - * @param cls closure (our "struct Plugin") - * @return NULL - */ -void * -libgnunet_plugin_datacache_mysql_done (void *cls) -{ - struct GNUNET_DATACACHE_PluginFunctions *api = cls; - struct Plugin *plugin = api->cls; - - GNUNET_MYSQL_context_destroy (plugin->mc); - GNUNET_free (plugin); - GNUNET_free (api); - return NULL; -} - - -/* end of plugin_datacache_mysql.c */ diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c index e9157742cd..e7d2e72c27 100644 --- a/src/datacache/plugin_datacache_postgres.c +++ b/src/datacache/plugin_datacache_postgres.c @@ -75,13 +75,18 @@ init_connection (struct Plugin *plugin) " type INTEGER NOT NULL DEFAULT 0," " discard_time BIGINT NOT NULL DEFAULT 0," " key BYTEA NOT NULL DEFAULT ''," - " value BYTEA NOT NULL DEFAULT '')" "WITH OIDS"); - if ((ret == NULL) || ((PQresultStatus (ret) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ - PQresultErrorField - (ret, - PG_DIAG_SQLSTATE))))) + " value BYTEA NOT NULL DEFAULT ''," + " path BYTEA DEFAULT '')" + "WITH OIDS"); + if ( (ret == NULL) || + ((PQresultStatus (ret) != PGRES_COMMAND_OK) && + (0 != strcmp ("42P07", /* duplicate table */ + PQresultErrorField + (ret, + PG_DIAG_SQLSTATE))))) { - (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "CREATE TABLE", + (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, + PGRES_COMMAND_OK, "CREATE TABLE", "gn090dc"); PQfinish (plugin->dbh); plugin->dbh = NULL; @@ -123,11 +128,11 @@ init_connection (struct Plugin *plugin) PQclear (ret); if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getkt", - "SELECT discard_time,type,value FROM gn090dc " + "SELECT discard_time,type,value,path FROM gn090dc " "WHERE key=$1 AND type=$2 ", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getk", - "SELECT discard_time,type,value FROM gn090dc " + "SELECT discard_time,type,value,path FROM gn090dc " "WHERE key=$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getm", @@ -137,8 +142,8 @@ init_connection (struct Plugin *plugin) GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090dc WHERE oid=$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "put", - "INSERT INTO gn090dc (type, discard_time, key, value) " - "VALUES ($1, $2, $3, $4)", 4))) + "INSERT INTO gn090dc (type, discard_time, key, value, path) " + "VALUES ($1, $2, $3, $4, $5)", 5))) { PQfinish (plugin->dbh); plugin->dbh = NULL; @@ -157,12 +162,16 @@ init_connection (struct Plugin *plugin) * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ -static size_t +static ssize_t postgres_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; PGresult *ret; @@ -173,22 +182,25 @@ postgres_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, (const char *) &btype, (const char *) &bexpi, (const char *) key, - (const char *) data + (const char *) data, + (const char *) path_info }; int paramLengths[] = { sizeof (btype), sizeof (bexpi), sizeof (struct GNUNET_HashCode), - size + size, + path_info_len * sizeof (struct GNUNET_PeerIdentity) }; - const int paramFormats[] = { 1, 1, 1, 1 }; + const int paramFormats[] = { 1, 1, 1, 1, 1 }; ret = - PQexecPrepared (plugin->dbh, "put", 4, paramValues, paramLengths, + PQexecPrepared (plugin->dbh, "put", 5, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != - GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) - return GNUNET_SYSERR; + GNUNET_POSTGRES_check_result (plugin->dbh, ret, + PGRES_COMMAND_OK, "PQexecPrepared", "put")) + return -1; PQclear (ret); return size + OVERHEAD; } @@ -226,6 +238,8 @@ postgres_plugin_get (void *cls, const struct GNUNET_HashCode * key, uint32_t size; unsigned int cnt; unsigned int i; + unsigned int path_len; + const struct GNUNET_PeerIdentity *path; PGresult *res; res = @@ -254,7 +268,7 @@ postgres_plugin_get (void *cls, const struct GNUNET_HashCode * key, PQclear (res); return cnt; } - if ((3 != PQnfields (res)) || (sizeof (uint64_t) != PQfsize (res, 0)) || + if ((4 != PQnfields (res)) || (sizeof (uint64_t) != PQfsize (res, 0)) || (sizeof (uint32_t) != PQfsize (res, 1))) { GNUNET_break (0); @@ -267,12 +281,23 @@ postgres_plugin_get (void *cls, const struct GNUNET_HashCode * key, GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); size = PQgetlength (res, i, 2); + path_len = PQgetlength (res, i, 3); + if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_break (0); + path_len = 0; + } + path_len %= sizeof (struct GNUNET_PeerIdentity); + path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3); LOG (GNUNET_ERROR_TYPE_DEBUG, "Found result of size %u bytes and type %u in database\n", (unsigned int) size, (unsigned int) type); if (GNUNET_SYSERR == - iter (iter_cls, expiration_time, key, size, PQgetvalue (res, i, 2), - (enum GNUNET_BLOCK_Type) type)) + iter (iter_cls, key, size, PQgetvalue (res, i, 2), + (enum GNUNET_BLOCK_Type) type, + expiration_time, + path_len, + path)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (client error)\n"); diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c index 74fa385441..3dae4643a7 100644 --- a/src/datacache/plugin_datacache_sqlite.c +++ b/src/datacache/plugin_datacache_sqlite.c @@ -95,12 +95,16 @@ sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8 encoded * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise + * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ -static size_t -sqlite_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, - const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) +static ssize_t +sqlite_plugin_put (void *cls, + const struct GNUNET_HashCode *key, + size_t size, const char *data, + enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; @@ -115,31 +119,38 @@ sqlite_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, dval = INT64_MAX; if (sq_prepare (plugin->dbh, - "INSERT INTO ds090 (type, expire, key, value) VALUES (?, ?, ?, ?)", + "INSERT INTO ds090 (type, expire, key, value, path) VALUES (?, ?, ?, ?, ?)", &stmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); - return 0; + return -1; } if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) || (SQLITE_OK != - sqlite3_bind_blob (stmt, 3, key, sizeof (struct GNUNET_HashCode), + sqlite3_bind_blob (stmt, 3, + key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || - (SQLITE_OK != sqlite3_bind_blob (stmt, 4, data, size, SQLITE_TRANSIENT))) + (SQLITE_OK != sqlite3_bind_blob (stmt, 4, + data, size, + SQLITE_TRANSIENT)) || + (SQLITE_OK != sqlite3_bind_blob (stmt, 5, + path_info, + path_info_len * sizeof (struct GNUNET_PeerIdentity), + SQLITE_TRANSIENT))) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_xxx"); sqlite3_finalize (stmt); - return 0; + return -1; } if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); sqlite3_finalize (stmt); - return 0; + return -1; } if (SQLITE_OK != sqlite3_finalize (stmt)) LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, @@ -173,8 +184,10 @@ sqlite_plugin_get (void *cls, const struct GNUNET_HashCode * key, unsigned int cnt; unsigned int off; unsigned int total; + unsigned int psize; char scratch[256]; int64_t ntime; + const struct GNUNET_PeerIdentity *path; now = GNUNET_TIME_absolute_get (); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' for key `%4s'\n", "GET", @@ -229,7 +242,7 @@ sqlite_plugin_get (void *cls, const struct GNUNET_HashCode * key, { off = (off + 1) % total; GNUNET_snprintf (scratch, sizeof (scratch), - "SELECT value,expire FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", + "SELECT value,expire,path FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", off); if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) { @@ -253,6 +266,17 @@ sqlite_plugin_get (void *cls, const struct GNUNET_HashCode * key, size = sqlite3_column_bytes (stmt, 0); dat = sqlite3_column_blob (stmt, 0); exp.abs_value = sqlite3_column_int64 (stmt, 1); + psize = sqlite3_column_bytes (stmt, 2); + if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) + { + GNUNET_break (0); + psize = 0; + } + psize /= sizeof (struct GNUNET_PeerIdentity); + if (0 != psize) + path = sqlite3_column_blob (stmt, 2); + else + path = NULL; ntime = (int64_t) exp.abs_value; if (ntime == INT64_MAX) exp = GNUNET_TIME_UNIT_FOREVER_ABS; @@ -260,7 +284,7 @@ sqlite_plugin_get (void *cls, const struct GNUNET_HashCode * key, LOG (GNUNET_ERROR_TYPE_DEBUG, "Found %u-byte result when processing `%s' for key `%4s'\n", (unsigned int) size, "GET", GNUNET_h2s (key)); - if (GNUNET_OK != iter (iter_cls, exp, key, size, dat, type)) + if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path)) { sqlite3_finalize (stmt); break; @@ -408,7 +432,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls) "CREATE TABLE ds090 (" " type INTEGER NOT NULL DEFAULT 0," " expire INTEGER NOT NULL DEFAULT 0," " key BLOB NOT NULL DEFAULT ''," - " value BLOB NOT NULL DEFAULT '')"); + " value BLOB NOT NULL DEFAULT ''," + " path BLOB DEFAULT '')"); SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds090 (key,type,expire)"); SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire ON ds090 (expire)"); plugin = GNUNET_malloc (sizeof (struct Plugin)); diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c index 6c43959825..306615571f 100644 --- a/src/datacache/plugin_datacache_template.c +++ b/src/datacache/plugin_datacache_template.c @@ -49,15 +49,19 @@ struct Plugin * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ -static size_t +static ssize_t template_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time) + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info) { GNUNET_break (0); - return 0; + return -1; } diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c index 1d8cd32952..5162924f72 100644 --- a/src/datacache/test_datacache.c +++ b/src/datacache/test_datacache.c @@ -38,9 +38,13 @@ static const char *plugin_name; static int -checkIt (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, size_t size, const char *data, - enum GNUNET_BLOCK_Type type) +checkIt (void *cls, + const struct GNUNET_HashCode *key, + size_t size, const char *data, + enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute exp, + unsigned int path_len, + const struct GNUNET_PeerIdentity *path) { if (size != sizeof (struct GNUNET_HashCode)) { @@ -83,7 +87,8 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), - (const char *) &n, 1 + i % 16, exp)); + (const char *) &n, 1 + i % 16, exp, + 0, NULL)); k = n; } memset (&k, 0, sizeof (struct GNUNET_HashCode)); @@ -99,7 +104,8 @@ run (void *cls, char *const *args, const char *cfgfile, ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), (const char *) &n, 792, - GNUNET_TIME_UNIT_FOREVER_ABS)); + GNUNET_TIME_UNIT_FOREVER_ABS, + 0, NULL)); ASSERT (0 != GNUNET_DATACACHE_get (h, &k, 792, &checkIt, &n)); GNUNET_DATACACHE_destroy (h); diff --git a/src/datacache/test_datacache_data_heap.conf b/src/datacache/test_datacache_data_heap.conf new file mode 100644 index 0000000000..082cf48f44 --- /dev/null +++ b/src/datacache/test_datacache_data_heap.conf @@ -0,0 +1,4 @@ +[testcache] +QUOTA = 1 MB +DATABASE = heap + diff --git a/src/datacache/test_datacache_data_mysql.conf b/src/datacache/test_datacache_data_mysql.conf deleted file mode 100644 index bc9daa3ad3..0000000000 --- a/src/datacache/test_datacache_data_mysql.conf +++ /dev/null @@ -1,13 +0,0 @@ -[testcache] -QUOTA = 1 MB -DATABASE = mysql - -[datacache-mysql] -DATABASE = gnunetcheck -# CONFIG = ~/.my.cnf -# USER = -# PASSWORD = -# HOST = -# PORT = - - diff --git a/src/datacache/test_datacache_quota.c b/src/datacache/test_datacache_quota.c index 1f252c14a5..cac4d18786 100644 --- a/src/datacache/test_datacache_quota.c +++ b/src/datacache/test_datacache_quota.c @@ -73,7 +73,7 @@ run (void *cls, char *const *args, const char *cfgfile, { exp.abs_value++; buf[j] = i; - ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, j, buf, 1 + i, exp)); + ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, j, buf, 1 + i, exp, 0, NULL)); ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); } k = n; diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c index b2cb93d12f..4768c14fd7 100644 --- a/src/dht/gnunet-service-dht_datacache.c +++ b/src/dht/gnunet-service-dht_datacache.c @@ -39,28 +39,6 @@ static struct GNUNET_DATACACHE_Handle *datacache; /** - * Entry for inserting data into datacache from the DHT. - */ -struct DHTPutEntry -{ - /** - * Size of data. - */ - uint16_t data_size; - - /** - * Length of recorded path. - */ - uint16_t path_length; - - /* PATH ENTRIES */ - - /* PUT DATA */ - -}; - - -/** * Handle a datum we've received from another peer. Cache if * possible. * @@ -80,14 +58,7 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data) { - size_t plen = - data_size + put_path_length * sizeof (struct GNUNET_PeerIdentity) + - sizeof (struct DHTPutEntry); - char buf[plen]; - struct DHTPutEntry *pe; - struct GNUNET_PeerIdentity *pp; - - if (datacache == NULL) + if (NULL == datacache) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("%s request received, but have no datacache!\n"), "PUT"); @@ -102,14 +73,9 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# ITEMS stored in datacache"), 1, GNUNET_NO); - pe = (struct DHTPutEntry *) buf; - pe->data_size = htons (data_size); - pe->path_length = htons ((uint16_t) put_path_length); - pp = (struct GNUNET_PeerIdentity *) &pe[1]; - memcpy (pp, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); - memcpy (&pp[put_path_length], data, data_size); - (void) GNUNET_DATACACHE_put (datacache, key, plen, (const char *) pe, type, - expiration); + (void) GNUNET_DATACACHE_put (datacache, key, + data_size, data, type, + expiration, put_path_length, put_path); } @@ -159,40 +125,26 @@ struct GetRequestContext * @param size the size of the data identified by key * @param data the actual data * @param type the type of the data - * + * @param put_path_length number of peers in 'put_path' + * @param put_path path the reply took on put * @return GNUNET_OK to continue iteration, anything else * to stop iteration. */ static int -datacache_get_iterator (void *cls, struct GNUNET_TIME_Absolute exp, +datacache_get_iterator (void *cls, const struct GNUNET_HashCode * key, size_t size, - const char *data, enum GNUNET_BLOCK_Type type) + const char *data, enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute exp, + unsigned int put_path_length, + const struct GNUNET_PeerIdentity *put_path) { struct GetRequestContext *ctx = cls; - const struct DHTPutEntry *pe; - const struct GNUNET_PeerIdentity *pp; - const char *rdata; - size_t rdata_size; - uint16_t put_path_length; enum GNUNET_BLOCK_EvaluationResult eval; - pe = (const struct DHTPutEntry *) data; - put_path_length = ntohs (pe->path_length); - rdata_size = ntohs (pe->data_size); - - if (size != - sizeof (struct DHTPutEntry) + rdata_size + - (put_path_length * sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_break (0); - return GNUNET_OK; - } - pp = (const struct GNUNET_PeerIdentity *) &pe[1]; - rdata = (const char *) &pp[put_path_length]; eval = GNUNET_BLOCK_evaluate (GDS_block_context, type, key, ctx->reply_bf, ctx->reply_bf_mutator, ctx->xquery, - ctx->xquery_size, rdata, rdata_size); + ctx->xquery_size, data, size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found reply for query %s in datacache, evaluation result is %d\n", GNUNET_h2s (key), (int) eval); @@ -206,11 +158,11 @@ datacache_get_iterator (void *cls, struct GNUNET_TIME_Absolute exp, gettext_noop ("# Good RESULTS found in datacache"), 1, GNUNET_NO); - GDS_CLIENTS_handle_reply (exp, key, 0, NULL, put_path_length, pp, type, - rdata_size, rdata); + GDS_CLIENTS_handle_reply (exp, key, 0, NULL, put_path_length, put_path, type, + size, data); /* forward to other peers */ - GDS_ROUTING_process (type, exp, key, put_path_length, pp, 0, NULL, rdata, - rdata_size); + GDS_ROUTING_process (type, exp, key, put_path_length, put_path, 0, NULL, data, + size); break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GDS_stats, diff --git a/src/include/gnunet_datacache_lib.h b/src/include/gnunet_datacache_lib.h index 071b304be2..4f97ee5264 100644 --- a/src/include/gnunet_datacache_lib.h +++ b/src/include/gnunet_datacache_lib.h @@ -74,18 +74,22 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h); * An iterator over a set of items stored in the datacache. * * @param cls closure - * @param exp when will the content expire? * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content + * @param exp when will the content expire? + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort */ typedef int (*GNUNET_DATACACHE_Iterator) (void *cls, - struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, size_t size, const char *data, - enum GNUNET_BLOCK_Type type); + enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute exp, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info); /** @@ -97,13 +101,17 @@ typedef int (*GNUNET_DATACACHE_Iterator) (void *cls, * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.) + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if duplicate */ int GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time); + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info); /** diff --git a/src/include/gnunet_datacache_plugin.h b/src/include/gnunet_datacache_plugin.h index 18268efd78..2e07501608 100644 --- a/src/include/gnunet_datacache_plugin.h +++ b/src/include/gnunet_datacache_plugin.h @@ -107,11 +107,15 @@ struct GNUNET_DATACACHE_PluginFunctions * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case - * @return 0 on error, number of bytes used otherwise + * @param path_info_len number of entries in 'path_info' + * @param path_info a path through the network + * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ - size_t (*put) (void *cls, const struct GNUNET_HashCode * key, size_t size, - const char *data, enum GNUNET_BLOCK_Type type, - struct GNUNET_TIME_Absolute discard_time); + ssize_t (*put) (void *cls, const struct GNUNET_HashCode * key, size_t size, + const char *data, enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute discard_time, + unsigned int path_info_len, + const struct GNUNET_PeerIdentity *path_info); /** |