diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 8d06cbbffcb676d889afc12f75e9add35dccc283..39634531350042e457f981d2e4cf7905af67cc4e 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.10 2001/11/05 17:46:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.11 2002/01/24 15:31:43 tgl Exp $ * * * NOTES: @@ -841,64 +841,59 @@ static bool insert_fsm_page_entry(FSMRelation *fsmrel, BlockNumber page, Size spaceAvail, FSMChunk *chunk, int chunkRelIndex) { - FSMChunk *newChunk; - int newChunkRelIndex; - - if (fsmrel->numPages >= fsmrel->numChunks * CHUNKPAGES) + /* Outer loop handles retry after compacting rel's page list */ + for (;;) { - /* No free space within chunk list, so need another chunk */ - if ((newChunk = FreeSpaceMap->freeChunks) == NULL) - return false; /* can't do it */ - FreeSpaceMap->freeChunks = newChunk->next; - FreeSpaceMap->numFreeChunks--; - newChunk->next = NULL; - newChunk->numPages = 0; - if (fsmrel->relChunks == NULL) - fsmrel->relChunks = newChunk; - else + if (fsmrel->numPages >= fsmrel->numChunks * CHUNKPAGES) { - FSMChunk *priorChunk = fsmrel->relChunks; + /* No free space within chunk list, so need another chunk */ + FSMChunk *newChunk; + + if ((newChunk = FreeSpaceMap->freeChunks) == NULL) + return false; /* can't do it */ + FreeSpaceMap->freeChunks = newChunk->next; + FreeSpaceMap->numFreeChunks--; + newChunk->next = NULL; + newChunk->numPages = 0; + if (fsmrel->relChunks == NULL) + fsmrel->relChunks = newChunk; + else + { + FSMChunk *priorChunk = fsmrel->relChunks; - while (priorChunk->next != NULL) - priorChunk = priorChunk->next; - priorChunk->next = newChunk; + while (priorChunk->next != NULL) + priorChunk = priorChunk->next; + priorChunk->next = newChunk; + } + fsmrel->numChunks++; + if (chunk == NULL) + { + /* Original search found that new page belongs at end */ + chunk = newChunk; + chunkRelIndex = 0; + } } - fsmrel->numChunks++; - if (chunk == NULL) + + /* Try to insert it the easy way, ie, just move down subsequent data */ + if (chunk && + push_fsm_page_entry(page, spaceAvail, chunk, chunkRelIndex)) { - /* Original search found that new page belongs at end */ - chunk = newChunk; - chunkRelIndex = 0; + fsmrel->numPages++; + fsmrel->nextPage++; /* don't return same page twice running */ + return true; } - } - /* Try to insert it the easy way, ie, just move down subsequent data */ - if (chunk && - push_fsm_page_entry(page, spaceAvail, chunk, chunkRelIndex)) - { - fsmrel->numPages++; - fsmrel->nextPage++; /* don't return same page twice running */ - return true; - } - - /* - * There is space available, but evidently it's before the place where - * the page entry needs to go. Compact the list and try again. This - * will require us to redo the search for the appropriate place. - */ - compact_fsm_page_list(fsmrel); - if (lookup_fsm_page_entry(fsmrel, page, &newChunk, &newChunkRelIndex)) - elog(ERROR, "insert_fsm_page_entry: entry already exists!"); - if (newChunk && - push_fsm_page_entry(page, spaceAvail, newChunk, newChunkRelIndex)) - { - fsmrel->numPages++; - fsmrel->nextPage++; /* don't return same page twice running */ - return true; + /* + * There is space available, but evidently it's before the place where + * the page entry needs to go. Compact the list and try again. This + * will require us to redo the search for the appropriate place. + * Furthermore, compact_fsm_page_list deletes empty end chunks, so + * we may need to repeat the action of grabbing a new end chunk. + */ + compact_fsm_page_list(fsmrel); + if (lookup_fsm_page_entry(fsmrel, page, &chunk, &chunkRelIndex)) + elog(ERROR, "insert_fsm_page_entry: entry already exists!"); } - /* Shouldn't get here given the initial if-test for space available */ - elog(ERROR, "insert_fsm_page_entry: failed to insert entry!"); - return false; /* keep compiler quiet */ } /*