|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.200 2001/06/29 20:14:27 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.201 2001/07/02 20:50:46 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
|
37 | 37 | #include "commands/vacuum.h" |
38 | 38 | #include "miscadmin.h" |
39 | 39 | #include "nodes/execnodes.h" |
| 40 | +#include "storage/freespace.h" |
40 | 41 | #include "storage/sinval.h" |
41 | 42 | #include "storage/smgr.h" |
42 | 43 | #include "tcop/tcopprot.h" |
@@ -146,6 +147,8 @@ static void vacuum_index(VacPageList vacpagelist, Relation indrel, |
146 | 147 | double num_tuples, int keep_tuples); |
147 | 148 | static void scan_index(Relation indrel, double num_tuples); |
148 | 149 | static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist); |
| 150 | +static void vac_update_fsm(Relation onerel, VacPageList fraged_pages, |
| 151 | + BlockNumber rel_pages); |
149 | 152 | static VacPage copy_vac_page(VacPage vacpage); |
150 | 153 | static void vpage_insert(VacPageList vacpagelist, VacPage vpnew); |
151 | 154 | static void get_indices(Relation relation, int *nindices, Relation **Irel); |
@@ -579,6 +582,9 @@ vacuum_rel(Oid relid) |
579 | 582 | activate_indexes_of_a_table(relid, true); |
580 | 583 | #endif /* NOT_USED */ |
581 | 584 |
|
| 585 | + /* update shared free space map with final free space info */ |
| 586 | + vac_update_fsm(onerel, &fraged_pages, vacrelstats->rel_pages); |
| 587 | + |
582 | 588 | /* all done with this class, but hold lock until commit */ |
583 | 589 | heap_close(onerel, NoLock); |
584 | 590 |
|
@@ -1157,6 +1163,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, |
1157 | 1163 | * useful as move targets, since we only want to move down. Note |
1158 | 1164 | * that since we stop the outer loop at last_move_dest_block, pages |
1159 | 1165 | * removed here cannot have had anything moved onto them already. |
| 1166 | + * |
| 1167 | + * Also note that we don't change the stored fraged_pages list, |
| 1168 | + * only our local variable num_fraged_pages; so the forgotten pages |
| 1169 | + * are still available to be loaded into the free space map later. |
1160 | 1170 | */ |
1161 | 1171 | while (num_fraged_pages > 0 && |
1162 | 1172 | fraged_pages->pagedesc[num_fraged_pages-1]->blkno >= blkno) |
@@ -2080,6 +2090,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, |
2080 | 2090 | if (blkno < nblocks) |
2081 | 2091 | { |
2082 | 2092 | blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno); |
| 2093 | + onerel->rd_nblocks = blkno; /* update relcache immediately */ |
| 2094 | + onerel->rd_targblock = InvalidBlockNumber; |
2083 | 2095 | vacrelstats->rel_pages = blkno; /* set new number of blocks */ |
2084 | 2096 | } |
2085 | 2097 |
|
@@ -2145,6 +2157,8 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages) |
2145 | 2157 | RelationGetRelationName(onerel), |
2146 | 2158 | vacrelstats->rel_pages, relblocks); |
2147 | 2159 | relblocks = smgrtruncate(DEFAULT_SMGR, onerel, relblocks); |
| 2160 | + onerel->rd_nblocks = relblocks; /* update relcache immediately */ |
| 2161 | + onerel->rd_targblock = InvalidBlockNumber; |
2148 | 2162 | vacrelstats->rel_pages = relblocks; /* set new number of |
2149 | 2163 | * blocks */ |
2150 | 2164 | } |
@@ -2414,6 +2428,45 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples, |
2414 | 2428 | heap_close(rd, RowExclusiveLock); |
2415 | 2429 | } |
2416 | 2430 |
|
| 2431 | +/* |
| 2432 | + * Update the shared Free Space Map with the info we now have about |
| 2433 | + * free space in the relation, discarding any old info the map may have. |
| 2434 | + */ |
| 2435 | +static void |
| 2436 | +vac_update_fsm(Relation onerel, VacPageList fraged_pages, |
| 2437 | + BlockNumber rel_pages) |
| 2438 | +{ |
| 2439 | + int nPages = fraged_pages->num_pages; |
| 2440 | + int i; |
| 2441 | + BlockNumber *pages; |
| 2442 | + Size *spaceAvail; |
| 2443 | + |
| 2444 | + /* +1 to avoid palloc(0) */ |
| 2445 | + pages = (BlockNumber *) palloc((nPages + 1) * sizeof(BlockNumber)); |
| 2446 | + spaceAvail = (Size *) palloc((nPages + 1) * sizeof(Size)); |
| 2447 | + |
| 2448 | + for (i = 0; i < nPages; i++) |
| 2449 | + { |
| 2450 | + pages[i] = fraged_pages->pagedesc[i]->blkno; |
| 2451 | + spaceAvail[i] = fraged_pages->pagedesc[i]->free; |
| 2452 | + /* |
| 2453 | + * fraged_pages may contain entries for pages that we later decided |
| 2454 | + * to truncate from the relation; don't enter them into the map! |
| 2455 | + */ |
| 2456 | + if (pages[i] >= rel_pages) |
| 2457 | + { |
| 2458 | + nPages = i; |
| 2459 | + break; |
| 2460 | + } |
| 2461 | + } |
| 2462 | + |
| 2463 | + MultiRecordFreeSpace(&onerel->rd_node, |
| 2464 | + 0, MaxBlockNumber, |
| 2465 | + nPages, pages, spaceAvail); |
| 2466 | + pfree(pages); |
| 2467 | + pfree(spaceAvail); |
| 2468 | +} |
| 2469 | + |
2417 | 2470 | /* Copy a VacPage structure */ |
2418 | 2471 | static VacPage |
2419 | 2472 | copy_vac_page(VacPage vacpage) |
|
0 commit comments