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

Commit 5f38403

Browse files
committed
Refactor parallelization processing code in src/bin/scripts/
The existing facility of vacuumdb to handle parallel connections into a given database with an authentication set is moved to a common file in src/bin/scripts/, named scripts_parallel.c. This introduces a set of routines to initialize, wait and terminate a set of connections, simplifying a bit the code of vacuumdb on the way. More routines related to result handling and database connection are moved to common.c. The initial plan is to use that for reindexdb, but it could be applied to other tools like clusterdb. While on it, clean up a set of variables "progname" which were defined as routine arguments for error messages. Since most of the callers have switched to pg_log_error() and such there is no need for this variable. Author: Julien Rouhaud Reviewed-by: Michael Paquier, Álvaro Herrera Discussion: https://postgr.es/m/CAOBaU_YrnH_Jqo46NhaJ7uRBiWWEcS40VNRQxgFbqYo9kApUsg@mail.gmail.com
1 parent b538c90 commit 5f38403

File tree

8 files changed

+446
-383
lines changed

8 files changed

+446
-383
lines changed

src/bin/scripts/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ createuser: createuser.o common.o $(WIN32RES) | submake-libpq submake-libpgport
2828
dropdb: dropdb.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
2929
dropuser: dropuser.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
3030
clusterdb: clusterdb.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
31-
vacuumdb: vacuumdb.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
31+
vacuumdb: vacuumdb.o common.o scripts_parallel.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
3232
reindexdb: reindexdb.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
3333
pg_isready: pg_isready.o common.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
3434

@@ -50,7 +50,7 @@ uninstall:
5050

5151
clean distclean maintainer-clean:
5252
rm -f $(addsuffix $(X), $(PROGRAMS)) $(addsuffix .o, $(PROGRAMS))
53-
rm -f common.o $(WIN32RES)
53+
rm -f common.o scripts_parallel.o $(WIN32RES)
5454
rm -rf tmp_check
5555

5656
check:

src/bin/scripts/clusterdb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ cluster_one_database(const char *dbname, bool verbose, const char *table,
206206
if (table)
207207
{
208208
appendPQExpBufferChar(&sql, ' ');
209-
appendQualifiedRelation(&sql, table, conn, progname, echo);
209+
appendQualifiedRelation(&sql, table, conn, echo);
210210
}
211211
appendPQExpBufferChar(&sql, ';');
212212

@@ -239,7 +239,7 @@ cluster_all_databases(bool verbose, const char *maintenance_db,
239239

240240
conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
241241
prompt_password, progname, echo);
242-
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
242+
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
243243
PQfinish(conn);
244244

245245
initPQExpBuffer(&connstr);

src/bin/scripts/common.c

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "fe_utils/connect.h"
2323
#include "fe_utils/string_utils.h"
2424

25+
#define ERRCODE_UNDEFINED_TABLE "42P01"
26+
2527

2628
static PGcancel *volatile cancelConn = NULL;
2729
bool CancelRequested = false;
@@ -146,8 +148,7 @@ connectDatabase(const char *dbname, const char *pghost,
146148
exit(1);
147149
}
148150

149-
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL,
150-
progname, echo));
151+
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
151152

152153
return conn;
153154
}
@@ -178,11 +179,35 @@ connectMaintenanceDatabase(const char *maintenance_db,
178179
return conn;
179180
}
180181

182+
/*
183+
* Disconnect the given connection, canceling any statement if one is active.
184+
*/
185+
void
186+
disconnectDatabase(PGconn *conn)
187+
{
188+
char errbuf[256];
189+
190+
Assert(conn != NULL);
191+
192+
if (PQtransactionStatus(conn) == PQTRANS_ACTIVE)
193+
{
194+
PGcancel *cancel;
195+
196+
if ((cancel = PQgetCancel(conn)))
197+
{
198+
(void) PQcancel(cancel, errbuf, sizeof(errbuf));
199+
PQfreeCancel(cancel);
200+
}
201+
}
202+
203+
PQfinish(conn);
204+
}
205+
181206
/*
182207
* Run a query, return the results, exit program on failure.
183208
*/
184209
PGresult *
185-
executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
210+
executeQuery(PGconn *conn, const char *query, bool echo)
186211
{
187212
PGresult *res;
188213

@@ -207,8 +232,7 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
207232
* As above for a SQL command (which returns nothing).
208233
*/
209234
void
210-
executeCommand(PGconn *conn, const char *query,
211-
const char *progname, bool echo)
235+
executeCommand(PGconn *conn, const char *query, bool echo)
212236
{
213237
PGresult *res;
214238

@@ -255,6 +279,57 @@ executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
255279
return r;
256280
}
257281

282+
/*
283+
* Consume all the results generated for the given connection until
284+
* nothing remains. If at least one error is encountered, return false.
285+
* Note that this will block if the connection is busy.
286+
*/
287+
bool
288+
consumeQueryResult(PGconn *conn)
289+
{
290+
bool ok = true;
291+
PGresult *result;
292+
293+
SetCancelConn(conn);
294+
while ((result = PQgetResult(conn)) != NULL)
295+
{
296+
if (!processQueryResult(conn, result))
297+
ok = false;
298+
}
299+
ResetCancelConn();
300+
return ok;
301+
}
302+
303+
/*
304+
* Process (and delete) a query result. Returns true if there's no error,
305+
* false otherwise -- but errors about trying to work on a missing relation
306+
* are reported and subsequently ignored.
307+
*/
308+
bool
309+
processQueryResult(PGconn *conn, PGresult *result)
310+
{
311+
/*
312+
* If it's an error, report it. Errors about a missing table are harmless
313+
* so we continue processing; but die for other errors.
314+
*/
315+
if (PQresultStatus(result) != PGRES_COMMAND_OK)
316+
{
317+
char *sqlState = PQresultErrorField(result, PG_DIAG_SQLSTATE);
318+
319+
pg_log_error("processing of database \"%s\" failed: %s",
320+
PQdb(conn), PQerrorMessage(conn));
321+
322+
if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) != 0)
323+
{
324+
PQclear(result);
325+
return false;
326+
}
327+
}
328+
329+
PQclear(result);
330+
return true;
331+
}
332+
258333

259334
/*
260335
* Split TABLE[(COLUMNS)] into TABLE and [(COLUMNS)] portions. When you
@@ -299,7 +374,7 @@ splitTableColumnsSpec(const char *spec, int encoding,
299374
*/
300375
void
301376
appendQualifiedRelation(PQExpBuffer buf, const char *spec,
302-
PGconn *conn, const char *progname, bool echo)
377+
PGconn *conn, bool echo)
303378
{
304379
char *table;
305380
const char *columns;
@@ -324,15 +399,15 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec,
324399
appendStringLiteralConn(&sql, table, conn);
325400
appendPQExpBufferStr(&sql, "::pg_catalog.regclass;");
326401

327-
executeCommand(conn, "RESET search_path;", progname, echo);
402+
executeCommand(conn, "RESET search_path;", echo);
328403

329404
/*
330405
* One row is a typical result, as is a nonexistent relation ERROR.
331406
* regclassin() unconditionally accepts all-digits input as an OID; if no
332407
* relation has that OID; this query returns no rows. Catalog corruption
333408
* might elicit other row counts.
334409
*/
335-
res = executeQuery(conn, sql.data, progname, echo);
410+
res = executeQuery(conn, sql.data, echo);
336411
ntups = PQntuples(res);
337412
if (ntups != 1)
338413
{
@@ -351,8 +426,7 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec,
351426
termPQExpBuffer(&sql);
352427
pg_free(table);
353428

354-
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL,
355-
progname, echo));
429+
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
356430
}
357431

358432

src/bin/scripts/common.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,24 @@ extern PGconn *connectMaintenanceDatabase(const char *maintenance_db,
3939
const char *pguser, enum trivalue prompt_password,
4040
const char *progname, bool echo);
4141

42-
extern PGresult *executeQuery(PGconn *conn, const char *query,
43-
const char *progname, bool echo);
42+
extern void disconnectDatabase(PGconn *conn);
4443

45-
extern void executeCommand(PGconn *conn, const char *query,
46-
const char *progname, bool echo);
44+
extern PGresult *executeQuery(PGconn *conn, const char *query, bool echo);
45+
46+
extern void executeCommand(PGconn *conn, const char *query, bool echo);
4747

4848
extern bool executeMaintenanceCommand(PGconn *conn, const char *query,
4949
bool echo);
5050

51+
extern bool consumeQueryResult(PGconn *conn);
52+
53+
extern bool processQueryResult(PGconn *conn, PGresult *result);
54+
5155
extern void splitTableColumnsSpec(const char *spec, int encoding,
5256
char **table, const char **columns);
5357

5458
extern void appendQualifiedRelation(PQExpBuffer buf, const char *name,
55-
PGconn *conn, const char *progname, bool echo);
59+
PGconn *conn, bool echo);
5660

5761
extern bool yesno_prompt(const char *question);
5862

src/bin/scripts/reindexdb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ reindex_one_database(const char *name, const char *dbname, ReindexType type,
348348
break;
349349
case REINDEX_INDEX:
350350
case REINDEX_TABLE:
351-
appendQualifiedRelation(&sql, name, conn, progname, echo);
351+
appendQualifiedRelation(&sql, name, conn, echo);
352352
break;
353353
case REINDEX_SCHEMA:
354354
appendPQExpBufferStr(&sql, name);
@@ -405,7 +405,7 @@ reindex_all_databases(const char *maintenance_db,
405405

406406
conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
407407
prompt_password, progname, echo);
408-
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
408+
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
409409
PQfinish(conn);
410410

411411
initPQExpBuffer(&connstr);

0 commit comments

Comments
 (0)