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; }
/* * 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; }