提交 08f4ada7 编写于 作者: P Pengcheng Tang

Backup and restore to report errors found from segments' status file

Gpcrondump and gpdbrestore redirect stderr into status file for segments,
errors should be reflected into the master's report file.
Warnings will be given if process completed but errors were generated in
the report file.

Also made some refactor of the code.

Authors: Pengcheng Tang, Nikhil Kak
上级 46617d39
......@@ -1053,16 +1053,24 @@ class PostDumpSegment(Operation):
logger.error('Could not locate status file: %s' % self.status_file)
raise NoStatusFile()
# Ensure that status file indicates successful dump
completed = False
error_found = False
with open(self.status_file, 'r') as f:
for line in f:
if line.find("Finished successfully") != -1:
break
completed = True
elif line.find("ERROR:") != -1 or line.find("[ERROR]") != -1:
error_found = True
if error_found:
if completed:
logger.warn("Status report file indicates dump completed with errors: %s" % self.status_file)
else:
logger.error("Status report file indicates errors: %s" % self.status_file)
logger.error("Status report file indicates dump incomplete with errors: %s" % self.status_file)
with open(self.status_file, 'r') as f:
for line in f:
logger.info(line)
logger.error("Status file contents dumped to log file")
raise StatusFileError()
logger.error("Status file contents dumped to log file")
raise StatusFileError()
# Ensure that dump file exists
if not os.path.exists(self.dump_file):
logger.error("Could not locate dump file: %s" % self.dump_file)
......
......@@ -439,8 +439,8 @@ def validate_tablenames(table_list):
class RestoreDatabase(Operation):
def __init__(self, restore_timestamp, no_analyze, drop_db, restore_global, master_datadir, backup_dir,
master_port, dump_dir, dump_prefix, no_plan, restore_tables, batch_default, no_ao_stats,
redirected_restore_db, report_status_dir, restore_stats, metadata_only, ddboost,
master_port, dump_dir, dump_prefix, no_plan, restore_tables, batch_default,
no_ao_stats, redirected_restore_db, report_status_dir, restore_stats, metadata_only, ddboost,
netbackup_service_host, netbackup_block_size, change_schema):
self.restore_timestamp = restore_timestamp
self.no_analyze = no_analyze
......@@ -523,7 +523,9 @@ class RestoreDatabase(Operation):
self.change_schema)
logger.info("Running metadata restore")
logger.info("Invoking commandline: %s" % restore_line)
Command('Invoking gp_restore', restore_line).run(validateAfter=True)
cmd = Command('Invoking gp_restore', restore_line)
cmd.run(validateAfter=False)
self._process_result(cmd)
logger.info("Expanding parent partitions if any in table filter")
self.restore_tables = expand_partition_tables(restore_db, self.restore_tables)
......@@ -541,7 +543,9 @@ class RestoreDatabase(Operation):
self.no_ao_stats, full_restore_with_filter,
self.change_schema)
logger.info('gp_restore commandline: %s: ' % restore_line)
Command('Invoking gp_restore', restore_line).run(validateAfter=True)
cmd = Command('Invoking gp_restore', restore_line)
cmd.run(validateAfter=False)
self._process_result(cmd)
if full_restore_with_filter:
restore_line = self._build_post_data_schema_only_restore_line(restore_timestamp,
......@@ -551,7 +555,9 @@ class RestoreDatabase(Operation):
full_restore_with_filter)
logger.info("Running post data restore")
logger.info('gp_restore commandline: %s: ' % restore_line)
Command('Invoking gp_restore', restore_line).run(validateAfter=True)
cmd = Command('Invoking gp_restore', restore_line)
cmd.run(validateAfter=False)
self._process_result(cmd)
if table_filter_file:
self.remove_filter_file(table_filter_file)
......@@ -564,6 +570,15 @@ class RestoreDatabase(Operation):
if self.restore_stats:
self._restore_stats(restore_timestamp, self.master_datadir, self.backup_dir, self.master_port, restore_db, self.restore_tables)
def _process_result(self, cmd):
res = cmd.get_results()
if res.rc == 0:
logger.info("gpdbrestore finished successfully")
elif res.rc == 2:
logger.warn("gpdbrestore finished but ERRORS were found, please check the restore report file for details")
else:
raise Exception('gpdbrestore finished unsuccessfully')
def _analyze(self, restore_db, master_port):
conn = None
logger.info('Commencing analyze of %s database, please wait' % restore_db)
......
......@@ -141,7 +141,6 @@ static int dd_boost_enabled = 0;
int
main(int argc, char **argv)
{
int failCount = -1;
int rc = 0; /* return code */
int remote_version;
......@@ -226,7 +225,7 @@ main(int argc, char **argv)
cleanup:
/* Produce results report */
failCount = reportBackupResults(inputOpts, &parmAr);
rc = reportBackupResults(inputOpts, &parmAr);
freeThreadParmArray(&parmAr);
FreeSegmentDatabaseArray(&segDBAr);
......@@ -241,8 +240,6 @@ cleanup:
if (master_db_conn != NULL)
PQfinish(master_db_conn);
rc = (failCount == 0 ? 0 : 1);
exit(rc);
}
......@@ -741,7 +738,7 @@ void addFileNameParam(const char* flag, char* file_name, InputOptions* pInputOpt
tmp_name = MakeString("%s%s", directory_name, short_file_name);
pInputOpts->pszPassThroughParms =
addPassThroughLongParm(flag, tmp_name, pInputOpts->pszPassThroughParms);
tableFileName = Safe_strdup(file_name);
tableFileName = pg_strdup(file_name);
free(tmp_name);
}
......@@ -966,7 +963,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 'E': /* Dump encoding */
dumpencoding = Safe_strdup(optarg);
dumpencoding = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughParm(c, optarg, pInputOpts->pszPassThroughParms);
break;
......@@ -981,7 +978,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
*/
case 'h': /* server host */
pInputOpts->pszPGHost = Safe_strdup(optarg);
pInputOpts->pszPGHost = pg_strdup(optarg);
break;
case 'i': /* ignore database version mismatch */
......@@ -990,7 +987,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 'n': /* Dump data for this schema only */
selectSchemaName = Safe_strdup(optarg);
selectSchemaName = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughParm(c, optarg, pInputOpts->pszPassThroughParms);
simple_string_list_append(&schema_include_patterns, optarg);
include_everything = false;
......@@ -1013,7 +1010,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 'p': /* server port */
pInputOpts->pszPGPort = Safe_strdup(optarg);
pInputOpts->pszPGPort = pg_strdup(optarg);
break;
case 'R':
......@@ -1031,7 +1028,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 't': /* Dump data for this table only */
selectTableName = Safe_strdup(optarg);
selectTableName = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughParm(c, optarg, pInputOpts->pszPassThroughParms);
simple_string_list_append(&table_include_patterns, optarg);
include_everything = false;
......@@ -1048,7 +1045,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 'U':
pInputOpts->pszUserName = Safe_strdup(optarg);
pInputOpts->pszUserName = pg_strdup(optarg);
break;
case 'v': /* verbose */
......@@ -1101,7 +1098,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
case 1:
/* gp-c remote compression program */
pInputOpts->pszCompressionProgram = "gzip"; /* Safe_strdup(optarg); */
pInputOpts->pszCompressionProgram = "gzip"; /* pg_strdup(optarg); */
break;
case 2:
......@@ -1128,12 +1125,12 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
case 3:
/* gp-d backup remote directory */
pInputOpts->pszBackupDirectory = Safe_strdup(optarg);
pInputOpts->pszBackupDirectory = pg_strdup(optarg);
break;
case 4:
/* gp-r report directory */
pInputOpts->pszReportDirectory = Safe_strdup(optarg);
pInputOpts->pszReportDirectory = pg_strdup(optarg);
break;
case 5:
......@@ -1146,7 +1143,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
else if (strncasecmp(optarg, "i", 1) == 0)
{
pInputOpts->actors = SET_INDIVIDUAL;
pInputOpts->pszRawDumpSet = Safe_strdup(optarg);
pInputOpts->pszRawDumpSet = pg_strdup(optarg);
}
else
{
......@@ -1205,7 +1202,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
break;
case 10:
pInputOpts->pszTimestampKey = Safe_strdup(optarg);
pInputOpts->pszTimestampKey = pg_strdup(optarg);
if (!ValidateTimestampKey(pInputOpts->pszTimestampKey)) {
mpp_err_msg_cache(logError, progname, "Invalid timestamp key provided\n");
goto cleanup;
......@@ -1216,34 +1213,34 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
no_expand_children = true;
break;
case 12:
dump_prefix = Safe_strdup(optarg);
dump_prefix = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("prefix", DUMP_PREFIX, pInputOpts->pszPassThroughParms);
break;
case 13:
incremental_filter = Safe_strdup(optarg);
incremental_filter = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("incremental-filter", incremental_filter, pInputOpts->pszPassThroughParms);
break;
case 14:
no_lock = true;
break;
case 15:
netbackup_service_host = Safe_strdup(optarg);
netbackup_service_host = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("netbackup-service-host", netbackup_service_host, pInputOpts->pszPassThroughParms);
break;
case 16:
netbackup_policy = Safe_strdup(optarg);
netbackup_policy = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("netbackup-policy", netbackup_policy, pInputOpts->pszPassThroughParms);
break;
case 17:
netbackup_schedule = Safe_strdup(optarg);
netbackup_schedule = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("netbackup-schedule", netbackup_schedule, pInputOpts->pszPassThroughParms);
break;
case 18:
netbackup_block_size = Safe_strdup(optarg);
netbackup_block_size = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("netbackup-block-size", netbackup_block_size, pInputOpts->pszPassThroughParms);
break;
case 19:
netbackup_keyword = Safe_strdup(optarg);
netbackup_keyword = pg_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("netbackup-keyword", netbackup_keyword, pInputOpts->pszPassThroughParms);
break;
case 20:
......@@ -1265,7 +1262,6 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
addFileNameParam("schema-file", optarg, pInputOpts);
include_everything = false;
break;
default:
mpp_err_msg_cache(logError, progname, "Try \"%s --help\" for more information.\n", progname);
goto cleanup;
......@@ -1297,9 +1293,9 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
/* If no directory is specified, for example when we gp_dump, then dump to default directory db_dumps */
if (pInputOpts->pszBackupDirectory)
ddboost_directory = Safe_strdup(pInputOpts->pszBackupDirectory);
ddboost_directory = pg_strdup(pInputOpts->pszBackupDirectory);
else
ddboost_directory = Safe_strdup("db_dumps/");
ddboost_directory = pg_strdup("db_dumps/");
pInputOpts->pszPassThroughParms = addPassThroughLongParm("dd_boost_dir", ddboost_directory, pInputOpts->pszPassThroughParms);
}
......@@ -1307,7 +1303,7 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
/* Get database name from command line */
if (optind < argc)
pInputOpts->pszDBName = Safe_strdup(argv[optind]);
pInputOpts->pszDBName = pg_strdup(argv[optind]);
/*
* get PG env variables, override only of no cmd-line value specified
......@@ -1315,19 +1311,19 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
if (pInputOpts->pszDBName == NULL)
{
if (getenv("PGDATABASE") != NULL)
pInputOpts->pszDBName = Safe_strdup(getenv("PGDATABASE"));
pInputOpts->pszDBName = pg_strdup(getenv("PGDATABASE"));
}
if (pInputOpts->pszPGPort == NULL)
{
if (getenv("PGPORT") != NULL)
pInputOpts->pszPGPort = Safe_strdup(getenv("PGPORT"));
pInputOpts->pszPGPort = pg_strdup(getenv("PGPORT"));
}
if (pInputOpts->pszPGHost == NULL)
{
if (getenv("PGHOST") != NULL)
pInputOpts->pszPGHost = Safe_strdup(getenv("PGHOST"));
pInputOpts->pszPGHost = pg_strdup(getenv("PGHOST"));
}
/*
......@@ -1629,6 +1625,7 @@ reportBackupResults(InputOptions inputopts, ThreadParmArray *pParmAr)
ThreadParm *pParm0;
int i;
int failCount;
int errorCount;
char *pszStatus;
char *pszMsg;
char *pszReportDirectory = inputopts.pszReportDirectory;
......@@ -1680,7 +1677,7 @@ reportBackupResults(InputOptions inputopts, ThreadParmArray *pParmAr)
* report directory not set by user - default to
* $MASTER_DATA_DIRECTORY
*/
pszReportDirectory = Safe_strdup(getenv("MASTER_DATA_DIRECTORY"));
pszReportDirectory = pg_strdup(getenv("MASTER_DATA_DIRECTORY"));
}
else
{
......@@ -1732,14 +1729,23 @@ reportBackupResults(InputOptions inputopts, ThreadParmArray *pParmAr)
appendPQExpBuffer(reportBuf, "Individual Results\n");
failCount = 0;
errorCount = 0;
for (i = 0; i < pParmAr->count; i++)
{
ThreadParm *pParm = &pParmAr->pData[i];
pszMsg = pParm->pszErrorMsg;
if (!pParm->bSuccess)
{
pszStatus = "Failed with error: \n{";
failCount++;
pszStatus = pParm->bSuccess ? "Succeeded" : "Failed with error: \n{";
pszMsg = pParm->pszErrorMsg;
}
else if (pParm->bSuccess && pszMsg != NULL)
{
pszStatus = "Finished but errors were found: \n{";
errorCount++;
}
else
pszStatus = "Succeeded";
if (pszMsg == NULL)
{
/* if we failed pre maturely try to get the predump error */
......@@ -1787,10 +1793,12 @@ reportBackupResults(InputOptions inputopts, ThreadParmArray *pParmAr)
}
}
if (failCount == 0)
if (failCount == 0 && errorCount == 0)
appendPQExpBuffer(reportBuf, "\n%s utility finished successfully.\n", progname);
else
else if(failCount > 0)
appendPQExpBuffer(reportBuf, "\n%s utility finished unsuccessfully with %d failures.\n", progname, failCount);
else
appendPQExpBuffer(reportBuf, "\n%s utility finished but errors were found.\n", progname);
/* write report to report file */
if (fRptFile != NULL)
......@@ -1808,7 +1816,11 @@ reportBackupResults(InputOptions inputopts, ThreadParmArray *pParmAr)
destroyPQExpBuffer(reportBuf);
return failCount;
if (failCount > 0)
return 1;
else if (errorCount > 0)
return 2;
return 0;
}
/*
......@@ -1864,7 +1876,7 @@ spinOffThreads(PGconn *pConn,
pParm->pTargetSegDBData = &psegDBAr->pData[i];
pParm->pOptionsData = pInputOpts;
pParm->bSuccess = false;
pParm->bSuccess = true;
mpp_msg(logInfo, progname, "Creating thread to backup dbid %d: host %s port %d database %s\n",
pParm->pTargetSegDBData->dbid,
......@@ -1935,10 +1947,10 @@ spinOffThreads(PGconn *pConn,
if (pParm->pTargetSegDBData->role == ROLE_MASTER && no_lock)
{
char *dumpkey = pParmAr->pData[0].pOptionsData->pszKey;
char *filedir = Safe_strdup(pInputOpts->pszReportDirectory);
char *filedir = pg_strdup(pInputOpts->pszReportDirectory);
if (filedir == NULL)
{
filedir = Safe_strdup(getenv("MASTER_DATA_DIRECTORY"));
filedir = pg_strdup(getenv("MASTER_DATA_DIRECTORY"));
}
char *signalFileName = MakeString("%s/gp_lockfile_%s", filedir, &dumpkey[8]);
mpp_msg(logInfo, progname, "Signal filename is %s.\n", signalFileName);
......@@ -2006,6 +2018,7 @@ threadProc(void *arg)
char *pszPassThroughCredentials;
PQExpBuffer Qry;
PQExpBuffer pqBuffer;
PGresult *pRes;
int sock;
bool bSentCancelMessage;
......@@ -2095,7 +2108,7 @@ threadProc(void *arg)
mpp_msg(logInfo, progname, "Successfully launched Greenplum Database backup on dbid %d server\n", pSegDB->dbid);
pParm->pszRemoteBackupPath = strdup(PQgetvalue(pRes, 0, 0));
pParm->pszRemoteBackupPath = pg_strdup(PQgetvalue(pRes, 0, 0));
PQclear(pRes);
destroyPQExpBuffer(Qry);
......@@ -2250,6 +2263,7 @@ threadProc(void *arg)
if (retryCnt >= max_probe_retries)
{
g_b_SendCancelMessage = true;
pParm->bSuccess = false;
pParm->pszErrorMsg = MakeString("Lost response from dump agent with dbid %d on host %s after 10 minutes.\n",
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"));
mpp_err_msg(logError, progname, pParm->pszErrorMsg);
......@@ -2259,15 +2273,27 @@ threadProc(void *arg)
/*
* We don't get here unless the BackupStateMachine reached a final state.
* If the status indicates an error, we process this error in the switch
* Segment may not catch all errors, scan the dump status file for ERRORS.
*/
if(pParm->bSuccess || pParm->pszErrorMsg == NULL)
{
pqBuffer = createPQExpBuffer();
int status = ReadBackendBackupFileError(pConn, pInputOpts->pszBackupDirectory, pszKey,
BFT_BACKUP_STATUS, progname, pqBuffer);
if(status != 0)
{
pParm->pszErrorMsg = pqBuffer->data;
}
}
/*
* If the status already indicated a specific error, we process this error in the switch
* statement below.
*/
if (!pState->bStatus)
{
g_b_SendCancelMessage = true;
pParm->bSuccess = false;
mpp_err_msg(logError, progname, "backup failed for dbid %d on host %s\n",
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"));
switch (pState->currentState)
{
......@@ -2283,14 +2309,7 @@ threadProc(void *arg)
"there are various reasons that may cause this to happen. Please "
"inspect the server log of dbid %d on host %s\n "
"Detail from remote status file: %s\n",
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"),
ReadBackendBackupFile(pConn, pInputOpts->pszBackupDirectory,
pszKey, BFT_BACKUP_STATUS, progname));
break;
case STATE_BACKUP_ERROR:
/* Make call to get error message from file on server */
pParm->pszErrorMsg = ReadBackendBackupFile(pConn, pInputOpts->pszBackupDirectory, pszKey, BFT_BACKUP_STATUS, progname);
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"), StringNotNull(pParm->pszErrorMsg, ""));
break;
......@@ -2302,18 +2321,24 @@ threadProc(void *arg)
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"));
break;
case STATE_BACKUP_ERROR:
default:
break;
}
mpp_err_msg(logError, progname, pParm->pszErrorMsg);
}
else
if (pParm->bSuccess)
{
pParm->bSuccess = true;
mpp_msg(logInfo, progname, "backup succeeded for dbid %d on host %s\n",
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"));
}
else
{
mpp_err_msg(logError, progname, "backup failed for dbid %d on host %s\n%s\n",
pSegDB->dbid, StringNotNull(pSegDB->pszHost, "localhost"), StringNotNull(pParm->pszErrorMsg, ""));
}
cleanup:
/*
......
......@@ -589,7 +589,7 @@ main(int argc, char **argv)
break;
case 'S': /* Username for superuser in plain text output */
outputSuperuser = strdup(optarg);
outputSuperuser = pg_strdup(optarg);
break;
case 't': /* include table(s) */
......@@ -654,13 +654,13 @@ main(int argc, char **argv)
case 1: /* MPP Dump Info Format is Key_role_dbid */
g_CDBDumpInfo = strdup(optarg);
g_CDBDumpInfo = pg_strdup(optarg);
if (!ParseCDBDumpInfo((char *) progname, g_CDBDumpInfo, &g_CDBDumpKey, &g_role, &g_dbID, &g_CDBPassThroughCredentials))
exit(1);
break;
case 2: /* --gp-d CDB Output Directory */
g_pszCDBOutputDirectory = strdup(optarg);
g_pszCDBOutputDirectory = pg_strdup(optarg);
break;
case 3: /* --table-file */
......@@ -684,25 +684,25 @@ main(int argc, char **argv)
}
break;
case 5:
dump_prefix = strdup(optarg);
dump_prefix = pg_strdup(optarg);
break;
#ifdef USE_DDBOOST
case 6:
g_pszDDBoostFile = strdup(optarg);
g_pszDDBoostFile = pg_strdup(optarg);
break;
case 7:
dd_boost_enabled = 1;
break;
case 8:
g_pszDDBoostDir = strdup(optarg);
g_pszDDBoostDir = pg_strdup(optarg);
break;
case 9:
sscanf(optarg, "%d", &dd_boost_buf_size);
break;
#endif
case 10:
incrementalFilter = strdup(optarg);
incrementalFilter = pg_strdup(optarg);
break;
/* Hack to pass NetBackup params to gp_dump_agent */
case 11:
......@@ -861,9 +861,9 @@ main(int argc, char **argv)
g_SegDB.dbid = g_dbID;
g_SegDB.role = g_role;
g_SegDB.port = pgport ? atoi(pgport) : 5432;
g_SegDB.pszHost = pghost ? strdup(pghost) : NULL;
g_SegDB.pszDBName = dbname ? strdup(dbname) : NULL;
g_SegDB.pszDBUser = username ? strdup(username) : NULL;
g_SegDB.pszHost = pghost ? pg_strdup(pghost) : NULL;
g_SegDB.pszDBName = dbname ? pg_strdup(dbname) : NULL;
g_SegDB.pszDBUser = username ? pg_strdup(username) : NULL;
g_SegDB.pszDBPswd = NULL;
/*
......@@ -1195,13 +1195,13 @@ dumpMain(bool oids, const char *dumpencoding, int outputBlobs, int plainText, Re
blobobj->objType = DO_BLOBS;
blobobj->catId = nilCatalogId;
AssignDumpId(blobobj);
blobobj->name = strdup("BLOBS");
blobobj->name = pg_strdup("BLOBS");
blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
blobobj->objType = DO_BLOB_COMMENTS;
blobobj->catId = nilCatalogId;
AssignDumpId(blobobj);
blobobj->name = strdup("BLOB COMMENTS");
blobobj->name = pg_strdup("BLOB COMMENTS");
}
/*
......@@ -2583,7 +2583,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
q = createPQExpBuffer();
delq = createPQExpBuffer();
qnspname = strdup(fmtId(nspinfo->dobj.name));
qnspname = pg_strdup(fmtId(nspinfo->dobj.name));
appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
......@@ -3190,7 +3190,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
defqry = createPQExpBuffer();
delqry = createPQExpBuffer();
qlanname = strdup(fmtId(plang->dobj.name));
qlanname = pg_strdup(fmtId(plang->dobj.name));
/*
* If dumping a HANDLER clause, treat the language as being in the handler
......@@ -3343,7 +3343,7 @@ getFuncOwner(Oid funcOid, const char *templateField)
if (ntups != 0)
{
i_funcowner = PQfnumber(res, "funcowner");
functionOwner = strdup(PQgetvalue(res, 0, i_funcowner));
functionOwner = pg_strdup(PQgetvalue(res, 0, i_funcowner));
}
PQclear(res);
......@@ -3391,8 +3391,8 @@ dumpPlTemplateFunc(Oid funcOid, const char *templateField, PQExpBuffer buffer)
{
i_signature = PQfnumber(res, "signature");
i_owner = PQfnumber(res, "owner");
functionSignature = strdup(PQgetvalue(res, 0, i_signature));
ownerName = strdup(PQgetvalue(res, 0, i_owner));
functionSignature = pg_strdup(PQgetvalue(res, 0, i_signature));
ownerName = pg_strdup(PQgetvalue(res, 0, i_owner));
if (functionSignature != NULL && ownerName != NULL)
{
......@@ -4237,7 +4237,7 @@ convertRegProcReference(const char *proc)
if (strcmp(proc, "-") == 0)
return NULL;
name = strdup(proc);
name = pg_strdup(proc);
/* find non-double-quoted left paren */
inquote = false;
for (paren = name; *paren; paren++)
......@@ -4276,7 +4276,7 @@ convertOperatorReference(const char *opr)
if (strcmp(opr, "0") == 0)
return NULL;
name = strdup(opr);
name = pg_strdup(opr);
/* find non-double-quoted left paren, and check for non-quoted dot */
inquote = false;
sawdot = false;
......@@ -4388,7 +4388,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
opckeytype = PQgetvalue(res, 0, i_opckeytype);
opcdefault = PQgetvalue(res, 0, i_opcdefault);
/* amname will still be needed after we PQclear res */
amname = strdup(PQgetvalue(res, 0, i_amname));
amname = pg_strdup(PQgetvalue(res, 0, i_amname));
/*
* DROP must be fully qualified in case same name appears in pg_catalog
......@@ -4921,7 +4921,7 @@ getFunctionName(Oid oid)
}
/* already quoted */
result = strdup(PQgetvalue(res, 0, 0));
result = pg_strdup(PQgetvalue(res, 0, 0));
PQclear(res);
destroyPQExpBuffer(query);
......@@ -4980,7 +4980,7 @@ dumpExtProtocol(Archive *fout, ExtProtInfo *ptcinfo)
if(protoFuncs[i].pfuncinfo != NULL)
{
protoFuncs[i].dumpable = true;
protoFuncs[i].name = strdup(protoFuncs[i].pfuncinfo->dobj.name);
protoFuncs[i].name = pg_strdup(protoFuncs[i].pfuncinfo->dobj.name);
protoFuncs[i].internal = false;
}
else
......@@ -5045,7 +5045,7 @@ dumpExtProtocol(Archive *fout, ExtProtInfo *ptcinfo)
NULL, NULL);
/* Handle the ACL */
namecopy = strdup(fmtId(ptcinfo->dobj.name));
namecopy = pg_strdup(fmtId(ptcinfo->dobj.name));
dumpACL(fout, ptcinfo->dobj.catId, ptcinfo->dobj.dumpId,
"PROTOCOL",
namecopy, ptcinfo->dobj.name,
......@@ -5125,7 +5125,7 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
dumpTableSchema(fout, tbinfo);
/* Handle the ACL here */
namecopy = strdup(fmtId(tbinfo->dobj.name));
namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
namecopy, tbinfo->dobj.name,
......@@ -5385,8 +5385,8 @@ dumpExternal(TableInfo *tbinfo, PQExpBuffer query, PQExpBuffer q, PQExpBuffer de
{
appendPQExpBuffer(q, "LOG ERRORS ");
char *errtablename = Safe_strdup(fmtId(errtblname));
char *tablename = Safe_strdup(fmtId(tbinfo->dobj.name));
char *errtablename = pg_strdup(fmtId(errtblname));
char *tablename = pg_strdup(fmtId(tbinfo->dobj.name));
/* Check error table was not generated by LOG ERRORS statement.
* To do: deprecate the use of LOG ERRORS INTO
......@@ -5807,8 +5807,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
for (i = 0; i < ntups; i++)
{
char tmpExtTable[500] = {0};
relname = strdup(PQgetvalue(res, i, i_relname));
parname = strdup(PQgetvalue(res, i, i_parname));
relname = pg_strdup(PQgetvalue(res, i, i_relname));
parname = pg_strdup(PQgetvalue(res, i, i_parname));
snprintf(tmpExtTable, sizeof(tmpExtTable), "%s%s", relname, EXT_PARTITION_NAME_POSTFIX);
appendPQExpBuffer(q, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "EXCHANGE PARTITION %s ", fmtId(parname));
......@@ -5855,8 +5855,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
for (i = 0; i < ntups; i++)
{
schemaname = strdup(PQgetvalue(res, i, i_schemaname));
relname = strdup(PQgetvalue(res, i, i_relname));
schemaname = pg_strdup(PQgetvalue(res, i, i_schemaname));
relname = pg_strdup(PQgetvalue(res, i, i_relname));
appendPQExpBuffer(q, "ALTER TABLE %s ", fmtId(relname));
appendPQExpBuffer(q, "SET SCHEMA %s;", fmtId(schemaname));
......@@ -6959,13 +6959,13 @@ getFormattedTypeName(Oid oid, OidOptions opts)
if (oid == 0)
{
if ((opts & zeroAsOpaque) != 0)
return strdup(g_opaque_type);
return pg_strdup(g_opaque_type);
else if ((opts & zeroAsAny) != 0)
return strdup("'any'");
return pg_strdup("'any'");
else if ((opts & zeroAsStar) != 0)
return strdup("*");
return pg_strdup("*");
else if ((opts & zeroAsNone) != 0)
return strdup("NONE");
return pg_strdup("NONE");
}
query = createPQExpBuffer();
......@@ -6985,7 +6985,7 @@ getFormattedTypeName(Oid oid, OidOptions opts)
}
/* already quoted */
result = strdup(PQgetvalue(res, 0, 0));
result = pg_strdup(PQgetvalue(res, 0, 0));
PQclear(res);
destroyPQExpBuffer(query);
......@@ -7670,7 +7670,7 @@ _check_database_version(ArchiveHandle *AH)
remoteversion = _parse_version(AH, remoteversion_str);
AH->public.remoteVersionStr = strdup(remoteversion_str);
AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
AH->public.remoteVersion = remoteversion;
if (myversion != remoteversion
......@@ -7781,7 +7781,7 @@ updateArchiveWithDDFile(ArchiveHandle *AH, char *g_pszDDBoostFile, const char *g
path1.su_name = DDP_SU_NAME;
if (g_pszDDBoostDir)
path1.path_name = strdup(g_pszDDBoostDir);
path1.path_name = pg_strdup(g_pszDDBoostDir);
else
path1.path_name = dir_name;
......
......@@ -490,15 +490,17 @@ ParseCDBDumpInfo(const char *progName, char *pszCDBDumpInfo, char **ppCDBDumpKey
/*
* ReadBackendBackupFile: This function calls the backend function gp_read_backup_file
* which reads the contents out of the appropriate file on the database server.
* If the call fails, it returns NULL. The returned pointer must be freed by the caller.
* If the call succeeds/fails, it returns status code 0/-1, an appropriate error string
* is inserted into the buffer of pszRtn.
*/
char *
ReadBackendBackupFile(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey, BackupFileType fileType, const char *progName)
int
ReadBackendBackupFileError(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey,
BackupFileType fileType, const char *progName, PQExpBuffer pszRtn)
{
char *pszRtn = NULL;
char *pszFileType;
char *pszFileType;
PQExpBuffer Qry;
PGresult *pRes;
int status = 0;
switch (fileType)
{
......@@ -512,34 +514,42 @@ ReadBackendBackupFile(PGconn *pConn, const char *pszBackupDirectory, const char
pszFileType = "2";
break;
default:
mpp_err_msg("ERROR", progName, "Unknown file type passed to ReadBackendBackupFile : %d\n", fileType);
return NULL;
appendPQExpBuffer(pszRtn, "Unknown file type passed to ReadBackendBackupFile");
mpp_err_msg("ERROR", progName, " %s: %d\n", pszRtn->data, fileType);
return -1;
}
Qry = createPQExpBuffer();
appendPQExpBuffer(Qry, "SELECT * FROM gp_read_backup_file('%s', '%s', %s)",
StringNotNull(pszBackupDirectory, ""),
StringNotNull(pszKey, ""),
pszFileType);
StringNotNull(pszBackupDirectory, ""),
StringNotNull(pszKey, ""),
pszFileType);
pRes = PQexec(pConn, Qry->data);
if (!pRes || PQresultStatus(pRes) != PGRES_TUPLES_OK || PQntuples(pRes) == 0)
{
mpp_err_msg_cache("ERROR", progName, "Error executing query %s : %s\n",
Qry->data,
PQerrorMessage(pConn));
appendPQExpBuffer(pszRtn, "Error executing query %s : %s\n", Qry->data, PQerrorMessage(pConn));
mpp_err_msg_cache("ERROR", progName, pszRtn->data);
status = -1;
}
else
{
pszRtn = strdup(PQgetvalue(pRes, 0, 0));
char *res = PQgetvalue(pRes, 0, 0);
appendPQExpBuffer(pszRtn, res);
if (strstr(res, "ERROR:") || strstr(res, "[ERROR]"))
{
status = -1;
}
}
PQclear(pRes);
destroyPQExpBuffer(Qry);
return pszRtn;
return status;
}
/*
* Safe_strdup: returns strdup if not NULL, NULL otherwise
*/
......
......@@ -121,8 +121,9 @@ extern char *MakeString(const char *fmt,...);
/* breaks the input parameter associated with --cdb-k into its components for cdb_dump and cdb_restore*/
extern bool ParseCDBDumpInfo(const char *progName, char *pszCDBDumpInfo, char **ppCDBDumpKey, int *pCDBInstID, int *pCDBSegID, char **ppCDBPassThroughCredentials);
/* reads the contents out of the appropriate file on the database server */
extern char *ReadBackendBackupFile(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey, BackupFileType fileType, const char *progName);
/* reads the contents for "ERROR:" and "[ERROR]" out of the appropriate file on the database server */
extern int ReadBackendBackupFileError(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey,
BackupFileType fileType, const char *progName, PQExpBuffer buf);
/* returns strdup if not NULL, NULL otherwise */
extern char *Safe_strdup(const char *s);
......
......@@ -70,7 +70,7 @@ static const char *logFatal = "FATAL";
const char *progname;
static char * addPassThroughLongParm(const char *Parm, const char *pszValue, char *pszPassThroughParmString);
static char *dump_prefix = NULL;
static char *status_file = NULL;
static char *status_file_dir = NULL;
/* NetBackup related variable */
static char *netbackup_service_host = NULL;
......@@ -92,6 +92,8 @@ main(int argc, char **argv)
SegmentDatabase *sourceSegDB = NULL;
SegmentDatabase *targetSegDB = NULL;
progname = get_progname(argv[0]);
/* This struct holds the values of the command line parameters */
InputOptions inputOpts;
......@@ -110,8 +112,6 @@ main(int argc, char **argv)
memset(&parmAr, 0, sizeof(parmAr));
memset(&masterParm, 0, sizeof(masterParm));
progname = get_progname(argv[0]);
#ifdef USE_DDBOOST
dd_boost_enabled = 0;
#endif
......@@ -254,7 +254,7 @@ cleanup:
if (pConn != NULL)
PQfinish(pConn);
return (failCount == 0 ? 0 : 1);
return failCount;
}
static void
......@@ -738,8 +738,8 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
pInputOpts->pszPassThroughParms = addPassThroughLongParm("prefix", DUMP_PREFIX, pInputOpts->pszPassThroughParms);
break;
case 14:
status_file = Safe_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("status", status_file, pInputOpts->pszPassThroughParms);
status_file_dir = Safe_strdup(optarg);
pInputOpts->pszPassThroughParms = addPassThroughLongParm("status", status_file_dir, pInputOpts->pszPassThroughParms);
break;
case 15:
netbackup_service_host = Safe_strdup(optarg);
......@@ -755,7 +755,6 @@ fillInputOptions(int argc, char **argv, InputOptions * pInputOpts)
if (change_schema!= NULL)
free(change_schema);
break;
default:
mpp_err_msg_cache(logError, progname, "Try \"%s --help\" for more information.\n", progname);
return false;
......@@ -984,6 +983,7 @@ threadProc(void *arg)
char *pszPassThroughCredentials;
char *pszPassThroughTargetInfo;
PQExpBuffer Qry;
PQExpBuffer pqBuffer;
PGresult *pRes;
int sock;
bool bSentCancelMessage;
......@@ -1020,7 +1020,7 @@ threadProc(void *arg)
sSegDB->pszDBName = Safe_strdup(pInputOpts->pszDBName);
}
/* connect to the source segDB to start gp_dump_agent there */
/* connect to the source segDB to start gp_restore_agent there */
pConn = MakeDBConnection(sSegDB, false);
if (PQstatus(pConn) == CONNECTION_BAD)
{
......@@ -1178,8 +1178,10 @@ threadProc(void *arg)
g_b_SendCancelMessage = true;
bIsFinished = true;
pParm->bSuccess = false;
pqBuffer = createPQExpBuffer();
/* Make call to get error message from file on server */
pParm->pszErrorMsg = ReadBackendBackupFile(pConn, pInputOpts->pszBackupDirectory, pszKey, BFT_RESTORE_STATUS, progname);
ReadBackendBackupFileError(pConn, status_file_dir, pszKey, BFT_RESTORE_STATUS, progname, pqBuffer);
pParm->pszErrorMsg = pqBuffer->data;
mpp_err_msg(logError, progname, "restore failed for source dbid %d, target dbid %d on host %s\n",
sSegDB->dbid, tSegDB->dbid, StringNotNull(sSegDB->pszHost, "localhost"));
......@@ -1208,6 +1210,20 @@ threadProc(void *arg)
}
}
/*
* If segment reports success or no errors so far, scan of the restore status file
* for ERRORS and report them if found
*/
if(pParm->bSuccess || pParm->pszErrorMsg == NULL)
{
pqBuffer = createPQExpBuffer();
int status = ReadBackendBackupFileError(pConn, status_file_dir, pszKey, BFT_RESTORE_STATUS, progname, pqBuffer);
if (status != 0)
{
pParm->pszErrorMsg = pqBuffer->data;
}
}
if (pszNotifyRelName != NULL)
free(pszNotifyRelName);
if (pszNotifyRelNameStart != NULL)
......@@ -1299,7 +1315,7 @@ restoreMaster(InputOptions * pInputOpts,
pParm->pTargetSegDBData = tSegDB;
pParm->pSourceSegDBData = sSegDB;
pParm->pOptionsData = pInputOpts;
pParm->bSuccess = false;
pParm->bSuccess = true;
pParm->pszErrorMsg = NULL;
pParm->pszRemoteBackupPath = NULL;
......@@ -1477,7 +1493,7 @@ spinOffThreads(PGconn *pConn, InputOptions * pInputOpts, const RestorePairArray
pParm->pSourceSegDBData = &restorePairAr->pData[i].segdb_source;
pParm->pTargetSegDBData = &restorePairAr->pData[i].segdb_target;
pParm->pOptionsData = pInputOpts;
pParm->bSuccess = false;
pParm->bSuccess = true;
/* exclude master node */
if (pParm->pTargetSegDBData->role == ROLE_MASTER)
......@@ -1582,6 +1598,7 @@ reportRestoreResults(const char *pszReportDirectory, const ThreadParm * pMasterP
char *pszFormat;
int i;
int failCount;
int errorCount;
const ThreadParm *pParm;
char *pszStatus;
char *pszMsg;
......@@ -1656,6 +1673,7 @@ reportRestoreResults(const char *pszReportDirectory, const ThreadParm * pMasterP
appendPQExpBuffer(reportBuf, "Individual Results\n");
failCount = 0;
errorCount = 0;
for (i = 0; i < pParmAr->count + 1; i++)
{
if (i == 0)
......@@ -1672,10 +1690,19 @@ reportRestoreResults(const char *pszReportDirectory, const ThreadParm * pMasterP
continue;
}
pszMsg = pParm->pszErrorMsg;
if (!pParm->bSuccess)
{
pszStatus = "Failed with error: \n{\n";
failCount++;
pszStatus = pParm->bSuccess ? "Succeeded" : "Failed with error: \n{\n";
pszMsg = pParm->pszErrorMsg;
}
else if (pParm->bSuccess && pszMsg != NULL)
{
pszStatus = "Completed but errors were found: \n{\n";
errorCount++;
}
else
pszStatus = "Succeeded";
if (pszMsg == NULL)
pszMsg = "";
......@@ -1691,10 +1718,12 @@ reportRestoreResults(const char *pszReportDirectory, const ThreadParm * pMasterP
);
}
if (failCount == 0)
if (failCount == 0 && errorCount == 0)
appendPQExpBuffer(reportBuf, "\n%s utility finished successfully.\n", progname);
else
else if (failCount > 0)
appendPQExpBuffer(reportBuf, "\n%s utility finished unsuccessfully with %d failures.\n", progname, failCount);
else
appendPQExpBuffer(reportBuf, "\n%s utility finished but errors were found.\n", progname);
/* write report to report file */
if (fRptFile != NULL)
......@@ -1712,7 +1741,11 @@ reportRestoreResults(const char *pszReportDirectory, const ThreadParm * pMasterP
destroyPQExpBuffer(reportBuf);
return failCount;
if (failCount > 0)
return 1;
else if (errorCount > 0)
return 2;
return 0;
}
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册