extern void PersistentFilespace_LookupTidAndSerialNum( Oid filespaceOid, /* The filespace OID for the lookup. */ ItemPointer persistentTid, /* TID of the gp_persistent_filespace_node tuple for the rel file */ int64 *persistentSerialNum) { READ_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; FilespaceDirEntry filespaceDirEntry; PersistentFilespace_VerifyInitScan(); READ_PERSISTENT_STATE_ORDERED_LOCK; filespaceDirEntry = PersistentFilespace_FindDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) elog(ERROR, "Did not find persistent filespace entry %u", filespaceOid); *persistentTid = filespaceDirEntry->persistentTid; *persistentSerialNum = filespaceDirEntry->persistentSerialNum; READ_PERSISTENT_STATE_ORDERED_UNLOCK; }
/* * PersistentFilespace_LookupMirrorDbid() * * Check the gp_persistent_filespace table to identify what dbid it contains * that does not match the primary dbid. If there are no filespaces currently * defined this check will return 0 even if there is an active mirror, because * the segment doesn't know any better. */ int16 PersistentFilespace_LookupMirrorDbid(int16 primaryDbid) { HASH_SEQ_STATUS status; FilespaceDirEntry dirEntry; int16 mirrorDbid = 0; PersistentFilespace_VerifyInitScan(); /* Start scan */ hash_seq_init(&status, persistentFilespaceSharedHashTable); dirEntry = (FilespaceDirEntry) hash_seq_search(&status); if (dirEntry != NULL) { if (dirEntry->dbId1 == primaryDbid) { mirrorDbid = dirEntry->dbId2; } else if (dirEntry->dbId2 == primaryDbid) { mirrorDbid = dirEntry->dbId1; } else { elog(FATAL, "dbid %d not found in gp_persistent_filespace_node", (int) primaryDbid); } /* Terminate the scan early */ hash_seq_term(&status); } return mirrorDbid; }
/* * Add a mirror. */ void PersistentFilespace_AddMirror(Oid filespace, char *mirpath, int16 pridbid, int16 mirdbid, bool set_mirror_existence) { PersistentFileSysObjName fsObjName; char *newpath; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; FilespaceDirEntry fde; if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); PersistentFilespace_VerifyInitScan(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName, filespace); WRITE_PERSISTENT_STATE_ORDERED_LOCK; fde = PersistentFilespace_FindDirUnderLock(filespace); if (fde == NULL) elog(ERROR, "did not find persistent filespace entry %u", filespace); if (fde->dbId1 == pridbid) { fde->dbId2 = mirdbid; PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, mirpath); newpath = fde->locationBlankPadded2; } else if (fde->dbId2 == pridbid) { fde->dbId1 = mirdbid; PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, mirpath); newpath = fde->locationBlankPadded1; } else { Insist(false); } PersistentFileSysObj_AddMirror(&fsObjName, &fde->persistentTid, fde->persistentSerialNum, pridbid, mirdbid, (void *)newpath, set_mirror_existence, /* flushToXlog */ false); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
void PersistentFilespace_FileRepVerify(void) { PersistentFilespace_VerifyInitScan(); PersistentFileSysObj_Scan( PersistentFsObjType_FilespaceDir, PersistentFilespace_FileRepVerifyScanTupleCallback); return; }
bool PersistentFilespace_TryGetFilespacePathUnderLock( Oid filespaceOid, char **filespaceLocation) { FilespaceDirEntry filespaceDirEntry; char *primaryBlankPadded = NULL; *filespaceLocation = NULL; #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (GPStandby()) { return mmxlog_filespace_get_path( filespaceOid, filespaceLocation); } #endif /* * Important to make this call AFTER we check if we are the Standby Master. */ PersistentFilespace_VerifyInitScan(); filespaceDirEntry = PersistentFilespace_FindDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) return false; /* * The persistent_filespace_node_table contains the paths for both the * primary and mirror nodes, and the table is the same on both sides of the * mirror. When it was first created the primary put its location first, * but we don't know if we were the primary when it was created or not. To * determine which path corresponds to this node we compare our dbid to the * one stored in the table. */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded1; /* These should both have been populated by one of the cases above */ Assert(primaryBlankPadded); PersistentFilespace_ConvertBlankPaddedLocation( filespaceLocation, primaryBlankPadded, /* isPrimary */ true); return true; }
bool PersistentFilespace_TryGetPrimaryAndMirror( Oid filespaceOid, /* The filespace OID to lookup. */ char **primaryFilespaceLocation, /* The primary filespace directory path. Return NULL for global and base. */ char **mirrorFilespaceLocation) /* * The primary filespace directory path. Return NULL for global and base. * Or, returns NULL when mirror not configured. */ { FilespaceDirEntry filespaceDirEntry; bool result = false; *primaryFilespaceLocation = NULL; *mirrorFilespaceLocation = NULL; #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (IsStandbyMode()) { return mmxlog_filespace_get_path( filespaceOid, primaryFilespaceLocation); } #endif /* * Important to make this call AFTER we check if we are the Standby * Master. */ PersistentFilespace_VerifyInitScan(); LWLockAcquire(FilespaceHashLock, LW_SHARED); filespaceDirEntry = PersistentFilespace_FindDirUnderLock(filespaceOid); if (filespaceDirEntry) { PersistentFilespace_GetPaths(filespaceDirEntry, primaryFilespaceLocation, mirrorFilespaceLocation); result = true; } LWLockRelease(FilespaceHashLock); return result; }
bool PersistentFilespace_Check( Oid filespace) { PersistentFilespace_VerifyInitScan(); persistentFilespaceCheck = filespace; persistentFilespaceCheckFound = false; PersistentFileSysObj_Scan( PersistentFsObjType_FilespaceDir, PersistentFilespace_CheckScanTupleCallback); return persistentFilespaceCheckFound; }
/* * Remove all reference to a segment from the gp_persistent_filespace_node table * and share memory structure. */ void PersistentFilespace_RemoveSegment(int16 dbid, bool ismirror) { HASH_SEQ_STATUS hstat; FilespaceDirEntry fde; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); hash_seq_init(&hstat, persistentFilespaceSharedHashTable); PersistentFilespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; while ((fde = hash_seq_search(&hstat)) != NULL) { Oid filespace = fde->key.filespaceOid; PersistentFileSysObjName fsObjName; PersistentFileSysObjName_SetFilespaceDir(&fsObjName, filespace); if (fde->dbId1 == dbid) { PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, ""); } else if (fde->dbId2 == dbid) { PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, ""); } PersistentFileSysObj_RemoveSegment(&fsObjName, &fde->persistentTid, fde->persistentSerialNum, dbid, ismirror, /* flushToXlog */ false); } WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
extern void PersistentFilespace_LookupTidAndSerialNum( Oid filespaceOid, /* The filespace OID for the lookup. */ ItemPointer persistentTid, /* TID of the gp_persistent_filespace_node tuple for the rel file */ int64 *persistentSerialNum) { FilespaceDirEntry filespaceDirEntry; PersistentFilespace_VerifyInitScan(); LWLockAcquire(FilespaceHashLock, LW_SHARED); filespaceDirEntry = PersistentFilespace_FindDirUnderLock(filespaceOid); if (filespaceDirEntry == NULL) elog(ERROR, "Did not find persistent filespace entry %u", filespaceOid); *persistentTid = filespaceDirEntry->persistentTid; *persistentSerialNum = filespaceDirEntry->persistentSerialNum; LWLockRelease(FilespaceHashLock); }
/* * Indicate we are aborting the create of a filespace file. * * This state will make sure the filespace gets dropped after a system crash. */ PersistentFileSysObjStateChangeResult PersistentFilespace_MarkAbortingCreate( Oid filespaceOid, /* The filespace OID for the aborting create. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum, /* Serial number for the filespace. Distinquishes the uses of the tuple. */ bool retryPossible) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; FilespaceDirEntry filespaceDirEntry; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent filespace %u because we are before persistence work", filespaceOid); return false; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentFilespace_VerifyInitScan(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName,filespaceOid); WRITE_PERSISTENT_STATE_ORDERED_LOCK; WRITE_FILESPACE_HASH_LOCK; filespaceDirEntry = PersistentFilespace_FindDirUnderLock(filespaceOid); if (filespaceDirEntry == NULL) elog(ERROR, "Did not find persistent filespace entry %u", filespaceOid); if (filespaceDirEntry->state != PersistentFileSysState_CreatePending) elog(ERROR, "Persistent filespace entry %u expected to be in 'Create Pending' (actual state '%s')", filespaceOid, PersistentFileSysObjState_Name(filespaceDirEntry->state)); filespaceDirEntry->state = PersistentFileSysState_AbortingCreate; WRITE_FILESPACE_HASH_UNLOCK; stateChangeResult = PersistentFileSysObj_StateChange( &fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_AbortingCreate, retryPossible, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: '%s' changed state from 'Create Pending' to 'Aborting Create', serial number " INT64_FORMAT " at TID %s (State-Change result '%s')", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(persistentTid), PersistentFileSysObjStateChangeResult_Name(stateChangeResult)); return stateChangeResult; }
/* * Indicate we intend to create a filespace file as part of the current transaction. * * An XLOG IntentToCreate record is generated that will guard the subsequent file-system * create in case the transaction aborts. * * After 1 or more calls to this routine to mark intention about filespace files that are going * to be created, call ~_DoPendingCreates to do the actual file-system creates. (See its * note on XLOG flushing). */ void PersistentFilespace_MarkCreatePending( Oid filespaceOid, /* The filespace where the filespace lives. */ int16 primaryDbId, char *primaryFilespaceLocation, /* * The primary filespace directory path. NOT Blank padded. * Just a NULL terminated string. */ int16 mirrorDbId, char *mirrorFilespaceLocation, MirroredObjectExistenceState mirrorExistenceState, ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 *persistentSerialNum, bool flushToXLog) /* When true, the XLOG record for this change will be flushed to disk. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; FilespaceDirEntry filespaceDirEntry; TransactionId topXid; Datum values[Natts_gp_persistent_filespace_node]; char mirrorFilespaceLocationBlankPadded[FilespaceLocationBlankPaddedWithNullTermLen]; char primaryFilespaceLocationBlankPadded[FilespaceLocationBlankPaddedWithNullTermLen]; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent filespace %u because we are before persistence work", filespaceOid); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentFilespace_VerifyInitScan(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName,filespaceOid); topXid = GetTopTransactionId(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentFilespace_BlankPadCopyLocation( primaryFilespaceLocationBlankPadded, primaryFilespaceLocation); PersistentFilespace_BlankPadCopyLocation( mirrorFilespaceLocationBlankPadded, mirrorFilespaceLocation); GpPersistentFilespaceNode_SetDatumValues( values, filespaceOid, primaryDbId, primaryFilespaceLocationBlankPadded, mirrorDbId, mirrorFilespaceLocationBlankPadded, PersistentFileSysState_CreatePending, /* createMirrorDataLossTrackingSessionNum */ 0, mirrorExistenceState, /* reserved */ 0, /* parentXid */ topXid, /* persistentSerialNum */ 0); // This will be set by PersistentFileSysObj_AddTuple. PersistentFileSysObj_AddTuple( PersistentFsObjType_FilespaceDir, values, flushToXLog, persistentTid, persistentSerialNum); WRITE_FILESPACE_HASH_LOCK; filespaceDirEntry = PersistentFilespace_CreateDirUnderLock(filespaceOid); Assert(filespaceDirEntry != NULL); filespaceDirEntry->dbId1 = primaryDbId; memcpy(filespaceDirEntry->locationBlankPadded1, primaryFilespaceLocationBlankPadded, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->dbId2 = mirrorDbId; memcpy(filespaceDirEntry->locationBlankPadded2, mirrorFilespaceLocationBlankPadded, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->state = PersistentFileSysState_CreatePending; ItemPointerCopy(persistentTid, &filespaceDirEntry->persistentTid); filespaceDirEntry->persistentSerialNum = *persistentSerialNum; WRITE_FILESPACE_HASH_UNLOCK; /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_filespace(filespaceOid); #endif SIMPLE_FAULT_INJECTOR(FaultBeforePendingDeleteFilespaceEntry); /* * MPP-18228 * To make adding 'Create Pending' entry to persistent table and adding * to the PendingDelete list atomic */ PendingDelete_AddCreatePendingEntryWrapper( &fsObjName, persistentTid, *persistentSerialNum); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: Add '%s' in state 'Created', mirror existence state '%s', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), MirroredObjectExistenceState_Name(mirrorExistenceState), *persistentSerialNum, ItemPointerToString(persistentTid)); }
/* * Indicate we intend to create a filespace file as part of the current transaction. * * An XLOG IntentToCreate record is generated that will guard the subsequent file-system * create in case the transaction aborts. * * After 1 or more calls to this routine to mark intention about filespace files that are going * to be created, call ~_DoPendingCreates to do the actual file-system creates. (See its * note on XLOG flushing). */ void PersistentFilespace_MarkCreatePending( Oid filespaceOid, char *filespaceLocation, ItemPointer persistentTid, int64 *persistentSerialNum, bool flushToXLog) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; FilespaceDirEntry filespaceDirEntry; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent filespace %u because we are before persistence work", filespaceOid); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentFilespace_VerifyInitScan(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName,filespaceOid,is_filespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; filespaceDirEntry = PersistentFilespace_CreateDirUnderLock(filespaceOid); if (filespaceDirEntry == NULL) { /* If out of shared memory, no need to promote to PANIC. */ WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Out of shared-memory for persistent filespaces"), errhint("You may need to increase the gp_max_filespaces value"), errOmitLocation(true))); } PersistentFilespace_BlankPadCopyLocation( filespaceDirEntry->locationBlankPadded1, filespaceLocation); filespaceDirEntry->state = PersistentFileSysState_CreatePending; PersistentFilespace_AddTuple( filespaceDirEntry, /* createMirrorDataLossTrackingSessionNum */ 0, /* reserved */ 0, /* parentXid */ GetTopTransactionId(), flushToXLog); *persistentTid = filespaceDirEntry->persistentTid; *persistentSerialNum = filespaceDirEntry->persistentSerialNum; /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_filespace(filespaceOid); #endif #ifdef FAULT_INJECTOR FaultInjector_InjectFaultIfSet( FaultBeforePendingDeleteFilespaceEntry, DDLNotSpecified, "", // databaseName ""); // tableName #endif /* * MPP-18228 * To make adding 'Create Pending' entry to persistent table and adding * to the PendingDelete list atomic */ PendingDelete_AddCreatePendingEntryWrapper( &fsObjName, persistentTid, *persistentSerialNum); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: Add '%s' in state 'Created', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), *persistentSerialNum, ItemPointerToString(persistentTid)); }
/* * Activate a standby master by removing reference to the dead master * and changing our dbid to the old master's dbid */ void PersistentFilespace_ActivateStandby(int16 oldmaster, int16 newmaster) { HASH_SEQ_STATUS hstat; FilespaceDirEntry fde; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); hash_seq_init(&hstat, persistentFilespaceSharedHashTable); PersistentFilespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; /* * We release FilespaceHashLock in the middle of the loop and re-acquire * it after doing persistent table change. This is needed to prevent * holding the lock for any purpose other than to protect the filespace * shared hash table. Not releasing this lock could result in file I/O * and potential deadlock due to other LW locks being acquired in the * process. Releasing the lock this way is safe because we are still * holding PersistentObjLock in exclusive mode. Any change to the * filespace shared hash table is also protected by PersistentObjLock. */ WRITE_FILESPACE_HASH_LOCK; while ((fde = hash_seq_search(&hstat)) != NULL) { Oid filespace = fde->key.filespaceOid; PersistentFileSysObjName fsObjName; ItemPointerData persistentTid; int64 persistentSerialNum = fde->persistentSerialNum; ItemPointerCopy(&fde->persistentTid, &persistentTid); PersistentFileSysObjName_SetFilespaceDir(&fsObjName, filespace); if (fde->dbId1 == oldmaster) { fde->dbId1 = InvalidDbid; fde->dbId2 = newmaster; /* Copy standby filespace location into new master location */ PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, fde->locationBlankPadded1); PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, ""); } else if (fde->dbId2 == oldmaster) { fde->dbId2 = InvalidDbid; fde->dbId1 = newmaster; /* Copy standby filespace location into new master location */ PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, fde->locationBlankPadded2); PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, ""); } WRITE_FILESPACE_HASH_UNLOCK; PersistentFileSysObj_ActivateStandby(&fsObjName, &persistentTid, persistentSerialNum, oldmaster, newmaster, /* flushToXlog */ false); WRITE_FILESPACE_HASH_LOCK; } WRITE_FILESPACE_HASH_UNLOCK; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
bool PersistentFilespace_TryGetPrimaryAndMirrorUnderLock( Oid filespaceOid, /* The filespace OID to lookup. */ char **primaryFilespaceLocation, /* The primary filespace directory path. Return NULL for global and base. */ char **mirrorFilespaceLocation) /* The primary filespace directory path. Return NULL for global and base. * Or, returns NULL when mirror not configured. */ { FilespaceDirEntry filespaceDirEntry; int16 primaryDbId; char *primaryBlankPadded = NULL; char *mirrorBlankPadded = NULL; *primaryFilespaceLocation = NULL; *mirrorFilespaceLocation = NULL; #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (IsStandbyMode()) { return mmxlog_filespace_get_path( filespaceOid, primaryFilespaceLocation); } #endif /* * Important to make this call AFTER we check if we are the Standby Master. */ PersistentFilespace_VerifyInitScan(); filespaceDirEntry = PersistentFilespace_FindDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) return false; /* * The persistent_filespace_node_table contains the paths for both the * primary and mirror nodes, and the table is the same on both sides of the * mirror. When it was first created the primary put its location first, * but we don't know if we were the primary when it was created or not. To * determine which path corresponds to this node we compare our dbid to the * one stored in the table. */ primaryDbId = GpIdentity.dbid; if (filespaceDirEntry->dbId1 == primaryDbId) { /* dbid == dbid1 */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded1; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded2; } else if (filespaceDirEntry->dbId2 == primaryDbId) { /* dbid == dbid2 */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded2; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded1; } else { /* * The dbid check above does not work for the Master Node during * initial startup, because the master doesn't yet know its own dbid. * To handle this we special case for the master node the master * always considers the first entry as the correct location. * * Note: This design may need to be reconsidered to handle standby * masters! */ PrimaryMirrorMode mode; getPrimaryMirrorStatusCodes(&mode, NULL, NULL, NULL); if (mode == PMModeMaster) { /* Master node */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded1; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded2; } else { /* * Current dbid matches neither dbid in table and was not started * as a master node. */ ereport(FATAL, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Unable to determine dbid for filespace lookup"))); } } /* These should both have been populated by one of the cases above */ Assert(primaryBlankPadded); Assert(mirrorBlankPadded); PersistentFilespace_ConvertBlankPaddedLocation( primaryFilespaceLocation, primaryBlankPadded, /* isPrimary */ true); PersistentFilespace_ConvertBlankPaddedLocation( mirrorFilespaceLocation, mirrorBlankPadded, /* isPrimary */ false); return true; }
// ----------------------------------------------------------------------------- // Rebuild filespace persistent table 'gp_persistent_filespace_node' // ----------------------------------------------------------------------------- void PersistentFilespace_AddCreated( Oid filespaceOid, /* The filespace OID to be added. */ bool flushToXLog) /* When true, the XLOG record for this change will be flushed to disk. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; ItemPointerData persistentTid; int64 persistentSerialNum; FilespaceDirEntry filespaceDirEntry; /*if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent filespace %u because we are before persistence work", filespaceOid); return; // The initdb process will load the persistent table once we out of bootstrap mode. }*/ PersistentFilespace_VerifyInitScan(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName,filespaceOid,is_filespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; filespaceDirEntry = PersistentFilespace_CreateDirUnderLock(filespaceOid); if (filespaceDirEntry == NULL) { /* If out of shared memory, no need to promote to PANIC. */ WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Out of shared-memory for persistent filespaces"), errhint("You may need to increase the gp_max_filespaces value"), errOmitLocation(true))); } // if it is a new generated one, we need to set info from pg_filespace_entry if(filespaceDirEntry->persistentSerialNum==0 || strlen(filespaceDirEntry->locationBlankPadded1)==0) { Relation pg_fs_entry_rel; HeapScanDesc scandesc; HeapTuple tuple; ScanKeyData entry[1]; bool isNull; Datum locDatum; char *loc; /* Lookup the information for the current pg_filespace_entry */ pg_fs_entry_rel = heap_open(FileSpaceEntryRelationId, AccessShareLock); ScanKeyInit(&entry[0], Anum_pg_filespace_entry_fsefsoid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(filespaceOid)); scandesc = heap_beginscan(pg_fs_entry_rel, SnapshotNow, 1, entry); tuple = heap_getnext(scandesc, ForwardScanDirection); /* We assume that there can be at most one matching tuple */ if (!HeapTupleIsValid(tuple)) { elog(ERROR, "filespace %u could not be found in pg_filespace_entry", filespaceOid); } locDatum = heap_getattr(tuple, Anum_pg_filespace_entry_fselocation, pg_fs_entry_rel->rd_att, &isNull); loc = TextDatumGetCString(locDatum); //convert location with blank padded memset(filespaceDirEntry->locationBlankPadded1, ' ', FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen-1]='\0'; memcpy(filespaceDirEntry->locationBlankPadded1, loc, strlen(loc)); if(isNull) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("internal error: filespace '%u' has no name defined", filespaceOid))); heap_endscan(scandesc); heap_close(pg_fs_entry_rel, AccessShareLock); } filespaceDirEntry->state = PersistentFileSysState_Created; PersistentFilespace_AddTuple( filespaceDirEntry, /* createMirrorDataLossTrackingSessionNum */ 0, /* reserved */ 0, /* parentXid */ InvalidTransactionId, flushToXLog); persistentTid = filespaceDirEntry->persistentTid; persistentSerialNum = filespaceDirEntry->persistentSerialNum; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: Add '%s' in state 'Created', serial number " INT64_FORMAT " at TID '%s' ", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(&persistentTid)); }
/* * Indicate we physically removed the filespace file. */ void PersistentFilespace_Dropped( PersistentFileSysObjName *fsObjName, /* The filespace OID for the dropped filespace. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum) /* Serial number for the filespace. Distinquishes the uses of the tuple. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; Oid filespaceOid = fsObjName->variant.filespaceOid; FilespaceDirEntry filespaceDirEntry; PersistentFileSysState oldState; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent filespace %u because we are before persistence work", filespaceOid); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentFilespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; filespaceDirEntry = PersistentFilespace_FindDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) elog(ERROR, "Did not find persistent filespace entry %u", filespaceOid); if (filespaceDirEntry->state != PersistentFileSysState_DropPending && filespaceDirEntry->state != PersistentFileSysState_AbortingCreate) elog(ERROR, "Persistent filespace entry %u expected to be in 'Drop Pending' or 'Aborting Create' (actual state '%s')", filespaceOid, PersistentFileSysObjState_Name(filespaceDirEntry->state)); stateChangeResult = PersistentFileSysObj_StateChange( fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_Free, /* retryPossible */ false, /* flushToXlog */ false, &oldState, PersistentFilespace_DroppedVerifiedActionCallback); filespaceDirEntry->state = PersistentFileSysState_Free; PersistentFilespace_RemoveDirUnderLock(filespaceDirEntry); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: '%s' changed state from '%s' to (Free), serial number " INT64_FORMAT " at TID %s (State-Change result '%s')", PersistentFileSysObjName_ObjectName(fsObjName), PersistentFileSysObjState_Name(oldState), persistentSerialNum, ItemPointerToString(persistentTid), PersistentFileSysObjStateChangeResult_Name(stateChangeResult)); }
/* * Activate a standby master by removing reference to the dead master * and changing our dbid to the old master's dbid */ void PersistentFilespace_ActivateStandby(int16 oldmaster, int16 newmaster) { HASH_SEQ_STATUS hstat; FilespaceDirEntry fde; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); hash_seq_init(&hstat, persistentFilespaceSharedHashTable); PersistentFilespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; while ((fde = hash_seq_search(&hstat)) != NULL) { Oid filespace = fde->key.filespaceOid; PersistentFileSysObjName fsObjName; PersistentFileSysObjName_SetFilespaceDir(&fsObjName, filespace); if (fde->dbId1 == oldmaster) { fde->dbId1 = InvalidDbid; fde->dbId2 = newmaster; /* Copy standby filespace location into new master location */ PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, fde->locationBlankPadded1); PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, ""); } else if (fde->dbId2 == oldmaster) { fde->dbId2 = InvalidDbid; fde->dbId1 = newmaster; /* Copy standby filespace location into new master location */ PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded1, fde->locationBlankPadded2); PersistentFilespace_BlankPadCopyLocation( fde->locationBlankPadded2, ""); } PersistentFileSysObj_ActivateStandby(&fsObjName, &fde->persistentTid, fde->persistentSerialNum, oldmaster, newmaster, /* flushToXlog */ false); } WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }