Commit f71519e5 authored by Robert Haas's avatar Robert Haas

Refactor and generalize the ParallelSlot machinery.

Create a wrapper object, ParallelSlotArray, to encapsulate the
number of slots and the slot array itself, plus some other relevant
bits of information. This reduces the number of parameters we have
to pass around all over the place.

Allow for a ParallelSlotArray to contain slots connected to
different databases within a single cluster. The current clients
of this mechanism don't need this, but it is expected to be used
by future patches.

Defer connecting to databases until we actually need the connection
for something. This is a slight behavior change for vacuumdb and
reindexdb. If you specify a number of jobs that is larger than the
number of objects, the extra connections will now not be used.
But, on the other hand, if you specify a number of jobs that is
so large that it's going to fail, the failure would previously have
happened before any operations were actually started, and now it
won't.

Mark Dilger, reviewed by me.

Discussion: http://postgr.es/m/12ED3DA8-25F0-4B68-937D-D907CFBF08E7@enterprisedb.com
Discussion: http://postgr.es/m/BA592F2D-F928-46FF-9516-2B827F067F57@enterprisedb.com
parent 2c0cefcd
......@@ -36,7 +36,7 @@ static SimpleStringList *get_parallel_object_list(PGconn *conn,
ReindexType type,
SimpleStringList *user_list,
bool echo);
static void reindex_one_database(const ConnParams *cparams, ReindexType type,
static void reindex_one_database(ConnParams *cparams, ReindexType type,
SimpleStringList *user_list,
const char *progname,
bool echo, bool verbose, bool concurrently,
......@@ -330,7 +330,7 @@ main(int argc, char *argv[])
}
static void
reindex_one_database(const ConnParams *cparams, ReindexType type,
reindex_one_database(ConnParams *cparams, ReindexType type,
SimpleStringList *user_list,
const char *progname, bool echo,
bool verbose, bool concurrently, int concurrentCons,
......@@ -341,7 +341,7 @@ reindex_one_database(const ConnParams *cparams, ReindexType type,
bool parallel = concurrentCons > 1;
SimpleStringList *process_list = user_list;
ReindexType process_type = type;
ParallelSlot *slots;
ParallelSlotArray *sa;
bool failed = false;
int items_count = 0;
......@@ -461,7 +461,8 @@ reindex_one_database(const ConnParams *cparams, ReindexType type,
Assert(process_list != NULL);
slots = ParallelSlotsSetup(cparams, progname, echo, conn, concurrentCons);
sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL);
ParallelSlotsAdoptConn(sa, conn);
cell = process_list->head;
do
......@@ -475,7 +476,7 @@ reindex_one_database(const ConnParams *cparams, ReindexType type,
goto finish;
}
free_slot = ParallelSlotsGetIdle(slots, concurrentCons);
free_slot = ParallelSlotsGetIdle(sa, NULL);
if (!free_slot)
{
failed = true;
......@@ -489,7 +490,7 @@ reindex_one_database(const ConnParams *cparams, ReindexType type,
cell = cell->next;
} while (cell != NULL);
if (!ParallelSlotsWaitCompletion(slots, concurrentCons))
if (!ParallelSlotsWaitCompletion(sa))
failed = true;
finish:
......@@ -499,8 +500,8 @@ finish:
pg_free(process_list);
}
ParallelSlotsTerminate(slots, concurrentCons);
pfree(slots);
ParallelSlotsTerminate(sa);
pfree(sa);
if (failed)
exit(1);
......
......@@ -45,7 +45,7 @@ typedef struct vacuumingOptions
} vacuumingOptions;
static void vacuum_one_database(const ConnParams *cparams,
static void vacuum_one_database(ConnParams *cparams,
vacuumingOptions *vacopts,
int stage,
SimpleStringList *tables,
......@@ -408,7 +408,7 @@ main(int argc, char *argv[])
* a list of tables from the database.
*/
static void
vacuum_one_database(const ConnParams *cparams,
vacuum_one_database(ConnParams *cparams,
vacuumingOptions *vacopts,
int stage,
SimpleStringList *tables,
......@@ -421,13 +421,14 @@ vacuum_one_database(const ConnParams *cparams,
PGresult *res;
PGconn *conn;
SimpleStringListCell *cell;
ParallelSlot *slots;
ParallelSlotArray *sa;
SimpleStringList dbtables = {NULL, NULL};
int i;
int ntups;
bool failed = false;
bool tables_listed = false;
bool has_where = false;
const char *initcmd;
const char *stage_commands[] = {
"SET default_statistics_target=1; SET vacuum_cost_delay=0;",
"SET default_statistics_target=10; RESET vacuum_cost_delay;",
......@@ -684,26 +685,25 @@ vacuum_one_database(const ConnParams *cparams,
concurrentCons = 1;
/*
* Setup the database connections. We reuse the connection we already have
* for the first slot. If not in parallel mode, the first slot in the
* array contains the connection.
* All slots need to be prepared to run the appropriate analyze stage, if
* caller requested that mode. We have to prepare the initial connection
* ourselves before setting up the slots.
*/
slots = ParallelSlotsSetup(cparams, progname, echo, conn, concurrentCons);
if (stage == ANALYZE_NO_STAGE)
initcmd = NULL;
else
{
initcmd = stage_commands[stage];
executeCommand(conn, initcmd, echo);
}
/*
* Prepare all the connections to run the appropriate analyze stage, if
* caller requested that mode.
* Setup the database connections. We reuse the connection we already have
* for the first slot. If not in parallel mode, the first slot in the
* array contains the connection.
*/
if (stage != ANALYZE_NO_STAGE)
{
int j;
/* We already emitted the message above */
for (j = 0; j < concurrentCons; j++)
executeCommand((slots + j)->connection,
stage_commands[stage], echo);
}
sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, initcmd);
ParallelSlotsAdoptConn(sa, conn);
initPQExpBuffer(&sql);
......@@ -719,7 +719,7 @@ vacuum_one_database(const ConnParams *cparams,
goto finish;
}
free_slot = ParallelSlotsGetIdle(slots, concurrentCons);
free_slot = ParallelSlotsGetIdle(sa, NULL);
if (!free_slot)
{
failed = true;
......@@ -740,12 +740,12 @@ vacuum_one_database(const ConnParams *cparams,
cell = cell->next;
} while (cell != NULL);
if (!ParallelSlotsWaitCompletion(slots, concurrentCons))
if (!ParallelSlotsWaitCompletion(sa))
failed = true;
finish:
ParallelSlotsTerminate(slots, concurrentCons);
pg_free(slots);
ParallelSlotsTerminate(sa);
pg_free(sa);
termPQExpBuffer(&sql);
......
This diff is collapsed.
......@@ -21,7 +21,7 @@ typedef bool (*ParallelSlotResultHandler) (PGresult *res, PGconn *conn,
typedef struct ParallelSlot
{
PGconn *connection; /* One connection */
bool isFree; /* Is it known to be idle? */
bool inUse; /* Is the slot being used? */
/*
* Prior to issuing a command or query on 'connection', a handler callback
......@@ -33,6 +33,16 @@ typedef struct ParallelSlot
void *handler_context;
} ParallelSlot;
typedef struct ParallelSlotArray
{
int numslots;
ConnParams *cparams;
const char *progname;
bool echo;
const char *initcmd;
ParallelSlot slots[FLEXIBLE_ARRAY_MEMBER];
} ParallelSlotArray;
static inline void
ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler,
void *context)
......@@ -48,15 +58,18 @@ ParallelSlotClearHandler(ParallelSlot *slot)
slot->handler_context = NULL;
}
extern ParallelSlot *ParallelSlotsGetIdle(ParallelSlot *slots, int numslots);
extern ParallelSlot *ParallelSlotsGetIdle(ParallelSlotArray *slots,
const char *dbname);
extern ParallelSlot *ParallelSlotsSetup(const ConnParams *cparams,
extern ParallelSlotArray *ParallelSlotsSetup(int numslots, ConnParams *cparams,
const char *progname, bool echo,
PGconn *conn, int numslots);
const char *initcmd);
extern void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn);
extern void ParallelSlotsTerminate(ParallelSlot *slots, int numslots);
extern void ParallelSlotsTerminate(ParallelSlotArray *sa);
extern bool ParallelSlotsWaitCompletion(ParallelSlot *slots, int numslots);
extern bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa);
extern bool TableCommandResultHandler(PGresult *res, PGconn *conn,
void *context);
......
......@@ -404,6 +404,7 @@ ConfigData
ConfigVariable
ConnCacheEntry
ConnCacheKey
ConnParams
ConnStatusType
ConnType
ConnectionStateEnum
......@@ -1730,6 +1731,7 @@ ParallelHashJoinState
ParallelIndexScanDesc
ParallelReadyList
ParallelSlot
ParallelSlotArray
ParallelState
ParallelTableScanDesc
ParallelTableScanDescData
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment