blob: 976873bad10c596ee5edfdca670f6c0296ca9038 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* cdb_seginst.c
*
* Structures and functions to read a join of cdb_seg, cdb_instance, and
* gp_segment_instance tables using libpq
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "pqexpbuffer.h"
#include "libpq-fe.h"
#include <regex.h>
#include <sys/stat.h>
#include <limits.h>
#include <assert.h>
#include "cdb_dump_util.h"
#include "cdb_table.h"
#include "cdb_seginst.h"
/* FreeSegmentDatabaseArray: This function frees the memory allocated for ther pSegDBAr->pData array,
* and the strings that were allocated for each element in the array
* It does NOT free the pSegDBAr itself.
*/
void
FreeSegmentDatabaseArray(SegmentDatabaseArray *pSegDBAr)
{
int i;
if (pSegDBAr == NULL)
return;
for (i = 0; i < pSegDBAr->count; i++)
{
SegmentDatabase *pSegDB = &pSegDBAr->pData[i];
if (pSegDB->pszHost != NULL)
free(pSegDB->pszHost);
}
if (pSegDBAr->pData != NULL)
free(pSegDBAr->pData);
pSegDBAr->count = 0;
pSegDBAr->pData = NULL;
}
void
FreeRestorePairArray(RestorePairArray * restorePairAr)
{
if (restorePairAr == NULL)
return;
if (restorePairAr->pData != NULL)
free(restorePairAr->pData);
restorePairAr->count = 0;
restorePairAr->pData = NULL;
}
/* GetSegmentDatabaseArray: This function reads all active instance segment pairs
* from the function gp_segment_instance_map().
* It then uses the set specification fo filter out any instid, segid combinations
* that don't match the set. bExcludeHead = true is used for restoring, because
* the head is restored first seperately from the rest of the databases.
*/
bool
GetDumpSegmentDatabaseArray(PGconn *pConn,
int remote_version,
SegmentDatabaseArray *pSegDBAr,
ActorSet actors,
char *dump_set_str,
bool dataOnly,
bool schemaOnly)
{
bool bRtn = true;
PQExpBuffer pQry = NULL;
PGresult *pRes = NULL;
int ntups;
int count;
int i_dbid;
int i_content;
int i_host;
int i_port;
int i;
int j;
int x;
int dbidset_count = 0;
int *dbidset = NULL;
SegmentDatabase *pSegDB;
pQry = createPQExpBuffer();
if (remote_version >= 80214)
/* 4.0 and beyond */
appendPQExpBuffer(pQry, "SELECT"
" dbid,"
" content,"
" hostname,"
" port "
"FROM "
" gp_segment_configuration "
"WHERE role='p' "
"ORDER BY content DESC");
else
/* pre 4.0 */
appendPQExpBuffer(pQry, "SELECT"
" dbid,"
" content,"
" hostname,"
" port "
"FROM"
" gp_configuration "
"WHERE valid = 't' "
"AND isPrimary = 't' "
"ORDER BY content DESC");
pRes = PQexec(pConn, pQry->data);
if (!pRes || PQresultStatus(pRes) != PGRES_TUPLES_OK)
{
mpp_err_msg("ERROR", "gp_dump", "query to obtain list of Greenplum segment databases failed: %s",
PQerrorMessage(pConn));
bRtn = false;
goto cleanup;
}
ntups = PQntuples(pRes);
if (ntups <= 0)
{
mpp_err_msg("ERROR", "gp_dump", "no Greenplum segment databases found on master segment schema");
bRtn = false;
goto cleanup;
}
count = ntups + 1;
/*
* See how many set elements there are that were specified by HostIP or
* name.
*/
/*
* Allocate enough memory for all of them, even though some may be
* filtered out.
*/
pSegDBAr->count = 0;
pSegDBAr->pData = (SegmentDatabase *) calloc(count, sizeof(SegmentDatabase));
if (pSegDBAr->pData == NULL)
{
mpp_err_msg("ERROR", "gp_dump", "Unable to allocate memory for Greenplum segment/instances information\n");
bRtn = false;
goto cleanup;
}
/* get the column numbers */
i_dbid = PQfnumber(pRes, "dbid");
i_content = PQfnumber(pRes, "content");
i_host = PQfnumber(pRes, "hostname");
i_port = PQfnumber(pRes, "port");
/*
* if an individual set of dbid's was requested to be dumped, parse it and
* check that it really exists and is a primary segment.
*/
if (actors == SET_INDIVIDUAL)
{
/* allocate dbidset. len is more than we need but it's a safe bet */
dbidset = (int *) calloc(strlen(dump_set_str), sizeof(int));
MemSet(dbidset, 0, strlen(dump_set_str) * sizeof(int));
if (dbidset == NULL)
{
mpp_err_msg("ERROR", "gp_dump", "Unable to allocate memory for Greenplum dbid set information\n");
bRtn = false;
goto cleanup;
}
/* parse the user specified dbid list, return dbid count */
dbidset_count = parseDbidSet(dbidset, dump_set_str);
if (dbidset_count < 1)
{
bRtn = false;
goto cleanup;
}
for (i = 0; i < dbidset_count; i++)
{
bool match = false;
for (j = 0; j < ntups; j++)
{
int dbid = atoi(PQgetvalue(pRes, j, i_dbid));
if (dbid == dbidset[i])
{
match = true;
break;
}
}
if (!match)
{
mpp_err_msg("ERROR", "gp_dump", "dbid %d is not a correct Greenplum segment databases "
"entry, or is not a primary segment\n ", dbidset[i]);
bRtn = false;
goto cleanup;
}
}
}
mpp_err_msg("INFO", "gp_dump", "Preparing to dump the following segments:\n");
/* Read through the results set (all primary segments) */
x = 0;
for (i = 0; i < ntups; i++)
{
int dbid = atoi(PQgetvalue(pRes, i, i_dbid));
int content = atoi(PQgetvalue(pRes, i, i_content));
bool should_dump = false;
/* in dataOnly we don't dump master information */
if (dataOnly && content == -1 && actors != SET_INDIVIDUAL)
continue;
/* in schemaOnly we skip all but the master */
if (schemaOnly && content != -1 && actors != SET_INDIVIDUAL)
continue;
if (actors == SET_INDIVIDUAL)
{
should_dump = false;
for (j = 0; j < dbidset_count; j++)
{
if (dbid == dbidset[j])
should_dump = true;
}
if (!should_dump)
continue;
}
pSegDB = &pSegDBAr->pData[x++];
pSegDB->dbid = dbid;
pSegDB->content = content;
pSegDB->role = (content == -1 ? ROLE_MASTER : ROLE_SEGDB);
pSegDB->port = atoi(PQgetvalue(pRes, i, i_port));
pSegDB->pszHost = strdup(PQgetvalue(pRes, i, i_host));
pSegDB->pszDBName = PQdb(pConn);
pSegDB->pszDBUser = PQuser(pConn);
pSegDB->pszDBPswd = PQpass(pConn);
if (pSegDB->role == ROLE_MASTER)
mpp_err_msg("INFO", "gp_dump", "Master (dbid 1)\n");
else
mpp_err_msg("INFO", "gp_dump", "Segment %d (dbid %d)\n",
pSegDB->content,
pSegDB->dbid);
}
/* set the count to be the number that passed the set inclusion test */
pSegDBAr->count = x;
cleanup:
if (pQry != NULL)
destroyPQExpBuffer(pQry);
if (pRes != NULL)
PQclear(pRes);
return bRtn;
}
bool
GetRestoreSegmentDatabaseArray(PGconn *pConn,
RestorePairArray * restorePairAr,
BackupLoc backupLocation,
char *restore_set_str,
bool dataOnly)
{
bool bRtn = true;
PQExpBuffer pQry = NULL;
PGresult *pRes = NULL;
int ntups;
int count;
int i_dbid;
int i_content;
int i_host;
int i_port;
int i;
int j;
int x;
int dbidset_count = 0;
int *dbidset = NULL;
SegmentDatabase *sourceSegDB;
SegmentDatabase *targetSegDB;
pQry = createPQExpBuffer();
appendPQExpBuffer(pQry, "SELECT"
" dbid,"
" content,"
" hostname,"
" port "
"FROM "
" gp_segment_configuration "
"WHERE role='p' "
"ORDER BY content DESC");
pRes = PQexec(pConn, pQry->data);
if (!pRes || PQresultStatus(pRes) != PGRES_TUPLES_OK)
{
mpp_err_msg("ERROR", "gp_restore", "query to obtain list of Greenplum segment databases failed: %s",
PQerrorMessage(pConn));
bRtn = false;
goto cleanup;
}
ntups = PQntuples(pRes);
if (ntups <= 0)
{
mpp_err_msg("ERROR", "gp_restore", "no Greenplum segment databases found on master segment schema");
bRtn = false;
goto cleanup;
}
count = ntups + 1;
/*
* Allocate enough memory for all of them, even though some may be
* filtered out.
*/
restorePairAr->count = 0;
restorePairAr->pData = (RestorePair *) calloc(count, sizeof(RestorePair));
if (restorePairAr->pData == NULL)
{
mpp_err_msg("ERROR", "gp_restore", "Unable to allocate memory for Greenplum segment database information\n");
bRtn = false;
goto cleanup;
}
/* get the column numbers */
i_dbid = PQfnumber(pRes, "dbid");
i_content = PQfnumber(pRes, "content");
i_host = PQfnumber(pRes, "hostname");
i_port = PQfnumber(pRes, "port");
/*
* if the dump file is on individual databases, parse the list of dbid's
* where those files exist.
*/
if (backupLocation == FILE_ON_INDIVIDUAL)
{
/* allocate dbidset. len is more than we need but it's a safe bet */
dbidset = (int *) calloc(strlen(restore_set_str), sizeof(int));
MemSet(dbidset, 0, strlen(restore_set_str) * sizeof(int));
if (dbidset == NULL)
{
mpp_err_msg("ERROR", "gp_restore", "Unable to allocate memory for Greenplum dbidset information\n");
bRtn = false;
goto cleanup;
}
/* parse the user specified dbid list, return dbid count */
dbidset_count = parseDbidSet(dbidset, restore_set_str);
if (dbidset_count < 1)
{
bRtn = false;
goto cleanup;
}
for (i = 0; i < dbidset_count; i++)
{
bool match = false;
for (j = 0; j < ntups; j++)
{
int dbid = atoi(PQgetvalue(pRes, j, i_dbid));
if (dbid == dbidset[i])
{
match = true;
break;
}
}
if (!match)
{
mpp_err_msg("ERROR", "gp_restore", "dbid %d is not a primary Greenplum segment databases entry\n",
dbidset[i]);
bRtn = false;
goto cleanup;
}
}
}
mpp_err_msg("INFO", "gp_restore", "Preparing to restore the following segments:\n");
/* Read through the results set. */
x = 0;
for (i = 0; i < ntups; i++)
{
int dbid = atoi(PQgetvalue(pRes, i, i_dbid));
int contentid = atoi(PQgetvalue(pRes, i, i_content));
bool should_restore = false;
/* if dataOnly don't restore the master (table definitions) */
if (dataOnly && contentid == -1)
continue;
if (backupLocation == FILE_ON_INDIVIDUAL)
{
should_restore = false;
for (j = 0; j < dbidset_count; j++)
{
if (dbid == dbidset[j])
should_restore = true;
}
if (!should_restore)
continue;
}
targetSegDB = &restorePairAr->pData[x].segdb_target;
targetSegDB->dbid = dbid;
targetSegDB->role = (contentid == -1 ? ROLE_MASTER : ROLE_SEGDB);
targetSegDB->port = atoi(PQgetvalue(pRes, i, i_port));
targetSegDB->pszHost = strdup(PQgetvalue(pRes, i, i_host));
targetSegDB->pszDBName = PQdb(pConn);
targetSegDB->pszDBUser = PQuser(pConn);
targetSegDB->pszDBPswd = PQpass(pConn);
targetSegDB->content = contentid;
sourceSegDB = &restorePairAr->pData[x].segdb_source;
sourceSegDB->dbid = targetSegDB->dbid;
sourceSegDB->role = targetSegDB->role;
sourceSegDB->port = targetSegDB->port;
sourceSegDB->pszHost = targetSegDB->pszHost;
sourceSegDB->pszDBName = targetSegDB->pszDBName;
sourceSegDB->pszDBUser = targetSegDB->pszDBUser;
if (targetSegDB->pszDBPswd)
sourceSegDB->pszDBPswd = targetSegDB->pszDBPswd;
if (targetSegDB->role == ROLE_MASTER)
mpp_err_msg("INFO", "gp_restore", "Master (dbid 1)\n");
else
mpp_err_msg("INFO", "gp_restore", "Segment %d (dbid %d)\n",
contentid,
targetSegDB->dbid);
x++;
}
/* set the count to be the number that passed the set inclusion test */
restorePairAr->count = x;
cleanup:
if (pQry != NULL)
destroyPQExpBuffer(pQry);
if (pRes != NULL)
PQclear(pRes);
return bRtn;
}