static void PersistentBuild_NonTransactionTruncate(RelFileNode *relFileNode) { SMgrRelation smgrRelation; PersistentFileSysObjName fsObjName; PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, /* segmentFileNum */ 0, is_tablespace_shared); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Non-transaction truncate of '%s'", PersistentFileSysObjName_ObjectName(&fsObjName)); smgrRelation = smgropen(*relFileNode); smgrtruncate( smgrRelation, 0, /* isTemp */ true, /* isLocalBuf */ false, /* persistentTid */ NULL, /* persistentSerialNum */ 0); smgrclose(smgrRelation); }
void PersistentRelation_Reset(void) { HASH_SEQ_STATUS stat; RelationDirEntry relationDirEntry; hash_seq_init(&stat, persistentRelationSharedHashTable); while (true) { RelationDirEntry removeRelationDirEntry; PersistentFileSysObjName fsObjName; RelFileNode relFileNode; relationDirEntry = hash_seq_search(&stat); if (relationDirEntry == NULL) { break; } relFileNode.spcNode = relationDirEntry->key.tablespaceOid; relFileNode.dbNode = relationDirEntry->key.databaseOid; relFileNode.relNode = relationDirEntry->key.relfilenodeOid; PersistentFileSysObjName_SetRelationDir( &fsObjName, &relFileNode, is_tablespace_shared); if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "Persistent relation directory: Resetting '%s' serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), relationDirEntry->persistentSerialNum, ItemPointerToString(&relationDirEntry->persistentTid)); } removeRelationDirEntry = (RelationDirEntry) hash_search(persistentRelationSharedHashTable, (void *) &relationDirEntry->key, HASH_REMOVE, NULL); if (removeRelationDirEntry == NULL) { elog(ERROR, "Trying to delete entry that does not exist"); } } }
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; }
extern void PersistentDatabase_Reset(void) { DatabaseDirEntry databaseDirEntry; databaseDirEntry = NULL; SharedOidSearch_Iterate( &persistentDatabaseSharedData->databaseDirSearchTable, (SharedOidSearchObjHeader**)&databaseDirEntry); while (true) { PersistentFileSysObjName fsObjName; DatabaseDirEntry nextDatabaseDirEntry; if (databaseDirEntry == NULL) { break; } PersistentFileSysObjName_SetDatabaseDir( &fsObjName, /* tablespaceOid */ databaseDirEntry->header.oid2, /* databaseOid */ databaseDirEntry->header.oid1, NULL); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent database directory: Resetting '%s' serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), databaseDirEntry->persistentSerialNum, ItemPointerToString(&databaseDirEntry->persistentTid)); nextDatabaseDirEntry = databaseDirEntry; SharedOidSearch_Iterate( &persistentDatabaseSharedData->databaseDirSearchTable, (SharedOidSearchObjHeader**)&nextDatabaseDirEntry); SharedOidSearch_Delete( &persistentDatabaseSharedData->databaseDirSearchTable, &databaseDirEntry->header); databaseDirEntry = nextDatabaseDirEntry; } }
void PersistentFilespace_Reset(void) { HASH_SEQ_STATUS stat; FilespaceDirEntry filespaceDirEntry; hash_seq_init(&stat, persistentFilespaceSharedHashTable); while (true) { FilespaceDirEntry removeFilespaceDirEntry; PersistentFileSysObjName fsObjName; filespaceDirEntry = hash_seq_search(&stat); if (filespaceDirEntry == NULL) break; PersistentFileSysObjName_SetFilespaceDir( &fsObjName, filespaceDirEntry->key.filespaceOid, is_filespace_shared); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent filespace directory: Resetting '%s' serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), filespaceDirEntry->persistentSerialNum, ItemPointerToString(&filespaceDirEntry->persistentTid)); removeFilespaceDirEntry = (FilespaceDirEntry) hash_search(persistentFilespaceSharedHashTable, (void *) &filespaceDirEntry->key, HASH_REMOVE, NULL); if (removeFilespaceDirEntry == NULL) elog(ERROR, "Trying to delete entry that does not exist"); } }
char *PersistentFileSysObjName_TypeAndObjectName( const PersistentFileSysObjName *name) { char *typeName; char *objectName; char resultLen; char *result; typeName = PersistentFileSysObjName_TypeName(name->type); objectName = PersistentFileSysObjName_ObjectName(name); resultLen = strlen(typeName) + 4 + strlen(objectName) + 1; result = (char*)palloc(resultLen); snprintf(result, resultLen, "%s: '%s'", typeName, objectName); pfree(objectName); return result; }
void PersistentRelation_AddCreated( RelFileNode *relFileNode, /* The tablespace, database, and relation OIDs for the create. */ int32 segmentFileNum, PersistentFileSysRelStorageMgr relStorageMgr, PersistentFileSysRelBufpoolKind relBufpoolKind, MirroredObjectExistenceState mirrorExistenceState, MirroredRelDataSynchronizationState relDataSynchronizationState, int64 mirrorAppendOnlyLossEof, int64 mirrorAppendOnlyNewEof, char *relationName, ItemPointer persistentTid, /* Resulting TID of the gp_persistent_rel_files tuple for the relation. */ int64 *persistentSerialNum, /* Resulting serial number for the relation. Distinquishes the uses of the tuple. */ bool flushToXLog) /* When true, the XLOG record for this change will be flushed to disk. */ { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; XLogRecPtr mirrorBufpoolResyncCkptLoc; ItemPointerData previousFreeTid; Datum values[Natts_gp_persistent_relation_node]; if(RelFileNode_IsEmpty(relFileNode)) elog(ERROR, "Invalid RelFileNode (0,0,0)"); MemSet(&previousFreeTid, 0, sizeof(ItemPointerData)); MemSet(&mirrorBufpoolResyncCkptLoc, 0, sizeof(XLogRecPtr)); if (!Persistent_BeforePersistenceWork()) elog(ERROR, "We can only add to persistent meta-data when special states"); // Verify PersistentFileSysObj_BuildInitScan has been called. PersistentRelation_VerifyInitScan(); PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, segmentFileNum); WRITE_PERSISTENT_STATE_ORDERED_LOCK; GpPersistentRelationNode_SetDatumValues( values, relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, segmentFileNum, relStorageMgr, PersistentFileSysState_Created, /* createMirrorDataLossTrackingSessionNum */ 0, mirrorExistenceState, relDataSynchronizationState, /* mirrorBufpoolMarkedForScanIncrementalResync */ false, /* mirrorBufpoolResyncChangedPageCount */ 0, &mirrorBufpoolResyncCkptLoc, /* mirrorBufpoolResyncCkptBlockNum */ 0, mirrorAppendOnlyLossEof, mirrorAppendOnlyNewEof, relBufpoolKind, InvalidTransactionId, /* persistentSerialNum */ 0, // This will be set by PersistentFileSysObj_AddTuple. &previousFreeTid); PersistentFileSysObj_AddTuple( PersistentFsObjType_RelationFile, values, flushToXLog, persistentTid, persistentSerialNum); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent relation: Add '%s', relation name '%s', in state 'Created', relation storage manager '%s', mirror existence state '%s', relation data resynchronization state '%s', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), relationName, PersistentFileSysRelStorageMgr_Name(relStorageMgr), MirroredObjectExistenceState_Name(mirrorExistenceState), MirroredRelDataSynchronizationState_Name(relDataSynchronizationState), *persistentSerialNum, ItemPointerToString(persistentTid)); }
/* * 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 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 PersistentRelation_AddCreated( RelFileNode *relFileNode, ItemPointer persistentTid, bool flushToXLog) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; ItemPointerData previousFreeTid; int64 persistentSerialNum; RelationDirEntry relationDirEntry; Datum values[Natts_gp_persistent_relation_node]; if (RelFileNode_IsEmpty(relFileNode)) { elog(ERROR, "Invalid RelFileNode (0,0,0)"); } MemSet(&previousFreeTid, 0, sizeof(ItemPointerData)); if (!Persistent_BeforePersistenceWork()) { elog(ERROR, "We can only add to persistent meta-data when special states"); } /* Verify PersistentFileSysObj_BuildInitScan has been called */ PersistentRelation_VerifyInitScan(); PersistentFileSysObjName_SetRelationDir( &fsObjName, relFileNode, is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; relationDirEntry = PersistentRelation_CreateEntryUnderLock(relFileNode); if (relationDirEntry == 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 relations"), errhint("You may need to increase the gp_max_relations value"), errOmitLocation(true))); } relationDirEntry->state = PersistentFileSysState_Created; GpPersistentRelationNode_SetDatumValues( values, relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, PersistentFileSysState_Created, /* reserved */ 0, /* parentXid */ InvalidTransactionId, /* persistentSerialNum */ 0, &previousFreeTid, is_tablespace_shared(relFileNode->spcNode)); PersistentFileSysObj_AddTuple( PersistentFsObjType_RelationDir, values, flushToXLog, persistentTid, &persistentSerialNum); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) { elog(Persistent_DebugPrintLevel(), "Persistent relation: Add '%s', in state 'Created', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), persistentSerialNum, ItemPointerToString(persistentTid)); } }
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; }
// ----------------------------------------------------------------------------- // 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 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)); }
/* * 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; }
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)); }
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. * * This function adds an entry in 'gp_persistent_relation_node' for either a new table (segment file * # 0) or a new segment file under AO table (segment file # > 0 for row/column-oriented AO) with a state * 'Create Pending'. An XLOG IntentToCreate record is generated that will guard the subsequent file-system * create in case the transaction aborts. * * Paramaters * ----------- * relFileNode = The tablespace, database, and relation OIDs for the create * segmentFileNum = As the name implies ( 0 for heap * >= 0 for RO/CO AO as applicable) * relStorageMgr = Persistent Relation storage Manager * relBufpoolKind = Buffer pool type beneath corrosponding relation * TODO bufferPollBulkLoad = ??? * TODO mirrorExistenceState = ??? * TODO relDataSynchronizationState = ??? * flushToXlog = If true, the XLOG record for this change will be flushed to disk. * TODO isLocalBuf = ??? * * Return * ------ * relationName = Name of the relation used for either debugging or to store in PendingDelete LL. * persistentTid = Resulting TID of the gp_persistent_rel_files tuple for the relation * serialNum = Resulting serial number for the relation. Distinquishes the uses of the tuple */ void PersistentRelation_AddCreatePending( RelFileNode *relFileNode, int32 segmentFileNum, PersistentFileSysRelStorageMgr relStorageMgr, PersistentFileSysRelBufpoolKind relBufpoolKind, bool bufferPoolBulkLoad, MirroredObjectExistenceState mirrorExistenceState, MirroredRelDataSynchronizationState relDataSynchronizationState, char *relationName, ItemPointer persistentTid, int64 *serialNum, bool flushToXLog, bool isLocalBuf) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; XLogRecPtr mirrorBufpoolResyncCkptLoc; ItemPointerData previousFreeTid; Datum values[Natts_gp_persistent_relation_node]; if(RelFileNode_IsEmpty(relFileNode)) elog(ERROR, "Invalid RelFileNode (0,0,0)"); MemSet(&previousFreeTid, 0, sizeof(ItemPointerData)); MemSet(&mirrorBufpoolResyncCkptLoc, 0, sizeof(XLogRecPtr)); if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are before persistence work", relpath(*relFileNode)); MemSet(persistentTid, 0, sizeof(ItemPointerData)); *serialNum = 0; return; // The initdb process will load the persistent table once we out of bootstrap mode. } /* Verify if the needed shared mem data structures for persistent tables are setup and inited */ PersistentRelation_VerifyInitScan(); /* Setup the file system object name */ PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, segmentFileNum); WRITE_PERSISTENT_STATE_ORDERED_LOCK; /* Create a values array which will be used to create a 'gp_persistent_relation_node' tuple */ GpPersistentRelationNode_SetDatumValues( values, relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, segmentFileNum, relStorageMgr, (bufferPoolBulkLoad ? PersistentFileSysState_BulkLoadCreatePending : PersistentFileSysState_CreatePending), /* createMirrorDataLossTrackingSessionNum */ 0, mirrorExistenceState, relDataSynchronizationState, /* mirrorBufpoolMarkedForScanIncrementalResync */ false, /* mirrorBufpoolResyncChangedPageCount */ 0, &mirrorBufpoolResyncCkptLoc, /* mirrorBufpoolResyncCkptBlockNum */ 0, /* mirrorAppendOnlyLossEof */ 0, /* mirrorAppendOnlyNewEof */ 0, relBufpoolKind, GetTopTransactionId(), /* persistentSerialNum */ 0, // This will be set by PersistentFileSysObj_AddTuple. &previousFreeTid); /* Add a new tuple to 'gp_persistent_relation_node' table for the new relation/segment file * we intend to create. This will also create and apply a new persistent serial number. */ PersistentFileSysObj_AddTuple( PersistentFsObjType_RelationFile, values, flushToXLog, persistentTid, serialNum); /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_relfilenode( relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, segmentFileNum); #endif #ifdef FAULT_INJECTOR FaultInjector_InjectFaultIfSet( FaultBeforePendingDeleteRelationEntry, DDLNotSpecified, "", // databaseName ""); // tableName #endif /* We'll add an entry to the PendingDelete LinkedList (LL) to remeber what we * created in this transaction (or sub-transaction). If the transaction * aborts then we can search for all such entries in this LL and get rid of (delete) * such relations or segment files on the disk. * * MPP-18228 * To make adding 'Create Pending' entry to persistent table and adding * to the PendingDelete list atomic */ PendingDelete_AddCreatePendingRelationEntry( &fsObjName, persistentTid, serialNum, relStorageMgr, relationName, isLocalBuf, bufferPoolBulkLoad); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent relation: Add '%s', relation name '%s' in state 'Create Pending', relation storage manager '%s', mirror existence state '%s', relation data resynchronization state '%s', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), relationName, PersistentFileSysRelStorageMgr_Name(relStorageMgr), MirroredObjectExistenceState_Name(mirrorExistenceState), MirroredRelDataSynchronizationState_Name(relDataSynchronizationState), *serialNum, ItemPointerToString(persistentTid)); }
void PersistentRelation_MarkBufPoolRelationForScanIncrementalResync( RelFileNode *relFileNode, /* The tablespace, database, and relation OIDs for the created relation. */ 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. */ { PersistentFileSysObjName fsObjName; if(RelFileNode_IsEmpty(relFileNode)) elog(ERROR, "Invalid RelFileNode (0,0,0)"); if (GpPersistent_SkipXLogInfo(relFileNode->relNode)) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because it is special", relpath(*relFileNode)); return; // Resynchronize will always handle these relations as 'Scan Incremental'.. } if (IsBootstrapProcessingMode()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are in bootstrap mode", relpath(*relFileNode)); return; // The initdb process will load the persistent table once we out of bootstrap mode. } if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are before persistence work", relpath(*relFileNode)); return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentRelation_VerifyInitScan(); PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, /* segmentFileNum */ 0); // Do this check after skipping out if in bootstrap mode. if (PersistentStore_IsZeroTid(persistentTid)) elog(ERROR, "TID for persistent '%s' tuple for mark physically truncated is invalid (0,0)", PersistentFileSysObjName_TypeAndObjectName(&fsObjName)); if (persistentSerialNum == 0) elog(ERROR, "Persistent '%s' serial number for mark physcially truncated is invalid (0)", PersistentFileSysObjName_TypeAndObjectName(&fsObjName)); PersistentFileSysObj_MarkBufPoolRelationForScanIncrementalResync( &fsObjName, persistentTid, persistentSerialNum, /* flushToXlog */ true); if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent relation: '%s' marked physically truncated, serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), 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, /* 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 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)); }
/* * 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; }
/* * 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; }
/* * 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)); }
/* * Indicate we are aborting the create of a relation file. * * This state will make sure the relation gets dropped after a system crash. */ PersistentFileSysObjStateChangeResult PersistentRelation_MarkAbortingCreate( RelFileNode *relFileNode, /* The tablespace, database, and relation OIDs for the aborting create. */ 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; 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. } /* MPP-16543: When inserting tuples into AO table, row numbers will be * generated from gp_fastsequence catalog table, as part of the design, * these sequence numbers are not reusable, even if the AO insert * transaction is aborted. The entry in gp_fastsequence was inserted * using frozen_heap_insert, which means it's always visible. * Aborted AO insert transaction will cause inconsistency between * gp_fastsequence and pg_class, the solution is to introduce "frozen * delete" - inplace update tuple's MVCC header to make it invisible. */ Relation gp_fastsequence_rel = heap_open(FastSequenceRelationId, RowExclusiveLock); HeapTuple tup; SysScanDesc scan; ScanKeyData skey; ScanKeyInit(&skey, Anum_gp_fastsequence_objid, BTEqualStrategyNumber, F_OIDEQ, relFileNode->relNode); scan = systable_beginscan(gp_fastsequence_rel, InvalidOid, false, SnapshotNow, 1, &skey); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_gp_fastsequence found = (Form_gp_fastsequence) GETSTRUCT(tup); if (found->objid == relFileNode->relNode) { if (Debug_persistent_print) { elog(LOG, "frozen deleting gp_fastsequence entry for aborted AO insert transaction on relation %s", relpath(*relFileNode)); } frozen_heap_inplace_delete(gp_fastsequence_rel, tup); } } systable_endscan(scan); heap_close(gp_fastsequence_rel, RowExclusiveLock); 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_AbortingCreate, retryPossible, /* flushToXlog */ false, /* oldState */ NULL, /* verifiedActionCallback */ NULL); 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; }
/* * 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)); }
/* * 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 PersistentRelfile_AddCreatePending( RelFileNode *relFileNode, /* The tablespace, database, and relation OIDs for the create. */ int32 segmentFileNum, PersistentFileSysRelStorageMgr relStorageMgr, PersistentFileSysRelBufpoolKind relBufpoolKind, bool bufferPoolBulkLoad, char *relationName, ItemPointer persistentTid, /* Resulting TID of the gp_persistent_relation_files tuple for the relation. */ int64 *serialNum, /* Resulting serial number for the relation. Distinquishes the uses of the tuple. */ bool flushToXLog, /* When true, the XLOG record for this change will be flushed to disk. */ bool isLocalBuf) { WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE; PersistentFileSysObjName fsObjName; XLogRecPtr mirrorBufpoolResyncCkptLoc; ItemPointerData previousFreeTid; Datum values[Natts_gp_persistent_relfile_node]; if(RelFileNode_IsEmpty(relFileNode)) elog(ERROR, "Invalid RelFileNode (0,0,0)"); MemSet(&previousFreeTid, 0, sizeof(ItemPointerData)); MemSet(&mirrorBufpoolResyncCkptLoc, 0, sizeof(XLogRecPtr)); if (Persistent_BeforePersistenceWork()) { if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Skipping persistent relation '%s' because we are before persistence work", relpath(*relFileNode)); MemSet(persistentTid, 0, sizeof(ItemPointerData)); *serialNum = 0; return; // The initdb process will load the persistent table once we out of bootstrap mode. } PersistentRelfile_VerifyInitScan(); PersistentFileSysObjName_SetRelationFile( &fsObjName, relFileNode, segmentFileNum, is_tablespace_shared); WRITE_PERSISTENT_STATE_ORDERED_LOCK; GpPersistentRelfileNode_SetDatumValues( values, relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, segmentFileNum, relStorageMgr, (bufferPoolBulkLoad ? PersistentFileSysState_BulkLoadCreatePending : PersistentFileSysState_CreatePending), relBufpoolKind, GetTopTransactionId(), /* persistentSerialNum */ 0, // This will be set by PersistentFileSysObj_AddTuple. &previousFreeTid, is_tablespace_shared(relFileNode->spcNode)); PersistentFileSysObj_AddTuple( PersistentFsObjType_RelationFile, values, flushToXLog, persistentTid, serialNum); /* * This XLOG must be generated under the persistent write-lock. */ #ifdef MASTER_MIRROR_SYNC mmxlog_log_create_relfilenode( relFileNode->spcNode, relFileNode->dbNode, relFileNode->relNode, segmentFileNum, persistentTid, serialNum); #endif #ifdef FAULT_INJECTOR FaultInjector_InjectFaultIfSet( FaultBeforePendingDeleteRelationEntry, DDLNotSpecified, "", // databaseName ""); // tableName #endif /* * MPP-18228 * To make adding 'Create Pending' entry to persistent table and adding * to the PendingDelete list atomic */ PendingDelete_AddCreatePendingRelationEntry( &fsObjName, persistentTid, serialNum, relStorageMgr, relationName, isLocalBuf, bufferPoolBulkLoad); WRITE_PERSISTENT_STATE_ORDERED_UNLOCK; if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Persistent relation: Add '%s', relation name '%s' in state 'Create Pending', relation storage manager '%s', serial number " INT64_FORMAT " at TID %s", PersistentFileSysObjName_ObjectName(&fsObjName), relationName, PersistentFileSysRelStorageMgr_Name(relStorageMgr), *serialNum, ItemPointerToString(persistentTid)); }