static bool PersistentStore_GetFreeTuple(
	PersistentStoreData 		*storeData,

	PersistentStoreSharedData 	*storeSharedData,

	ItemPointer				freeTid)
{
	Datum			*values;
	HeapTuple		tupleCopy;

	int64					persistentSerialNum;
	ItemPointerData			previousFreeTid;

	MemSet(freeTid, 0, sizeof(ItemPointerData));

	if (Debug_persistent_store_print)
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_GetFreeTuple: Enter: maximum free order number " INT64_FORMAT ", free TID %s ('%s')",
			 storeSharedData->maxFreeOrderNum, 
			 ItemPointerToString(&storeSharedData->freeTid),
			 storeData->tableName);

	if (storeSharedData->maxFreeOrderNum == 0)
	{
		return false;	// No free tuples.
	}

	if (gp_persistent_skip_free_list)
	{
		if (Debug_persistent_store_print)
			elog(PersistentStore_DebugPrintLevel(), 
				 "PersistentStore_GetFreeTuple: Skipping because gp_persistent_skip_free_list GUC is ON ('%s')",
				 storeData->tableName);
		return false;	// Pretend no free tuples.
	}

	Assert(storeSharedData->freeTid.ip_posid != 0);

	/*
	 * Read the current last free tuple.
	 */
	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));
	
	PersistentStore_ReadTuple(
						storeData,
						storeSharedData,
						&storeSharedData->freeTid,
						values,
						&tupleCopy);

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

	if (PersistentStore_IsZeroTid(&previousFreeTid))
		elog(ERROR, "Expected persistent store tuple at %s to be free ('%s')", 
			 ItemPointerToString(&storeSharedData->freeTid),
			 storeData->tableName);

	if (storeSharedData->maxFreeOrderNum == 1)
		Assert(ItemPointerCompare(&previousFreeTid, &storeSharedData->freeTid) == 0);

	if (persistentSerialNum != storeSharedData->maxFreeOrderNum)
		elog(ERROR, "Expected persistent store tuple at %s to have order number " INT64_FORMAT " (found " INT64_FORMAT ", '%s')", 
			 ItemPointerToString(&storeSharedData->freeTid),
			 storeSharedData->maxFreeOrderNum,
			 persistentSerialNum,
			 storeData->tableName);

	*freeTid = storeSharedData->freeTid;
	storeSharedData->maxFreeOrderNum--;
	storeSharedData->freeTid = previousFreeTid;

	pfree(values);

	heap_freetuple(tupleCopy);

	if (Debug_persistent_store_print)
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_GetFreeTuple: Exit: maximum free order number " INT64_FORMAT ", free TID %s ('%s')",
			 storeSharedData->maxFreeOrderNum, 
			 ItemPointerToString(&storeSharedData->freeTid),
			 storeData->tableName);

	return true;
}
Пример #2
0
/*
 * Check if the free TID is valid. If not, the free list is corrupted and we
 * pretend there are no free tuples to reset the free list. The corrupted free
 * list will be detached and cleaned during recovery or pt rebuild.
 */
static bool PersistentStore_ValidateFreeTID(
	PersistentStoreData 		*storeData,
	PersistentStoreSharedData 	*storeSharedData,
	ItemPointer					previousFreeTid)
{
	Datum				*values;
	HeapTuple			tupleCopy;
	int64				persistentSerialNum;
	bool				tidIsValid = true;

	if (storeSharedData->maxFreeOrderNum <= 0)
		return true; /* No tuple to check */

	values = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));
	PersistentStore_ReadTuple(
					storeData,
					storeSharedData,
					&storeSharedData->freeTid,
					values,
					&tupleCopy);

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

	if (storeSharedData->maxFreeOrderNum == 1 && ItemPointerCompare(previousFreeTid, &storeSharedData->freeTid) != 0)
	{
		tidIsValid = false;
		ereport(WARNING,
				(errmsg("integrity check for PT freeTid failed"),
				 errdetail("expected to have previous FreeTID at %s equal to itself (found %s, %s)",
						ItemPointerToString(&storeSharedData->freeTid),
						ItemPointerToString2(previousFreeTid),
						storeData->tableName)));
	}

	if (PersistentStore_IsZeroTid(previousFreeTid))
	{
		tidIsValid = false;
		ereport(WARNING,
				(errmsg("integrity check for PT freeTid failed"),
				 errdetail("expected to have previous FreeTID at %s to be free (found %s, %s)",
						ItemPointerToString(&storeSharedData->freeTid),
						ItemPointerToString2(previousFreeTid),
						storeData->tableName)));
	}

	if (persistentSerialNum != storeSharedData->maxFreeOrderNum)
	{
		tidIsValid = false;
		ereport(WARNING,
				(errmsg("integrity check for PT freeTid failed"),
				 errdetail("expected persistent store tuple at %s to have order number " INT64_FORMAT " (found " INT64_FORMAT ", '%s')",
						ItemPointerToString(&storeSharedData->freeTid),
						storeSharedData->maxFreeOrderNum,
						persistentSerialNum,
						storeData->tableName)));
	}

	pfree(values);
	heap_freetuple(tupleCopy);

	/* If the free TID is not valid, switch to a new free list here */
	if (!tidIsValid)
	{
		ItemPointerSet(previousFreeTid, 0, 0);
		storeSharedData->maxFreeOrderNum = 0;
		MemSet(&storeSharedData->freeTid, 0, sizeof(ItemPointerData));
		ereport(WARNING,
				(errmsg("switched to new free TID list")));
	}

	return tidIsValid;
}