*** freespace.c Sun Apr 24 12:51:49 2005 --- freespace.new.c Fri May 20 13:13:37 2005 *************** *** 70,75 **** --- 70,78 ---- #include "storage/lwlock.h" #include "storage/shmem.h" + #include "utils/relcache.h" + #include "utils/lsyscache.h" + /* Initial value for average-request moving average */ #define INITIAL_AVERAGE ((Size) (BLCKSZ / 32)) *************** typedef BlockIdData IndexFSMPageData; *** 123,128 **** --- 126,132 ---- * relfilenode * isIndex * avgRequest + * minRequest * lastPageCount * storedPages * arena data array of storedPages FSMPageData or IndexFSMPageData *************** typedef struct FsmCacheRelHeader *** 152,157 **** --- 156,162 ---- RelFileNode key; /* hash key (must be first) */ bool isIndex; /* if true, we store only page numbers */ uint32 avgRequest; /* moving average of space requests */ + uint32 minRequest; /* minimum of space requests */ int32 lastPageCount; /* pages passed to RecordRelationFreeSpace */ int32 storedPages; /* # of pages stored in arena */ } FsmCacheRelHeader; *************** struct FSMRelation *** 206,211 **** --- 211,217 ---- FSMRelation *priorPhysical; /* prior rel in arena-storage order */ bool isIndex; /* if true, we store only page numbers */ Size avgRequest; /* moving average of space requests */ + Size minRequest; /* minimum of space requests */ int lastPageCount; /* pages passed to RecordRelationFreeSpace */ int firstChunk; /* chunk # of my first chunk in arena */ int storedPages; /* # of pages stored in arena */ *************** GetPageWithFreeSpace(RelFileNode *rel, S *** 385,390 **** --- 391,398 ---- cur_avg += ((int) spaceNeeded - cur_avg) / 32; fsmrel->avgRequest = (Size) cur_avg; + if(fsmrel->minRequest > spaceNeeded) + fsmrel->minRequest = spaceNeeded; } freepage = find_free_space(fsmrel, spaceNeeded); LWLockRelease(FreeSpaceLock); *************** RecordAndGetPageWithFreeSpace(RelFileNod *** 429,434 **** --- 437,444 ---- cur_avg += ((int) spaceNeeded - cur_avg) / 32; fsmrel->avgRequest = (Size) cur_avg; + if(fsmrel->minRequest > spaceNeeded) + fsmrel->minRequest = spaceNeeded; } /* Do the Get */ freepage = find_free_space(fsmrel, spaceNeeded); *************** DumpFreeSpaceMap(int code, Datum arg) *** 793,798 **** --- 803,809 ---- relheader.key = fsmrel->key; relheader.isIndex = fsmrel->isIndex; relheader.avgRequest = fsmrel->avgRequest; + relheader.minRequest = fsmrel->minRequest; relheader.lastPageCount = fsmrel->lastPageCount; relheader.storedPages = fsmrel->storedPages; if (fwrite(&relheader, 1, sizeof(relheader), fp) != sizeof(relheader)) *************** LoadFreeSpaceMap(void) *** 902,907 **** --- 913,919 ---- if (fread(&relheader, 1, sizeof(relheader), fp) != sizeof(relheader) || (relheader.isIndex != false && relheader.isIndex != true) || relheader.avgRequest >= BLCKSZ || + relheader.minRequest >= BLCKSZ || relheader.lastPageCount < 0 || relheader.storedPages < 0) { *************** LoadFreeSpaceMap(void) *** 936,941 **** --- 948,954 ---- */ fsmrel = create_fsm_rel(&relheader.key); fsmrel->avgRequest = relheader.avgRequest; + fsmrel->minRequest = relheader.minRequest; curAlloc = realloc_fsm_rel(fsmrel, relheader.lastPageCount, relheader.isIndex); *************** create_fsm_rel(RelFileNode *rel) *** 1046,1051 **** --- 1059,1065 ---- /* New hashtable entry, initialize it (hash_search set the key) */ fsmrel->isIndex = false; /* until we learn different */ fsmrel->avgRequest = INITIAL_AVERAGE; + fsmrel->minRequest = BLCKSZ-1; fsmrel->lastPageCount = 0; fsmrel->firstChunk = -1; /* no space allocated */ fsmrel->storedPages = 0; *************** find_free_space(FSMRelation *fsmrel, Siz *** 1268,1273 **** --- 1282,1315 ---- pageIndex = 0; } + if(spaceNeeded >= fsmrel->minRequest && fsmrel->storedPages > 0) + { + /* Free space becomes empty. */ + + /* Notify. */ + Relation r; + r = RelationIdGetRelation(fsmrel->key.relNode); + if(r) + { + elog(LOG, "FreeSpace for \"%s.%s\" becomes empty. (stored=%d, avg=%d, min=%d)", + get_namespace_name(RelationGetNamespace(r)), + RelationGetRelationName(r), + fsmrel->storedPages, fsmrel->avgRequest, fsmrel->minRequest); + RelationClose(r); + } + else + { + elog(LOG, "FreeSpace for %u/%u/%u becomes empty. (stored=%d, avg=%d, min=%d)", + fsmrel->key.spcNode, fsmrel->key.dbNode, fsmrel->key.relNode, + fsmrel->storedPages, fsmrel->avgRequest, fsmrel->minRequest); + } + + /* Detach empty fsm relation. */ + fsmrel->storedPages = 0; + /* XXX: or delete_fsm_rel(fsmrel) */ + /* XXX: or kick autovacuum */ + } + return InvalidBlockNumber; /* nothing found */ } *************** DumpFreeSpace(void) *** 1876,1885 **** for (fsmrel = FreeSpaceMap->usageList; fsmrel; fsmrel = fsmrel->nextUsage) { relNum++; ! fprintf(stderr, "Map %d: rel %u/%u/%u isIndex %d avgRequest %u lastPageCount %d nextPage %d\nMap= ", relNum, fsmrel->key.spcNode, fsmrel->key.dbNode, fsmrel->key.relNode, ! (int) fsmrel->isIndex, fsmrel->avgRequest, fsmrel->lastPageCount, fsmrel->nextPage); if (fsmrel->isIndex) { --- 1918,1927 ---- for (fsmrel = FreeSpaceMap->usageList; fsmrel; fsmrel = fsmrel->nextUsage) { relNum++; ! fprintf(stderr, "Map %d: rel %u/%u/%u isIndex %d avgRequest %d minRequest %d lastPageCount %d nextPage %d\nMap= ", relNum, fsmrel->key.spcNode, fsmrel->key.dbNode, fsmrel->key.relNode, ! (int) fsmrel->isIndex, fsmrel->avgRequest, fsmrel->minRequest, fsmrel->lastPageCount, fsmrel->nextPage); if (fsmrel->isIndex) {