aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_postgres.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-08 19:55:45 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-08 19:55:45 +0000
commitbe86840fb6144a631ff18237bc31abb7a97938f7 (patch)
treedfa68dcd690a40c5c060cd6ad7ad017696333655 /src/namestore/plugin_namestore_postgres.c
parent5049585e7942ad3fe3f8742832a2b4f76ec5a954 (diff)
downloadgnunet-be86840fb6144a631ff18237bc31abb7a97938f7.tar.gz
gnunet-be86840fb6144a631ff18237bc31abb7a97938f7.zip
towards implementing postgres backend for namestore (#2987)
Diffstat (limited to 'src/namestore/plugin_namestore_postgres.c')
-rw-r--r--src/namestore/plugin_namestore_postgres.c780
1 files changed, 412 insertions, 368 deletions
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index fe4280a3c..4697923d0 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -23,7 +23,6 @@
23 * @brief postgres-based namestore backend 23 * @brief postgres-based namestore backend
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26
27#include "platform.h" 26#include "platform.h"
28#include "gnunet_namestore_plugin.h" 27#include "gnunet_namestore_plugin.h"
29#include "gnunet_namestore_service.h" 28#include "gnunet_namestore_service.h"
@@ -80,17 +79,20 @@ create_indices (PGconn * dbh)
80{ 79{
81 /* create indices */ 80 /* create indices */
82 if ( (GNUNET_OK != 81 if ( (GNUNET_OK !=
83 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) || 82 GNUNET_POSTGRES_exec (dbh,
84 (GNUNET_OK != 83 "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) ||
85 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX is_block_expiration ON ns096blocks (expiration_time)")) ||
86 (GNUNET_OK != 84 (GNUNET_OK !=
87 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX is_pkey_reverse ON ns097records (zone_private_key,pkey)")) || 85 GNUNET_POSTGRES_exec (dbh,
86 "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)")) ||
88 (GNUNET_OK != 87 (GNUNET_OK !=
89 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_zone ON ns091records (zone_hash)")) || 88 GNUNET_POSTGRES_exec (dbh,
89 "CREATE INDEX ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) ||
90 (GNUNET_OK != 90 (GNUNET_OK !=
91 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_name_rv ON ns091records (record_name_hash,rvalue)")) || 91 GNUNET_POSTGRES_exec (dbh,
92 "CREATE INDEX ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) ||
92 (GNUNET_OK != 93 (GNUNET_OK !=
93 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_rv ON ns091records (rvalue)")) ) 94 GNUNET_POSTGRES_exec (dbh,
95 "CREATE INDEX it_iter ON ns097records (rvalue)")) )
94 LOG (GNUNET_ERROR_TYPE_ERROR, 96 LOG (GNUNET_ERROR_TYPE_ERROR,
95 _("Failed to create indices\n")); 97 _("Failed to create indices\n"));
96} 98}
@@ -120,42 +122,77 @@ database_setup (struct Plugin *plugin)
120 { 122 {
121 res = 123 res =
122 PQexec (plugin->dbh, 124 PQexec (plugin->dbh,
123 "CREATE TEMPORARY TABLE ns091records (" 125 "CREATE TEMPORARY TABLE ns097records ("
124 " zone_key BYTEA NOT NULL DEFAULT ''," 126 " zone_private_key BYTEA NOT NULL DEFAULT '',"
125 " zone_delegation BYTEA NOT NULL DEFAULT ''," 127 " pkey BYTEA DEFAULT '',"
126 " zone_hash BYTEA NOT NULL DEFAULT ''," 128 " rvalue BYTEA NOT NULL DEFAULT '',"
127 " record_count INTEGER NOT NULL DEFAULT 0," 129 " record_count INTEGER NOT NULL DEFAULT 0,"
128 " record_data BYTEA NOT NULL DEFAULT ''," 130 " record_data BYTEA NOT NULL DEFAULT '',"
129 " block_expiration_time BIGINT NOT NULL DEFAULT 0," 131 " label TEXT NOT NULL DEFAULT ''"
130 " signature BYTEA NOT NULL DEFAULT '',"
131 " record_name TEXT NOT NULL DEFAULT '',"
132 " record_name_hash BYTEA NOT NULL DEFAULT '',"
133 " rvalue BIGINT NOT NULL DEFAULT 0"
134 ")" "WITH OIDS"); 132 ")" "WITH OIDS");
135 } 133 }
136 else 134 else
135 {
137 res = 136 res =
138 PQexec (plugin->dbh, 137 PQexec (plugin->dbh,
139 "CREATE TABLE ns091records (" 138 "CREATE TABLE ns097records ("
140 " zone_key BYTEA NOT NULL DEFAULT ''," 139 " zone_private_key BYTEA NOT NULL DEFAULT '',"
141 " zone_delegation BYTEA NOT NULL DEFAULT ''," 140 " pkey BYTEA DEFAULT '',"
142 " zone_hash BYTEA NOT NULL DEFAULT ''," 141 " rvalue BYTEA NOT NULL DEFAULT '',"
143 " record_count INTEGER NOT NULL DEFAULT 0," 142 " record_count INTEGER NOT NULL DEFAULT 0,"
144 " record_data BYTEA NOT NULL DEFAULT ''," 143 " record_data BYTEA NOT NULL DEFAULT '',"
145 " block_expiration_time BIGINT NOT NULL DEFAULT 0," 144 " label TEXT NOT NULL DEFAULT ''"
146 " signature BYTEA NOT NULL DEFAULT '',"
147 " record_name TEXT NOT NULL DEFAULT '',"
148 " record_name_hash BYTEA NOT NULL DEFAULT '',"
149 " rvalue BIGINT NOT NULL DEFAULT 0"
150 ")" "WITH OIDS"); 145 ")" "WITH OIDS");
146 }
147 if ( (NULL == res) ||
148 ((PQresultStatus (res) != PGRES_COMMAND_OK) &&
149 (0 != strcmp ("42P07", /* duplicate table */
150 PQresultErrorField
151 (res,
152 PG_DIAG_SQLSTATE)))))
153 {
154 (void) GNUNET_POSTGRES_check_result (plugin->dbh, res,
155 PGRES_COMMAND_OK, "CREATE TABLE",
156 "ns097records");
157 PQfinish (plugin->dbh);
158 plugin->dbh = NULL;
159 return GNUNET_SYSERR;
160 }
161
151 162
152 if ((NULL == res) || ((PQresultStatus (res) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ 163 if (GNUNET_YES ==
153 PQresultErrorField 164 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
154 (res, 165 "namestore-postgres",
155 PG_DIAG_SQLSTATE))))) 166 "TEMPORARY_TABLE"))
156 { 167 {
157 (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "CREATE TABLE", 168 res =
158 "ns091records"); 169 PQexec (plugin->dbh,
170 "CREATE TEMPORARY TABLE ns096blocks ("
171 " query BYTEA NOT NULL DEFAULT '',"
172 " block BYTEA NOT NULL DEFAULT '',"
173 " expiration_time BIGINT NOT NULL DEFAULT 0"
174 ")" "WITH OIDS");
175 }
176 else
177 {
178 res =
179 PQexec (plugin->dbh,
180 "CREATE TABLE ns096blocks ("
181 " query BYTEA NOT NULL DEFAULT '',"
182 " block BYTEA NOT NULL DEFAULT '',"
183 " expiration_time BIGINT NOT NULL DEFAULT 0"
184 ")" "WITH OIDS");
185 }
186 if ( (NULL == res) ||
187 ((PQresultStatus (res) != PGRES_COMMAND_OK) &&
188 (0 != strcmp ("42P07", /* duplicate table */
189 PQresultErrorField
190 (res,
191 PG_DIAG_SQLSTATE)))))
192 {
193 (void) GNUNET_POSTGRES_check_result (plugin->dbh, res,
194 PGRES_COMMAND_OK, "CREATE TABLE",
195 "ns096blocks");
159 PQfinish (plugin->dbh); 196 PQfinish (plugin->dbh);
160 plugin->dbh = NULL; 197 plugin->dbh = NULL;
161 return GNUNET_SYSERR; 198 return GNUNET_SYSERR;
@@ -166,43 +203,46 @@ database_setup (struct Plugin *plugin)
166 203
167 if ((GNUNET_OK != 204 if ((GNUNET_OK !=
168 GNUNET_POSTGRES_prepare (plugin->dbh, 205 GNUNET_POSTGRES_prepare (plugin->dbh,
169 "put_records", 206 "cache_block",
170 "INSERT INTO ns091records (zone_key, record_name, record_count, record_data, block_expiration_time, signature" 207 "INSERT INTO ns096blocks (query, block, expiration_time) VALUES "
171 ", zone_delegation, zone_hash, record_name_hash, rvalue) VALUES " 208 "($1, $2, $3)", 3)) ||
172 "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", 10)) ||
173 (GNUNET_OK != 209 (GNUNET_OK !=
174 GNUNET_POSTGRES_prepare (plugin->dbh, 210 GNUNET_POSTGRES_prepare (plugin->dbh,
175 "remove_records", 211 "expire_blocks",
176 "DELETE FROM ns091records WHERE zone_hash=$1 AND record_name_hash=$2", 2)) || 212 "DELETE FROM ns096blocks WHERE expiration_time<$1", 1)) ||
177 (GNUNET_OK != 213 (GNUNET_OK !=
178 GNUNET_POSTGRES_prepare (plugin->dbh, 214 GNUNET_POSTGRES_prepare (plugin->dbh,
179 "iterate_records", 215 "delete_block",
180 "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" 216 "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2)) ||
181 " FROM ns091records WHERE zone_hash=$1 AND record_name_hash=$2 ORDER BY rvalue LIMIT 1 OFFSET $3", 3)) ||
182 (GNUNET_OK != 217 (GNUNET_OK !=
183 GNUNET_POSTGRES_prepare (plugin->dbh, 218 GNUNET_POSTGRES_prepare (plugin->dbh,
184 "iterate_by_zone", 219 "lookup_block",
185 "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" 220 "SELECT block FROM ns096blocks WHERE query=$1"
186 " FROM ns091records WHERE zone_hash=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || 221 " ORDER BY expiration_time DESC LIMIT 1", 1)) ||
187 (GNUNET_OK != 222 (GNUNET_OK !=
188 GNUNET_POSTGRES_prepare (plugin->dbh, 223 GNUNET_POSTGRES_prepare (plugin->dbh,
189 "iterate_by_name", 224 "store_records",
190 "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" 225 "INSERT INTO ns097records (zone_private_key, pkey, value, record_count, record_data, label) VALUES "
191 " FROM ns091records WHERE record_name_hash=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || 226 "($1, $2, $3, $4, $5, $6)", 6)) ||
192 (GNUNET_OK != 227 (GNUNET_OK !=
193 GNUNET_POSTGRES_prepare (plugin->dbh, 228 GNUNET_POSTGRES_prepare (plugin->dbh,
194 "iterate_all", 229 "delete_records",
195 "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" 230 "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) ||
196 " FROM ns091records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) ||
197 (GNUNET_OK != 231 (GNUNET_OK !=
198 GNUNET_POSTGRES_prepare (plugin->dbh, 232 GNUNET_POSTGRES_prepare (plugin->dbh,
199 "zone_to_name", 233 "zone_to_name",
200 "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" 234 "SELECT record_count,record_data,label FROM ns097records"
201 " FROM ns091records WHERE zone_hash=$1 AND zone_delegation=$2", 2)) || 235 " WHERE zone_private_key=$1 AND pkey=$2", 2)) ||
236 (GNUNET_OK !=
237 GNUNET_POSTGRES_prepare (plugin->dbh,
238 "iterate_zone",
239 "SELECT record_count, record_data, label FROM ns097records"
240 " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) ||
202 (GNUNET_OK != 241 (GNUNET_OK !=
203 GNUNET_POSTGRES_prepare (plugin->dbh, 242 GNUNET_POSTGRES_prepare (plugin->dbh,
204 "delete_zone", 243 "iterate_all_zones",
205 "DELETE FROM ns091records WHERE zone_hash=$1", 1))) 244 "SELECT record_count,record_data,label,zone_private_key"
245 " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)))
206 { 246 {
207 PQfinish (plugin->dbh); 247 PQfinish (plugin->dbh);
208 plugin->dbh = NULL; 248 plugin->dbh = NULL;
@@ -211,99 +251,236 @@ database_setup (struct Plugin *plugin)
211 return GNUNET_OK; 251 return GNUNET_OK;
212} 252}
213 253
214#if 0
215 254
216TODO: removed 255/**
256 * Removes any expired block.
257 *
258 * @param plugin the plugin
259 */
260static void
261namestore_postgres_expire_blocks (struct Plugin *plugin)
262{
263 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
264 struct GNUNET_TIME_AbsoluteNBO now_be = GNUNET_TIME_absolute_hton (now);
265 const char *paramValues[] = {
266 (const char *) &now_be
267 };
268 int paramLengths[] = {
269 sizeof (now_be)
270 };
271 const int paramFormats[] = { 1 };
272 PGresult *res;
273
274 res =
275 PQexecPrepared (plugin->dbh, "expire_blocks", 1,
276 paramValues, paramLengths, paramFormats, 1);
277 if (GNUNET_OK !=
278 GNUNET_POSTGRES_check_result (plugin->dbh,
279 res,
280 PGRES_COMMAND_OK,
281 "PQexecPrepared",
282 "expire_blocks"))
283 return;
284 PQclear (res);
285}
286
287
288/**
289 * Delete older block in the datastore.
290 *
291 * @param the plugin
292 * @param query query for the block
293 * @param expiration time how old does the block have to be for deletion
294 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
295 */
296static void
297delete_old_block (struct Plugin *plugin,
298 const struct GNUNET_HashCode *query,
299 struct GNUNET_TIME_AbsoluteNBO expiration_time)
300{
301 const char *paramValues[] = {
302 (const char *) query,
303 (const char *) &expiration_time
304 };
305 int paramLengths[] = {
306 sizeof (*query),
307 sizeof (expiration_time)
308 };
309 const int paramFormats[] = { 1, 1 };
310 PGresult *res;
311
312 res =
313 PQexecPrepared (plugin->dbh, "delete_block", 2,
314 paramValues, paramLengths, paramFormats, 1);
315 if (GNUNET_OK !=
316 GNUNET_POSTGRES_check_result (plugin->dbh,
317 res,
318 PGRES_COMMAND_OK,
319 "PQexecPrepared",
320 "delete_block"))
321 return;
322 PQclear (res);
323}
324
217 325
218/** 326/**
219 * Removes any existing record in the given zone with the same name. 327 * Cache a block in the datastore.
220 * 328 *
221 * @param cls closure (internal context for the plugin) 329 * @param cls closure (internal context for the plugin)
222 * @param zone hash of the public key of the zone 330 * @param block block to cache
223 * @param name name to remove (at most 255 characters long) 331 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
224 * @return GNUNET_OK on success
225 */ 332 */
226static int 333static int
227namestore_postgres_remove_records (void *cls, 334namestore_postgres_cache_block (void *cls,
228 const struct GNUNET_CRYPTO_ShortHashCode *zone, 335 const struct GNUNET_NAMESTORE_Block *block)
229 const char *name)
230{ 336{
231 struct Plugin *plugin = cls; 337 struct Plugin *plugin = cls;
232 PGresult *ret; 338 struct GNUNET_HashCode query;
233 struct GNUNET_CRYPTO_ShortHashCode nh; 339 size_t block_size = ntohl (block->purpose.size) +
340 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) +
341 sizeof (struct GNUNET_CRYPTO_EccSignature);
234 const char *paramValues[] = { 342 const char *paramValues[] = {
235 (const char *) zone, 343 (const char *) &query,
236 (const char *) &nh 344 (const char *) block,
345 (const char *) &block->expiration_time
237 }; 346 };
238 int paramLengths[] = { 347 int paramLengths[] = {
239 sizeof (struct GNUNET_CRYPTO_ShortHashCode), 348 sizeof (query),
240 sizeof (struct GNUNET_CRYPTO_ShortHashCode) 349 (int) block_size,
350 sizeof (block->expiration_time)
241 }; 351 };
242 const int paramFormats[] = { 1, 1 }; 352 const int paramFormats[] = { 1, 1, 1 };
243 size_t name_len; 353 PGresult *res;
244 354
245 name_len = strlen (name); 355 namestore_postgres_expire_blocks (plugin);
246 GNUNET_CRYPTO_short_hash (name, name_len, &nh); 356 GNUNET_CRYPTO_hash (&block->derived_key,
247 ret = 357 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
248 PQexecPrepared (plugin->dbh, "remove_records", 2, paramValues, paramLengths, 358 &query);
249 paramFormats, 1); 359 if (block_size > 64 * 65536)
360 {
361 GNUNET_break (0);
362 return GNUNET_SYSERR;
363 }
364 delete_old_block (plugin, &query, block->expiration_time);
365
366 res =
367 PQexecPrepared (plugin->dbh, "cache_block", 3,
368 paramValues, paramLengths, paramFormats, 1);
250 if (GNUNET_OK != 369 if (GNUNET_OK !=
251 GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "remove_records")) 370 GNUNET_POSTGRES_check_result (plugin->dbh,
371 res,
372 PGRES_COMMAND_OK,
373 "PQexecPrepared",
374 "cache_block"))
252 return GNUNET_SYSERR; 375 return GNUNET_SYSERR;
253 PQclear (ret); 376 PQclear (res);
254 return GNUNET_OK; 377 return GNUNET_OK;
255} 378}
256 379
257 380
381/**
382 * Get the block for a particular zone and label in the
383 * datastore. Will return at most one result to the iterator.
384 *
385 * @param cls closure (internal context for the plugin)
386 * @param query hash of public key derived from the zone and the label
387 * @param iter function to call with the result
388 * @param iter_cls closure for @a iter
389 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
390 */
391static int
392namestore_postgres_lookup_block (void *cls,
393 const struct GNUNET_HashCode *query,
394 GNUNET_NAMESTORE_BlockCallback iter, void *iter_cls)
395{
396 struct Plugin *plugin = cls;
397 const char *paramValues[] = {
398 (const char *) query
399 };
400 int paramLengths[] = {
401 sizeof (*query)
402 };
403 const int paramFormats[] = { 1 };
404 PGresult *res;
405 unsigned int cnt;
406 size_t bsize;
407 const struct GNUNET_NAMESTORE_Block *block;
408
409 res = PQexecPrepared (plugin->dbh,
410 "lookup_block", 1,
411 paramValues, paramLengths, paramFormats,
412 1);
413 if (GNUNET_OK !=
414 GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK,
415 "PQexecPrepared",
416 "lookup_block"))
417 {
418 LOG (GNUNET_ERROR_TYPE_DEBUG,
419 "Failing lookup (postgres error)\n");
420 return GNUNET_SYSERR;
421 }
422 if (0 == (cnt = PQntuples (res)))
423 {
424 /* no result */
425 LOG (GNUNET_ERROR_TYPE_DEBUG,
426 "Ending iteration (no more results)\n");
427 PQclear (res);
428 return GNUNET_NO;
429 }
430 GNUNET_assert (1 == cnt);
431 GNUNET_assert (1 != PQnfields (res));
432 bsize = PQgetlength (res, 0, 0);
433 block = (const struct GNUNET_NAMESTORE_Block *) PQgetvalue (res, 0, 0);
434 if ( (bsize < sizeof (*block)) ||
435 (bsize != ntohl (block->purpose.size) +
436 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) +
437 sizeof (struct GNUNET_CRYPTO_EccSignature)) )
438 {
439 GNUNET_break (0);
440 LOG (GNUNET_ERROR_TYPE_DEBUG,
441 "Failing lookup (corrupt block)\n");
442 PQclear (res);
443 return GNUNET_SYSERR;
444 }
445 iter (iter_cls, block);
446 PQclear (res);
447 return GNUNET_OK;
448}
449
258 450
259/** 451/**
260 * Store a record in the datastore. Removes any existing record in the 452 * Store a record in the datastore. Removes any existing record in the
261 * same zone with the same name. 453 * same zone with the same name.
262 * 454 *
263 * @param cls closure (internal context for the plugin) 455 * @param cls closure (internal context for the plugin)
264 * @param zone_key public key of the zone 456 * @param zone_key private key of the zone
265 * @param expire when does the corresponding block in the DHT expire (until 457 * @param label name that is being mapped (at most 255 characters long)
266 * when should we never do a DHT lookup for the same name again)? 458 * @param rd_count number of entries in @a rd array
267 * @param name name that is being mapped (at most 255 characters long)
268 * @param rd_count number of entries in 'rd' array
269 * @param rd array of records with data to store 459 * @param rd array of records with data to store
270 * @param signature signature of the record block, NULL if signature is unavailable (i.e. 460 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
271 * because the user queried for a particular record type only)
272 * @return GNUNET_OK on success, else GNUNET_SYSERR
273 */ 461 */
274static int 462static int
275namestore_postgres_put_records (void *cls, 463namestore_postgres_store_records (void *cls,
276 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key, 464 const struct GNUNET_CRYPTO_EccPrivateKey *zone_key,
277 struct GNUNET_TIME_Absolute expire, 465 const char *label,
278 const char *name, 466 unsigned int rd_count,
279 unsigned int rd_count, 467 const struct GNUNET_NAMESTORE_RecordData *rd)
280 const struct GNUNET_NAMESTORE_RecordData *rd,
281 const struct GNUNET_CRYPTO_EccSignature *signature)
282{ 468{
283 struct Plugin *plugin = cls; 469 struct Plugin *plugin = cls;
284 PGresult *ret; 470 struct GNUNET_CRYPTO_EccPublicSignKey pkey;
285 struct GNUNET_CRYPTO_ShortHashCode zone;
286 struct GNUNET_CRYPTO_ShortHashCode zone_delegation;
287 struct GNUNET_CRYPTO_ShortHashCode nh;
288 size_t name_len;
289 uint64_t rvalue; 471 uint64_t rvalue;
472 uint32_t rd_count_nbo = htonl ((uint32_t) rd_count);
290 size_t data_size; 473 size_t data_size;
291 unsigned int i; 474 unsigned int i;
292 475
293 GNUNET_CRYPTO_short_hash (zone_key, 476 memset (&pkey, 0, sizeof (pkey));
294 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
295 &zone);
296 (void) namestore_postgres_remove_records (plugin, &zone, name);
297 name_len = strlen (name);
298 GNUNET_CRYPTO_short_hash (name, name_len, &nh);
299 memset (&zone_delegation, 0, sizeof (zone_delegation));
300 for (i=0;i<rd_count;i++) 477 for (i=0;i<rd_count;i++)
301 if (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PKEY) 478 if (GNUNET_NAMESTORE_TYPE_PKEY == rd[i].record_type)
302 { 479 {
303 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_ShortHashCode) == rd[i].data_size); 480 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) == rd[i].data_size);
304 memcpy (&zone_delegation, 481 memcpy (&pkey,
305 rd[i].data, 482 rd[i].data,
306 sizeof (struct GNUNET_CRYPTO_ShortHashCode)); 483 rd[i].data_size);
307 break; 484 break;
308 } 485 }
309 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); 486 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
@@ -315,34 +492,24 @@ namestore_postgres_put_records (void *cls,
315 } 492 }
316 { 493 {
317 char data[data_size]; 494 char data[data_size];
318 uint64_t expire_be = GNUNET_htonll (expire.abs_value_us);
319 uint64_t rvalue_be = GNUNET_htonll (rvalue);
320 uint32_t rd_count_be = htonl ((uint32_t) rd_count);
321 const char *paramValues[] = { 495 const char *paramValues[] = {
322 (const char *) zone_key, 496 (const char *) zone_key,
323 (const char *) name, 497 (const char *) &pkey,
324 (const char *) &rd_count_be, 498 (const char *) &rvalue,
499 (const char *) &rd_count_nbo,
325 (const char *) data, 500 (const char *) data,
326 (const char *) &expire_be, 501 label
327 (const char *) signature,
328 (const char *) &zone_delegation,
329 (const char *) &zone,
330 (const char *) &nh,
331 (const char *) &rvalue_be
332 }; 502 };
333 int paramLengths[] = { 503 int paramLengths[] = {
334 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), 504 sizeof (*zone_key),
335 name_len, 505 sizeof (pkey),
336 sizeof (uint32_t), 506 sizeof (rvalue),
507 sizeof (rd_count_nbo),
337 data_size, 508 data_size,
338 sizeof (uint64_t), 509 strlen (label)
339 sizeof (struct GNUNET_CRYPTO_EccSignature),
340 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
341 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
342 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
343 sizeof (uint64_t)
344 }; 510 };
345 const int paramFormats[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 511 const int paramFormats[] = { 1, 1, 1, 1, 1, 1 };
512 PGresult *res;
346 513
347 if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd, 514 if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd,
348 data_size, data)) 515 data_size, data))
@@ -350,89 +517,89 @@ namestore_postgres_put_records (void *cls,
350 GNUNET_break (0); 517 GNUNET_break (0);
351 return GNUNET_SYSERR; 518 return GNUNET_SYSERR;
352 } 519 }
353 ret = 520
354 PQexecPrepared (plugin->dbh, "put_records", 10, paramValues, paramLengths, 521 res =
355 paramFormats, 1); 522 PQexecPrepared (plugin->dbh, "store_records", 6,
523 paramValues, paramLengths, paramFormats, 1);
356 if (GNUNET_OK != 524 if (GNUNET_OK !=
357 GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put_records")) 525 GNUNET_POSTGRES_check_result (plugin->dbh,
526 res,
527 PGRES_COMMAND_OK,
528 "PQexecPrepared",
529 "store_records"))
358 return GNUNET_SYSERR; 530 return GNUNET_SYSERR;
359 PQclear (ret); 531 PQclear (res);
532 return GNUNET_OK;
360 } 533 }
361 return GNUNET_OK;
362} 534}
363#endif
364 535
365#if 0 536
366/** 537/**
367 * The given 'postgres' result was obtained from the database. 538 * A statement has been run. We should evaluate the result, and if possible
368 * Parse the record and give it to the iterator. 539 * call the given @a iter with the result.
369 * 540 *
370 * @param plugin plugin context 541 * @param plugin plugin context
371 * @param stmt_name name of the prepared statement that was executed 542 * @param res result from the statement that was run (to be cleaned up)
372 * @param res result from postgres to interpret (and then clean up) 543 * @param zone_key private key of the zone, could be NULL, in which case we should
544 * get the zone from @a res
373 * @param iter iterator to call with the result 545 * @param iter iterator to call with the result
374 * @param iter_cls closure for 'iter' 546 * @param iter_cls closure for @a iter
375 * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error 547 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
376 * 'iter' will have been called unless the return value is 'GNUNET_SYSERR'
377 */ 548 */
378static int 549static int
379get_record_and_call_iterator (struct Plugin *plugin, 550get_record_and_call_iterator (struct Plugin *plugin,
380 const char *stmt_name, 551 PGresult *res,
381 PGresult *res, 552 const struct GNUNET_CRYPTO_EccPrivateKey *zone_key,
382 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 553 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
383{ 554{
384 unsigned int record_count;
385 size_t data_size;
386 /* const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key; */
387 const struct GNUNET_CRYPTO_EccPrivateKey *zone_key;
388 /* const struct GNUNET_CRYPTO_EccSignature *sig; */
389 /* struct GNUNET_TIME_Absolute expiration; */
390 const char *data; 555 const char *data;
391 const char *name; 556 size_t data_size;
557 uint32_t record_count;
558 const char *label;
559 size_t label_len;
392 unsigned int cnt; 560 unsigned int cnt;
393 size_t name_len;
394 561
395 if (GNUNET_OK != 562 if (GNUNET_OK !=
396 GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", 563 GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK,
397 stmt_name)) 564 "PQexecPrepared",
565 "iteration"))
398 { 566 {
399 LOG (GNUNET_ERROR_TYPE_DEBUG, 567 LOG (GNUNET_ERROR_TYPE_DEBUG,
400 "Ending iteration (postgres error)\n"); 568 "Failing lookup (postgres error)\n");
401 return GNUNET_SYSERR; 569 return GNUNET_SYSERR;
402 } 570 }
403
404 if (0 == (cnt = PQntuples (res))) 571 if (0 == (cnt = PQntuples (res)))
405 { 572 {
406 /* no result */ 573 /* no result */
407 LOG (GNUNET_ERROR_TYPE_DEBUG, 574 LOG (GNUNET_ERROR_TYPE_DEBUG,
408 "Ending iteration (no more results)\n"); 575 "Ending iteration (no more results)\n");
409 PQclear (res); 576 PQclear (res);
410
411 iter (iter_cls, NULL, NULL, 0, NULL);
412 return GNUNET_NO; 577 return GNUNET_NO;
413 } 578 }
414 GNUNET_assert (1 == cnt); 579 GNUNET_assert (1 == cnt);
415 if ((6 != PQnfields (res)) || 580 GNUNET_assert (3 + ((NULL == zone_key) ? 1 : 0) == PQnfields (res));
416 (sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) != PQgetlength (res, 0, 0)) || 581 if (NULL == zone_key)
417 (sizeof (uint32_t) != PQfsize (res, 2)) || 582 {
418 (sizeof (uint64_t) != PQfsize (res, 4)) || 583 if (sizeof (struct GNUNET_CRYPTO_EccPrivateKey) != PQgetlength (res, 0, 3))
419 (sizeof (struct GNUNET_CRYPTO_EccSignature) != PQgetlength (res, 0, 5))) 584 {
585 GNUNET_break (0);
586 PQclear (res);
587 return GNUNET_SYSERR;
588 }
589 zone_key = (const struct GNUNET_CRYPTO_EccPrivateKey *) PQgetvalue (res, 0, 3);
590 }
591 if (sizeof (uint32_t) != PQfsize (res, 0))
420 { 592 {
421 GNUNET_break (0); 593 GNUNET_break (0);
422 PQclear (res); 594 PQclear (res);
423 return GNUNET_SYSERR; 595 return GNUNET_SYSERR;
424 } 596 }
425 zone_key = (const struct GNUNET_CRYPTO_EccPrivateKey *) PQgetvalue (res, 0, 0); 597
426 /* zone_key = (const struct GNUNET_CRYPTO_EccPublicSignKey *) PQgetvalue (res, 0, 0); */ 598 record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0));
427 name = PQgetvalue (res, 0, 1); 599 data = PQgetvalue (res, 0, 1);
428 name_len = PQgetlength (res, 0, 1); 600 data_size = PQgetlength (res, 0, 1);
429 record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 2)); 601 label = PQgetvalue (res, 0, 2);
430 data_size = PQgetlength (res, 0, 3); 602 label_len = PQgetlength (res, 0, 1);
431 data = PQgetvalue (res, 0, 3);
432 /*
433 expiration.abs_value_us =
434 GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, 0, 4));
435 sig = (const struct GNUNET_CRYPTO_EccSignature*) PQgetvalue (res, 0, 5); */
436 if (record_count > 64 * 1024) 603 if (record_count > 64 * 1024)
437 { 604 {
438 /* sanity check, don't stack allocate far too much just 605 /* sanity check, don't stack allocate far too much just
@@ -443,10 +610,10 @@ get_record_and_call_iterator (struct Plugin *plugin,
443 } 610 }
444 { 611 {
445 struct GNUNET_NAMESTORE_RecordData rd[record_count]; 612 struct GNUNET_NAMESTORE_RecordData rd[record_count];
446 char buf[name_len + 1]; 613 char buf[label_len + 1];
447 614
448 memcpy (buf, name, name_len); 615 memcpy (buf, label, label_len);
449 buf[name_len] = '\0'; 616 buf[label_len] = '\0';
450 if (GNUNET_OK != 617 if (GNUNET_OK !=
451 GNUNET_NAMESTORE_records_deserialize (data_size, data, 618 GNUNET_NAMESTORE_records_deserialize (data_size, data,
452 record_count, rd)) 619 record_count, rd))
@@ -460,7 +627,7 @@ get_record_and_call_iterator (struct Plugin *plugin,
460 PQclear (res); 627 PQclear (res);
461 return GNUNET_OK; 628 return GNUNET_OK;
462} 629}
463#endif 630
464 631
465/** 632/**
466 * Iterate over the results for a particular key and zone in the 633 * Iterate over the results for a particular key and zone in the
@@ -470,81 +637,60 @@ get_record_and_call_iterator (struct Plugin *plugin,
470 * @param zone hash of public key of the zone, NULL to iterate over all zones 637 * @param zone hash of public key of the zone, NULL to iterate over all zones
471 * @param offset offset in the list of all matching records 638 * @param offset offset in the list of all matching records
472 * @param iter function to call with the result 639 * @param iter function to call with the result
473 * @param iter_cls closure for iter 640 * @param iter_cls closure for @a iter
474 * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error 641 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
475 * 'iter' will have been called unless the return value is 'GNUNET_SYSERR'
476 */ 642 */
477static int 643static int
478namestore_postgres_iterate_records (void *cls, 644namestore_postgres_iterate_records (void *cls,
479 const struct GNUNET_CRYPTO_EccPrivateKey *zone, 645 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
480 uint64_t offset, 646 uint64_t offset,
481 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 647 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
482{ 648{
483#if 0
484 struct Plugin *plugin = cls; 649 struct Plugin *plugin = cls;
485 const char *stmt_name;
486 struct GNUNET_CRYPTO_ShortHashCode name_hase;
487 uint64_t offset_be = GNUNET_htonll (offset); 650 uint64_t offset_be = GNUNET_htonll (offset);
488 const char *paramValues[] = {
489 (const char *) zone,
490 (const char *) &name_hase,
491 (const char *) &offset_be,
492 (const char *) zone,
493 (const char *) &offset_be,
494 };
495 int paramLengths[] = {
496 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
497 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
498 sizeof (uint64_t),
499 sizeof (struct GNUNET_CRYPTO_ShortHashCode),
500 sizeof (uint64_t)
501 };
502 const int paramFormats[] = { 1, 1, 1, 1, 1 };
503 unsigned int num_params;
504 unsigned int first_param;
505 PGresult *res;
506 651
507 if (NULL == zone) 652 if (NULL == zone)
508 if (NULL == name) 653 {
509 { 654 const char *paramValues[] = {
510 stmt_name = "iterate_all"; 655 (const char *) &offset_be
511 num_params = 1; 656 };
512 first_param = 2; 657 int paramLengths[] = {
513 } 658 sizeof (offset_be)
514 else 659 };
515 { 660 const int paramFormats[] = { 1 };
516 /* TODO Adapt to new API 661 PGresult *res;
517 * GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); 662
518 */ 663 res = PQexecPrepared (plugin->dbh,
519 stmt_name = "iterate_by_name"; 664 "iterate_all_zones", 1,
520 num_params = 2; 665 paramValues, paramLengths, paramFormats,
521 first_param = 1; 666 1);
522 } 667 return get_record_and_call_iterator (plugin,
668 res,
669 NULL,
670 iter, iter_cls);
671 }
523 else 672 else
524 if (NULL == name) 673 {
525 { 674 const char *paramValues[] = {
526 stmt_name = "iterate_by_zone"; 675 (const char *) zone,
527 num_params = 2; 676 (const char *) &offset_be
528 first_param = 3; 677 };
529 } 678 int paramLengths[] = {
530 else 679 sizeof (*zone),
531 { 680 sizeof (offset_be)
532 /* TODO Adapt to new API 681 };
533 * GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); 682 const int paramFormats[] = { 1, 1 };
534 */ 683 PGresult *res;
535 stmt_name = "iterate_records"; 684
536 num_params = 3; 685 res = PQexecPrepared (plugin->dbh,
537 first_param = 0; 686 "iterate_zone", 2,
538 } 687 paramValues, paramLengths, paramFormats,
539 res = 688 1);
540 PQexecPrepared (plugin->dbh, stmt_name, num_params, 689 return get_record_and_call_iterator (plugin,
541 &paramValues[first_param], 690 res,
542 &paramLengths[first_param], 691 zone,
543 &paramFormats[first_param], 1); 692 iter, iter_cls);
544 return get_record_and_call_iterator (plugin, stmt_name, res, iter, iter_cls); 693 }
545#endif
546 GNUNET_break (0);
547 return GNUNET_SYSERR;
548} 694}
549 695
550 696
@@ -553,137 +699,38 @@ namestore_postgres_iterate_records (void *cls,
553 * Returns at most one result to the iterator. 699 * Returns at most one result to the iterator.
554 * 700 *
555 * @param cls closure (internal context for the plugin) 701 * @param cls closure (internal context for the plugin)
556 * @param zone hash of public key of the zone to look up in, never NULL 702 * @param zone private key of the zone to look up in, never NULL
557 * @param value_zone hash of the public key of the target zone (value), never NULL 703 * @param value_zone public key of the target zone (value), never NULL
558 * @param iter function to call with the result 704 * @param iter function to call with the result
559 * @param iter_cls closure for iter 705 * @param iter_cls closure for @a iter
560 * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error 706 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
561 * 'iter' will have been called unless the return value is 'GNUNET_SYSERR'
562 */ 707 */
563static int 708static int
564namestore_postgres_zone_to_name (void *cls, 709namestore_postgres_zone_to_name (void *cls,
565 const struct GNUNET_CRYPTO_EccPrivateKey *zone, 710 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
566 const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone, 711 const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone,
567 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 712 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
568{ 713{
569#if 0
570 struct Plugin *plugin = cls; 714 struct Plugin *plugin = cls;
571 const char *paramValues[] = { 715 const char *paramValues[] = {
572 (const char *) zone, 716 (const char *) zone,
573 (const char *) value_zone 717 (const char *) value_zone
574 }; 718 };
575 int paramLengths[] = { 719 int paramLengths[] = {
576 sizeof (struct GNUNET_CRYPTO_ShortHashCode), 720 sizeof (*zone),
577 sizeof (struct GNUNET_CRYPTO_ShortHashCode) 721 sizeof (*value_zone)
578 }; 722 };
579 const int paramFormats[] = { 1, 1 }; 723 const int paramFormats[] = { 1, 1 };
580 PGresult *res; 724 PGresult *res;
581 725
582 res = 726 res = PQexecPrepared (plugin->dbh,
583 PQexecPrepared (plugin->dbh, "zone_to_name", 2, 727 "zone_to_name", 2,
584 paramValues, paramLengths, paramFormats, 1); 728 paramValues, paramLengths, paramFormats,
585 return get_record_and_call_iterator (plugin, "zone_to_name", res, iter, iter_cls); 729 1);
586#endif 730 return get_record_and_call_iterator (plugin,
587 GNUNET_break (0); 731 res,
588 return GNUNET_SYSERR; 732 zone,
589} 733 iter, iter_cls);
590
591#if 0
592/**
593 * Delete an entire zone (all records). Not used in normal operation.
594 *
595 * @param cls closure (internal context for the plugin)
596 * @param zone zone to delete
597 */
598static void
599namestore_postgres_delete_zone (void *cls,
600 const struct GNUNET_CRYPTO_ShortHashCode *zone)
601{
602 struct Plugin *plugin = cls;
603 PGresult *ret;
604 const char *paramValues[] = {
605 (const char *) zone,
606 };
607
608 int paramLengths[] = {
609 sizeof (struct GNUNET_CRYPTO_ShortHashCode)
610 };
611 const int paramFormats[] = { 1 };
612
613 ret =
614 PQexecPrepared (plugin->dbh, "delete_zone", 1, paramValues, paramLengths,
615 paramFormats, 1);
616 if (GNUNET_OK !=
617 GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delete_zone"))
618 {
619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
620 "Deleting zone failed!\n");
621 return;
622 }
623 PQclear (ret);
624}
625#endif
626
627/**
628 * Cache a block in the datastore.
629 *
630 * @param cls closure (internal context for the plugin)
631 * @param block block to cache
632 * @return GNUNET_OK on success, else GNUNET_SYSERR
633 */
634static int
635namestore_postgres_cache_block (void *cls,
636 const struct GNUNET_NAMESTORE_Block *block)
637{
638 // struct Plugin *plugin = cls;
639 GNUNET_break (0);
640 /* To be implemented */
641 return GNUNET_OK;
642}
643
644/**
645 * Get the block for a particular zone and label in the
646 * datastore. Will return at most one result to the iterator.
647 *
648 * @param cls closure (internal context for the plugin)
649 * @param query hash of public key derived from the zone and the label
650 * @param iter function to call with the result
651 * @param iter_cls closure for iter
652 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
653 */
654static int
655namestore_postgres_lookup_block (void *cls,
656 const struct GNUNET_HashCode *query,
657 GNUNET_NAMESTORE_BlockCallback iter, void *iter_cls)
658{
659 // struct Plugin *plugin = cls;
660 GNUNET_break (0);
661 /* To be implemented */
662 return GNUNET_OK;
663}
664
665/**
666 * Store a record in the datastore. Removes any existing record in the
667 * same zone with the same name.
668 *
669 * @param cls closure (internal context for the plugin)
670 * @param zone_key private key of the zone
671 * @param label name that is being mapped (at most 255 characters long)
672 * @param rd_count number of entries in 'rd' array
673 * @param rd array of records with data to store
674 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
675 */
676static int
677namestore_postgres_store_records (void *cls,
678 const struct GNUNET_CRYPTO_EccPrivateKey *zone_key,
679 const char *label,
680 unsigned int rd_count,
681 const struct GNUNET_NAMESTORE_RecordData *rd)
682{
683 // struct Plugin *plugin = cls;
684 GNUNET_break (0);
685 /* To be implemented */
686 return GNUNET_OK;
687} 734}
688 735
689 736
@@ -723,16 +770,13 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
723 database_shutdown (&plugin); 770 database_shutdown (&plugin);
724 return NULL; 771 return NULL;
725 } 772 }
726 api = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_PluginFunctions)); 773 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
727 api->cls = &plugin; 774 api->cls = &plugin;
728 /* api->put_records = &namestore_postgres_put_records; */
729 /* api->remove_records = &namestore_postgres_remove_records; */
730 api->cache_block = &namestore_postgres_cache_block; 775 api->cache_block = &namestore_postgres_cache_block;
731 api->lookup_block = &namestore_postgres_lookup_block; 776 api->lookup_block = &namestore_postgres_lookup_block;
732 api->store_records = &namestore_postgres_store_records; 777 api->store_records = &namestore_postgres_store_records;
733 api->iterate_records = &namestore_postgres_iterate_records; 778 api->iterate_records = &namestore_postgres_iterate_records;
734 api->zone_to_name = &namestore_postgres_zone_to_name; 779 api->zone_to_name = &namestore_postgres_zone_to_name;
735 /* api->delete_zone = &namestore_postgres_delete_zone; */
736 LOG (GNUNET_ERROR_TYPE_INFO, 780 LOG (GNUNET_ERROR_TYPE_INFO,
737 _("Postgres database running\n")); 781 _("Postgres database running\n"));
738 return api; 782 return api;