/* * 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; }
/* * 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; }
/* * 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)); }
/* * 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; }
/* * 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; }
/* * 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)); }