Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 46639d6

Browse files
committed
Merge commit '0421001d2d784ae4e6100a689c516cda8b177209' into PGPROEE10_pg_shardman
2 parents dd44cc9 + 0421001 commit 46639d6

File tree

8 files changed

+2620
-928
lines changed

8 files changed

+2620
-928
lines changed

contrib/pg_shardman/conf.add

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
shared_preload_libraries='pg_pathman'
1+
shared_preload_libraries='pg_shardman, pg_pathman'

contrib/pg_shardman/pg_shardman--0.0.2.sql

Lines changed: 1137 additions & 458 deletions
Large diffs are not rendered by default.

contrib/pg_shardman/pg_shardman.c

Lines changed: 124 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@
77
* -------------------------------------------------------------------------
88
*/
99
#include "postgres.h"
10-
#include "libpq-fe.h"
11-
#include "miscadmin.h"
10+
11+
#include "access/htup_details.h"
12+
#include "access/xact.h"
13+
#include "access/xlog.h"
14+
#include "catalog/pg_type.h"
15+
#include "commands/event_trigger.h"
1216
#include "executor/spi.h"
1317
#include "funcapi.h"
18+
#include "libpq-fe.h"
19+
#include "miscadmin.h"
1420
#include "pgstat.h"
21+
#include "storage/latch.h"
1522
#include "utils/guc.h"
1623
#include "utils/rel.h"
1724
#include "utils/builtins.h"
1825
#include "utils/lsyscache.h"
19-
#include "catalog/pg_type.h"
20-
#include "access/htup_details.h"
21-
#include "access/xlog.h"
22-
#include "storage/latch.h"
2326

2427
/* ensure that extension won't load against incompatible version of Postgres */
2528
PG_MODULE_MAGIC;
@@ -31,6 +34,7 @@ PG_FUNCTION_INFO_V1(broadcast);
3134
PG_FUNCTION_INFO_V1(reconstruct_table_attrs);
3235
PG_FUNCTION_INFO_V1(pq_conninfo_parse);
3336
PG_FUNCTION_INFO_V1(get_system_identifier);
37+
PG_FUNCTION_INFO_V1(reset_synchronous_standby_names_on_commit);
3438

3539
/* GUC variables */
3640
static bool is_lord;
@@ -39,6 +43,11 @@ static char *shardlord_connstring;
3943

4044
extern void _PG_init(void);
4145

46+
static bool reset_ssn_callback_set = false;
47+
static bool reset_ssn_requested = false;
48+
49+
static void reset_ssn_xact_callback(XactEvent event, void *arg);
50+
4251
/*
4352
* Entrypoint of the module. Define GUCs.
4453
*/
@@ -75,6 +84,15 @@ _PG_init()
7584
PGC_SUSET,
7685
0,
7786
NULL, NULL, NULL);
87+
88+
/*
89+
* Tell pathman that we want it to do shardman-specific COPY FROM: that
90+
* is, support copy to foreign partitions by copying to foreign parent.
91+
* For now we just ask to do it always. Better to turn on this in copy
92+
* hook turn off after, however for that we need metadata on all nodes.
93+
*/
94+
*find_rendezvous_variable(
95+
"shardman_pathman_copy_from_rendezvous") = DatumGetPointer(1);
7896
}
7997

8098
Datum
@@ -95,6 +113,10 @@ is_shardlord(PG_FUNCTION_ARGS)
95113
PG_RETURN_BOOL(is_lord);
96114
}
97115

116+
/*
117+
* Wait until PQgetResult would certainly be non-blocking. Returns true if
118+
* everything is ok, false on error.
119+
*/
98120
static bool
99121
wait_command_completion(PGconn* conn)
100122
{
@@ -119,7 +141,7 @@ wait_command_completion(PGconn* conn)
119141
return false;
120142
}
121143
}
122-
return true;
144+
return true;
123145
}
124146

125147
typedef struct
@@ -139,22 +161,25 @@ broadcast(PG_FUNCTION_ARGS)
139161
bool sync_commit_on = PG_GETARG_BOOL(3);
140162
bool sequential = PG_GETARG_BOOL(4);
141163
bool super_connstr = PG_GETARG_BOOL(5);
164+
char* iso_level = (PG_GETARG_POINTER(6) != NULL) ?
165+
text_to_cstring(PG_GETARG_TEXT_PP(6)) : NULL;
142166
char* sep;
143167
char* sql;
144168
PGresult *res;
145169
char* fetch_node_connstr;
146170
int rc;
147171
int node_id;
148-
int n;
172+
int n;
149173
char* conn_str;
150174
int n_cmds = 0;
151175
int i;
152-
int n_cons = 1024;
176+
int n_cons = 1024; /* num of channels allocated currently */
153177
Channel* chan;
154178
PGconn* con;
155179
StringInfoData resp;
180+
StringInfoData fin_sql;
156181

157-
char const* errmsg = "";
182+
char const* errstr = "";
158183

159184
elog(DEBUG1, "Broadcast commmand '%s'", cmd);
160185

@@ -163,6 +188,7 @@ broadcast(PG_FUNCTION_ARGS)
163188
SPI_connect();
164189
chan = (Channel*) palloc(sizeof(Channel) * n_cons);
165190

191+
/* Open connections and send all queries */
166192
while ((sep = strchr(cmd, *cmd == '{' ? '}' : ';')) != NULL)
167193
{
168194
*sep = '\0';
@@ -171,9 +197,10 @@ broadcast(PG_FUNCTION_ARGS)
171197
cmd += 1;
172198
rc = sscanf(cmd, "%d:%n", &node_id, &n);
173199
if (rc != 1) {
174-
elog(ERROR, "SHARDMAN: Invalid command string: '%s' in '%s'", cmd, sql_full);
200+
elog(ERROR, "SHARDMAN: Invalid command string: '%s' in '%s'",
201+
cmd, sql_full);
175202
}
176-
sql = cmd + n;
203+
sql = cmd + n; /* eat node id and colon */
177204
cmd = sep + 1;
178205
if (node_id != 0)
179206
{
@@ -187,7 +214,8 @@ broadcast(PG_FUNCTION_ARGS)
187214
}
188215
pfree(fetch_node_connstr);
189216

190-
conn_str = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
217+
conn_str = SPI_getvalue(SPI_tuptable->vals[0],
218+
SPI_tuptable->tupdesc, 1);
191219
}
192220
else
193221
{
@@ -212,39 +240,40 @@ broadcast(PG_FUNCTION_ARGS)
212240
{
213241
if (ignore_errors)
214242
{
215-
errmsg = psprintf("%s<error>%d:Connection failure: %s</error>",
216-
errmsg, node_id, PQerrorMessage(con));
243+
errstr = psprintf("%s<error>%d:Connection failure: %s</error>",
244+
errstr, node_id, PQerrorMessage(con));
217245
chan[n_cmds-1].sql = NULL;
218246
continue;
219247
}
220-
errmsg = psprintf("Failed to connect to node %d: %s", node_id,
248+
errstr = psprintf("Failed to connect to node %d: %s", node_id,
221249
PQerrorMessage(con));
222250
goto cleanup;
223251
}
252+
/* Build the actual sql to send, mem freed with ctxt */
253+
initStringInfo(&fin_sql);
224254
if (!sync_commit_on)
225-
{
226-
/* mem freed with context */
227-
if (two_phase)
228-
{
229-
sql = psprintf("SET SESSION synchronous_commit TO local; BEGIN; %s; PREPARE TRANSACTION 'shardlord';", sql);
230-
}
231-
else
232-
{
233-
sql = psprintf("SET SESSION synchronous_commit TO local; %s", sql);
234-
}
235-
}
236-
elog(DEBUG1, "Send command '%s' to node %d", sql, node_id);
237-
if (!PQsendQuery(con, sql)
255+
appendStringInfoString(&fin_sql, "SET SESSION synchronous_commit TO local; ");
256+
if (iso_level)
257+
appendStringInfo(&fin_sql, "BEGIN TRANSACTION ISOLATION LEVEL %s; ", iso_level);
258+
appendStringInfoString(&fin_sql, sql);
259+
appendStringInfoChar(&fin_sql, ';'); /* it was removed after strchr */
260+
if (two_phase)
261+
appendStringInfoString(&fin_sql, "PREPARE TRANSACTION 'shardlord';");
262+
else if (iso_level)
263+
appendStringInfoString(&fin_sql, "END;");
264+
265+
elog(DEBUG1, "Sending command '%s' to node %d", fin_sql.data, node_id);
266+
if (!PQsendQuery(con, fin_sql.data)
238267
|| (sequential && !wait_command_completion(con)))
239268
{
240269
if (ignore_errors)
241270
{
242-
errmsg = psprintf("%s<error>%d:Failed to send query '%s': %s</error>",
243-
errmsg, node_id, sql, PQerrorMessage(con));
271+
errstr = psprintf("%s<error>%d:Failed to send query '%s': %s</error>",
272+
errstr, node_id, fin_sql.data, PQerrorMessage(con));
244273
chan[n_cmds-1].sql = NULL;
245274
continue;
246275
}
247-
errmsg = psprintf("Failed to send query '%s' to node %d: %s'", sql,
276+
errstr = psprintf("Failed to send query '%s' to node %d: %s'", fin_sql.data,
248277
node_id, PQerrorMessage(con));
249278
goto cleanup;
250279
}
@@ -255,6 +284,9 @@ broadcast(PG_FUNCTION_ARGS)
255284
elog(ERROR, "SHARDMAN: Junk at end of command list: %s", cmd);
256285
}
257286

287+
/*
288+
* Now collect results
289+
*/
258290
for (i = 0; i < n_cmds; i++)
259291
{
260292
PGresult* next_res;
@@ -269,6 +301,7 @@ broadcast(PG_FUNCTION_ARGS)
269301
continue;
270302
}
271303

304+
/* Skip all but the last result */
272305
while ((next_res = PQgetResult(con)) != NULL)
273306
{
274307
if (res != NULL)
@@ -277,31 +310,32 @@ broadcast(PG_FUNCTION_ARGS)
277310
}
278311
res = next_res;
279312
}
313+
280314
if (res == NULL)
281315
{
282316
if (ignore_errors)
283317
{
284-
errmsg = psprintf("%s<error>%d:Failed to received response for '%s': %s</error>",
285-
errmsg, chan[i].node, chan[i].sql, PQerrorMessage(con));
318+
errstr = psprintf("%s<error>%d:Failed to received response for '%s': %s</error>",
319+
errstr, chan[i].node, chan[i].sql, PQerrorMessage(con));
286320
continue;
287321
}
288-
errmsg = psprintf("Failed to receive response for query %s from node %d: %s",
322+
errstr = psprintf("Failed to receive response for query %s from node %d: %s",
289323
chan[i].sql, chan[i].node, PQerrorMessage(con));
290324
goto cleanup;
291325
}
292326

293-
/* Ok, result was successfully fetched */
327+
/* Ok, result was successfully fetched, add it to resp */
294328
status = PQresultStatus(res);
295329
if (status != PGRES_TUPLES_OK && status != PGRES_COMMAND_OK)
296330
{
297331
if (ignore_errors)
298332
{
299-
errmsg = psprintf("%s<error>%d:Command %s failed: %s</error>",
300-
errmsg, chan[i].node, chan[i].sql, PQerrorMessage(con));
333+
errstr = psprintf("%s<error>%d:Command %s failed: %s</error>",
334+
errstr, chan[i].node, chan[i].sql, PQerrorMessage(con));
301335
PQclear(res);
302336
continue;
303337
}
304-
errmsg = psprintf("Command %s failed at node %d: %s",
338+
errstr = psprintf("Command %s failed at node %d: %s",
305339
chan[i].sql, chan[i].node, PQerrorMessage(con));
306340
PQclear(res);
307341
goto cleanup;
@@ -322,7 +356,7 @@ broadcast(PG_FUNCTION_ARGS)
322356
}
323357
else
324358
{
325-
errmsg = psprintf("Query '%s' doesn't return single tuple at node %d",
359+
errstr = psprintf("Query '%s' doesn't return single tuple at node %d",
326360
chan[i].sql, chan[i].node);
327361
PQclear(res);
328362
goto cleanup;
@@ -339,13 +373,14 @@ broadcast(PG_FUNCTION_ARGS)
339373
}
340374
PQclear(res);
341375
}
376+
342377
cleanup:
343378
for (i = 0; i < n_cmds; i++)
344379
{
345380
con = chan[i].con;
346381
if (two_phase)
347382
{
348-
if (*errmsg)
383+
if (*errstr)
349384
{
350385
res = PQexec(con, "ROLLBACK PREPARED 'shardlord'");
351386
if (PQresultStatus(res) != PGRES_COMMAND_OK)
@@ -369,17 +404,19 @@ broadcast(PG_FUNCTION_ARGS)
369404
PQfinish(con);
370405
}
371406

372-
if (*errmsg)
407+
if (*errstr)
373408
{
374409
if (ignore_errors)
375410
{
376411
resetStringInfo(&resp);
377-
appendStringInfoString(&resp, errmsg);
378-
elog(WARNING, "SHARDMAN: %s", errmsg);
412+
appendStringInfoString(&resp, errstr);
413+
elog(WARNING, "SHARDMAN: %s", errstr);
379414
}
380415
else
381416
{
382-
elog(ERROR, "SHARDMAN: %s", errmsg);
417+
ereport(ERROR,
418+
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
419+
errmsg("SHARDMAN: %s", errstr)));
383420
}
384421
}
385422

@@ -605,3 +642,45 @@ get_system_identifier(PG_FUNCTION_ARGS)
605642
{
606643
PG_RETURN_INT64(GetSystemIdentifier());
607644
}
645+
646+
/*
647+
* Execute "ALTER SYSTEM SET synchronous_standby_names = '' on commit"
648+
*/
649+
Datum
650+
reset_synchronous_standby_names_on_commit(PG_FUNCTION_ARGS)
651+
{
652+
if (!reset_ssn_callback_set)
653+
RegisterXactCallback(reset_ssn_xact_callback, NULL);
654+
reset_ssn_requested = true;
655+
PG_RETURN_VOID();
656+
}
657+
658+
static void
659+
reset_ssn_xact_callback(XactEvent event, void *arg)
660+
{
661+
if (reset_ssn_requested)
662+
{
663+
/* I just wanted to practice a bit with PG nodes and lists */
664+
A_Const *aconst = makeNode(A_Const);
665+
List *set_stmt_args = list_make1(aconst);
666+
VariableSetStmt setstmt;
667+
AlterSystemStmt altersysstmt;
668+
669+
aconst->val.type = T_String;
670+
aconst->val.val.str = ""; /* set it to empty value */
671+
aconst->location = -1;
672+
673+
setstmt.type = T_VariableSetStmt;
674+
setstmt.kind = VAR_SET_VALUE;
675+
setstmt.name = "synchronous_standby_names";
676+
setstmt.args = set_stmt_args;
677+
678+
altersysstmt.type = T_AlterSystemStmt;
679+
altersysstmt.setstmt = &setstmt;
680+
AlterSystemSetConfigFile(&altersysstmt);
681+
pg_reload_conf(NULL);
682+
683+
list_free_deep(setstmt.args);
684+
reset_ssn_requested = false;
685+
}
686+
}

contrib/pg_shardman/postgresql.conf.common

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
shared_preload_libraries = 'pg_pathman'
1+
shared_preload_libraries = 'pg_shardman, pg_pathman'
22

33
shardman.shardlord_connstring = 'port=5432' # shardlord's connstring
44

contrib/pg_shardman/postgresql.conf.worker

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ synchronous_commit = on
2222
# for 2pc
2323
max_prepared_transactions = 1000
2424
postgres_fdw.use_2pc = on
25-
# only for testing performace; setting this to 'on' violates visibility
25+
# only for testing performance; setting this to 'off' violates visibility
2626
postgres_fdw.use_repeatable_read = off
2727

2828
# This node is shardlord?

0 commit comments

Comments
 (0)