diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-09-30 20:03:59 +0900 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-09-30 20:03:59 +0900 |
commit | 2754420df146495766e5efa8e8a8150ae904d209 (patch) | |
tree | b129092b8001c3235f1e23d29414736ac8a4891d | |
parent | 51b6cf4d3944152ea0c62a5aa41224f6227d62f7 (diff) | |
download | gnunet-2754420df146495766e5efa8e8a8150ae904d209.tar.gz gnunet-2754420df146495766e5efa8e8a8150ae904d209.zip |
-fix
-rw-r--r-- | src/namestore/plugin_namestore_postgres.c | 171 |
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 | |||
62 | static int | 67 | static int |
63 | init_database (struct Plugin *plugin, char **emsg, int drop) | 68 | init_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 | ||
165 | static int | ||
166 | database_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 |