void PersistentTablespace_ActivateStandby(int16 oldmaster, int16 newmaster) { TablespaceDirEntry tablespaceDirEntry; HASH_SEQ_STATUS hstat; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; hash_seq_init(&hstat, persistentTablespaceSharedHashTable); if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); PersistentTablespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; LWLockAcquire(TablespaceHashLock, LW_SHARED); while ((tablespaceDirEntry = hash_seq_search(&hstat)) != NULL) { PersistentFileSysObjName fsObjName; Oid tblspc = tablespaceDirEntry->key.tablespaceOid; ItemPointerData persistentTid; uint64 persistentSerialNum; tablespaceDirEntry = PersistentTablespace_FindEntryUnderLock(tblspc); if (tablespaceDirEntry == NULL) elog(ERROR, "cannot find persistent tablespace entry %u", tblspc); persistentSerialNum = tablespaceDirEntry->persistentSerialNum; ItemPointerCopy(&tablespaceDirEntry->persistentTid, &persistentTid); /* * We release TablespaceHashLock 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 tablespace 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. */ LWLockRelease(TablespaceHashLock); PersistentFileSysObjName_SetTablespaceDir(&fsObjName, tblspc); PersistentFileSysObj_ActivateStandby(&fsObjName, &persistentTid, persistentSerialNum, oldmaster, newmaster, /* flushToXlog */ false); LWLockAcquire(TablespaceHashLock, LW_SHARED); } LWLockRelease(TablespaceHashLock); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
void PersistentTablespace_Reset(void) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; HASH_SEQ_STATUS stat; TablespaceDirEntry tablespaceDirEntry; hash_seq_init(&stat, persistentTablespaceSharedHashTable); WRITE_PERSISTENT_STATE_ORDERED_LOCK; WRITE_TABLESPACE_HASH_LOCK; while (true) { TablespaceDirEntry removeTablespaceDirEntry; PersistentFileSysObjName fsObjName; tablespaceDirEntry = hash_seq_search(&stat); if (tablespaceDirEntry == NULL) break; PersistentFileSysObjName_SetTablespaceDir( &fsObjName, tablespaceDirEntry->key.tablespaceOid); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent tablespace directory: Resetting '%s' serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), tablespaceDirEntry->persistentSerialNum, ItemPointerToString(&tablespaceDirEntry->persistentTid)); removeTablespaceDirEntry = (TablespaceDirEntry) hash_search(persistentTablespaceSharedHashTable, (void *) &tablespaceDirEntry->key, HASH_REMOVE, NULL); if (removeTablespaceDirEntry == NULL) elog(ERROR, "Trying to delete entry that does not exist"); } WRITE_TABLESPACE_HASH_UNLOCK; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
void PersistentTablespace_RemoveSegment(int16 dbid, bool ismirror) { TablespaceDirEntry tablespaceDirEntry; HASH_SEQ_STATUS hstat; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; hash_seq_init(&hstat, persistentTablespaceSharedHashTable); if (Persistent_BeforePersistenceWork()) elog(ERROR, "persistent table changes forbidden"); PersistentTablespace_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; LWLockAcquire(TablespaceHashLock, LW_SHARED); while ((tablespaceDirEntry = hash_seq_search(&hstat)) != NULL) { PersistentFileSysObjName fsObjName; Oid tblspc = tablespaceDirEntry->key.tablespaceOid; ItemPointerData persistentTid; uint64 persistentSerialNum; tablespaceDirEntry = PersistentTablespace_FindEntryUnderLock(tblspc); LWLockRelease(TablespaceHashLock); if (tablespaceDirEntry == NULL) elog(ERROR, "Did not find persistent tablespace entry %u", tblspc); persistentSerialNum = tablespaceDirEntry->persistentSerialNum; ItemPointerCopy(&tablespaceDirEntry->persistentTid, &persistentTid); PersistentFileSysObjName_SetTablespaceDir(&fsObjName, tblspc); PersistentFileSysObj_RemoveSegment(&fsObjName, &persistentTid, persistentSerialNum, dbid, ismirror, /* flushToXlog */ false); LWLockAcquire(TablespaceHashLock, LW_SHARED); } LWLockRelease(TablespaceHashLock); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
void GpPersistent_GetCommonValues( PersistentFsObjType fsObjType, Datum *values, PersistentFileSysObjName *fsObjName, PersistentFileSysState *persistentState, MirroredObjectExistenceState *mirrorExistenceState, TransactionId *parentXid, int64 *persistentSerialNum) { int64 createMirrorDataLossTrackingSessionNum; int32 reserved; switch (fsObjType) { case PersistentFsObjType_RelationFile: { RelFileNode relFileNode; int32 segmentFileNum; PersistentFileSysRelStorageMgr relationStorageManager; MirroredRelDataSynchronizationState mirrorDataSynchronizationState; bool mirrorBufpoolMarkedForScanIncrementalResync; int64 mirrorBufpoolResyncChangedPageCount; XLogRecPtr mirrorBufpoolResyncCkptLoc; BlockNumber mirrorBufpoolResyncCkptBlockNum; int64 mirrorAppendOnlyLossEof; int64 mirrorAppendOnlyNewEof; PersistentFileSysRelBufpoolKind relBufpoolKind; GpPersistentRelationNode_GetValues( values, &relFileNode.spcNode, &relFileNode.dbNode, &relFileNode.relNode, &segmentFileNum, &relationStorageManager, persistentState, &createMirrorDataLossTrackingSessionNum, mirrorExistenceState, &mirrorDataSynchronizationState, &mirrorBufpoolMarkedForScanIncrementalResync, &mirrorBufpoolResyncChangedPageCount, &mirrorBufpoolResyncCkptLoc, &mirrorBufpoolResyncCkptBlockNum, &mirrorAppendOnlyLossEof, &mirrorAppendOnlyNewEof, &relBufpoolKind, parentXid, persistentSerialNum); PersistentFileSysObjName_SetRelationFile( fsObjName, &relFileNode, segmentFileNum); } break; case PersistentFsObjType_DatabaseDir: { DbDirNode dbDirNode; GpPersistentDatabaseNode_GetValues( values, &dbDirNode.tablespace, &dbDirNode.database, persistentState, &createMirrorDataLossTrackingSessionNum, mirrorExistenceState, &reserved, parentXid, persistentSerialNum); PersistentFileSysObjName_SetDatabaseDir( fsObjName, dbDirNode.tablespace, dbDirNode.database); } break; case PersistentFsObjType_TablespaceDir: { Oid tablespaceOid; Oid filespaceOid; GpPersistentTablespaceNode_GetValues( values, &filespaceOid, &tablespaceOid, persistentState, &createMirrorDataLossTrackingSessionNum, mirrorExistenceState, &reserved, parentXid, persistentSerialNum); PersistentFileSysObjName_SetTablespaceDir( fsObjName, tablespaceOid); } break; case PersistentFsObjType_FilespaceDir: { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; int16 dbId2; char locationBlankPadded2[FilespaceLocationBlankPaddedWithNullTermLen]; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, &dbId2, locationBlankPadded2, persistentState, &createMirrorDataLossTrackingSessionNum, mirrorExistenceState, &reserved, parentXid, persistentSerialNum); PersistentFileSysObjName_SetFilespaceDir( fsObjName, filespaceOid); } break; default: elog(ERROR, "Unexpected persistent file-system object type: %d", fsObjType); } }
/* * Indicate the transaction commited and the tablespace is officially created. */ void PersistentTablespace_Created( Oid tablespaceOid, /* The tablespace OID for the create. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum, /* Serial number for the tablespace. Distinquishes the uses of the tuple. */ bool retryPossible) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; TablespaceDirEntry tablespaceDirEntry; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent tablespace %u because we are before persistence work", tablespaceOid); return; /* * The initdb process will load the persistent table once we out of * bootstrap mode. */ } PersistentTablespace_VerifyInitScan(); PersistentFileSysObjName_SetTablespaceDir(&fsObjName, tablespaceOid); WRITE_PERSISTENT_STATE_ORDERED_LOCK; WRITE_TABLESPACE_HASH_LOCK; tablespaceDirEntry = PersistentTablespace_FindEntryUnderLock(tablespaceOid); if (tablespaceDirEntry == NULL) elog(ERROR, "Did not find persistent tablespace entry %u", tablespaceOid); if (tablespaceDirEntry->state != PersistentFileSysState_CreatePending) elog(ERROR, "Persistent tablespace entry %u expected to be in 'Create Pending' state (actual state '%s')", tablespaceOid, PersistentFileSysObjState_Name(tablespaceDirEntry->state)); tablespaceDirEntry->state = PersistentFileSysState_Created; WRITE_TABLESPACE_HASH_UNLOCK; stateChangeResult = PersistentFileSysObj_StateChange( &fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_Created, retryPossible, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent tablespace directory: '%s' changed state from 'Create Pending' to 'Created', serial number " INT64_FORMAT " at TID %s (State-Change result '%s')", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(persistentTid), PersistentFileSysObjStateChangeResult_Name(stateChangeResult)); }
void PersistentTablespace_AddCreated( Oid filespaceOid, /* The filespace where the tablespace lives. */ Oid tablespaceOid, /* The tablespace OID to be added. */ MirroredObjectExistenceState mirrorExistenceState, 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; TablespaceDirEntry tablespaceDirEntry; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent tablespace %u because we are before persistence work", tablespaceOid); return; /* * The initdb process will load the persistent table once we out of * bootstrap mode. */ } PersistentTablespace_VerifyInitScan(); PersistentFileSysObjName_SetTablespaceDir(&fsObjName, tablespaceOid); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentTablespace_AddTuple( filespaceOid, tablespaceOid, PersistentFileSysState_Created, /* createMirrorDataLossTrackingSessionNum */ 0, mirrorExistenceState, /* reserved */ 0, InvalidTransactionId, flushToXLog, &persistentTid, &persistentSerialNum); WRITE_TABLESPACE_HASH_LOCK; tablespaceDirEntry = PersistentTablespace_CreateEntryUnderLock(filespaceOid, tablespaceOid); Assert(tablespaceDirEntry != NULL); tablespaceDirEntry->state = PersistentFileSysState_Created; ItemPointerCopy(&persistentTid, &tablespaceDirEntry->persistentTid); tablespaceDirEntry->persistentSerialNum = persistentSerialNum; WRITE_TABLESPACE_HASH_UNLOCK; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent tablespace 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 tablespace 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 tablespace files that are going * to be created, call ~_DoPendingCreates to do the actual file-system creates. (See its * note on XLOG flushing). */ void PersistentTablespace_MarkCreatePending( Oid filespaceOid, /* The filespace where the tablespace lives. */ Oid tablespaceOid, /* The tablespace OID for the create. */ 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; TablespaceDirEntry tablespaceDirEntry; TransactionId topXid; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent tablespace %u because we are before persistence work", tablespaceOid); return; /* * The initdb process will load the persistent table once we out of * bootstrap mode. */ } PersistentTablespace_VerifyInitScan(); PersistentFileSysObjName_SetTablespaceDir(&fsObjName, tablespaceOid); topXid = GetTopTransactionId(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentTablespace_AddTuple( filespaceOid, tablespaceOid, PersistentFileSysState_CreatePending, /* createMirrorDataLossTrackingSessionNum */ 0, mirrorExistenceState, /* reserved */ 0, /* parentXid */ topXid, flushToXLog, persistentTid, persistentSerialNum); WRITE_TABLESPACE_HASH_LOCK; tablespaceDirEntry = PersistentTablespace_CreateEntryUnderLock(filespaceOid, tablespaceOid); Assert(tablespaceDirEntry != NULL); tablespaceDirEntry->state = PersistentFileSysState_CreatePending; ItemPointerCopy(persistentTid, &tablespaceDirEntry->persistentTid); tablespaceDirEntry->persistentSerialNum = *persistentSerialNum; WRITE_TABLESPACE_HASH_UNLOCK; /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_tablespace( filespaceOid, tablespaceOid); #endif SIMPLE_FAULT_INJECTOR(FaultBeforePendingDeleteTablespaceEntry); /* * 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 tablespace 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)); }
void GpPersistent_GetCommonValues( PersistentFsObjType fsObjType, Datum *values, PersistentFileSysObjName *fsObjName, PersistentFileSysState *persistentState, TransactionId *parentXid, int64 *persistentSerialNum) { int32 reserved; ItemPointerData previousFreeTid; bool sharedStorage; switch (fsObjType) { case PersistentFsObjType_RelationFile: { RelFileNode relFileNode; int32 segmentFileNum; PersistentFileSysRelStorageMgr relationStorageManager; PersistentFileSysRelBufpoolKind relBufpoolKind; GpPersistentRelfileNode_GetValues( values, &relFileNode.spcNode, &relFileNode.dbNode, &relFileNode.relNode, &segmentFileNum, &relationStorageManager, persistentState, &relBufpoolKind, parentXid, persistentSerialNum, &previousFreeTid, &sharedStorage); PersistentFileSysObjName_SetRelationFile( fsObjName, &relFileNode, segmentFileNum, NULL); fsObjName->hasInited = true; fsObjName->sharedStorage = sharedStorage; } break; case PersistentFsObjType_RelationDir: { RelFileNode relFileNode; GpPersistentRelationNode_GetValues( values, &relFileNode.spcNode, &relFileNode.dbNode, &relFileNode.relNode, persistentState, &reserved, parentXid, persistentSerialNum, &previousFreeTid, &sharedStorage); PersistentFileSysObjName_SetRelationDir( fsObjName, &relFileNode, NULL); fsObjName->hasInited = true; fsObjName->sharedStorage = sharedStorage; } break; case PersistentFsObjType_DatabaseDir: { DbDirNode dbDirNode; GpPersistentDatabaseNode_GetValues( values, &dbDirNode.tablespace, &dbDirNode.database, persistentState, &reserved, parentXid, persistentSerialNum, &previousFreeTid, &sharedStorage); PersistentFileSysObjName_SetDatabaseDir( fsObjName, dbDirNode.tablespace, dbDirNode.database, NULL); fsObjName->hasInited = true; fsObjName->sharedStorage = sharedStorage; } break; case PersistentFsObjType_TablespaceDir: { Oid tablespaceOid; Oid filespaceOid; GpPersistentTablespaceNode_GetValues( values, &filespaceOid, &tablespaceOid, persistentState, &reserved, parentXid, persistentSerialNum, &previousFreeTid, &sharedStorage); PersistentFileSysObjName_SetTablespaceDir( fsObjName, tablespaceOid, NULL); fsObjName->hasInited = true; fsObjName->sharedStorage = sharedStorage; } break; case PersistentFsObjType_FilespaceDir: { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, persistentState, &reserved, parentXid, persistentSerialNum, &previousFreeTid, &sharedStorage); PersistentFileSysObjName_SetFilespaceDir( fsObjName, filespaceOid, NULL); fsObjName->hasInited = true; fsObjName->sharedStorage = sharedStorage; } break; default: elog(ERROR, "Unexpected persistent file-system object type: %d", fsObjType); } }