aboutsummaryrefslogtreecommitdiff
path: root/src/datacache
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-06-02 23:12:31 +0200
committerChristian Grothoff <christian@grothoff.org>2017-06-02 23:12:31 +0200
commit0266efed64df149fd11a73e575be18cf03f36d25 (patch)
treeedcdaac70ee6b6f018f54127f5523ecfc0e9c17c /src/datacache
parent70de9f42a397dc5f862355c81a16cb297ad2ee00 (diff)
downloadgnunet-0266efed64df149fd11a73e575be18cf03f36d25.tar.gz
gnunet-0266efed64df149fd11a73e575be18cf03f36d25.zip
more work on pq-ification of datacache
Diffstat (limited to 'src/datacache')
-rw-r--r--src/datacache/Makefile.am1
-rw-r--r--src/datacache/plugin_datacache_postgres.c463
2 files changed, 221 insertions, 243 deletions
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am
index 670a64926..602b1d437 100644
--- a/src/datacache/Makefile.am
+++ b/src/datacache/Makefile.am
@@ -72,6 +72,7 @@ libgnunet_plugin_datacache_postgres_la_SOURCES = \
72 plugin_datacache_postgres.c 72 plugin_datacache_postgres.c
73libgnunet_plugin_datacache_postgres_la_LIBADD = \ 73libgnunet_plugin_datacache_postgres_la_LIBADD = \
74 $(top_builddir)/src/postgres/libgnunetpostgres.la \ 74 $(top_builddir)/src/postgres/libgnunetpostgres.la \
75 $(top_builddir)/src/pq/libgnunetpq.la \
75 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 76 $(top_builddir)/src/statistics/libgnunetstatistics.la \
76 $(top_builddir)/src/util/libgnunetutil.la \ 77 $(top_builddir)/src/util/libgnunetutil.la \
77 $(GN_PLUGIN_LDFLAGS) -lpq 78 $(GN_PLUGIN_LDFLAGS) -lpq
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index 8f5cdbde1..e69f2b2c6 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -26,6 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_postgres_lib.h" 28#include "gnunet_postgres_lib.h"
29#include "gnunet_pq_lib.h"
29#include "gnunet_datacache_plugin.h" 30#include "gnunet_datacache_plugin.h"
30 31
31#define LOG(kind,...) GNUNET_log_from (kind, "datacache-postgres", __VA_ARGS__) 32#define LOG(kind,...) GNUNET_log_from (kind, "datacache-postgres", __VA_ARGS__)
@@ -66,115 +67,67 @@ struct Plugin
66static int 67static int
67init_connection (struct Plugin *plugin) 68init_connection (struct Plugin *plugin)
68{ 69{
69 PGresult *ret; 70 struct GNUNET_PQ_ExecuteStatement es[] = {
71 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn090dc ("
72 " type INTEGER NOT NULL DEFAULT 0,"
73 " discard_time BIGINT NOT NULL DEFAULT 0,"
74 " key BYTEA NOT NULL DEFAULT '',"
75 " value BYTEA NOT NULL DEFAULT '',"
76 " path BYTEA DEFAULT '')"
77 "WITH OIDS"),
78 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_key ON gn090dc (key)"),
79 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_dt ON gn090dc (discard_time)"),
80 GNUNET_PQ_make_execute ("ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"),
81 GNUNET_PQ_make_execute ("ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"),
82 GNUNET_PQ_EXECUTE_STATEMENT_END
83 };
84 struct GNUNET_PQ_PreparedStatement ps[] = {
85 GNUNET_PQ_make_prepare ("getkt",
86 "SELECT discard_time,type,value,path FROM gn090dc "
87 "WHERE key=$1 AND type=$2",
88 2),
89 GNUNET_PQ_make_prepare ("getk",
90 "SELECT discard_time,type,value,path FROM gn090dc "
91 "WHERE key=$1",
92 1),
93 GNUNET_PQ_make_prepare ("getm",
94 "SELECT length(value) AS len,oid,key FROM gn090dc "
95 "ORDER BY discard_time ASC LIMIT 1",
96 0),
97 GNUNET_PQ_make_prepare ("get_random",
98 "SELECT discard_time,type,value,path,key FROM gn090dc "
99 "ORDER BY key ASC LIMIT 1 OFFSET $1",
100 1),
101 GNUNET_PQ_make_prepare ("get_closest",
102 "SELECT discard_time,type,value,path,key FROM gn090dc "
103 "WHERE key>=$1 ORDER BY key ASC LIMIT $2",
104 1),
105 GNUNET_PQ_make_prepare ("delrow",
106 "DELETE FROM gn090dc WHERE oid=$1",
107 1),
108 GNUNET_PQ_make_prepare ("put",
109 "INSERT INTO gn090dc (type, discard_time, key, value, path) "
110 "VALUES ($1, $2, $3, $4, $5)",
111 5),
112 GNUNET_PQ_PREPARED_STATEMENT_END
113 };
70 114
71 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->env->cfg, 115 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->env->cfg,
72 "datacache-postgres"); 116 "datacache-postgres");
73 if (NULL == plugin->dbh) 117 if (NULL == plugin->dbh)
74 return GNUNET_SYSERR; 118 return GNUNET_SYSERR;
75 ret =
76 PQexec (plugin->dbh,
77 "CREATE TEMPORARY TABLE IF NOT EXISTS gn090dc ("
78 " type INTEGER NOT NULL DEFAULT 0,"
79 " discard_time BIGINT NOT NULL DEFAULT 0,"
80 " key BYTEA NOT NULL DEFAULT '',"
81 " value BYTEA NOT NULL DEFAULT '',"
82 " path BYTEA DEFAULT '')"
83 "WITH OIDS");
84 if ( (ret == NULL) ||
85 ((PQresultStatus (ret) != PGRES_COMMAND_OK) &&
86 (0 != strcmp ("42P07", /* duplicate table */
87 PQresultErrorField
88 (ret,
89 PG_DIAG_SQLSTATE)))))
90 {
91 (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret,
92 PGRES_COMMAND_OK,
93 "CREATE TABLE",
94 "gn090dc");
95 PQfinish (plugin->dbh);
96 plugin->dbh = NULL;
97 return GNUNET_SYSERR;
98 }
99 if (PQresultStatus (ret) == PGRES_COMMAND_OK)
100 {
101 if ((GNUNET_OK !=
102 GNUNET_POSTGRES_exec (plugin->dbh,
103 "CREATE INDEX IF NOT EXISTS idx_key ON gn090dc (key)")) ||
104 (GNUNET_OK !=
105 GNUNET_POSTGRES_exec (plugin->dbh,
106 "CREATE INDEX IF NOT EXISTS idx_dt ON gn090dc (discard_time)")))
107 {
108 PQclear (ret);
109 PQfinish (plugin->dbh);
110 plugin->dbh = NULL;
111 return GNUNET_SYSERR;
112 }
113 }
114 PQclear (ret);
115 ret =
116 PQexec (plugin->dbh,
117 "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL");
118 if (GNUNET_OK != 119 if (GNUNET_OK !=
119 GNUNET_POSTGRES_check_result (plugin->dbh, 120 GNUNET_PQ_exec_statements (plugin->dbh,
120 ret, 121 es))
121 PGRES_COMMAND_OK,
122 "ALTER TABLE",
123 "gn090dc"))
124 { 122 {
125 PQfinish (plugin->dbh); 123 PQfinish (plugin->dbh);
126 plugin->dbh = NULL; 124 plugin->dbh = NULL;
127 return GNUNET_SYSERR; 125 return GNUNET_SYSERR;
128 } 126 }
129 PQclear (ret); 127
130 ret = PQexec (plugin->dbh,
131 "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN");
132 if (GNUNET_OK != 128 if (GNUNET_OK !=
133 GNUNET_POSTGRES_check_result (plugin->dbh, 129 GNUNET_PQ_prepare_statements (plugin->dbh,
134 ret, 130 ps))
135 PGRES_COMMAND_OK,
136 "ALTER TABLE",
137 "gn090dc"))
138 {
139 PQfinish (plugin->dbh);
140 plugin->dbh = NULL;
141 return GNUNET_SYSERR;
142 }
143 PQclear (ret);
144 if ((GNUNET_OK !=
145 GNUNET_POSTGRES_prepare (plugin->dbh,
146 "getkt",
147 "SELECT discard_time,type,value,path FROM gn090dc "
148 "WHERE key=$1 AND type=$2 ", 2)) ||
149 (GNUNET_OK !=
150 GNUNET_POSTGRES_prepare (plugin->dbh,
151 "getk",
152 "SELECT discard_time,type,value,path FROM gn090dc "
153 "WHERE key=$1", 1)) ||
154 (GNUNET_OK !=
155 GNUNET_POSTGRES_prepare (plugin->dbh,
156 "getm",
157 "SELECT length(value),oid,key FROM gn090dc "
158 "ORDER BY discard_time ASC LIMIT 1", 0)) ||
159 (GNUNET_OK !=
160 GNUNET_POSTGRES_prepare (plugin->dbh,
161 "get_random",
162 "SELECT discard_time,type,value,path,key FROM gn090dc "
163 "ORDER BY key ASC LIMIT 1 OFFSET $1", 1)) ||
164 (GNUNET_OK !=
165 GNUNET_POSTGRES_prepare (plugin->dbh,
166 "get_closest",
167 "SELECT discard_time,type,value,path,key FROM gn090dc "
168 "WHERE key>=$1 ORDER BY key ASC LIMIT $2", 1)) ||
169 (GNUNET_OK !=
170 GNUNET_POSTGRES_prepare (plugin->dbh,
171 "delrow",
172 "DELETE FROM gn090dc WHERE oid=$1", 1)) ||
173 (GNUNET_OK !=
174 GNUNET_POSTGRES_prepare (plugin->dbh,
175 "put",
176 "INSERT INTO gn090dc (type, discard_time, key, value, path) "
177 "VALUES ($1, $2, $3, $4, $5)", 5)))
178 { 131 {
179 PQfinish (plugin->dbh); 132 PQfinish (plugin->dbh);
180 plugin->dbh = NULL; 133 plugin->dbh = NULL;
@@ -189,7 +142,7 @@ init_connection (struct Plugin *plugin)
189 * 142 *
190 * @param cls closure (our `struct Plugin`) 143 * @param cls closure (our `struct Plugin`)
191 * @param key key to store @a data under 144 * @param key key to store @a data under
192 * @param size number of bytes in @a data 145 * @param data_size number of bytes in @a data
193 * @param data data to store 146 * @param data data to store
194 * @param type type of the value 147 * @param type type of the value
195 * @param discard_time when to discard the value in any case 148 * @param discard_time when to discard the value in any case
@@ -200,7 +153,7 @@ init_connection (struct Plugin *plugin)
200static ssize_t 153static ssize_t
201postgres_plugin_put (void *cls, 154postgres_plugin_put (void *cls,
202 const struct GNUNET_HashCode *key, 155 const struct GNUNET_HashCode *key,
203 size_t size, 156 size_t data_size,
204 const char *data, 157 const char *data,
205 enum GNUNET_BLOCK_Type type, 158 enum GNUNET_BLOCK_Type type,
206 struct GNUNET_TIME_Absolute discard_time, 159 struct GNUNET_TIME_Absolute discard_time,
@@ -208,36 +161,125 @@ postgres_plugin_put (void *cls,
208 const struct GNUNET_PeerIdentity *path_info) 161 const struct GNUNET_PeerIdentity *path_info)
209{ 162{
210 struct Plugin *plugin = cls; 163 struct Plugin *plugin = cls;
211 PGresult *ret; 164 uint32_t type32 = (uint32_t) type;
212 uint32_t btype = htonl (type); 165 struct GNUNET_PQ_QueryParam params[] = {
213 uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value_us__; 166 GNUNET_PQ_query_param_uint32 (&type32),
214 167 GNUNET_PQ_query_param_absolute_time (&discard_time),
215 const char *paramValues[] = { 168 GNUNET_PQ_query_param_auto_from_type (key),
216 (const char *) &btype, 169 GNUNET_PQ_query_param_fixed_size (data, data_size),
217 (const char *) &bexpi, 170 GNUNET_PQ_query_param_fixed_size (path_info,
218 (const char *) key, 171 path_info_len * sizeof (struct GNUNET_PeerIdentity)),
219 (const char *) data, 172 GNUNET_PQ_query_param_end
220 (const char *) path_info
221 };
222 int paramLengths[] = {
223 sizeof (btype),
224 sizeof (bexpi),
225 sizeof (struct GNUNET_HashCode),
226 size,
227 path_info_len * sizeof (struct GNUNET_PeerIdentity)
228 }; 173 };
229 const int paramFormats[] = { 1, 1, 1, 1, 1 }; 174 enum GNUNET_PQ_QueryStatus ret;
230 175
231 ret = 176 ret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
232 PQexecPrepared (plugin->dbh, "put", 5, paramValues, paramLengths, 177 "put",
233 paramFormats, 1); 178 params);
234 if (GNUNET_OK != 179 if (0 > ret)
235 GNUNET_POSTGRES_check_result (plugin->dbh, ret,
236 PGRES_COMMAND_OK, "PQexecPrepared", "put"))
237 return -1; 180 return -1;
238 plugin->num_items++; 181 plugin->num_items++;
239 PQclear (ret); 182 return data_size + OVERHEAD;
240 return size + OVERHEAD; 183}
184
185
186/**
187 * Closure for #handle_results.
188 */
189struct HandleResultContext
190{
191
192 /**
193 * Function to call on each result, may be NULL.
194 */
195 GNUNET_DATACACHE_Iterator iter;
196
197 /**
198 * Closure for @e iter.
199 */
200 void *iter_cls;
201
202 /**
203 * Key used.
204 */
205 const struct GNUNET_HashCode *key;
206};
207
208
209/**
210 * Function to be called with the results of a SELECT statement
211 * that has returned @a num_results results. Parse the result
212 * and call the callback given in @a cls
213 *
214 * @param cls closure of type `struct HandleResultContext`
215 * @param result the postgres result
216 * @param num_result the number of results in @a result
217 */
218static void
219handle_results (void *cls,
220 PGresult *result,
221 unsigned int num_results)
222{
223 struct HandleResultContext *hrc = cls;
224
225 for (unsigned int i=0;i<num_results;i++)
226 {
227 struct GNUNET_TIME_Absolute expiration_time;
228 uint32_t type;
229 void *data;
230 size_t data_size;
231 struct GNUNET_PeerIdentity *path;
232 size_t path_len;
233 struct GNUNET_PQ_ResultSpec rs[] = {
234 GNUNET_PQ_result_spec_absolute_time ("discard_time",
235 &expiration_time),
236 GNUNET_PQ_result_spec_uint32 ("type",
237 &type),
238 GNUNET_PQ_result_spec_variable_size ("value",
239 &data,
240 &data_size),
241 GNUNET_PQ_result_spec_variable_size ("path",
242 (void **) &path,
243 &path_len),
244 GNUNET_PQ_result_spec_end
245 };
246
247 if (GNUNET_YES !=
248 GNUNET_PQ_extract_result (result,
249 rs,
250 i))
251 {
252 GNUNET_break (0);
253 return;
254 }
255 if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity)))
256 {
257 GNUNET_break (0);
258 path_len = 0;
259 }
260 path_len %= sizeof (struct GNUNET_PeerIdentity);
261 LOG (GNUNET_ERROR_TYPE_DEBUG,
262 "Found result of size %u bytes and type %u in database\n",
263 (unsigned int) data_size,
264 (unsigned int) type);
265 if ( (NULL != hrc->iter) &&
266 (GNUNET_SYSERR ==
267 hrc->iter (hrc->iter_cls,
268 hrc->key,
269 data_size,
270 data,
271 (enum GNUNET_BLOCK_Type) type,
272 expiration_time,
273 path_len,
274 path)) )
275 {
276 LOG (GNUNET_ERROR_TYPE_DEBUG,
277 "Ending iteration (client error)\n");
278 GNUNET_PQ_cleanup_result (rs);
279 return;
280 }
281 GNUNET_PQ_cleanup_result (rs);
282 }
241} 283}
242 284
243 285
@@ -260,94 +302,30 @@ postgres_plugin_get (void *cls,
260 void *iter_cls) 302 void *iter_cls)
261{ 303{
262 struct Plugin *plugin = cls; 304 struct Plugin *plugin = cls;
263 uint32_t btype = htonl (type); 305 uint32_t type32 = (uint32_t) type;
264 306 struct GNUNET_PQ_QueryParam paramk[] = {
265 const char *paramValues[] = { 307 GNUNET_PQ_query_param_auto_from_type (key),
266 (const char *) key, 308 GNUNET_PQ_query_param_end
267 (const char *) &btype
268 }; 309 };
269 int paramLengths[] = { 310 struct GNUNET_PQ_QueryParam paramkt[] = {
270 sizeof (struct GNUNET_HashCode), 311 GNUNET_PQ_query_param_auto_from_type (key),
271 sizeof (btype) 312 GNUNET_PQ_query_param_uint32 (&type32),
313 GNUNET_PQ_query_param_end
272 }; 314 };
273 const int paramFormats[] = { 1, 1 }; 315 enum GNUNET_PQ_QueryStatus res;
274 struct GNUNET_TIME_Absolute expiration_time; 316 struct HandleResultContext hr_ctx;
275 uint32_t size; 317
276 unsigned int cnt; 318 hr_ctx.iter = iter;
277 unsigned int i; 319 hr_ctx.iter_cls = iter_cls;
278 unsigned int path_len; 320 hr_ctx.key = key;
279 const struct GNUNET_PeerIdentity *path; 321 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
280 PGresult *res; 322 (0 == type) ? "getk" : "getkt",
281 323 (0 == type) ? paramk : paramkt,
282 res = 324 &handle_results,
283 PQexecPrepared (plugin->dbh, (type == 0) ? "getk" : "getkt", 325 &hr_ctx);
284 (type == 0) ? 1 : 2, paramValues, paramLengths, 326 if (res < 0)
285 paramFormats, 1);
286 if (GNUNET_OK !=
287 GNUNET_POSTGRES_check_result (plugin->dbh,
288 res,
289 PGRES_TUPLES_OK,
290 "PQexecPrepared",
291 (type == 0) ? "getk" : "getkt"))
292 {
293 LOG (GNUNET_ERROR_TYPE_DEBUG,
294 "Ending iteration (postgres error)\n");
295 return 0;
296 }
297
298 if (0 == (cnt = PQntuples (res)))
299 {
300 /* no result */
301 LOG (GNUNET_ERROR_TYPE_DEBUG,
302 "Ending iteration (no more results)\n");
303 PQclear (res);
304 return 0;
305 }
306 if (iter == NULL)
307 {
308 PQclear (res);
309 return cnt;
310 }
311 if ( (4 != PQnfields (res)) ||
312 (sizeof (uint64_t) != PQfsize (res, 0)) ||
313 (sizeof (uint32_t) != PQfsize (res, 1)))
314 {
315 GNUNET_break (0);
316 PQclear (res);
317 return 0; 327 return 0;
318 } 328 return res;
319 for (i = 0; i < cnt; i++)
320 {
321 expiration_time.abs_value_us =
322 GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0));
323 type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1));
324 size = PQgetlength (res, i, 2);
325 path_len = PQgetlength (res, i, 3);
326 if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity)))
327 {
328 GNUNET_break (0);
329 path_len = 0;
330 }
331 path_len %= sizeof (struct GNUNET_PeerIdentity);
332 path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3);
333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Found result of size %u bytes and type %u in database\n",
335 (unsigned int) size, (unsigned int) type);
336 if (GNUNET_SYSERR ==
337 iter (iter_cls, key, size, PQgetvalue (res, i, 2),
338 (enum GNUNET_BLOCK_Type) type,
339 expiration_time,
340 path_len,
341 path))
342 {
343 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "Ending iteration (client error)\n");
345 PQclear (res);
346 return cnt;
347 }
348 }
349 PQclear (res);
350 return cnt;
351} 329}
352 330
353 331
@@ -362,54 +340,53 @@ static int
362postgres_plugin_del (void *cls) 340postgres_plugin_del (void *cls)
363{ 341{
364 struct Plugin *plugin = cls; 342 struct Plugin *plugin = cls;
343 struct GNUNET_PQ_QueryParam pempty[] = {
344 GNUNET_PQ_query_param_end
345 };
365 uint32_t size; 346 uint32_t size;
366 uint32_t oid; 347 uint32_t oid;
367 struct GNUNET_HashCode key; 348 struct GNUNET_HashCode key;
368 PGresult *res; 349 struct GNUNET_PQ_ResultSpec rs[] = {
350 GNUNET_PQ_result_spec_uint32 ("len",
351 &size),
352 GNUNET_PQ_result_spec_uint32 ("oid",
353 &oid),
354 GNUNET_PQ_result_spec_auto_from_type ("key",
355 &key),
356 GNUNET_PQ_result_spec_end
357 };
358 enum GNUNET_PQ_QueryStatus res;
359 struct GNUNET_PQ_QueryParam dparam[] = {
360 GNUNET_PQ_query_param_uint32 (&oid),
361 GNUNET_PQ_query_param_end
362 };
369 363
370 res = PQexecPrepared (plugin->dbh, 364 res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh,
371 "getm", 365 "getm",
372 0, NULL, NULL, NULL, 1); 366 pempty,
373 if (GNUNET_OK != 367 rs);
374 GNUNET_POSTGRES_check_result (plugin->dbh, 368 if (0 > res)
375 res, 369 return GNUNET_SYSERR;
376 PGRES_TUPLES_OK, 370 if (GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS == res)
377 "PQexecPrepared",
378 "getm"))
379 {
380 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "Ending iteration (postgres error)\n");
382 return 0;
383 }
384 if (0 == PQntuples (res))
385 { 371 {
386 /* no result */ 372 /* no result */
387 LOG (GNUNET_ERROR_TYPE_DEBUG, 373 LOG (GNUNET_ERROR_TYPE_DEBUG,
388 "Ending iteration (no more results)\n"); 374 "Ending iteration (no more results)\n");
389 PQclear (res);
390 return GNUNET_SYSERR;
391 }
392 if ((3 != PQnfields (res)) || (sizeof (size) != PQfsize (res, 0)) ||
393 (sizeof (oid) != PQfsize (res, 1)) ||
394 (sizeof (struct GNUNET_HashCode) != PQgetlength (res, 0, 2)))
395 {
396 GNUNET_break (0);
397 PQclear (res);
398 return 0; 375 return 0;
399 } 376 }
400 size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); 377 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
401 oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); 378 "delrow",
402 GNUNET_memcpy (&key, PQgetvalue (res, 0, 2), sizeof (struct GNUNET_HashCode)); 379 dparam);
403 PQclear (res); 380 if (0 > res)
404 if (GNUNET_OK != 381 {
405 GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, 382 GNUNET_PQ_cleanup_result (rs);
406 "delrow",
407 oid))
408 return GNUNET_SYSERR; 383 return GNUNET_SYSERR;
384 }
409 plugin->num_items--; 385 plugin->num_items--;
410 plugin->env->delete_notify (plugin->env->cls, 386 plugin->env->delete_notify (plugin->env->cls,
411 &key, 387 &key,
412 size + OVERHEAD); 388 size + OVERHEAD);
389 GNUNET_PQ_cleanup_result (rs);
413 return GNUNET_OK; 390 return GNUNET_OK;
414} 391}
415 392