void xlog_create_database(DbDirNode *db) { DatabaseDirEntry dbe; SharedOidSearchAddResult addResult; WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentDatabase_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; /* * XXX:mat3: This is the dead code in HAWQ. There is no local recovery on * segment. And master has its own rerecover code path. */ dbe = (DatabaseDirEntry) SharedOidSearch_Find( &persistentDatabaseSharedData->databaseDirSearchTable, db->database, db->tablespace); if (dbe != NULL) elog(ERROR, "persistent database entry '%s' already exists " "in state '%s'", GetDatabasePath( db->database, db->tablespace), PersistentFileSysObjState_Name(dbe->state)); addResult = SharedOidSearch_Add( &persistentDatabaseSharedData->databaseDirSearchTable, db->database, db->tablespace, (SharedOidSearchObjHeader**)&dbe); if (addResult == SharedOidSearchAddResult_NoMemory) elog(ERROR, "out of shared-memory for persistent databases"); else if (addResult == SharedOidSearchAddResult_Exists) elog(PANIC, "persistent database entry '%s' already exists in " "state '%s'", GetDatabasePath( db->database, db->tablespace), PersistentFileSysObjState_Name(dbe->state)); else Insist(addResult == SharedOidSearchAddResult_Ok); dbe->state = PersistentFileSysState_Created; dbe->iteratorRefCount = 0; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
static bool PersistentTablespace_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { Oid filespaceOid; Oid tablespaceOid; PersistentFileSysState state; int64 createMirrorDataLossTrackingSessionNum; MirroredObjectExistenceState mirrorExistenceState; int32 reserved; TransactionId parentXid; int64 serialNum; TablespaceDirEntry tablespaceDirEntry; GpPersistentTablespaceNode_GetValues( values, &filespaceOid, &tablespaceOid, &state, &createMirrorDataLossTrackingSessionNum, &mirrorExistenceState, &reserved, &parentXid, &serialNum); /* * Normally we would acquire this lock with the WRITE_TABLESPACE_HASH_LOCK * macro, however, this particular function can be called during startup. * During startup, which executes in a single threaded context, no * PersistentObjLock exists and we cannot assert that we're holding it. */ LWLockAcquire(TablespaceHashLock, LW_EXCLUSIVE); tablespaceDirEntry = PersistentTablespace_CreateEntryUnderLock(filespaceOid, tablespaceOid); tablespaceDirEntry->state = state; tablespaceDirEntry->persistentSerialNum = serialNum; tablespaceDirEntry->persistentTid = *persistentTid; LWLockRelease(TablespaceHashLock); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentTablespace_ScanTupleCallback: tablespace %u, filespace %u, state %s, TID %s, serial number " INT64_FORMAT, tablespaceOid, filespaceOid, PersistentFileSysObjState_Name(state), ItemPointerToString2(persistentTid), persistentSerialNum); return true; /* Continue. */ }
static bool PersistentFilespace_FileRepVerifyScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; int16 dbId2; char locationBlankPadded2[FilespaceLocationBlankPaddedWithNullTermLen]; PersistentFileSysState state; int64 createMirrorDataLossTrackingSessionNum; MirroredObjectExistenceState mirrorExistenceState; int32 reserved; TransactionId parentXid; int64 serialNum; ItemPointerData previousFreeTid; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, &dbId2, locationBlankPadded2, &state, &createMirrorDataLossTrackingSessionNum, &mirrorExistenceState, &reserved, &parentXid, &serialNum, &previousFreeTid); elog(LOG, "PersistentFilespace_FileRepVerify: filespace %u, location1 %s location2 %s dbId1 %d, dbId2 %d, state '%s', mirror existence state '%s', TID %s, serial number " INT64_FORMAT, filespaceOid, locationBlankPadded1, locationBlankPadded2, dbId1, dbId2, PersistentFileSysObjState_Name(state), MirroredObjectExistenceState_Name(mirrorExistenceState), ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. }
bool PersistentDatabase_DirIsCreated(DbDirNode *dbDirNode) { READ_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; DatabaseDirEntry databaseDirEntry; bool result; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before " "persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); /* * The initdb process will load the persistent table once we out of * bootstrap mode. */ return true; } PersistentDatabase_VerifyInitScan(); READ_PERSISTENT_STATE_ORDERED_LOCK; databaseDirEntry = (DatabaseDirEntry) SharedOidSearch_Find( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace); result = (databaseDirEntry != NULL); if (result && databaseDirEntry->state != PersistentFileSysState_Created && databaseDirEntry->state != PersistentFileSysState_CreatePending && databaseDirEntry->state != PersistentFileSysState_JustInTimeCreatePending) elog(ERROR, "Persistent database entry %s expected to be in 'Create Pending' or 'Created' (actual state '%s')", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); READ_PERSISTENT_STATE_ORDERED_UNLOCK; return result; }
void PersistentDatabase_AddCreated( DbDirNode *dbDirNode, /* The tablespace and database OIDs for the create. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ bool flushToXLog) /* When true, the XLOG record for this change will be flushed to disk. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; DatabaseDirEntry databaseDirEntry; SharedOidSearchAddResult addResult; int64 persistentSerialNum; if (!Persistent_BeforePersistenceWork()) elog(ERROR, "We can only add to persistent meta-data when special states"); // Verify PersistentFileSysObj_BuildInitScan has been called. PersistentDatabase_VerifyInitScan(); PersistentFileSysObjName_SetDatabaseDir(&fsObjName,dbDirNode->tablespace,dbDirNode->database,is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; /* * GpIdentity.segindex * In the initdb, GpIdentity.segindex is set to -10000. It will update this * value to the correct GpIdentity.segindex. */ databaseDirEntry = (DatabaseDirEntry) SharedOidSearch_Find( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace); if (databaseDirEntry != NULL) elog(ERROR, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); addResult = SharedOidSearch_Add( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace, (SharedOidSearchObjHeader**)&databaseDirEntry); if (addResult == SharedOidSearchAddResult_NoMemory) { /* 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 databases"), errhint("You may need to increase the gp_max_databases and " "gp_max_tablespaces value"), errOmitLocation(true))); } else if (addResult == SharedOidSearchAddResult_Exists) elog(PANIC, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); else Assert(addResult == SharedOidSearchAddResult_Ok); databaseDirEntry->state = PersistentFileSysState_Created; databaseDirEntry->iteratorRefCount = 0; PersistentDatabase_AddTuple( databaseDirEntry, /* reserved */ 0, InvalidTransactionId, flushToXLog); *persistentTid = databaseDirEntry->persistentTid; persistentSerialNum = databaseDirEntry->persistentSerialNum; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent database directory: Add '%s' in state 'Created', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(persistentTid)); }
/* * Indicate we intend to create a relation 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 relation files that are going * to be created, call ~_DoPendingCreates to do the actual file-system creates. (See its * note on XLOG flushing). */ void PersistentDatabase_MarkCreatePending( DbDirNode *dbDirNode, ItemPointer persistentTid, int64 *persistentSerialNum, bool flushToXLog) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; DatabaseDirEntry databaseDirEntry; SharedOidSearchAddResult addResult; PersistentFileSysObjName fsObjName; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); /* * The initdb process will load the persistent table once we * out of bootstrap mode. */ return; } PersistentDatabase_VerifyInitScan(); PersistentFileSysObjName_SetDatabaseDir( &fsObjName, dbDirNode->tablespace, dbDirNode->database, is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; databaseDirEntry = (DatabaseDirEntry) SharedOidSearch_Find( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace); if (databaseDirEntry != NULL) elog(ERROR, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); addResult = SharedOidSearch_Add( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace, (SharedOidSearchObjHeader**)&databaseDirEntry); if (addResult == SharedOidSearchAddResult_NoMemory) { /* 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 databases"), errhint("You may need to increase the gp_max_databases and " "gp_max_tablespaces value"), errOmitLocation(true))); } else if (addResult == SharedOidSearchAddResult_Exists) elog(PANIC, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); else Assert(addResult == SharedOidSearchAddResult_Ok); databaseDirEntry->state = PersistentFileSysState_CreatePending; databaseDirEntry->iteratorRefCount = 0; PersistentDatabase_AddTuple( databaseDirEntry, /* reserved */ 0, /* parentXid */ GetTopTransactionId(), flushToXLog); *persistentTid = databaseDirEntry->persistentTid; *persistentSerialNum = databaseDirEntry->persistentSerialNum; /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_database(dbDirNode->tablespace, dbDirNode->database); #endif #ifdef FAULT_INJECTOR FaultInjector_InjectFaultIfSet( FaultBeforePendingDeleteDatabaseEntry, 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; }
/* * Indicate the non-transaction just-in-time database create was NOT successful. */ void PersistentDatabase_AbandonJustInTimeCreatePending( DbDirNode *dbDirNode, ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum) /* Serial number for the relation. Distinquishes the uses of the tuple. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; DatabaseDirEntry databaseDirEntry; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentDatabase_VerifyInitScan(); PersistentFileSysObjName_SetDatabaseDir(&fsObjName,dbDirNode->tablespace,dbDirNode->database,is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentDatabase_LookupExistingDbDir( dbDirNode, &databaseDirEntry); if (databaseDirEntry->state != PersistentFileSysState_JustInTimeCreatePending) elog(ERROR, "Persistent database entry %s expected to be in 'Just-In-Time Create Pending' state (actual state '%s')", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); stateChangeResult = PersistentFileSysObj_StateChange( &fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_Free, /* retryPossible */ false, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); databaseDirEntry->state = PersistentFileSysState_Free; if (databaseDirEntry->iteratorRefCount == 0) SharedOidSearch_Delete( &persistentDatabaseSharedData->databaseDirSearchTable, &databaseDirEntry->header); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent database directory: Abandon '%s' in state 'Just-In-Time Create Pending', serial number " INT64_FORMAT " at TID %s (State-Change result '%s')", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(persistentTid), PersistentFileSysObjStateChangeResult_Name(stateChangeResult)); }
void PersistentDatabase_MarkJustInTimeCreatePending( DbDirNode *dbDirNode, ItemPointer persistentTid, int64 *persistentSerialNum) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; DatabaseDirEntry databaseDirEntry; SharedOidSearchAddResult addResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentDatabase_VerifyInitScan(); PersistentFileSysObjName_SetDatabaseDir(&fsObjName,dbDirNode->tablespace,dbDirNode->database,is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; databaseDirEntry = (DatabaseDirEntry) SharedOidSearch_Find( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace); if (databaseDirEntry != NULL) { /* * An existence check should have been done before calling this routine. */ elog(ERROR, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); } addResult = SharedOidSearch_Add( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode->database, dbDirNode->tablespace, (SharedOidSearchObjHeader**)&databaseDirEntry); if (addResult == SharedOidSearchAddResult_NoMemory) { /* 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 databases"), errhint("You may need to increase the gp_max_databases and " "gp_max_tablespaces value"), errOmitLocation(true))); } else if (addResult == SharedOidSearchAddResult_Exists) elog(PANIC, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); else Assert(addResult == SharedOidSearchAddResult_Ok); databaseDirEntry->state = PersistentFileSysState_JustInTimeCreatePending; PersistentDatabase_AddTuple( databaseDirEntry, /* reserved */ 0, /* parentXid */ InvalidTransactionId, /* flushToXLog */ true); *persistentTid = databaseDirEntry->persistentTid; *persistentSerialNum = databaseDirEntry->persistentSerialNum; /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_database(dbDirNode->tablespace, dbDirNode->database); #endif WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; }
/* * 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( PersistentFileSysObjName *fsObjName, /* 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; Oid filespaceOid = fsObjName->variant.filespaceOid; 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(); 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_CreatePending) elog(ERROR, "Persistent filespace entry %u expected to be in 'Create Pending' (actual state '%s')", filespaceOid, PersistentFileSysObjState_Name(filespaceDirEntry->state)); stateChangeResult = PersistentFileSysObj_StateChange( fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_AbortingCreate, retryPossible, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); filespaceDirEntry->state = PersistentFileSysState_AbortingCreate; 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; }
PersistentFileSysObjStateChangeResult PersistentRelation_MarkAbortingCreate( PersistentFileSysObjName *fsObjName, ItemPointer persistentTid, int64 persistentSerialNum, bool retryPossible) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; RelFileNode *relFileNode = &fsObjName->variant.rel.relFileNode; RelationDirEntry relationDirEntry; PersistentFileSysObjStateChangeResult stateChangeResult; if (RelFileNode_IsEmpty(relFileNode)) { elog(ERROR, "Invalid RelFileNode (0,0,0)"); } if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are before persistence work", relpath(*relFileNode)); /* * The initdb process will load the persistent table once we out of bootstrap mode. */ return PersistentFileSysObjStateChangeResult_None; } } PersistentRelation_VerifyInitScan(); /* * Do this check after skipping out if in bootstrap mode. */ if (PersistentStore_IsZeroTid(persistentTid)) { elog(ERROR, "TID for persistent '%s' tuple for mark DROP pending is invalid (0,0)", PersistentFileSysObjName_TypeAndObjectName(fsObjName)); } if (persistentSerialNum == 0) { elog(ERROR, "Persistent '%s' serial number for mark DROP pending is invalid (0)", PersistentFileSysObjName_TypeAndObjectName(fsObjName)); } WRITE_PERSISTENT_STATE_ORDERED_LOCK; relationDirEntry = PersistentRelation_FindEntryUnderLock(relFileNode); if (relationDirEntry == NULL) { elog(ERROR, "Did not find persistent relation entry %u/%u/%u", relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode); } if (relationDirEntry->state != PersistentFileSysState_CreatePending) { elog(ERROR, "Persistent relation entry %u/%u/%u expected to be in 'Create Pending' (actual state '%s')", relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, PersistentFileSysObjState_Name(relationDirEntry->state)); } stateChangeResult = PersistentFileSysObj_StateChange( fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_AbortingCreate, retryPossible, /* flushToXLog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); relationDirEntry->state = PersistentFileSysState_AbortingCreate; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "Persistent relation: '%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; }
static bool PersistentRelation_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { RelFileNode relFileNode; PersistentFileSysState state; int32 reserved; TransactionId parentXid; int64 serialNum; ItemPointerData previousFreeTid; RelationDirEntry relationDirEntry; bool sharedStorage; GpPersistentRelationNode_GetValues( values, &relFileNode.spcNode, &relFileNode.dbNode, &relFileNode.relNode, &state, &reserved, &parentXid, &serialNum, &previousFreeTid, &sharedStorage); if (state == PersistentFileSysState_Free) { if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "PersistentRelation_ScanTupleCallback: TID %s, serial number " INT64_FORMAT " is free", ItemPointerToString2(persistentTid), persistentSerialNum); } return true; } relationDirEntry = PersistentRelation_CreateEntryUnderLock(&relFileNode); if (relationDirEntry == NULL) { elog(ERROR, "Out of shared-memory for persistent relations"); } relationDirEntry->state = state; relationDirEntry->persistentSerialNum = serialNum; relationDirEntry->persistentTid = *persistentTid; if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "PersistentRelation_ScanTupleCallback: tablespace %u, database %u, relation %u, state %s, TID %s, serial number " INT64_FORMAT, relFileNode.spcNode, relFileNode.dbNode, relFileNode.relNode, PersistentFileSysObjState_Name(state), ItemPointerToString2(persistentTid), persistentSerialNum); } return true; }
/* * Indicate we intend to drop a relation file as part of the current transaction. * * This relation file to drop will be listed inside a commit, distributed commit, a distributed * prepared, and distributed commit prepared XOG records. * * For any of the commit type records, once that XLOG record is flushed then the actual * file-system delete will occur. The flush guarantees the action will be retried after system * crash. */ PersistentFileSysObjStateChangeResult PersistentRelation_MarkDropPending( RelFileNode *relFileNode, /* The tablespace, database, and relation OIDs for the drop. */ int32 segmentFileNum, ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the relation. */ int64 persistentSerialNum, /* Serial number for the relation. Distinquishes the uses of the tuple. */ bool retryPossible) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; PersistentFileSysState oldState; PersistentFileSysObjStateChangeResult stateChangeResult; if(RelFileNode_IsEmpty(relFileNode)) elog(ERROR, "Invalid RelFileNode (0,0,0)"); if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are before persistence work", relpath(*relFileNode)); return false; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentRelation_VerifyInitScan(); PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, segmentFileNum); // Do this check after skipping out if in bootstrap mode. if (PersistentStore_IsZeroTid(persistentTid)) elog(ERROR, "TID for persistent '%s' tuple for mark DROP pending is invalid (0,0)", PersistentFileSysObjName_TypeAndObjectName(&fsObjName)); if (persistentSerialNum == 0) elog(ERROR, "Persistent '%s' serial number for mark DROP pending is invalid (0)", PersistentFileSysObjName_TypeAndObjectName(&fsObjName)); WRITE_PERSISTENT_STATE_ORDERED_LOCK; stateChangeResult = PersistentFileSysObj_StateChange( &fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_DropPending, retryPossible, /* flushToXlog */ false, &oldState, /* verifiedActionCallback */ NULL); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent relation: '%s' changed state from '%s' to 'Drop Pending', serial number " INT64_FORMAT " TID %s (State-Change result '%s')", PersistentFileSysObjName_ObjectName(&fsObjName), PersistentFileSysObjState_Name(oldState), persistentSerialNum, ItemPointerToString(persistentTid), PersistentFileSysObjStateChangeResult_Name(stateChangeResult)); return stateChangeResult; }
static bool PersistentFilespace_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; int16 dbId2; char locationBlankPadded2[FilespaceLocationBlankPaddedWithNullTermLen]; PersistentFileSysState state; int64 createMirrorDataLossTrackingSessionNum; MirroredObjectExistenceState mirrorExistenceState; int32 reserved; TransactionId parentXid; int64 serialNum; FilespaceDirEntry filespaceDirEntry; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, &dbId2, locationBlankPadded2, &state, &createMirrorDataLossTrackingSessionNum, &mirrorExistenceState, &reserved, &parentXid, &serialNum); /* * Normally we would acquire this lock with the WRITE_FILESPACE_HASH_LOCK * macro, however, this particular function can be called during startup. * During startup, which executes in a single threaded context, no * PersistentObjLock exists and we cannot assert that we're holding it. */ LWLockAcquire(FilespaceHashLock, LW_EXCLUSIVE); filespaceDirEntry = PersistentFilespace_CreateDirUnderLock(filespaceOid); filespaceDirEntry->dbId1 = dbId1; memcpy(filespaceDirEntry->locationBlankPadded1, locationBlankPadded1, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->dbId2 = dbId2; memcpy(filespaceDirEntry->locationBlankPadded2, locationBlankPadded2, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->state = state; filespaceDirEntry->persistentSerialNum = serialNum; filespaceDirEntry->persistentTid = *persistentTid; LWLockRelease(FilespaceHashLock); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentFilespace_ScanTupleCallback: filespace %u, dbId1 %d, dbId2 %d, state '%s', mirror existence state '%s', TID %s, serial number " INT64_FORMAT, filespaceOid, dbId1, dbId2, PersistentFileSysObjState_Name(state), MirroredObjectExistenceState_Name(mirrorExistenceState), ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. }
/* * Indicate we physically removed the filespace file. */ void PersistentFilespace_Dropped( Oid filespaceOid, /* 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; PersistentFileSysObjName fsObjName; 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(); PersistentFileSysObjName_SetFilespaceDir(&fsObjName,filespaceOid); WRITE_PERSISTENT_STATE_ORDERED_LOCK; stateChangeResult = PersistentFileSysObj_StateChange( &fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_Free, /* retryPossible */ false, /* flushToXlog */ false, &oldState, PersistentFilespace_DroppedVerifiedActionCallback); 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_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)); filespaceDirEntry->state = PersistentFileSysState_Free; PersistentFilespace_RemoveDirUnderLock(filespaceDirEntry); WRITE_FILESPACE_HASH_UNLOCK; 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)); }
static bool PersistentFilespace_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; int16 dbId2; char locationBlankPadded2[FilespaceLocationBlankPaddedWithNullTermLen]; PersistentFileSysState state; int64 createMirrorDataLossTrackingSessionNum; MirroredObjectExistenceState mirrorExistenceState; int32 reserved; TransactionId parentXid; int64 serialNum; ItemPointerData previousFreeTid; FilespaceDirEntry filespaceDirEntry; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, &dbId2, locationBlankPadded2, &state, &createMirrorDataLossTrackingSessionNum, &mirrorExistenceState, &reserved, &parentXid, &serialNum, &previousFreeTid); if (state == PersistentFileSysState_Free) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentFilespace_ScanTupleCallback: TID %s, serial number " INT64_FORMAT " is free", ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. } filespaceDirEntry = PersistentFilespace_CreateDirUnderLock( filespaceOid); filespaceDirEntry->dbId1 = dbId1; memcpy(filespaceDirEntry->locationBlankPadded1, locationBlankPadded1, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->dbId2 = dbId2; memcpy(filespaceDirEntry->locationBlankPadded2, locationBlankPadded2, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->state = state; filespaceDirEntry->persistentSerialNum = serialNum; filespaceDirEntry->persistentTid = *persistentTid; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentFilespace_ScanTupleCallback: filespace %u, dbId1 %d, dbId2 %d, state '%s', mirror existence state '%s', TID %s, serial number " INT64_FORMAT, filespaceOid, dbId1, dbId2, PersistentFileSysObjState_Name(state), MirroredObjectExistenceState_Name(mirrorExistenceState), ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. }
/* * Indicate we are aborting the create of a relation file. * * This state will make sure the relation gets dropped after a system crash. */ PersistentFileSysObjStateChangeResult PersistentDatabase_MarkAbortingCreate( PersistentFileSysObjName *fsObjName, /* The tablespace and database OIDs for the aborting create. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum, /* Serial number for the relation. Distinquishes the uses of the tuple. */ bool retryPossible) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; DbDirNode *dbDirNode = &fsObjName->variant.dbDirNode; DatabaseDirEntry databaseDirEntry; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); return false; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentDatabase_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentDatabase_LookupExistingDbDir( dbDirNode, &databaseDirEntry); if (databaseDirEntry->state != PersistentFileSysState_CreatePending) elog(ERROR, "Persistent database entry %s expected to be in 'Create Pending' (actual state '%s')", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); stateChangeResult = PersistentFileSysObj_StateChange( fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_AbortingCreate, retryPossible, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); databaseDirEntry->state = PersistentFileSysState_AbortingCreate; WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent database 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; }
static bool PersistentDatabase_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { DbDirNode dbDirNode; PersistentFileSysState state; int32 reserved; TransactionId parentXid; int64 serialNum; ItemPointerData previousFreeTid; SharedOidSearchAddResult addResult; DatabaseDirEntry databaseDirEntry; bool sharedStorage; GpPersistentDatabaseNode_GetValues( values, &dbDirNode.tablespace, &dbDirNode.database, &state, &reserved, &parentXid, &serialNum, &previousFreeTid, &sharedStorage); if (state == PersistentFileSysState_Free) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentDatabase_ScanTupleCallback: TID %s, serial number " INT64_FORMAT " is free", ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. } addResult = SharedOidSearch_Add( &persistentDatabaseSharedData->databaseDirSearchTable, dbDirNode.database, dbDirNode.tablespace, (SharedOidSearchObjHeader**)&databaseDirEntry); if (addResult == SharedOidSearchAddResult_NoMemory) elog(ERROR, "Out of shared-memory for persistent relations"); else if (addResult == SharedOidSearchAddResult_Exists) elog(PANIC, "Persistent database entry '%s' already exists in state '%s'", GetDatabasePath(dbDirNode.database, dbDirNode.tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); else Assert(addResult == SharedOidSearchAddResult_Ok); databaseDirEntry->state = state; databaseDirEntry->persistentSerialNum = serialNum; databaseDirEntry->persistentTid = *persistentTid; databaseDirEntry->iteratorRefCount = 0; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentDatabase_ScanTupleCallback: database %u, tablespace %u, state %s, TID %s, serial number " INT64_FORMAT, dbDirNode.database, dbDirNode.tablespace, PersistentFileSysObjState_Name(state), ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. }
/* * Indicate we physically removed the relation file. */ void PersistentDatabase_Dropped( PersistentFileSysObjName *fsObjName, /* The tablespace and database OIDs for the dropped relation. */ ItemPointer persistentTid, /* TID of the gp_persistent_rel_files tuple for the rel file */ int64 persistentSerialNum) /* Serial number for the relation. Distinquishes the uses of the tuple. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; DbDirNode *dbDirNode = &fsObjName->variant.dbDirNode; DatabaseDirEntry databaseDirEntry; PersistentFileSysState oldState; PersistentFileSysObjStateChangeResult stateChangeResult; if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent database '%s' because we are before persistence work", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace)); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentDatabase_VerifyInitScan(); WRITE_PERSISTENT_STATE_ORDERED_LOCK; PersistentDatabase_LookupExistingDbDir( dbDirNode, &databaseDirEntry); if (databaseDirEntry->state != PersistentFileSysState_DropPending && databaseDirEntry->state != PersistentFileSysState_AbortingCreate) elog(ERROR, "Persistent database entry %s expected to be in 'Drop Pending' or 'Aborting Create' (actual state '%s')", GetDatabasePath( dbDirNode->database, dbDirNode->tablespace), PersistentFileSysObjState_Name(databaseDirEntry->state)); stateChangeResult = PersistentFileSysObj_StateChange( fsObjName, persistentTid, persistentSerialNum, PersistentFileSysState_Free, /* retryPossible */ false, /* flushToXlog */ false, &oldState, PersistentDatabase_DroppedVerifiedActionCallback); databaseDirEntry->state = PersistentFileSysState_Free; if (databaseDirEntry->iteratorRefCount == 0) SharedOidSearch_Delete( &persistentDatabaseSharedData->databaseDirSearchTable, &databaseDirEntry->header); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent database 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)); }
/* * 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)); }
static bool PersistentFilespace_ScanTupleCallback( ItemPointer persistentTid, int64 persistentSerialNum, Datum *values) { Oid filespaceOid; int16 dbId1; char locationBlankPadded1[FilespaceLocationBlankPaddedWithNullTermLen]; PersistentFileSysState state; int32 reserved; TransactionId parentXid; int64 serialNum; ItemPointerData previousFreeTid; FilespaceDirEntry filespaceDirEntry; bool sharedStorage; GpPersistentFilespaceNode_GetValues( values, &filespaceOid, &dbId1, locationBlankPadded1, &state, &reserved, &parentXid, &serialNum, &previousFreeTid, &sharedStorage); if (state == PersistentFileSysState_Free) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentFilespace_ScanTupleCallback: TID %s, serial number " INT64_FORMAT " is free", ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. } filespaceDirEntry = PersistentFilespace_CreateDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) elog(ERROR, "Out of shared-memory for persistent filespaces"); memcpy(filespaceDirEntry->locationBlankPadded1, locationBlankPadded1, FilespaceLocationBlankPaddedWithNullTermLen); filespaceDirEntry->state = state; filespaceDirEntry->persistentSerialNum = serialNum; filespaceDirEntry->persistentTid = *persistentTid; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "PersistentFilespace_ScanTupleCallback: filespace %u, dbId1 %d, state '%s', TID %s, serial number " INT64_FORMAT, filespaceOid, dbId1, PersistentFileSysObjState_Name(state), ItemPointerToString2(persistentTid), persistentSerialNum); return true; // Continue. }