aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-09-30 20:03:59 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-09-30 20:03:59 +0900
commit2754420df146495766e5efa8e8a8150ae904d209 (patch)
treeb129092b8001c3235f1e23d29414736ac8a4891d
parent51b6cf4d3944152ea0c62a5aa41224f6227d62f7 (diff)
downloadgnunet-2754420df146495766e5efa8e8a8150ae904d209.tar.gz
gnunet-2754420df146495766e5efa8e8a8150ae904d209.zip
-fix
-rw-r--r--src/namestore/plugin_namestore_postgres.c171
1 files changed, 102 insertions, 69 deletions
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index e3b8dc745..6e5c1c718 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -45,6 +45,11 @@ struct Plugin
45 const struct GNUNET_CONFIGURATION_Handle *cfg; 45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46 46
47 /** 47 /**
48 * Database is prepared and ready
49 */
50 int ready;
51
52 /**
48 * Postgres database handle. 53 * Postgres database handle.
49 */ 54 */
50 struct GNUNET_PQ_Context *dbh; 55 struct GNUNET_PQ_Context *dbh;
@@ -62,11 +67,9 @@ struct Plugin
62static int 67static int
63init_database (struct Plugin *plugin, char **emsg, int drop) 68init_database (struct Plugin *plugin, char **emsg, int drop)
64{ 69{
65 struct GNUNET_PQ_ExecuteStatement es_drop =
66 GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS ns098records");
67 struct GNUNET_PQ_ExecuteStatement es_temporary = 70 struct GNUNET_PQ_ExecuteStatement es_temporary =
68 GNUNET_PQ_make_execute ( 71 GNUNET_PQ_make_execute (
69 "CREATE TEMPORARY TABLE IF NOT EXISTS ns098records (" 72 "CREATE TEMPORARY TABLE ns098records ("
70 " seq BIGSERIAL PRIMARY KEY," 73 " seq BIGSERIAL PRIMARY KEY,"
71 " zone_private_key BYTEA NOT NULL DEFAULT ''," 74 " zone_private_key BYTEA NOT NULL DEFAULT '',"
72 " pkey BYTEA DEFAULT ''," 75 " pkey BYTEA DEFAULT '',"
@@ -77,7 +80,7 @@ init_database (struct Plugin *plugin, char **emsg, int drop)
77 " CONSTRAINT zl UNIQUE (zone_private_key,label)" 80 " CONSTRAINT zl UNIQUE (zone_private_key,label)"
78 ")"); 81 ")");
79 struct GNUNET_PQ_ExecuteStatement es_default = 82 struct GNUNET_PQ_ExecuteStatement es_default =
80 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" 83 GNUNET_PQ_make_execute ("CREATE TABLE ns098records ("
81 " seq BIGSERIAL PRIMARY KEY," 84 " seq BIGSERIAL PRIMARY KEY,"
82 " zone_private_key BYTEA NOT NULL DEFAULT ''," 85 " zone_private_key BYTEA NOT NULL DEFAULT '',"
83 " pkey BYTEA DEFAULT ''," 86 " pkey BYTEA DEFAULT '',"
@@ -89,30 +92,21 @@ init_database (struct Plugin *plugin, char **emsg, int drop)
89 ")"); 92 ")");
90 const struct GNUNET_PQ_ExecuteStatement *cr; 93 const struct GNUNET_PQ_ExecuteStatement *cr;
91 struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END; 94 struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END;
92 struct GNUNET_PQ_ExecuteStatement sc2 = GNUNET_PQ_EXECUTE_STATEMENT_END; 95 struct GNUNET_PQ_ExecuteStatement es_drop =
96 GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS ns098records");
93 if (GNUNET_YES == 97 if (GNUNET_YES ==
94 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, 98 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
95 "namestore-postgres", 99 "namestore-postgres",
96 "TEMPORARY_TABLE")) 100 "TEMPORARY_TABLE"))
97 {
98 cr = &es_temporary; 101 cr = &es_temporary;
99 }
100 else 102 else
101 {
102 cr = &es_default; 103 cr = &es_default;
103 }
104 104
105 if (GNUNET_YES == 105 if (GNUNET_YES ==
106 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, 106 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
107 "namestore-postgres", 107 "namestore-postgres",
108 "ASYNC_COMMIT")) 108 "ASYNC_COMMIT"))
109 {
110 sc = GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off"); 109 sc = GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off");
111 if (GNUNET_YES == drop)
112 sc2 = es_drop;
113 }
114 else if (GNUNET_YES == drop)
115 sc = es_drop;
116 110
117 { 111 {
118 struct GNUNET_PQ_ExecuteStatement es[] = { 112 struct GNUNET_PQ_ExecuteStatement es[] = {
@@ -126,15 +120,37 @@ init_database (struct Plugin *plugin, char **emsg, int drop)
126 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label " 120 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label "
127 "ON ns098records (zone_private_key,label)"), 121 "ON ns098records (zone_private_key,label)"),
128 sc, 122 sc,
129 sc2,
130 GNUNET_PQ_EXECUTE_STATEMENT_END 123 GNUNET_PQ_EXECUTE_STATEMENT_END
131 }; 124 };
132 125 struct GNUNET_PQ_ExecuteStatement es_alt[] = {
133 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, 126 es_drop,
134 "namestore-postgres", 127 *cr,
135 NULL, 128 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
136 es, 129 "ON ns098records (zone_private_key,pkey)"),
137 NULL); 130 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
131 "ON ns098records (zone_private_key,seq)"),
132 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
133 "ON ns098records (label)"),
134 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label "
135 "ON ns098records (zone_private_key,label)"),
136 sc,
137 GNUNET_PQ_EXECUTE_STATEMENT_END
138 };
139 if (GNUNET_NO == drop)
140 {
141 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
142 "namestore-postgres",
143 NULL,
144 es,
145 NULL);
146 }
147 else {
148 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
149 "namestore-postgres",
150 NULL,
151 es_alt,
152 NULL);
153 }
138 } 154 }
139 if (NULL == plugin->dbh) 155 if (NULL == plugin->dbh)
140 { 156 {
@@ -146,6 +162,57 @@ init_database (struct Plugin *plugin, char **emsg, int drop)
146 return GNUNET_OK; 162 return GNUNET_OK;
147} 163}
148 164
165static int
166database_prepare (struct Plugin *plugin)
167{
168 enum GNUNET_GenericReturnValue ret;
169 if (GNUNET_YES == plugin->ready)
170 return GNUNET_OK;
171 struct GNUNET_PQ_PreparedStatement ps[] = {
172 GNUNET_PQ_make_prepare ("store_records",
173 "INSERT INTO ns098records"
174 " (zone_private_key, pkey, rvalue, record_count, record_data, label)"
175 " VALUES ($1, $2, $3, $4, $5, $6)"
176 " ON CONFLICT ON CONSTRAINT zl"
177 " DO UPDATE"
178 " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
179 " WHERE ns098records.zone_private_key = $1"
180 " AND ns098records.label = $6",
181 6),
182 GNUNET_PQ_make_prepare ("delete_records",
183 "DELETE FROM ns098records "
184 "WHERE zone_private_key=$1 AND label=$2",
185 2),
186 GNUNET_PQ_make_prepare ("zone_to_name",
187 "SELECT seq,record_count,record_data,label FROM ns098records"
188 " WHERE zone_private_key=$1 AND pkey=$2",
189 2),
190 GNUNET_PQ_make_prepare ("iterate_zone",
191 "SELECT seq,record_count,record_data,label FROM ns098records "
192 "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3",
193 3),
194 GNUNET_PQ_make_prepare ("iterate_all_zones",
195 "SELECT seq,record_count,record_data,label,zone_private_key"
196 " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2",
197 2),
198 GNUNET_PQ_make_prepare ("lookup_label",
199 "SELECT seq,record_count,record_data,label "
200 "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
201 2),
202 GNUNET_PQ_make_prepare ("edit_set",
203 "SELECT seq,record_count,record_data,label "
204 "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE NOWAIT",
205 2),
206 GNUNET_PQ_PREPARED_STATEMENT_END
207 };
208 ret = GNUNET_PQ_prepare_statements (plugin->dbh, ps);
209 if (GNUNET_OK != ret)
210 return ret;
211 plugin->ready = GNUNET_YES;
212 return GNUNET_OK;
213}
214
215
149/** 216/**
150 * Initialize the database connections and associated 217 * Initialize the database connections and associated
151 * data structures (create tables and indices 218 * data structures (create tables and indices
@@ -178,51 +245,11 @@ database_connect (struct Plugin *plugin)
178 GNUNET_free (emsg); 245 GNUNET_free (emsg);
179 } 246 }
180 } 247 }
181 { 248 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
182 struct GNUNET_PQ_PreparedStatement ps[] = { 249 "namestore-postgres",
183 GNUNET_PQ_make_prepare ("store_records", 250 NULL,
184 "INSERT INTO ns098records" 251 NULL,
185 " (zone_private_key, pkey, rvalue, record_count, record_data, label)" 252 NULL);
186 " VALUES ($1, $2, $3, $4, $5, $6)"
187 " ON CONFLICT ON CONSTRAINT zl"
188 " DO UPDATE"
189 " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
190 " WHERE ns098records.zone_private_key = $1"
191 " AND ns098records.label = $6",
192 6),
193 GNUNET_PQ_make_prepare ("delete_records",
194 "DELETE FROM ns098records "
195 "WHERE zone_private_key=$1 AND label=$2",
196 2),
197 GNUNET_PQ_make_prepare ("zone_to_name",
198 "SELECT seq,record_count,record_data,label FROM ns098records"
199 " WHERE zone_private_key=$1 AND pkey=$2",
200 2),
201 GNUNET_PQ_make_prepare ("iterate_zone",
202 "SELECT seq,record_count,record_data,label FROM ns098records "
203 "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3",
204 3),
205 GNUNET_PQ_make_prepare ("iterate_all_zones",
206 "SELECT seq,record_count,record_data,label,zone_private_key"
207 " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2",
208 2),
209 GNUNET_PQ_make_prepare ("lookup_label",
210 "SELECT seq,record_count,record_data,label "
211 "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
212 2),
213 GNUNET_PQ_make_prepare ("edit_set",
214 "SELECT seq,record_count,record_data,label "
215 "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE NOWAIT",
216 2),
217 GNUNET_PQ_PREPARED_STATEMENT_END
218 };
219
220 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
221 "namestore-postgres",
222 NULL,
223 NULL,
224 ps);
225 }
226 if (NULL == plugin->dbh) 253 if (NULL == plugin->dbh)
227 return GNUNET_SYSERR; 254 return GNUNET_SYSERR;
228 return GNUNET_OK; 255 return GNUNET_OK;
@@ -254,6 +281,7 @@ namestore_postgres_store_records (void *cls,
254 uint32_t rd_count32 = (uint32_t) rd_count; 281 uint32_t rd_count32 = (uint32_t) rd_count;
255 ssize_t data_size; 282 ssize_t data_size;
256 283
284 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
257 memset (&pkey, 285 memset (&pkey,
258 0, 286 0,
259 sizeof(pkey)); 287 sizeof(pkey));
@@ -386,7 +414,7 @@ parse_result_call_iterator (void *cls,
386 struct ParserContext *pc = cls; 414 struct ParserContext *pc = cls;
387 415
388 if (NULL == pc->iter) 416 if (NULL == pc->iter)
389 return; /* no need to do more work */ 417 return; /* no need to do more work */
390 LOG (GNUNET_ERROR_TYPE_DEBUG, 418 LOG (GNUNET_ERROR_TYPE_DEBUG,
391 "Got %d results from PQ.\n", num_results); 419 "Got %d results from PQ.\n", num_results);
392 for (unsigned int i = 0; i < num_results; i++) 420 for (unsigned int i = 0; i < num_results; i++)
@@ -459,7 +487,6 @@ parse_result_call_iterator (void *cls,
459 pc->limit -= num_results; 487 pc->limit -= num_results;
460} 488}
461 489
462
463/** 490/**
464 * Lookup records in the datastore for which we are the authority. 491 * Lookup records in the datastore for which we are the authority.
465 * 492 *
@@ -481,6 +508,7 @@ lookup_records (void *cls,
481 const char*method) 508 const char*method)
482{ 509{
483 struct Plugin *plugin = cls; 510 struct Plugin *plugin = cls;
511 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
484 struct GNUNET_PQ_QueryParam params[] = { 512 struct GNUNET_PQ_QueryParam params[] = {
485 GNUNET_PQ_query_param_auto_from_type (zone), 513 GNUNET_PQ_query_param_auto_from_type (zone),
486 GNUNET_PQ_query_param_string (label), 514 GNUNET_PQ_query_param_string (label),
@@ -577,6 +605,7 @@ namestore_postgres_iterate_records (void *cls,
577 enum GNUNET_DB_QueryStatus res; 605 enum GNUNET_DB_QueryStatus res;
578 struct ParserContext pc; 606 struct ParserContext pc;
579 607
608 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
580 pc.iter = iter; 609 pc.iter = iter;
581 pc.iter_cls = iter_cls; 610 pc.iter_cls = iter_cls;
582 pc.zone_key = zone; 611 pc.zone_key = zone;
@@ -641,6 +670,7 @@ namestore_postgres_zone_to_name (void *cls,
641 void *iter_cls) 670 void *iter_cls)
642{ 671{
643 struct Plugin *plugin = cls; 672 struct Plugin *plugin = cls;
673 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
644 struct GNUNET_PQ_QueryParam params[] = { 674 struct GNUNET_PQ_QueryParam params[] = {
645 GNUNET_PQ_query_param_auto_from_type (zone), 675 GNUNET_PQ_query_param_auto_from_type (zone),
646 GNUNET_PQ_query_param_auto_from_type (value_zone), 676 GNUNET_PQ_query_param_auto_from_type (value_zone),
@@ -674,6 +704,7 @@ namestore_postgres_transaction_begin (void *cls,
674 char **emsg) 704 char **emsg)
675{ 705{
676 struct Plugin *plugin = cls; 706 struct Plugin *plugin = cls;
707 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
677 struct GNUNET_PQ_ExecuteStatement es[] = { 708 struct GNUNET_PQ_ExecuteStatement es[] = {
678 GNUNET_PQ_make_execute ("BEGIN"), 709 GNUNET_PQ_make_execute ("BEGIN"),
679 GNUNET_PQ_EXECUTE_STATEMENT_END 710 GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -695,6 +726,7 @@ namestore_postgres_transaction_rollback (void *cls,
695 char **emsg) 726 char **emsg)
696{ 727{
697 struct Plugin *plugin = cls; 728 struct Plugin *plugin = cls;
729 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
698 struct GNUNET_PQ_ExecuteStatement es[] = { 730 struct GNUNET_PQ_ExecuteStatement es[] = {
699 GNUNET_PQ_make_execute ("ROLLBACK"), 731 GNUNET_PQ_make_execute ("ROLLBACK"),
700 GNUNET_PQ_EXECUTE_STATEMENT_END 732 GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -716,6 +748,7 @@ namestore_postgres_transaction_commit (void *cls,
716 char **emsg) 748 char **emsg)
717{ 749{
718 struct Plugin *plugin = cls; 750 struct Plugin *plugin = cls;
751 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
719 struct GNUNET_PQ_ExecuteStatement es[] = { 752 struct GNUNET_PQ_ExecuteStatement es[] = {
720 GNUNET_PQ_make_execute ("COMMIT"), 753 GNUNET_PQ_make_execute ("COMMIT"),
721 GNUNET_PQ_EXECUTE_STATEMENT_END 754 GNUNET_PQ_EXECUTE_STATEMENT_END