aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_postgres.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-06-01 21:48:19 +0200
committerChristian Grothoff <christian@grothoff.org>2017-06-01 21:48:19 +0200
commit1defd30dfeb1867c2756b3fe6a437f695951d0c9 (patch)
treeb48c0fe6bb32469cfcb4284bfac3142e22417ae8 /src/namestore/plugin_namestore_postgres.c
parentbbbe0b2404d131cc0d9eda26725b65b47a7e073a (diff)
downloadgnunet-1defd30dfeb1867c2756b3fe6a437f695951d0c9.tar.gz
gnunet-1defd30dfeb1867c2756b3fe6a437f695951d0c9.zip
adding more good helpers to libgnunetpq
Diffstat (limited to 'src/namestore/plugin_namestore_postgres.c')
-rw-r--r--src/namestore/plugin_namestore_postgres.c200
1 files changed, 95 insertions, 105 deletions
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index 01dbf9e61..4bf931c93 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -1,6 +1,6 @@
1 /* 1 /*
2 * This file is part of GNUnet 2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013, 2016 GNUnet e.V. 3 * Copyright (C) 2009-2013, 2016, 2017 GNUnet e.V.
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
@@ -75,30 +75,6 @@ struct Plugin
75 75
76 76
77/** 77/**
78 * Create our database indices.
79 *
80 * @param dbh handle to the database
81 */
82static void
83create_indices (PGconn * dbh)
84{
85 /* create indices */
86 if ( (GNUNET_OK !=
87 GNUNET_POSTGRES_exec (dbh,
88 "CREATE INDEX IF NOT EXISTS ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) ||
89 (GNUNET_OK !=
90 GNUNET_POSTGRES_exec (dbh,
91 "CREATE INDEX IF NOT EXISTS ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) ||
92 (GNUNET_OK !=
93 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS it_iter ON ns097records (rvalue)")) ||
94 (GNUNET_OK !=
95 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_label ON ns097records (label)")) )
96 LOG (GNUNET_ERROR_TYPE_ERROR,
97 _("Failed to create indices\n"));
98}
99
100
101/**
102 * Initialize the database connections and associated 78 * Initialize the database connections and associated
103 * data structures (create tables and indices 79 * data structures (create tables and indices
104 * as needed as well). 80 * as needed as well).
@@ -109,10 +85,30 @@ create_indices (PGconn * dbh)
109static int 85static int
110database_setup (struct Plugin *plugin) 86database_setup (struct Plugin *plugin)
111{ 87{
112 PGresult *res; 88 struct GNUNET_PQ_ExecuteStatement es_temporary =
113 89 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns097records ("
114 plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, 90 " zone_private_key BYTEA NOT NULL DEFAULT '',"
115 "namestore-postgres"); 91 " pkey BYTEA DEFAULT '',"
92 " rvalue BYTEA NOT NULL DEFAULT '',"
93 " record_count INTEGER NOT NULL DEFAULT 0,"
94 " record_data BYTEA NOT NULL DEFAULT '',"
95 " label TEXT NOT NULL DEFAULT ''"
96 ")"
97 "WITH OIDS");
98 struct GNUNET_PQ_ExecuteStatement es_default =
99 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns097records ("
100 " zone_private_key BYTEA NOT NULL DEFAULT '',"
101 " pkey BYTEA DEFAULT '',"
102 " rvalue BYTEA NOT NULL DEFAULT '',"
103 " record_count INTEGER NOT NULL DEFAULT 0,"
104 " record_data BYTEA NOT NULL DEFAULT '',"
105 " label TEXT NOT NULL DEFAULT ''"
106 ")"
107 "WITH OIDS");
108 const struct GNUNET_PQ_ExecuteStatement *cr;
109
110 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
111 "namestore-postgres");
116 if (NULL == plugin->dbh) 112 if (NULL == plugin->dbh)
117 return GNUNET_SYSERR; 113 return GNUNET_SYSERR;
118 if (GNUNET_YES == 114 if (GNUNET_YES ==
@@ -120,80 +116,70 @@ database_setup (struct Plugin *plugin)
120 "namestore-postgres", 116 "namestore-postgres",
121 "TEMPORARY_TABLE")) 117 "TEMPORARY_TABLE"))
122 { 118 {
123 res = 119 cr = &es_temporary;
124 PQexec (plugin->dbh,
125 "CREATE TEMPORARY TABLE IF NOT EXISTS ns097records ("
126 " zone_private_key BYTEA NOT NULL DEFAULT '',"
127 " pkey BYTEA DEFAULT '',"
128 " rvalue BYTEA NOT NULL DEFAULT '',"
129 " record_count INTEGER NOT NULL DEFAULT 0,"
130 " record_data BYTEA NOT NULL DEFAULT '',"
131 " label TEXT NOT NULL DEFAULT ''"
132 ")" "WITH OIDS");
133 } 120 }
134 else 121 else
135 { 122 {
136 res = 123 cr = &es_default;
137 PQexec (plugin->dbh,
138 "CREATE TABLE IF NOT EXISTS ns097records ("
139 " zone_private_key BYTEA NOT NULL DEFAULT '',"
140 " pkey BYTEA DEFAULT '',"
141 " rvalue BYTEA NOT NULL DEFAULT '',"
142 " record_count INTEGER NOT NULL DEFAULT 0,"
143 " record_data BYTEA NOT NULL DEFAULT '',"
144 " label TEXT NOT NULL DEFAULT ''"
145 ")" "WITH OIDS");
146 } 124 }
147 if ( (NULL == res) || 125
148 ((PQresultStatus (res) != PGRES_COMMAND_OK) &&
149 (0 != strcmp ("42P07", /* duplicate table */
150 PQresultErrorField
151 (res,
152 PG_DIAG_SQLSTATE)))))
153 { 126 {
154 (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, 127 struct GNUNET_PQ_ExecuteStatement es[] = {
155 PGRES_COMMAND_OK, "CREATE TABLE", 128 *cr,
156 "ns097records"); 129 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
157 PQfinish (plugin->dbh); 130 "ON ns097records (zone_private_key,pkey)"),
158 plugin->dbh = NULL; 131 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
159 return GNUNET_SYSERR; 132 "ON ns097records (zone_private_key,rvalue)"),
133 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS it_iter "
134 "ON ns097records (rvalue)"),
135 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
136 "ON ns097records (label)"),
137 GNUNET_PQ_EXECUTE_STATEMENT_END
138 };
139
140 if (GNUNET_OK !=
141 GNUNET_PQ_exec_statements (plugin->dbh,
142 es))
143 {
144 PQfinish (plugin->dbh);
145 plugin->dbh = NULL;
146 return GNUNET_SYSERR;
147 }
160 } 148 }
161 create_indices (plugin->dbh); 149
162
163 if ((GNUNET_OK !=
164 GNUNET_POSTGRES_prepare (plugin->dbh,
165 "store_records",
166 "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES "
167 "($1, $2, $3, $4, $5, $6)", 6)) ||
168 (GNUNET_OK !=
169 GNUNET_POSTGRES_prepare (plugin->dbh,
170 "delete_records",
171 "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) ||
172 (GNUNET_OK !=
173 GNUNET_POSTGRES_prepare (plugin->dbh,
174 "zone_to_name",
175 "SELECT record_count,record_data,label FROM ns097records"
176 " WHERE zone_private_key=$1 AND pkey=$2", 2)) ||
177 (GNUNET_OK !=
178 GNUNET_POSTGRES_prepare (plugin->dbh,
179 "iterate_zone",
180 "SELECT record_count,record_data,label FROM ns097records"
181 " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) ||
182 (GNUNET_OK !=
183 GNUNET_POSTGRES_prepare (plugin->dbh,
184 "iterate_all_zones",
185 "SELECT record_count,record_data,label,zone_private_key"
186 " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) ||
187 (GNUNET_OK !=
188 GNUNET_POSTGRES_prepare (plugin->dbh,
189 "lookup_label",
190 "SELECT record_count,record_data,label"
191 " FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)))
192 { 150 {
193 PQfinish (plugin->dbh); 151 struct GNUNET_PQ_PreparedStatement ps[] = {
194 plugin->dbh = NULL; 152 GNUNET_PQ_make_prepare ("store_records",
195 return GNUNET_SYSERR; 153 "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES "
154 "($1, $2, $3, $4, $5, $6)", 6),
155 GNUNET_PQ_make_prepare ("delete_records",
156 "DELETE FROM ns097records "
157 "WHERE zone_private_key=$1 AND label=$2", 2),
158 GNUNET_PQ_make_prepare ("zone_to_name",
159 "SELECT record_count,record_data,label FROM ns097records"
160 " WHERE zone_private_key=$1 AND pkey=$2", 2),
161 GNUNET_PQ_make_prepare ("iterate_zone",
162 "SELECT record_count,record_data,label FROM ns097records "
163 "WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2),
164 GNUNET_PQ_make_prepare ("iterate_all_zones",
165 "SELECT record_count,record_data,label,zone_private_key"
166 " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1),
167 GNUNET_PQ_make_prepare ("lookup_label",
168 "SELECT record_count,record_data,label "
169 "FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2),
170 GNUNET_PQ_PREPARED_STATEMENT_END
171 };
172
173 if (GNUNET_OK !=
174 GNUNET_PQ_prepare_statements (plugin->dbh,
175 ps))
176 {
177 PQfinish (plugin->dbh);
178 plugin->dbh = NULL;
179 return GNUNET_SYSERR;
180 }
196 } 181 }
182
197 return GNUNET_OK; 183 return GNUNET_OK;
198} 184}
199 185
@@ -221,19 +207,19 @@ namestore_postgres_store_records (void *cls,
221 uint64_t rvalue; 207 uint64_t rvalue;
222 uint32_t rd_count_nbo = htonl ((uint32_t) rd_count); 208 uint32_t rd_count_nbo = htonl ((uint32_t) rd_count);
223 size_t data_size; 209 size_t data_size;
224 unsigned int i;
225 210
226 memset (&pkey, 0, sizeof (pkey)); 211 memset (&pkey, 0, sizeof (pkey));
227 for (i=0;i<rd_count;i++) 212 for (unsigned int i=0;i<rd_count;i++)
228 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) 213 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type)
229 { 214 {
230 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); 215 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size);
231 GNUNET_memcpy (&pkey, 216 GNUNET_memcpy (&pkey,
232 rd[i].data, 217 rd[i].data,
233 rd[i].data_size); 218 rd[i].data_size);
234 break; 219 break;
235 } 220 }
236 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); 221 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
222 UINT64_MAX);
237 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); 223 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
238 if (data_size > 64 * 65536) 224 if (data_size > 64 * 65536)
239 { 225 {
@@ -262,9 +248,10 @@ namestore_postgres_store_records (void *cls,
262 const int paramFormats[] = { 1, 1, 1, 1, 1, 1 }; 248 const int paramFormats[] = { 1, 1, 1, 1, 1, 1 };
263 PGresult *res; 249 PGresult *res;
264 250
265 if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, 251 if (data_size !=
266 data_size, data)) 252 GNUNET_GNSRECORD_records_serialize (rd_count, rd,
267 { 253 data_size, data))
254 {
268 GNUNET_break (0); 255 GNUNET_break (0);
269 return GNUNET_SYSERR; 256 return GNUNET_SYSERR;
270 } 257 }
@@ -301,7 +288,8 @@ static int
301get_record_and_call_iterator (struct Plugin *plugin, 288get_record_and_call_iterator (struct Plugin *plugin,
302 PGresult *res, 289 PGresult *res,
303 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, 290 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
304 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 291 GNUNET_NAMESTORE_RecordIterator iter,
292 void *iter_cls)
305{ 293{
306 const char *data; 294 const char *data;
307 size_t data_size; 295 size_t data_size;
@@ -311,7 +299,9 @@ get_record_and_call_iterator (struct Plugin *plugin,
311 unsigned int cnt; 299 unsigned int cnt;
312 300
313 if (GNUNET_OK != 301 if (GNUNET_OK !=
314 GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, 302 GNUNET_POSTGRES_check_result (plugin->dbh,
303 res,
304 PGRES_TUPLES_OK,
315 "PQexecPrepared", 305 "PQexecPrepared",
316 "iteration")) 306 "iteration"))
317 { 307 {