|
8 | 8 | * Portions Copyright (c) 1994, Regents of the University of California |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.10 2001/11/05 17:46:27 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.11 2002/01/24 15:31:43 tgl Exp $ |
12 | 12 | * |
13 | 13 | * |
14 | 14 | * NOTES: |
@@ -841,64 +841,59 @@ static bool |
841 | 841 | insert_fsm_page_entry(FSMRelation *fsmrel, BlockNumber page, Size spaceAvail, |
842 | 842 | FSMChunk *chunk, int chunkRelIndex) |
843 | 843 | { |
844 | | - FSMChunk *newChunk; |
845 | | - int newChunkRelIndex; |
846 | | - |
847 | | - if (fsmrel->numPages >= fsmrel->numChunks * CHUNKPAGES) |
| 844 | + /* Outer loop handles retry after compacting rel's page list */ |
| 845 | + for (;;) |
848 | 846 | { |
849 | | - /* No free space within chunk list, so need another chunk */ |
850 | | - if ((newChunk = FreeSpaceMap->freeChunks) == NULL) |
851 | | - return false; /* can't do it */ |
852 | | - FreeSpaceMap->freeChunks = newChunk->next; |
853 | | - FreeSpaceMap->numFreeChunks--; |
854 | | - newChunk->next = NULL; |
855 | | - newChunk->numPages = 0; |
856 | | - if (fsmrel->relChunks == NULL) |
857 | | - fsmrel->relChunks = newChunk; |
858 | | - else |
| 847 | + if (fsmrel->numPages >= fsmrel->numChunks * CHUNKPAGES) |
859 | 848 | { |
860 | | - FSMChunk *priorChunk = fsmrel->relChunks; |
| 849 | + /* No free space within chunk list, so need another chunk */ |
| 850 | + FSMChunk *newChunk; |
| 851 | + |
| 852 | + if ((newChunk = FreeSpaceMap->freeChunks) == NULL) |
| 853 | + return false; /* can't do it */ |
| 854 | + FreeSpaceMap->freeChunks = newChunk->next; |
| 855 | + FreeSpaceMap->numFreeChunks--; |
| 856 | + newChunk->next = NULL; |
| 857 | + newChunk->numPages = 0; |
| 858 | + if (fsmrel->relChunks == NULL) |
| 859 | + fsmrel->relChunks = newChunk; |
| 860 | + else |
| 861 | + { |
| 862 | + FSMChunk *priorChunk = fsmrel->relChunks; |
861 | 863 |
|
862 | | - while (priorChunk->next != NULL) |
863 | | - priorChunk = priorChunk->next; |
864 | | - priorChunk->next = newChunk; |
| 864 | + while (priorChunk->next != NULL) |
| 865 | + priorChunk = priorChunk->next; |
| 866 | + priorChunk->next = newChunk; |
| 867 | + } |
| 868 | + fsmrel->numChunks++; |
| 869 | + if (chunk == NULL) |
| 870 | + { |
| 871 | + /* Original search found that new page belongs at end */ |
| 872 | + chunk = newChunk; |
| 873 | + chunkRelIndex = 0; |
| 874 | + } |
865 | 875 | } |
866 | | - fsmrel->numChunks++; |
867 | | - if (chunk == NULL) |
| 876 | + |
| 877 | + /* Try to insert it the easy way, ie, just move down subsequent data */ |
| 878 | + if (chunk && |
| 879 | + push_fsm_page_entry(page, spaceAvail, chunk, chunkRelIndex)) |
868 | 880 | { |
869 | | - /* Original search found that new page belongs at end */ |
870 | | - chunk = newChunk; |
871 | | - chunkRelIndex = 0; |
| 881 | + fsmrel->numPages++; |
| 882 | + fsmrel->nextPage++; /* don't return same page twice running */ |
| 883 | + return true; |
872 | 884 | } |
873 | | - } |
874 | 885 |
|
875 | | - /* Try to insert it the easy way, ie, just move down subsequent data */ |
876 | | - if (chunk && |
877 | | - push_fsm_page_entry(page, spaceAvail, chunk, chunkRelIndex)) |
878 | | - { |
879 | | - fsmrel->numPages++; |
880 | | - fsmrel->nextPage++; /* don't return same page twice running */ |
881 | | - return true; |
882 | | - } |
883 | | - |
884 | | - /* |
885 | | - * There is space available, but evidently it's before the place where |
886 | | - * the page entry needs to go. Compact the list and try again. This |
887 | | - * will require us to redo the search for the appropriate place. |
888 | | - */ |
889 | | - compact_fsm_page_list(fsmrel); |
890 | | - if (lookup_fsm_page_entry(fsmrel, page, &newChunk, &newChunkRelIndex)) |
891 | | - elog(ERROR, "insert_fsm_page_entry: entry already exists!"); |
892 | | - if (newChunk && |
893 | | - push_fsm_page_entry(page, spaceAvail, newChunk, newChunkRelIndex)) |
894 | | - { |
895 | | - fsmrel->numPages++; |
896 | | - fsmrel->nextPage++; /* don't return same page twice running */ |
897 | | - return true; |
| 886 | + /* |
| 887 | + * There is space available, but evidently it's before the place where |
| 888 | + * the page entry needs to go. Compact the list and try again. This |
| 889 | + * will require us to redo the search for the appropriate place. |
| 890 | + * Furthermore, compact_fsm_page_list deletes empty end chunks, so |
| 891 | + * we may need to repeat the action of grabbing a new end chunk. |
| 892 | + */ |
| 893 | + compact_fsm_page_list(fsmrel); |
| 894 | + if (lookup_fsm_page_entry(fsmrel, page, &chunk, &chunkRelIndex)) |
| 895 | + elog(ERROR, "insert_fsm_page_entry: entry already exists!"); |
898 | 896 | } |
899 | | - /* Shouldn't get here given the initial if-test for space available */ |
900 | | - elog(ERROR, "insert_fsm_page_entry: failed to insert entry!"); |
901 | | - return false; /* keep compiler quiet */ |
902 | 897 | } |
903 | 898 |
|
904 | 899 | /* |
|
0 commit comments