void PersistentEndXactRec_Print( char *procName, PersistentEndXactRecObjects *objects) { int i; elog(Persistent_DebugPrintLevel(), "%s: file-system action count %d, Append-Only mirror resync EOFs count %d", procName, objects->typed.fileSysActionInfosCount, objects->typed.appendOnlyMirrorResyncEofsCount); for (i = 0; i < objects->typed.fileSysActionInfosCount; i++) { PersistentEndXactFileSysActionInfo *fileSysActionInfos = &objects->typed.fileSysActionInfos[i]; elog(Persistent_DebugPrintLevel(), "%s: [%d] action '%s' %s, relation storage manager '%s', persistent serial num " INT64_FORMAT ", TID %s", procName, i, PersistentEndXactFileSysAction_Name(fileSysActionInfos->action), PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos->fsObjName), PersistentFileSysRelStorageMgr_Name(fileSysActionInfos->relStorageMgr), fileSysActionInfos->persistentSerialNum, ItemPointerToString(&fileSysActionInfos->persistentTid)); } for (i = 0; i < objects->typed.appendOnlyMirrorResyncEofsCount; i++) { PersistentEndXactAppendOnlyMirrorResyncEofs *eofs = &objects->typed.appendOnlyMirrorResyncEofs[i]; elog(Persistent_DebugPrintLevel(), "%s: [%d] Append-Only Mirror Resync EOFs %u/%u/%u, segment file #%d -- persistent serial num " INT64_FORMAT ", TID %s, mirror loss EOF " INT64_FORMAT ", mirror new EOF " INT64_FORMAT, procName, i, eofs->relFileNode.spcNode, eofs->relFileNode.dbNode, eofs->relFileNode.relNode, eofs->segmentFileNum, eofs->persistentSerialNum, ItemPointerToString(&eofs->persistentTid), eofs->mirrorLossEof, eofs->mirrorNewEof); } }
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 void PersistentEndXactRec_VerifyFileSysActionInfos( EndXactRecKind endXactRecKind, PersistentEndXactFileSysActionInfo *fileSysActionInfos, int count) { int i; ItemPointerData maxTid; if (InRecovery || Persistent_BeforePersistenceWork()) return; for (i = 0; i < count; i++) { PersistentTidIsKnownResult persistentTidIsKnownResult; if (!PersistentEndXactFileSysAction_IsValid(fileSysActionInfos[i].action)) elog(ERROR, "Persistent file-system action is invalid (%d) (index %d, transaction kind '%s')", fileSysActionInfos[i].action, i, EndXactRecKind_Name(endXactRecKind)); if (!PersistentFsObjType_IsValid(fileSysActionInfos[i].fsObjName.type)) elog(ERROR, "Persistent file-system object type is invalid (%d) (index %d, transaction kind '%s')", fileSysActionInfos[i].fsObjName.type, i, EndXactRecKind_Name(endXactRecKind)); if (PersistentStore_IsZeroTid(&fileSysActionInfos[i].persistentTid)) elog(ERROR, "TID for persistent '%s' tuple is invalid (0,0) (index %d, transaction kind '%s')", PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos[i].fsObjName), i, EndXactRecKind_Name(endXactRecKind)); persistentTidIsKnownResult = PersistentFileSysObj_TidIsKnown( fileSysActionInfos[i].fsObjName.type, &fileSysActionInfos[i].persistentTid, &maxTid); switch (persistentTidIsKnownResult) { case PersistentTidIsKnownResult_BeforePersistenceWork: elog(ERROR, "Shouldn't being trying to verify persistent TID before persistence work"); break; case PersistentTidIsKnownResult_ScanNotPerformedYet: // UNDONE: For now, just debug log this. if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "Can't verify persistent TID if we haven't done the persistent scan yet"); break; case PersistentTidIsKnownResult_MaxTidIsZero: // UNDONE: For now, just debug log this. if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "TID for persistent '%s' tuple TID %s and the last known TID zero (0,0) (index %d, transaction kind '%s')", PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos[i].fsObjName), ItemPointerToString(&fileSysActionInfos[i].persistentTid), i, EndXactRecKind_Name(endXactRecKind)); break; case PersistentTidIsKnownResult_NotKnown: // UNDONE: For now, just debug log this. if (Debug_persistent_print) elog(Persistent_DebugPrintLevel(), "TID for persistent '%s' tuple TID %s is beyond the last known TID %s (index %d, transaction kind '%s')", PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos[i].fsObjName), ItemPointerToString(&fileSysActionInfos[i].persistentTid), ItemPointerToString2(&maxTid), i, EndXactRecKind_Name(endXactRecKind)); break; case PersistentTidIsKnownResult_Known: /* OK */ break; default: elog(ERROR, "Unexpected persistent file-system TID is known result: %d", persistentTidIsKnownResult); } if (fileSysActionInfos[i].persistentSerialNum == 0) elog(ERROR, "Persistent '%s' serial number is invalid (0) (index %d, transaction kind '%s')", PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos[i].fsObjName), i, EndXactRecKind_Name(endXactRecKind)); if (fileSysActionInfos[i].fsObjName.type == PersistentFsObjType_RelationFile && !PersistentFileSysRelStorageMgr_IsValid(fileSysActionInfos[i].relStorageMgr)) elog(ERROR, "Persistent '%s' relation storage manager has invalid value (%d) (index %d, transaction kind '%s')", PersistentFileSysObjName_TypeAndObjectName(&fileSysActionInfos[i].fsObjName), fileSysActionInfos[i].relStorageMgr, i, EndXactRecKind_Name(endXactRecKind)); } }
/* * 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 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; }
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)); }