/* * ParseCDBDumpInfo: This function takes the command line parameter and parses it * into its 4 pieces: the dump key, the contextid, the dbid, and the CDBPassThroughCredentials * based on the format convention key_contextid_dbid_credentials */ bool ParseCDBDumpInfo(const char *progName, char *pszCDBDumpInfo, char **ppCDBDumpKey, int *pRole, int *pContentID, int *pDbID, char **ppCDBPassThroughCredentials) { int rtn; regmatch_t matches[5]; regex_t rCDBDumpInfo; if (0 != regcomp(&rCDBDumpInfo, "([0-9]+)_(-?[0-9]+)_([0-9]+)_([^[:space:]]*)", REG_EXTENDED)) { mpp_err_msg_cache("ERROR", progName, "Error compiling regular expression for parsing CDB Dump Info\n"); return false; } assert(rCDBDumpInfo.re_nsub == 4); /* match the pszCDBDumpInfo against the regex. */ rtn = regexec(&rCDBDumpInfo, pszCDBDumpInfo, 5, matches, 0); if (rtn != 0) { char errbuf[1024]; regerror(rtn, &rCDBDumpInfo, errbuf, 1024); mpp_err_msg_cache("Error", progName, "parsing CDBDumpInfo %s: not valid : %s\n", pszCDBDumpInfo, errbuf); regfree(&rCDBDumpInfo); return false; } regfree(&rCDBDumpInfo); *ppCDBDumpKey = GetMatchString(&matches[1], pszCDBDumpInfo); if (*ppCDBDumpKey == NULL) { mpp_err_msg_cache("ERROR", progName, "Error parsing CDBDumpInfo %s: CDBDumpKey not valid\n", pszCDBDumpInfo); return false; } *pContentID = GetMatchInt(&matches[2], pszCDBDumpInfo); *pDbID = GetMatchInt(&matches[3], pszCDBDumpInfo); *pRole = (*pDbID == 1) ? 1 : 0; *ppCDBPassThroughCredentials = GetMatchString(&matches[4], pszCDBDumpInfo); if (*ppCDBPassThroughCredentials == NULL) { mpp_err_msg_cache("ERROR", progName, "Error parsing CDBDumpInfo %s: CDBDumpKey not valid\n", pszCDBDumpInfo); return false; } return true; }
/* * DoCancelNotifyListen: This function executes a LISTEN or a NOTIFY command, with * name in the format N%s_%d_%d, where the %s is replaced by the CDBDumpKey, * and the 2 integers are the contentid and dbid. */ void DoCancelNotifyListen(PGconn *pConn, bool bListen, const char *pszCDBDumpKey, int role_id, int db_id, int target_db_id, const char *pszSuffix) { PGresult *pRes; PQExpBuffer q = createPQExpBuffer(); char *pszCmd = bListen ? "LISTEN" : "NOTIFY"; appendPQExpBuffer(q, "%s N%s_%d_%d", pszCmd, pszCDBDumpKey, role_id, db_id); /* this is valid only for restore operations */ if (target_db_id != -1) appendPQExpBuffer(q, "_T%d", target_db_id); if (pszSuffix != NULL) appendPQExpBuffer(q, "_%s", pszSuffix); pRes = PQexec(pConn, q->data); if (pRes == NULL || PQresultStatus(pRes) != PGRES_COMMAND_OK) { mpp_err_msg_cache("%s command failed for for backup key %s, instid %d, segid %d failed : %s", pszCmd, pszCDBDumpKey, role_id, db_id, PQerrorMessage(pConn)); } PQclear(pRes); destroyPQExpBuffer(q); }
/* * 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 succeeds/fails, it returns status code 0/-1, an appropriate error string * is inserted into the buffer of pszRtn. */ int ReadBackendBackupFileError(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey, BackupFileType fileType, const char *progName, PQExpBuffer pszRtn) { char *pszFileType; PQExpBuffer Qry; PGresult *pRes; int status = 0; switch (fileType) { case BFT_BACKUP: pszFileType = "0"; break; case BFT_BACKUP_STATUS: pszFileType = "1"; break; case BFT_RESTORE_STATUS: pszFileType = "2"; break; default: 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); pRes = PQexec(pConn, Qry->data); if (!pRes || PQresultStatus(pRes) != PGRES_TUPLES_OK || PQntuples(pRes) == 0) { appendPQExpBuffer(pszRtn, "Error executing query %s : %s\n", Qry->data, PQerrorMessage(pConn)); mpp_err_msg_cache("ERROR", progName, pszRtn->data); status = -1; } else { char *res = PQgetvalue(pRes, 0, 0); appendPQExpBufferStr(pszRtn, res); if (strstr(res, "ERROR:") || strstr(res, "[ERROR]")) { status = -1; } } PQclear(pRes); destroyPQExpBuffer(Qry); return status; }
/* * 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. */ char * ReadBackendBackupFile(PGconn *pConn, const char *pszBackupDirectory, const char *pszKey, BackupFileType fileType, const char *progName) { char *pszRtn = NULL; char *pszFileType; PQExpBuffer Qry; PGresult *pRes; switch (fileType) { case BFT_BACKUP: pszFileType = "0"; break; case BFT_BACKUP_STATUS: pszFileType = "1"; break; case BFT_RESTORE_STATUS: pszFileType = "2"; break; default: mpp_err_msg("ERROR", progName, "Unknown file type passed to ReadBackendBackupFile : %d\n", fileType); return NULL; } Qry = createPQExpBuffer(); appendPQExpBuffer(Qry, "SELECT * FROM gp_read_backup_file('%s', '%s', %s)", 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)); } else { pszRtn = strdup(PQgetvalue(pRes, 0, 0)); } PQclear(pRes); destroyPQExpBuffer(Qry); return pszRtn; }
/* * GetMasterConnection: This function makes a database connection with the given parameters. * The connection handle is returned. * An interactive password prompt is automatically issued if required. * This is a copy of the one in pg_dump. */ PGconn * GetMasterConnection(const char *progName, const char *dbname, const char *pghost, const char *pgport, const char *username, int reqPwd, int ignoreVersion, bool bDispatch) { char *pszPassword = NULL; bool need_pass = false; PGconn *pConn = NULL; SegmentDatabase masterDB; if (reqPwd) { pszPassword = simple_prompt("Password: "******"ERROR", progName, "out of memory when allocating password"); return NULL; } } masterDB.dbid = 0; masterDB.role = 0; masterDB.port = pgport ? atoi(pgport) : 5432; masterDB.pszHost = (char *) pghost; masterDB.pszDBName = (char *) dbname; masterDB.pszDBUser = (char *) username; masterDB.pszDBPswd = pszPassword; /* * Start the connection. Loop until we have a password if requested by * backend. */ do { need_pass = false; pConn = MakeDBConnection(&masterDB, bDispatch); if (pConn == NULL) { mpp_err_msg_cache("ERROR", progName, "failed to connect to database"); return (NULL); } if (PQstatus(pConn) == CONNECTION_BAD && strcmp(PQerrorMessage(pConn), "fe_sendauth: no password supplied\n") == 0 && !feof(stdin)) { PQfinish(pConn); need_pass = true; free(pszPassword); pszPassword = NULL; pszPassword = simple_prompt("Password: "******"ERROR", progName, "connection to database \"%s\" failed : %s", PQdb(pConn), PQerrorMessage(pConn)); PQfinish(pConn); return (NULL); } return pConn; }