void PersistentStore_Scan(
	PersistentStoreData 		*storeData,

	PersistentStoreSharedData 	*storeSharedData,

	PersistentStoreScanTupleCallback	scanTupleCallback)
{
	WRITE_PERSISTENT_STATE_ORDERED_LOCK_DECLARE;

	PersistentStoreScan storeScan;

	ItemPointerData			persistentTid;
	int64					persistentSerialNum = 0;

	Datum					*values;

	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));

	WRITE_PERSISTENT_STATE_ORDERED_LOCK;

	PersistentStore_BeginScan(
						storeData,
						storeSharedData,
						&storeScan);

	while (PersistentStore_GetNext(
							&storeScan,
							values,
							&persistentTid,
							&persistentSerialNum))
	{
		bool okToContinue;

		okToContinue = (*scanTupleCallback)(
								&persistentTid,
								persistentSerialNum,
								values);

		if (!okToContinue)
			break;

	}
	
	PersistentStore_EndScan(&storeScan);

	WRITE_PERSISTENT_STATE_ORDERED_UNLOCK;

	pfree(values);
}
static void PersistentStore_DoInitScan(
	PersistentStoreData 		*storeData,

	PersistentStoreSharedData 	*storeSharedData)
{
	PersistentStoreScan storeScan;

	ItemPointerData			persistentTid;
	int64					persistentSerialNum;

	ItemPointerData			previousFreeTid;

	Datum					*values;

	int64			globalSequenceNum;

	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));

	MemSet(&storeSharedData->maxTid, 0, sizeof(ItemPointerData));

	PersistentStore_BeginScan(
						storeData,
						storeSharedData,
						&storeScan);

	while (PersistentStore_GetNext(
							&storeScan,
							values,
							&persistentTid,
							&persistentSerialNum))
	{
		/*
		 * We are scanning from low to high TID.
		 */
		Assert(
			PersistentStore_IsZeroTid(&storeSharedData->maxTid)
			||
			ItemPointerCompare(
							&storeSharedData->maxTid,
							&persistentTid) == -1);	// Less-Than.
							
		storeSharedData->maxTid = persistentTid;

		PersistentStore_ExtractOurTupleData(
									storeData,
									values,
									&persistentSerialNum,
									&previousFreeTid);
		
		if (Debug_persistent_recovery_print)
			(*storeData->printTupleCallback)(
										PersistentRecovery_DebugPrintLevel(),
										"SCAN",
										&persistentTid,
										values);
		
		if (!PersistentStore_IsZeroTid(&previousFreeTid))
		{
			/*
			 * Non-zero previousFreeTid implies a free entry.
			 */
			if (storeSharedData->maxFreeOrderNum < persistentSerialNum)
			{
				storeSharedData->maxFreeOrderNum = persistentSerialNum;
				storeSharedData->freeTid = persistentTid;
			}

			if (!gp_persistent_skip_free_list)
			{
				PersistentStore_InitScanAddFreeEntry(
												&persistentTid,
												&previousFreeTid,
												/* freeOrderNum */ persistentSerialNum);
			}
		}
		else 
		{
			storeSharedData->inUseCount++;

			if (storeSharedData->maxInUseSerialNum < persistentSerialNum)
			{
				storeSharedData->maxInUseSerialNum = persistentSerialNum;
				storeData->myHighestSerialNum = storeSharedData->maxInUseSerialNum;
			}
		}

		if (storeData->scanTupleCallback != NULL)
			(*storeData->scanTupleCallback)(
										&persistentTid,
										persistentSerialNum,
										values);

	}

	PersistentStore_EndScan(&storeScan);

	pfree(values);

	globalSequenceNum = GlobalSequence_Current(storeData->gpGlobalSequence);

	/*
	 * Note: Originally the below IF STMT was guarded with a InRecovery flag check.
	 * However, this routine should not be called during recovery since the entries are
	 * not consistent...
	 */
	Assert(!InRecovery);
	
	if (globalSequenceNum < storeSharedData->maxInUseSerialNum)
	{
		/*
		 * We seem to have a corruption problem.
		 *
		 * Use the gp_persistent_repair_global_sequence GUC to get the system up.
		 */

		if (gp_persistent_repair_global_sequence)
		{
			elog(LOG, "Need to Repair global sequence number " INT64_FORMAT " so use scanned maximum value " INT64_FORMAT " ('%s')",
				 globalSequenceNum,
				 storeSharedData->maxInUseSerialNum,
				 storeData->tableName);
		}
		else
		{
			elog(ERROR, "Global sequence number " INT64_FORMAT " less than maximum value " INT64_FORMAT " found in scan ('%s')",
				 globalSequenceNum,
				 storeSharedData->maxInUseSerialNum,
				 storeData->tableName);
		}
		
	}
	else
	{
		storeSharedData->maxCachedSerialNum = globalSequenceNum;
	}
	
	if (Debug_persistent_recovery_print)
		elog(PersistentRecovery_DebugPrintLevel(), 
			 "PersistentStore_DoInitScan ('%s'): maximum in-use serial number " INT64_FORMAT ", maximum free order number " INT64_FORMAT ", free TID %s, maximum known TID %s",
			 storeData->tableName,
			 storeSharedData->maxInUseSerialNum, 
			 storeSharedData->maxFreeOrderNum, 
			 ItemPointerToString(&storeSharedData->freeTid),
			 ItemPointerToString2(&storeSharedData->maxTid));

	if (!gp_persistent_skip_free_list)
	{
		PersistentStore_InitScanVerifyFreeEntries(
											storeData,
											storeSharedData);
	}
	else
	{
		if (Debug_persistent_recovery_print)
			elog(PersistentRecovery_DebugPrintLevel(), 
				 "PersistentStore_DoInitScan ('%s'): Skipping verification because gp_persistent_skip_free_list GUC is ON",
				 storeData->tableName);
	}
}
Esempio n. 3
0
static void PersistentStore_DoInitScan(
	PersistentStoreData 		*storeData,
	PersistentStoreSharedData 	*storeSharedData)
{
	PersistentStoreScan 	storeScan;
	ItemPointerData			persistentTid;
	int64					persistentSerialNum;
	Datum					*values;
	int64					globalSequenceNum;

	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));

	PersistentStore_BeginScan(
						storeData,
						storeSharedData,
						&storeScan);

	while (PersistentStore_GetNext(
							&storeScan,
							values,
							&persistentTid,
							&persistentSerialNum))
	{
		/*
		 * We are scanning from low to high TID.
		 */
		PersistentStore_ExtractOurTupleData(
									storeData,
									values,
									&persistentSerialNum);

		if (Debug_persistent_recovery_print)
			(*storeData->printTupleCallback)(
										PersistentRecovery_DebugPrintLevel(),
										"SCAN",
										&persistentTid,
										values);

		storeSharedData->inUseCount++;

		if (storeSharedData->maxInUseSerialNum < persistentSerialNum)
		{
			storeSharedData->maxInUseSerialNum = persistentSerialNum;
			storeData->myHighestSerialNum = storeSharedData->maxInUseSerialNum;
		}

		if (storeData->scanTupleCallback != NULL)
			(*storeData->scanTupleCallback)(
										&persistentTid,
										persistentSerialNum,
										values);

	}

	PersistentStore_EndScan(&storeScan);

	pfree(values);

	globalSequenceNum = GlobalSequence_Current(storeData->gpGlobalSequence);

	/*
	 * Note: Originally the below IF STMT was guarded with a InRecovery flag check.
	 * However, this routine should not be called during recovery since the entries are
	 * not consistent...
	 */
	Assert(!InRecovery);

	if (globalSequenceNum < storeSharedData->maxInUseSerialNum)
	{
		/*
		 * We seem to have a corruption problem.
		 *
		 * Use the gp_persistent_repair_global_sequence GUC to get the
		 * system up.
		 */

		if (gp_persistent_repair_global_sequence)
		{
			elog(LOG, "need to repair global sequence number " INT64_FORMAT
				 " so use scanned maximum value " INT64_FORMAT " ('%s')",
				 globalSequenceNum,
				 storeSharedData->maxInUseSerialNum,
				 storeData->tableName);
		}
		else
		{
			elog(ERROR, "global sequence number " INT64_FORMAT " less than "
				 "maximum value " INT64_FORMAT " found in scan ('%s')",
				 globalSequenceNum,
				 storeSharedData->maxInUseSerialNum,
				 storeData->tableName);
		}
	}
	else
	{
		storeSharedData->maxInUseSerialNum = globalSequenceNum;
	}

	if (Debug_persistent_recovery_print)
		elog(PersistentRecovery_DebugPrintLevel(),
			 "PersistentStore_DoInitScan ('%s'): maximum in-use serial number "
			 INT64_FORMAT ,
			 storeData->tableName,
			 storeSharedData->maxInUseSerialNum);
}
Esempio n. 4
0
/*
 * Rebuild free TID list based on freeEntryHashTable.  Returns number
 * of free tuples in the rebuilt free list.
 */
uint64
PersistentStore_RebuildFreeList(
	PersistentStoreData 		*storeData,
	PersistentStoreSharedData 	*storeSharedData)
{
	Datum				*values;
	PersistentStoreScan storeScan;
	ItemPointerData		persistentTid;
	ItemPointerData		previousFreeTid;
	ItemPointerData		previousTid;
	uint64				persistentSerialNum;
	uint64				freeOrderNum;


	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));

	/*
	 * PT shared data must be already initialized, even when we are
	 * called during recovery.
	 */
	Assert(!PersistentStore_IsZeroTid(&storeSharedData->maxTid));

	if (storeSharedData->maxFreeOrderNum < 1)
	{
		elog(LOG, "no free tuples in %s, not building any free list",
			 storeData->tableName);
		return 0;
	}
	elog(LOG, "rebuilding free list in %s with " INT64_FORMAT " free tuples",
		 storeData->tableName, storeSharedData->maxFreeOrderNum);

	/*
	 * Scan PT for free entries (in TID order) and establish links
	 * with previous free entry as we go on.
	 */
	previousTid.ip_posid = 0;
	freeOrderNum = 0;
	PersistentStore_BeginScan(storeData, storeSharedData, &storeScan);
	while (PersistentStore_GetNext(
				   &storeScan,
				   values,
				   &persistentTid,
				   (int64 *)&persistentSerialNum))
	{
		/*
		 * We are scanning from low to high TID.  All TIDs we
		 * encounter should be smaller or equal to the known
		 * maxTid.
		 */
		Assert(ItemPointerCompare(
					   &storeSharedData->maxTid,
					   &persistentTid) >= 0);

		PersistentStore_ExtractOurTupleData(
				storeData,
				values,
				(int64 *)&persistentSerialNum,
				&previousFreeTid);

		if (!PersistentStore_IsZeroTid(&previousFreeTid))
		{
			values[storeData->attNumPersistentSerialNum - 1] =
					Int64GetDatum(++freeOrderNum);
			values[storeData->attNumPreviousFreeTid - 1] =
					ItemPointerIsValid(&previousTid) ?
					PointerGetDatum(&previousTid) :
					PointerGetDatum(&persistentTid);
#ifdef FAULT_INJECTOR
			/*
			 * Inject fault after free list is partially built - a few
			 * tuples are updated but at least one is yet to be
			 * updated.
			 */
			if (freeOrderNum > 3)
			{
				FaultInjector_InjectFaultIfSet(
						RebuildPTDB,
						DDLNotSpecified,
						"",	// databaseName
						""); // tableName
			}
#endif
			PersistentStore_UpdateTuple(
					storeData, storeSharedData,	&persistentTid, values, true);
			ItemPointerCopy(&persistentTid, &previousTid);
		}
	}
	PersistentStore_EndScan(&storeScan);
	pfree(values);
	if (ItemPointerIsValid(&previousTid))
	{
		Assert(freeOrderNum > 0);
		ItemPointerCopy(&previousTid, &storeSharedData->freeTid);
		storeSharedData->maxFreeOrderNum = freeOrderNum;
		elog(LOG, "rebuilt free list in %s:  maxFreeOrderNum = " INT64_FORMAT
			 " freeTid = %s", storeData->tableName, freeOrderNum,
			 ItemPointerToString(&persistentTid));
	}
	return freeOrderNum;
}
Esempio n. 5
0
static void PersistentStore_DiagnoseDumpTable(
	PersistentStoreData 		*storeData,
	PersistentStoreSharedData 	*storeSharedData)
{

	if (disable_persistent_diagnostic_dump)
	{
		return;
	}

	MIRROREDLOCK_BUFMGR_DECLARE;

	PersistentStoreScan storeScan;
	ItemPointerData			persistentTid;
	int64					persistentSerialNum;
	Datum					*values;
	BlockNumber				lastDisplayedBlockNum;
	bool					displayedOne;
	BlockNumber				currentBlockNum;

	elog(LOG, 
		 "Diagnostic dump of persistent table ('%s'): maximum in-use serial number " INT64_FORMAT ", maximum free order number " INT64_FORMAT ", free TID %s, maximum known TID %s",
		 storeData->tableName,
		 storeSharedData->maxInUseSerialNum, 
		 storeSharedData->maxFreeOrderNum, 
		 ItemPointerToString(&storeSharedData->freeTid),
		 ItemPointerToString2(&storeSharedData->maxTid));

	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));

	PersistentStore_BeginScan(
						storeData,
						storeSharedData,
						&storeScan);

	lastDisplayedBlockNum = 0;
	displayedOne = false;
	while (PersistentStore_GetNext(
							&storeScan,
							values,
							&persistentTid,
							&persistentSerialNum))
	{
		/*
		 * Use the BlockIdGetBlockNumber routine because ItemPointerGetBlockNumber 
		 * asserts for valid TID.
		 */
		currentBlockNum = BlockIdGetBlockNumber(&persistentTid.ip_blkid);
		if (!displayedOne || currentBlockNum != lastDisplayedBlockNum)
		{
			Buffer		buffer;
			PageHeader	page;
			XLogRecPtr	lsn;

			/*
			 * Fetch the block and display the LSN.
			 */
			
			// -------- MirroredLock ----------
			MIRROREDLOCK_BUFMGR_LOCK;
			
			buffer = ReadBuffer(
							storeScan.persistentRel,
							currentBlockNum);

			page = (PageHeader) BufferGetPage(buffer);
			lsn = PageGetLSN(page);
			ReleaseBuffer(buffer);

			MIRROREDLOCK_BUFMGR_UNLOCK;
			// -------- MirroredLock ----------

			elog(LOG, "Diagnostic LSN %s of page %u",
				 XLogLocationToString(&lsn),
				 currentBlockNum);

			lastDisplayedBlockNum = currentBlockNum;
			displayedOne = true;
		}

		/*
		 * Display the persistent tuple.
		 */
		(*storeData->printTupleCallback)(
									LOG,
									"DIAGNOSE",
									&persistentTid,
									values);
	}
	
	PersistentStore_EndScan(&storeScan);

	pfree(values);
}
static void PersistentBuild_ScanGpPersistentRelationNodeForGlobal(
	Relation 	gp_relation_node,

	int64		*count)
{
	PersistentFileSysObjData *fileSysObjData;
	PersistentFileSysObjSharedData	*fileSysObjSharedData;

	PersistentStoreScan storeScan;
	 
	Datum values[Natts_gp_persistent_relfile_node];
	 
	ItemPointerData persistentTid;
	int64 persistentSerialNum;

	PersistentFileSysObj_GetDataPtrs(
								PersistentFsObjType_RelationFile,
								&fileSysObjData,
								&fileSysObjSharedData);
		 
	PersistentStore_BeginScan(
						&fileSysObjData->storeData,
						&fileSysObjSharedData->storeSharedData,
						&storeScan);

	while (PersistentStore_GetNext(
							&storeScan,
							values,
							&persistentTid,
							&persistentSerialNum))
	{
		RelFileNode 					relFileNode;
		int32 							segmentFileNum;
		PersistentFileSysRelStorageMgr	relationStorageManager;
		PersistentFileSysState			persistentState;
		PersistentFileSysRelBufpoolKind relBufpoolKind;
		TransactionId					parentXid;
		int64							serialNum;
		ItemPointerData					previousFreeTid;
		
		PersistentFileSysObjName		fsObjName;
		bool							sharedStorage;

		GpPersistentRelfileNode_GetValues(
										values,
										&relFileNode.spcNode,
										&relFileNode.dbNode,
										&relFileNode.relNode,
										&segmentFileNum,
										&relationStorageManager,
										&persistentState,
										&relBufpoolKind,
										&parentXid,
										&serialNum,
										&previousFreeTid,
										&sharedStorage);

		if (persistentState == PersistentFileSysState_Free)
			continue;

		PersistentFileSysObjName_SetRelationFile(
											&fsObjName,
											&relFileNode,
											segmentFileNum,
											NULL);
		fsObjName.hasInited = true;
		fsObjName.sharedStorage = sharedStorage;

		if (relFileNode.spcNode != GLOBALTABLESPACE_OID)
			continue;

		if (relationStorageManager != PersistentFileSysRelStorageMgr_BufferPool)
			elog(ERROR, "Only expecting global tables to be Buffer Pool managed");

		InsertGpRelfileNodeTuple(
						gp_relation_node,
						relFileNode.relNode, 	// pg_class OID
						/* relationName */ NULL,	// Optional.
						relFileNode.relNode,	// pg_class relfilenode
						/* segmentFileNum */ 0,
						/* updateIndex */ false,
						&persistentTid,
						persistentSerialNum);

		(*count)++;
	}

	PersistentStore_EndScan(&storeScan);
}