aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-07-25 23:12:26 +0000
committerChristian Grothoff <christian@grothoff.org>2009-07-25 23:12:26 +0000
commit6ec2c6dc89a62810fe44696d7faaad9d837105cd (patch)
treec8c0380028555266b8aa968027b23d3177e81ffb
parentc890b76cde9288a8d9f2faa3046fbb06341c8082 (diff)
downloadgnunet-6ec2c6dc89a62810fe44696d7faaad9d837105cd.tar.gz
gnunet-6ec2c6dc89a62810fe44696d7faaad9d837105cd.zip
making plugin compile
-rw-r--r--src/datacache/datacache_api.c37
-rw-r--r--src/datacache/plugin_datacache_sqlite.c823
-rw-r--r--src/datacache/plugin_datacache_template.c16
-rw-r--r--src/datacache/test_datacache_api.c19
4 files changed, 333 insertions, 562 deletions
diff --git a/src/datacache/datacache_api.c b/src/datacache/datacache_api.c
index 1fe428b08..05dfb89e2 100644
--- a/src/datacache/datacache_api.c
+++ b/src/datacache/datacache_api.c
@@ -69,11 +69,16 @@ struct GNUNET_DATACACHE_Handle
69 * Name of the library (i.e. "gnunet_plugin_datacache_sqlite"). 69 * Name of the library (i.e. "gnunet_plugin_datacache_sqlite").
70 */ 70 */
71 char *lib_name; 71 char *lib_name;
72
73 /**
74 * Name for the bloom filter file.
75 */
76 char *bloom_name;
72 77
73 /** 78 /**
74 * Environment provided to our plugin. 79 * Environment provided to our plugin.
75 */ 80 */
76 struct GNUNET_DATASTORE_PluginEnvironment env; 81 struct GNUNET_DATACACHE_PluginEnvironment env;
77 82
78 /** 83 /**
79 * How much space is in use right now? 84 * How much space is in use right now?
@@ -116,21 +121,22 @@ GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
116 struct GNUNET_CONFIGURATION_Handle *cfg, 121 struct GNUNET_CONFIGURATION_Handle *cfg,
117 const char *section) 122 const char *section)
118{ 123{
124 int fd;
119 unsigned int bf_size; 125 unsigned int bf_size;
126 unsigned long long quota;
120 struct GNUNET_DATACACHE_Handle *ret; 127 struct GNUNET_DATACACHE_Handle *ret;
121 struct DatacachePlugin *ret;
122 char *libname; 128 char *libname;
123 char *name; 129 char *name;
124 130
125 if (GNUNET_OK != 131 if (GNUNET_OK !=
126 GNUNET_CONFIGURATION_get_value_number (c, 132 GNUNET_CONFIGURATION_get_value_number (cfg,
127 section, "QUOTA", &quota)) 133 section, "QUOTA", &quota))
128 { 134 {
129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
130 _("No `%s' specified for `%s' in configuration!\n"), 136 _("No `%s' specified for `%s' in configuration!\n"),
131 "QUOTA", 137 "QUOTA",
132 section); 138 section);
133 return; 139 return NULL;
134 } 140 }
135 if (GNUNET_OK != 141 if (GNUNET_OK !=
136 GNUNET_CONFIGURATION_get_value_string (cfg, 142 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -146,16 +152,26 @@ GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
146 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ 152 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
147 153
148 ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle)); 154 ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle));
149 /* FIXME: create a temporary file for the bloomfilter to better 155 ret->bloom_name = GNUNET_strdup ("/tmp/datacachebloomXXXXXX");
150 support deletions! */ 156 fd = mkstemp (ret->bloom_name);
151 ret->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, bf_size, 5); /* approx. 3% false positives at max use */ 157 if (fd != -1)
158 {
159 ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name,
160 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */
161 5);
162 CLOSE (fd);
163 }
164 else
165 {
166 ret->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, bf_size, 5); /* approx. 3% false positives at max use */
167 }
152 ret->section = GNUNET_strdup (section); 168 ret->section = GNUNET_strdup (section);
153 ret->env.sched = s; 169 ret->env.sched = sched;
154 ret->env.cfg = cfg; 170 ret->env.cfg = cfg;
155 ret->env.delete_notify = &env_delete_notify; 171 ret->env.delete_notify = &env_delete_notify;
156 ret->env.section = ret->section; 172 ret->env.section = ret->section;
157 ret->env.cls = ret; 173 ret->env.cls = ret;
158 ret->env.delete_notify = &delete_notify; 174 ret->env.delete_notify = &env_delete_notify;
159 ret->env.quota = quota; 175 ret->env.quota = quota;
160 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 176 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
161 _("Loading `%s' datacache plugin\n"), name); 177 _("Loading `%s' datacache plugin\n"), name);
@@ -187,6 +203,7 @@ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
187 GNUNET_free (h->lib_name); 203 GNUNET_free (h->lib_name);
188 GNUNET_free (h->short_name); 204 GNUNET_free (h->short_name);
189 GNUNET_free (h->section); 205 GNUNET_free (h->section);
206 GNUNET_free (h->bloom_name);
190 GNUNET_free (h); 207 GNUNET_free (h);
191} 208}
192 209
@@ -221,7 +238,7 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
221 if (used == 0) 238 if (used == 0)
222 return GNUNET_SYSERR; 239 return GNUNET_SYSERR;
223 GNUNET_CONTAINER_bloomfilter_add (h->filter, key); 240 GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
224 while (h->utilization + used > h->api.quota) 241 while (h->utilization + used > h->env.quota)
225 GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); 242 GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
226 h->utilization += used; 243 h->utilization += used;
227 return GNUNET_OK; 244 return GNUNET_OK;
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index e386b55de..800241126 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet
3 (C) 2006, 2007, 2008 Christian Grothoff (and other contributing authors) 3 (C) 2006, 2009 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -19,64 +19,55 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file applications/dstore_sqlite/dstore.c 22 * @file datacache/plugin_datacache_sqlite.c
23 * @brief SQLite based implementation of the dstore service 23 * @brief sqlite for an implementation of a database backend for the datacache
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @todo Indexes, statistics
26 *
27 * Database: SQLite
28 */ 25 */
29
30#include "platform.h" 26#include "platform.h"
31#include "gnunet_util.h" 27#include "gnunet_util_lib.h"
32#include "gnunet_dstore_service.h" 28#include "plugin_datacache.h"
33#include "gnunet_stats_service.h"
34#include <sqlite3.h> 29#include <sqlite3.h>
35 30
36#define DEBUG_DSTORE GNUNET_NO 31#define DEBUG_DATACACHE_SQLITE GNUNET_YES
37
38/**
39 * Maximum size for an individual item.
40 */
41#define MAX_CONTENT_SIZE 65536
42 32
43/** 33/**
44 * Bytes used 34 * How much overhead do we assume per entry in the
35 * datacache?
45 */ 36 */
46static unsigned long long payload; 37#define OVERHEAD (sizeof(GNUNET_HashCode) + 32)
47 38
48/** 39/**
49 * Maximum bytes available 40 * Context for all functions in this plugin.
50 */ 41 */
51static unsigned long long quota; 42struct Plugin
52 43{
53/** 44 /**
54 * Filename of this database 45 * Our execution environment.
55 */ 46 */
56static char *fn; 47 struct GNUNET_DATACACHE_PluginEnvironment *env;
57static char *fn_utf8; 48
49 /**
50 * Handle to the sqlite database.
51 */
52 sqlite3 *dbh;
58 53
59static GNUNET_CoreAPIForPlugins *coreAPI; 54 /**
55 * Filename used for the DB.
56 */
57 char *fn;
58};
60 59
61static struct GNUNET_Mutex *lock;
62 60
63/** 61/**
64 * Statistics service. 62 * Log an error message at log-level 'level' that indicates
63 * a failure of the command 'cmd' on file 'filename'
64 * with the message given by strerror(errno).
65 */ 65 */
66static GNUNET_Stats_ServiceAPI *stats; 66#define LOG_SQLITE(db, level, cmd) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db)); } while(0)
67 67
68static unsigned int stat_dstore_size;
69
70static unsigned int stat_dstore_quota;
71
72/**
73 * Estimate of the per-entry overhead (including indices).
74 */
75#define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(GNUNET_HashCode)*5+32))
76 68
77struct GNUNET_BloomFilter *bloom; 69#define SQLITE3_EXEC(db, cmd) do { emsg = NULL; if (SQLITE_OK != sqlite3_exec(db, cmd, NULL, NULL, &emsg)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, _("`%s' failed at %s:%d with error: %s\n"), "sqlite3_exec", __FILE__, __LINE__, emsg); sqlite3_free(emsg); } } while(0)
78 70
79static char *bloom_name;
80 71
81/** 72/**
82 * @brief Prepare a SQL statement 73 * @brief Prepare a SQL statement
@@ -91,375 +82,75 @@ sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8 encoded
91 strlen (zSql), ppStmt, (const char **) &dummy); 82 strlen (zSql), ppStmt, (const char **) &dummy);
92} 83}
93 84
94#define SQLITE3_EXEC(db, cmd) do { emsg = NULL; if (SQLITE_OK != sqlite3_exec(db, cmd, NULL, NULL, &emsg)) { GNUNET_GE_LOG(coreAPI->ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, _("`%s' failed at %s:%d with error: %s\n"), "sqlite3_exec", __FILE__, __LINE__, emsg); sqlite3_free(emsg); } } while(0)
95
96/**
97 * Log an error message at log-level 'level' that indicates
98 * a failure of the command 'cmd' on file 'filename'
99 * with the message given by strerror(errno).
100 */
101#define LOG_SQLITE(db, level, cmd) do { GNUNET_GE_LOG(coreAPI->ectx, level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db)); } while(0)
102
103static void
104db_init (sqlite3 * dbh)
105{
106 char *emsg;
107
108 SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY");
109 SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
110 SQLITE3_EXEC (dbh, "PRAGMA count_changes=OFF");
111 SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
112 SQLITE3_EXEC (dbh,
113 "CREATE TABLE ds080 ("
114 " size INTEGER NOT NULL DEFAULT 0,"
115 " type INTEGER NOT NULL DEFAULT 0,"
116 " puttime INTEGER NOT NULL DEFAULT 0,"
117 " expire INTEGER NOT NULL DEFAULT 0,"
118 " key BLOB NOT NULL DEFAULT '',"
119 " vhash BLOB NOT NULL DEFAULT '',"
120 " value BLOB NOT NULL DEFAULT '')");
121 SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds080 (key,type,expire)");
122 SQLITE3_EXEC (dbh,
123 "CREATE INDEX idx_allidx ON ds080 (key,vhash,type,size)");
124 SQLITE3_EXEC (dbh, "CREATE INDEX idx_puttime ON ds080 (puttime)");
125}
126
127static int
128db_reset ()
129{
130 int fd;
131 sqlite3 *dbh;
132 char *tmpl;
133 const char *tmpdir;
134
135 if (fn != NULL)
136 {
137 UNLINK (fn);
138 GNUNET_free (fn);
139 GNUNET_free (fn_utf8);
140 }
141 payload = 0;
142
143 tmpdir = getenv ("TMPDIR");
144 tmpdir = tmpdir ? tmpdir : "/tmp";
145
146#define TEMPLATE "/gnunet-dstoreXXXXXX"
147 tmpl = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1);
148 strcpy (tmpl, tmpdir);
149 strcat (tmpl, TEMPLATE);
150#undef TEMPLATE
151
152#ifdef MINGW
153 fn = (char *) GNUNET_malloc (MAX_PATH + 1);
154 plibc_conv_to_win_path (tmpl, fn);
155 GNUNET_free (tmpl);
156#else
157 fn = tmpl;
158#endif
159 fd = mkstemp (fn);
160 if (fd == -1)
161 {
162 GNUNET_GE_BREAK (NULL, 0);
163 GNUNET_free (fn);
164 fn = NULL;
165 return GNUNET_SYSERR;
166 }
167 CLOSE (fd);
168 fn_utf8 = GNUNET_convert_string_to_utf8 (coreAPI->ectx, fn, strlen (fn),
169#ifdef ENABLE_NLS
170 nl_langinfo (CODESET)
171#else
172 "UTF-8" /* good luck */
173#endif
174 );
175 if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
176 {
177 GNUNET_free (fn);
178 GNUNET_free (fn_utf8);
179 fn = NULL;
180 return GNUNET_SYSERR;
181 }
182 db_init (dbh);
183 sqlite3_close (dbh);
184 return GNUNET_OK;
185}
186
187/**
188 * Check that we are within quota.
189 * @return GNUNET_OK if we are.
190 */
191static int
192checkQuota (sqlite3 * dbh)
193{
194 GNUNET_HashCode dkey;
195 GNUNET_HashCode vhash;
196 unsigned int dsize;
197 unsigned int dtype;
198 sqlite3_stmt *stmt;
199 sqlite3_stmt *dstmt;
200 int err;
201
202 if (payload * 10 <= quota * 9)
203 return GNUNET_OK; /* we seem to be about 10% off */
204#if DEBUG_DSTORE
205 GNUNET_GE_LOG (coreAPI->ectx,
206 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
207 "DStore above qutoa (have %llu, allowed %llu), will delete some data.\n",
208 payload, quota);
209#endif
210 stmt = NULL;
211 dstmt = NULL;
212 if ((sq_prepare (dbh,
213 "SELECT size, type, key, vhash FROM ds080 ORDER BY puttime ASC LIMIT 1",
214 &stmt) != SQLITE_OK) ||
215 (sq_prepare (dbh,
216 "DELETE FROM ds080 "
217 "WHERE key=? AND vhash=? AND type=? AND size=?",
218 &dstmt) != SQLITE_OK))
219 {
220 GNUNET_GE_LOG (coreAPI->ectx,
221 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
222 _("`%s' failed at %s:%d with error: %s\n"),
223 "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
224 GNUNET_GE_BREAK (NULL, 0);
225 if (dstmt != NULL)
226 sqlite3_finalize (dstmt);
227 if (stmt != NULL)
228 sqlite3_finalize (stmt);
229 return GNUNET_SYSERR;
230 }
231 err = SQLITE_DONE;
232 while ((payload * 10 > quota * 9) && /* we seem to be about 10% off */
233 ((err = sqlite3_step (stmt)) == SQLITE_ROW))
234 {
235 dsize = sqlite3_column_int (stmt, 0);
236 dtype = sqlite3_column_int (stmt, 1);
237 GNUNET_GE_BREAK (NULL,
238 sqlite3_column_bytes (stmt,
239 2) == sizeof (GNUNET_HashCode));
240 GNUNET_GE_BREAK (NULL,
241 sqlite3_column_bytes (stmt,
242 3) == sizeof (GNUNET_HashCode));
243 memcpy (&dkey, sqlite3_column_blob (stmt, 2), sizeof (GNUNET_HashCode));
244 memcpy (&vhash, sqlite3_column_blob (stmt, 3),
245 sizeof (GNUNET_HashCode));
246 sqlite3_reset (stmt);
247 sqlite3_bind_blob (dstmt,
248 1, &dkey, sizeof (GNUNET_HashCode),
249 SQLITE_TRANSIENT);
250 sqlite3_bind_blob (dstmt,
251 2, &vhash, sizeof (GNUNET_HashCode),
252 SQLITE_TRANSIENT);
253 sqlite3_bind_int (dstmt, 3, dtype);
254 sqlite3_bind_int (dstmt, 4, dsize);
255 if ((err = sqlite3_step (dstmt)) != SQLITE_DONE)
256 {
257 GNUNET_GE_LOG (coreAPI->ectx,
258 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
259 _("`%s' failed at %s:%d with error: %s\n"),
260 "sqlite3_step", __FILE__, __LINE__,
261 sqlite3_errmsg (dbh));
262 sqlite3_reset (dstmt);
263 GNUNET_GE_BREAK (NULL, 0); /* should delete but cannot!? */
264 break;
265 }
266 if (sqlite3_total_changes (dbh) > 0)
267 {
268 if (bloom != NULL)
269 GNUNET_bloomfilter_remove (bloom, &dkey);
270 payload -= (dsize + OVERHEAD);
271 }
272#if DEBUG_DSTORE
273 GNUNET_GE_LOG (coreAPI->ectx,
274 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
275 GNUNET_GE_DEVELOPER,
276 "Deleting %u bytes decreases DStore payload to %llu out of %llu\n",
277 dsize, payload, quota);
278#endif
279 sqlite3_reset (dstmt);
280 }
281 if (err != SQLITE_DONE)
282 {
283 GNUNET_GE_LOG (coreAPI->ectx,
284 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
285 _("`%s' failed at %s:%d with error: %s\n"),
286 "sqlite3_step", __FILE__, __LINE__,
287 sqlite3_errmsg (dbh));
288 }
289 sqlite3_finalize (dstmt);
290 sqlite3_finalize (stmt);
291 if (payload * 10 > quota * 9)
292 {
293 /* we seem to be about 10% off */
294 GNUNET_GE_LOG (coreAPI->ectx,
295 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_DEVELOPER,
296 "Failed to delete content to drop below quota (bug?).\n",
297 payload, quota);
298 return GNUNET_SYSERR;
299 }
300 return GNUNET_OK;
301}
302 85
303/** 86/**
304 * Store an item in the datastore. 87 * Store an item in the datastore.
305 * 88 *
306 * @return GNUNET_OK on success, GNUNET_SYSERR on error 89 * @param key key to store data under
90 * @param size number of bytes in data
91 * @param data data to store
92 * @param type type of the value
93 * @param discard_time when to discard the value in any case
94 * @return 0 on error, number of bytes used otherwise
307 */ 95 */
308static int 96static uint32_t
309d_put (const GNUNET_HashCode * key, 97sqlite_plugin_put (void *cls,
310 unsigned int type, 98 const GNUNET_HashCode * key,
311 GNUNET_CronTime discard_time, unsigned int size, const char *data) 99 uint32_t size,
100 const char *data,
101 uint32_t type,
102 struct GNUNET_TIME_Absolute discard_time)
312{ 103{
313 GNUNET_HashCode vhash; 104 struct Plugin *plugin = cls;
314 sqlite3 *dbh;
315 sqlite3_stmt *stmt; 105 sqlite3_stmt *stmt;
316 int ret;
317 GNUNET_CronTime now;
318
319 if (size > MAX_CONTENT_SIZE)
320 return GNUNET_SYSERR;
321 GNUNET_hash (data, size, &vhash);
322 GNUNET_mutex_lock (lock);
323 if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)))
324 {
325 db_reset (dbh);
326 GNUNET_mutex_unlock (lock);
327 return GNUNET_SYSERR;
328 }
329 now = GNUNET_get_time ();
330#if DEBUG_DSTORE
331 GNUNET_GE_LOG (coreAPI->ectx,
332 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
333 "dstore processes put `%.*s' with expiration %llu\n",
334 size, data, discard_time);
335#endif
336 106
337 /* first try UPDATE */ 107#if DEBUG_DATACACHE_SQLITE
338 if (sq_prepare (dbh, 108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
339 "UPDATE ds080 SET puttime=?, expire=? " 109 "Processing `%s' of %u bytes with key `%4s' and expiration %llums\n",
340 "WHERE key=? AND vhash=? AND type=? AND size=?", 110 "PUT",
341 &stmt) != SQLITE_OK) 111 (unsigned int) size,
112 GNUNET_h2s (key),
113 (unsigned long long) GNUNET_TIME_absolute_get_remaining (discard_time).value);
114#endif
115 if (sq_prepare (plugin->dbh,
116 "INSERT INTO ds090 "
117 "(type, expire, key, value) "
118 "VALUES (?, ?, ?, ?)", &stmt) != SQLITE_OK)
342 { 119 {
343 GNUNET_GE_LOG (coreAPI->ectx, 120 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
344 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, 121 _("`%s' failed at %s:%d with error: %s\n"),
345 _("`%s' failed at %s:%d with error: %s\n"), 122 "sq_prepare", __FILE__, __LINE__,
346 "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh)); 123 sqlite3_errmsg (plugin->dbh));
347 sqlite3_close (dbh); 124 return 0;
348 GNUNET_mutex_unlock (lock);
349 return GNUNET_SYSERR;
350 } 125 }
351 if ((SQLITE_OK != 126 if ( (SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) ||
352 sqlite3_bind_int64 (stmt, 1, now)) || 127 (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, discard_time.value)) ||
353 (SQLITE_OK != 128 (SQLITE_OK != sqlite3_bind_blob (stmt, 3, key, sizeof (GNUNET_HashCode),
354 sqlite3_bind_int64 (stmt, 2, discard_time)) || 129 SQLITE_TRANSIENT)) ||
355 (SQLITE_OK != 130 (SQLITE_OK != sqlite3_bind_blob (stmt, 4, data, size, SQLITE_TRANSIENT)))
356 sqlite3_bind_blob (stmt, 3, key, sizeof (GNUNET_HashCode),
357 SQLITE_TRANSIENT)) ||
358 (SQLITE_OK !=
359 sqlite3_bind_blob (stmt, 4, &vhash, sizeof (GNUNET_HashCode),
360 SQLITE_TRANSIENT)) ||
361 (SQLITE_OK != sqlite3_bind_int (stmt, 5, type)) ||
362 (SQLITE_OK != sqlite3_bind_int (stmt, 6, size)))
363 { 131 {
364 GNUNET_GE_LOG (coreAPI->ectx, 132 LOG_SQLITE (plugin->dbh,
365 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, 133 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
366 _("`%s' failed at %s:%d with error: %s\n"), 134 "sqlite3_bind_xxx");
367 "sqlite3_bind_xxx", __FILE__, __LINE__,
368 sqlite3_errmsg (dbh));
369 sqlite3_finalize (stmt); 135 sqlite3_finalize (stmt);
370 sqlite3_close (dbh); 136 return 0;
371 GNUNET_mutex_unlock (lock);
372 return GNUNET_SYSERR;
373 } 137 }
374 if (SQLITE_DONE != sqlite3_step (stmt)) 138 if (SQLITE_DONE != sqlite3_step (stmt))
375 { 139 {
376 GNUNET_GE_LOG (coreAPI->ectx, 140 LOG_SQLITE (plugin->dbh,
377 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, 141 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
378 _("`%s' failed at %s:%d with error: %s\n"), 142 "sqlite3_step");
379 "sqlite3_step", __FILE__, __LINE__,
380 sqlite3_errmsg (dbh));
381 sqlite3_finalize (stmt); 143 sqlite3_finalize (stmt);
382 sqlite3_close (dbh); 144 return 0;
383 GNUNET_mutex_unlock (lock);
384 return GNUNET_SYSERR;
385 }
386 ret = sqlite3_changes (dbh);
387 sqlite3_finalize (stmt);
388 if (ret > 0)
389 {
390 sqlite3_close (dbh);
391 GNUNET_mutex_unlock (lock);
392 return GNUNET_OK;
393 }
394 if (GNUNET_OK != checkQuota (dbh))
395 {
396 sqlite3_close (dbh);
397 GNUNET_mutex_unlock (lock);
398 return GNUNET_SYSERR;
399 }
400 if (sq_prepare (dbh,
401 "INSERT INTO ds080 "
402 "(size, type, puttime, expire, key, vhash, value) "
403 "VALUES (?, ?, ?, ?, ?, ?, ?)", &stmt) != SQLITE_OK)
404 {
405 GNUNET_GE_LOG (coreAPI->ectx,
406 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
407 _("`%s' failed at %s:%d with error: %s\n"),
408 "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
409 sqlite3_close (dbh);
410 GNUNET_mutex_unlock (lock);
411 return GNUNET_SYSERR;
412 }
413 if ((SQLITE_OK == sqlite3_bind_int (stmt, 1, size)) &&
414 (SQLITE_OK == sqlite3_bind_int (stmt, 2, type)) &&
415 (SQLITE_OK == sqlite3_bind_int64 (stmt, 3, now)) &&
416 (SQLITE_OK == sqlite3_bind_int64 (stmt, 4, discard_time)) &&
417 (SQLITE_OK ==
418 sqlite3_bind_blob (stmt, 5, key, sizeof (GNUNET_HashCode),
419 SQLITE_TRANSIENT)) &&
420 (SQLITE_OK ==
421 sqlite3_bind_blob (stmt, 6, &vhash, sizeof (GNUNET_HashCode),
422 SQLITE_TRANSIENT))
423 && (SQLITE_OK ==
424 sqlite3_bind_blob (stmt, 7, data, size, SQLITE_TRANSIENT)))
425 {
426 if (SQLITE_DONE != sqlite3_step (stmt))
427 {
428 LOG_SQLITE (dbh,
429 GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN
430 | GNUNET_GE_BULK, "sqlite3_step");
431 }
432 else
433 {
434 payload += size + OVERHEAD;
435 if (bloom != NULL)
436 GNUNET_bloomfilter_add (bloom, key);
437 }
438 if (SQLITE_OK != sqlite3_finalize (stmt))
439 LOG_SQLITE (dbh,
440 GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN |
441 GNUNET_GE_BULK, "sqlite3_finalize");
442 }
443 else
444 {
445 LOG_SQLITE (dbh,
446 GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN |
447 GNUNET_GE_BULK, "sqlite3_bind_xxx");
448 } 145 }
449#if DEBUG_DSTORE 146 if (SQLITE_OK != sqlite3_finalize (stmt))
450 GNUNET_GE_LOG (coreAPI->ectx, 147 LOG_SQLITE (plugin->dbh,
451 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER, 148 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
452 "Storing %u bytes increases DStore payload to %llu out of %llu\n", 149 "sqlite3_finalize");
453 size, payload, quota); 150 return size + OVERHEAD;
454#endif
455 checkQuota (dbh);
456 sqlite3_close (dbh);
457 GNUNET_mutex_unlock (lock);
458 if (stats != NULL)
459 stats->set (stat_dstore_size, payload);
460 return GNUNET_OK;
461} 151}
462 152
153
463/** 154/**
464 * Iterate over the results for a particular key 155 * Iterate over the results for a particular key
465 * in the datastore. 156 * in the datastore.
@@ -467,16 +158,18 @@ d_put (const GNUNET_HashCode * key,
467 * @param key 158 * @param key
468 * @param type entries of which type are relevant? 159 * @param type entries of which type are relevant?
469 * @param iter maybe NULL (to just count) 160 * @param iter maybe NULL (to just count)
470 * @return the number of results, GNUNET_SYSERR if the 161 * @return the number of results found
471 * iter is non-NULL and aborted the iteration
472 */ 162 */
473static int 163static unsigned int
474d_get (const GNUNET_HashCode * key, 164sqlite_plugin_get (void *cls,
475 unsigned int type, GNUNET_ResultProcessor handler, void *closure) 165 const GNUNET_HashCode * key,
166 uint32_t type,
167 GNUNET_DATACACHE_Iterator iter,
168 void *iter_cls)
476{ 169{
477 sqlite3 *dbh; 170 struct Plugin *plugin = cls;
478 sqlite3_stmt *stmt; 171 sqlite3_stmt *stmt;
479 GNUNET_CronTime now; 172 struct GNUNET_TIME_Absolute now;
480 unsigned int size; 173 unsigned int size;
481 const char *dat; 174 const char *dat;
482 unsigned int cnt; 175 unsigned int cnt;
@@ -484,193 +177,261 @@ d_get (const GNUNET_HashCode * key,
484 unsigned int total; 177 unsigned int total;
485 char scratch[256]; 178 char scratch[256];
486 179
487 GNUNET_mutex_lock (lock); 180 now = GNUNET_TIME_absolute_get ();
488 if ((bloom != NULL) && (GNUNET_NO == GNUNET_bloomfilter_test (bloom, key))) 181
489 { 182#if DEBUG_DATACACHE_SQLITE
490 GNUNET_mutex_unlock (lock); 183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 return 0; 184 "Processing `%s' for key `%4s'\n",
492 } 185 "GET",
493 if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))) 186 GNUNET_h2s (key));
494 {
495 db_reset (dbh);
496 GNUNET_mutex_unlock (lock);
497 return GNUNET_SYSERR;
498 }
499 now = GNUNET_get_time ();
500#if DEBUG_DSTORE
501 GNUNET_GE_LOG (coreAPI->ectx,
502 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
503 "dstore processes get at `%llu'\n", now);
504#endif 187#endif
505 if (sq_prepare (dbh, 188 if (sq_prepare (plugin->dbh,
506 "SELECT count(*) FROM ds080 WHERE key=? AND type=? AND expire >= ?", 189 "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?",
507 &stmt) != SQLITE_OK) 190 &stmt) != SQLITE_OK)
508 { 191 {
509 GNUNET_GE_LOG (coreAPI->ectx, 192 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
510 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, 193 _("`%s' failed at %s:%d with error: %s\n"),
511 _("`%s' failed at %s:%d with error: %s\n"), 194 "sq_prepare", __FILE__, __LINE__,
512 "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh)); 195 sqlite3_errmsg (plugin->dbh));
513 sqlite3_close (dbh); 196 return 0;
514 db_reset (dbh);
515 GNUNET_mutex_unlock (lock);
516 return GNUNET_SYSERR;
517 } 197 }
518 sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), 198 sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode),
519 SQLITE_TRANSIENT); 199 SQLITE_TRANSIENT);
520 sqlite3_bind_int (stmt, 2, type); 200 sqlite3_bind_int (stmt, 2, type);
521 sqlite3_bind_int64 (stmt, 3, now); 201 sqlite3_bind_int64 (stmt, 3, now.value);
522 if (SQLITE_ROW != sqlite3_step (stmt)) 202 if (SQLITE_ROW != sqlite3_step (stmt))
523 { 203 {
524 LOG_SQLITE (dbh, 204 LOG_SQLITE (plugin->dbh,
525 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER | 205 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
526 GNUNET_GE_BULK, "sqlite_step"); 206 "sqlite_step");
527 sqlite3_reset (stmt);
528 sqlite3_finalize (stmt); 207 sqlite3_finalize (stmt);
529 db_reset (dbh); 208 return 0;
530 GNUNET_mutex_unlock (lock);
531 return GNUNET_SYSERR;
532 } 209 }
533 total = sqlite3_column_int (stmt, 0); 210 total = sqlite3_column_int (stmt, 0);
534 sqlite3_reset (stmt);
535 sqlite3_finalize (stmt); 211 sqlite3_finalize (stmt);
536 if ((total == 0) || (handler == NULL)) 212 if ( (total == 0) || (iter == NULL) )
537 { 213 return total;
538 sqlite3_close (dbh);
539 GNUNET_mutex_unlock (lock);
540 return total;
541 }
542 214
543 cnt = 0; 215 cnt = 0;
544 off = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, total); 216 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
545 while (cnt < total) 217 while (cnt < total)
546 { 218 {
547 off = (off + 1) % total; 219 off = (off + 1) % total;
548 GNUNET_snprintf (scratch, 256, 220 GNUNET_snprintf (scratch,
549 "SELECT size, value FROM ds080 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", 221 sizeof(scratch),
222 "SELECT value FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u",
550 off); 223 off);
551 if (sq_prepare (dbh, scratch, &stmt) != SQLITE_OK) 224 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
552 { 225 {
553 GNUNET_GE_LOG (coreAPI->ectx, 226 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
554 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, 227 _("`%s' failed at %s:%d with error: %s\n"),
555 _("`%s' failed at %s:%d with error: %s\n"), 228 "sq_prepare", __FILE__, __LINE__,
556 "sq_prepare", __FILE__, __LINE__, 229 sqlite3_errmsg (plugin->dbh));
557 sqlite3_errmsg (dbh)); 230 return cnt;
558 sqlite3_close (dbh);
559 GNUNET_mutex_unlock (lock);
560 return GNUNET_SYSERR;
561 } 231 }
562 sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), 232 sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode),
563 SQLITE_TRANSIENT); 233 SQLITE_TRANSIENT);
564 sqlite3_bind_int (stmt, 2, type); 234 sqlite3_bind_int (stmt, 2, type);
565 sqlite3_bind_int64 (stmt, 3, now); 235 sqlite3_bind_int64 (stmt, 3, now.value);
566 if (sqlite3_step (stmt) != SQLITE_ROW) 236 if (sqlite3_step (stmt) != SQLITE_ROW)
567 break; 237 break;
568 size = sqlite3_column_int (stmt, 0); 238 size = sqlite3_column_bytes (stmt, 0);
569 if (size != sqlite3_column_bytes (stmt, 1))
570 {
571 GNUNET_GE_BREAK (NULL, 0);
572 sqlite3_finalize (stmt);
573 continue;
574 }
575 dat = sqlite3_column_blob (stmt, 1); 239 dat = sqlite3_column_blob (stmt, 1);
576 cnt++; 240 cnt++;
577#if DEBUG_DSTORE 241 if (GNUNET_OK != iter (iter_cls,
578 GNUNET_GE_LOG (coreAPI->ectx, 242 key,
579 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | 243 size,
580 GNUNET_GE_DEVELOPER, 244 dat,
581 "dstore found result for get: `%.*s'\n", size, dat); 245 type))
582#endif
583 if ((handler != NULL) &&
584 (GNUNET_OK != handler (key, type, size, dat, closure)))
585 { 246 {
586 sqlite3_finalize (stmt); 247 sqlite3_finalize (stmt);
587 break; 248 break;
588 } 249 }
589 sqlite3_finalize (stmt); 250 sqlite3_finalize (stmt);
590 } 251 }
591 sqlite3_close (dbh);
592 GNUNET_mutex_unlock (lock);
593 return cnt; 252 return cnt;
594} 253}
595 254
596GNUNET_Dstore_ServiceAPI * 255
597provide_module_dstore_sqlite (GNUNET_CoreAPIForPlugins * capi) 256/**
257 * Delete the entry with the lowest expiration value
258 * from the datacache right now.
259 *
260 * @return GNUNET_OK on success, GNUNET_SYSERR on error
261 */
262static int
263sqlite_plugin_del (void *cls)
598{ 264{
599 static GNUNET_Dstore_ServiceAPI api; 265 struct Plugin *plugin = cls;
600 int fd; 266 unsigned int dsize;
267 unsigned int dtype;
268 sqlite3_stmt *stmt;
269 sqlite3_stmt *dstmt;
601 270
602#if DEBUG_SQLITE 271#if DEBUG_DATACACHE_SQLITE
603 GNUNET_GE_LOG (capi->ectx, 272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, 273 "Processing `%s'\n",
605 "SQLite Dstore: initializing database\n"); 274 "DEL");
606#endif 275#endif
607 coreAPI = capi; 276 stmt = NULL;
608 if (GNUNET_OK != db_reset ()) 277 dstmt = NULL;
278 if ((sq_prepare (plugin->dbh,
279 "SELECT type, key, value FROM ds090 ORDER BY expire ASC LIMIT 1",
280 &stmt) != SQLITE_OK) ||
281 (sq_prepare (plugin->dbh,
282 "DELETE FROM ds080 "
283 "WHERE key=? AND value=? AND type=?",
284 &dstmt) != SQLITE_OK))
609 { 285 {
610 GNUNET_GE_BREAK (capi->ectx, 0); 286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
611 return NULL; 287 _("`%s' failed at %s:%d with error: %s\n"),
288 "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh));
289 if (dstmt != NULL)
290 sqlite3_finalize (dstmt);
291 if (stmt != NULL)
292 sqlite3_finalize (stmt);
293 return GNUNET_SYSERR;
612 } 294 }
613 lock = GNUNET_mutex_create (GNUNET_NO); 295 if (SQLITE_ROW != sqlite3_step (stmt))
614
615
616 api.get = &d_get;
617 api.put = &d_put;
618 GNUNET_GC_get_configuration_value_number (coreAPI->cfg,
619 "DSTORE", "QUOTA", 1, 1024, 1,
620 &quota);
621 if (quota == 0) /* error */
622 quota = 1;
623 quota *= 1024 * 1024;
624
625 bloom_name = GNUNET_strdup ("/tmp/dbloomXXXXXX");
626 fd = mkstemp (bloom_name);
627 if (fd != -1)
628 { 296 {
629 bloom = GNUNET_bloomfilter_load (coreAPI->ectx, bloom_name, quota / (OVERHEAD + 1024), /* 8 bit per entry in DB, expect 1k entries */ 297 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
630 5); 298 _("`%s' failed at %s:%d with error: %s\n"),
631 CLOSE (fd); 299 "sqlite3_step", __FILE__, __LINE__,
300 sqlite3_errmsg (plugin->dbh));
301 sqlite3_finalize (dstmt);
302 sqlite3_finalize (stmt);
303 return GNUNET_SYSERR;
632 } 304 }
633 stats = capi->service_request ("stats"); 305 dtype = sqlite3_column_int (stmt, 0);
634 if (stats != NULL) 306 GNUNET_break (sqlite3_column_bytes (stmt, 1) == sizeof (GNUNET_HashCode));
307 dsize = sqlite3_column_bytes (stmt, 2);
308 sqlite3_bind_blob (dstmt,
309 1, sqlite3_column_blob (stmt, 1),
310 sizeof (GNUNET_HashCode),
311 SQLITE_TRANSIENT);
312 sqlite3_bind_blob (dstmt,
313 2, sqlite3_column_blob (stmt, 2),
314 dsize,
315 SQLITE_TRANSIENT);
316 sqlite3_bind_int (dstmt, 3, dtype);
317 if (sqlite3_step (dstmt) != SQLITE_DONE)
635 { 318 {
636 stat_dstore_size = stats->create (gettext_noop ("# bytes in dstore")); 319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
637 stat_dstore_quota = 320 _("`%s' failed at %s:%d with error: %s\n"),
638 stats->create (gettext_noop ("# max bytes allowed in dstore")); 321 "sqlite3_step", __FILE__, __LINE__,
639 stats->set (stat_dstore_quota, quota); 322 sqlite3_errmsg (plugin->dbh));
323 sqlite3_finalize (dstmt);
324 sqlite3_finalize (stmt);
325 return GNUNET_SYSERR;
640 } 326 }
641 return &api; 327 plugin->env->delete_notify (plugin->env->cls,
328 sqlite3_column_blob (stmt, 1),
329 dsize + OVERHEAD);
330 sqlite3_finalize (dstmt);
331 sqlite3_finalize (stmt);
332 return GNUNET_OK;
642} 333}
643 334
335
644/** 336/**
645 * Shutdown the module. 337 * Entry point for the plugin.
646 */ 338 */
647void 339void *
648release_module_dstore_sqlite () 340libgnunet_plugin_datacache_sqlite_init (void *cls)
649{ 341{
650 UNLINK (fn); 342 struct GNUNET_DATACACHE_PluginEnvironment *env = cls;
651 GNUNET_free (fn); 343 struct GNUNET_DATACACHE_PluginFunctions *api;
652 GNUNET_free (fn_utf8); 344 struct Plugin *plugin;
653 fn = NULL; 345 char *fn;
654 if (bloom != NULL) 346 char *fn_utf8;
347 int fd;
348 sqlite3 *dbh;
349 char *tmpl;
350 const char *tmpdir;
351 char *emsg;
352
353 tmpdir = getenv ("TMPDIR");
354 tmpdir = tmpdir ? tmpdir : "/tmp";
355
356#define TEMPLATE "/gnunet-dstoreXXXXXX"
357 tmpl = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1);
358 strcpy (tmpl, tmpdir);
359 strcat (tmpl, TEMPLATE);
360#undef TEMPLATE
361#ifdef MINGW
362 fn = (char *) GNUNET_malloc (MAX_PATH + 1);
363 plibc_conv_to_win_path (tmpl, fn);
364 GNUNET_free (tmpl);
365#else
366 fn = tmpl;
367#endif
368 fd = mkstemp (fn);
369 if (fd == -1)
655 { 370 {
656 GNUNET_bloomfilter_free (bloom); 371 GNUNET_break (0);
657 bloom = NULL; 372 GNUNET_free (fn);
373 return NULL;
658 } 374 }
659 UNLINK (bloom_name); 375 CLOSE (fd);
660 GNUNET_free (bloom_name); 376 fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn),
661 bloom_name = NULL; 377#ifdef ENABLE_NLS
662 if (stats != NULL) 378 nl_langinfo (CODESET)
379#else
380 "UTF-8" /* good luck */
381#endif
382 );
383 if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
663 { 384 {
664 coreAPI->service_release (stats); 385 GNUNET_free (fn);
665 stats = NULL; 386 GNUNET_free (fn_utf8);
387 return NULL;
666 } 388 }
667#if DEBUG_SQLITE 389 GNUNET_free (fn);
668 GNUNET_GE_LOG (coreAPI->ectx, 390
669 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, 391 SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY");
670 "SQLite Dstore: database shutdown\n"); 392 SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
671#endif 393 SQLITE3_EXEC (dbh, "PRAGMA count_changes=OFF");
672 GNUNET_mutex_destroy (lock); 394 SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
673 coreAPI = NULL; 395 SQLITE3_EXEC (dbh,
396 "CREATE TABLE ds090 ("
397 " type INTEGER NOT NULL DEFAULT 0,"
398 " expire INTEGER NOT NULL DEFAULT 0,"
399 " key BLOB NOT NULL DEFAULT '',"
400 " value BLOB NOT NULL DEFAULT '')");
401 SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds080 (key,type,expire)");
402 plugin = GNUNET_malloc (sizeof (struct Plugin));
403 plugin->env = env;
404 plugin->dbh = dbh;
405 plugin->fn = fn_utf8;
406 api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions));
407 api->cls = plugin;
408 api->get = &sqlite_plugin_get;
409 api->put = &sqlite_plugin_put;
410 api->del = &sqlite_plugin_del;
411 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
412 "sqlite", _("Sqlite datacache running\n"));
413 return api;
414}
415
416
417/**
418 * Exit point from the plugin.
419 */
420void *
421libgnunet_plugin_datacache_sqlite_done (void *cls)
422{
423 struct GNUNET_DATACACHE_PluginFunctions *api = cls;
424 struct Plugin *plugin = api->cls;
425
426 UNLINK (plugin->fn);
427 GNUNET_free (plugin->fn);
428 sqlite3_close (plugin->dbh);
429 GNUNET_free (plugin);
430 GNUNET_free (api);
431 return NULL;
674} 432}
675 433
676/* end of dstore.c */ 434
435
436/* end of plugin_datacache_sqlite.c */
437
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c
index d1f162c17..501284c30 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -23,20 +23,10 @@
23 * @brief template for an implementation of a database backend for the datacache 23 * @brief template for an implementation of a database backend for the datacache
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#ifndef PLUGIN_DATACACHE_H 26#include "platform.h"
27#define PLUGIN_DATACACHE_H 27#include "gnunet_util_lib.h"
28
29#include "plugin_datacache.h" 28#include "plugin_datacache.h"
30 29
31#ifdef __cplusplus
32extern "C"
33{
34#if 0 /* keep Emacsens' auto-indent happy */
35}
36#endif
37#endif
38
39
40 30
41/** 31/**
42 * Context for all functions in this plugin. 32 * Context for all functions in this plugin.
@@ -46,7 +36,7 @@ struct Plugin
46 /** 36 /**
47 * Our execution environment. 37 * Our execution environment.
48 */ 38 */
49 struct GNUNET_DATASTORE_PluginEnvironment *env; 39 struct GNUNET_DATACACHE_PluginEnvironment *env;
50}; 40};
51 41
52 42
diff --git a/src/datacache/test_datacache_api.c b/src/datacache/test_datacache_api.c
index 00b63cda8..d4fea584f 100644
--- a/src/datacache/test_datacache_api.c
+++ b/src/datacache/test_datacache_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2006 Christian Grothoff (and other contributing authors) 3 (C) 2006, 2009 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -18,17 +18,16 @@
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20/* 20/*
21 * @file applications/dstore/dstore_test.c 21 * @file datacache/test_datacache_api.c
22 * @brief Test for the dstore implementations. 22 * @brief Test for the datacache implementations.
23 * @author Nils Durner 23 * @author Nils Durner
24 */ 24 */
25 25
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h" 28#include "gnunet_datacache_lib.h"
29#include "gnunet_dstore_service.h"
30#include "core.h"
31 29
30#if 0
32#define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0) 31#define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0)
33 32
34static int error; 33static int error;
@@ -85,10 +84,12 @@ FAILURE:
85} 84}
86 85
87#define TEST_DB "/tmp/GNUnet_dstore_test/" 86#define TEST_DB "/tmp/GNUnet_dstore_test/"
87#endif
88 88
89int 89int
90main (int argc, char *argv[]) 90main (int argc, char *argv[])
91{ 91{
92#if 0
92 GNUNET_Dstore_ServiceAPI *api; 93 GNUNET_Dstore_ServiceAPI *api;
93 int ok; 94 int ok;
94 struct GNUNET_GC_Configuration *cfg; 95 struct GNUNET_GC_Configuration *cfg;
@@ -115,6 +116,8 @@ main (int argc, char *argv[])
115 if (ok == GNUNET_SYSERR) 116 if (ok == GNUNET_SYSERR)
116 return 1; 117 return 1;
117 return error; 118 return error;
119#endif
120 return 0;
118} 121}
119 122
120/* end of dstore_test.c */ 123/* end of test_datacache_api.c */