diff -crN ../src.orig/backend/commands/vacuum.c ./backend/commands/vacuum.c *** ../src.orig/backend/commands/vacuum.c Thu Oct 30 10:17:36 2003 --- ./backend/commands/vacuum.c Thu Oct 30 10:27:57 2003 *************** *** 98,103 **** --- 98,107 ---- } VRelStats; + bool vacuum_buffer_hack = true; + bool vacuum_buffer_hack_active = false; + + static MemoryContext vac_context = NULL; static int elevel = -1; *************** *** 279,284 **** --- 283,295 ---- } /* + * Change the buffer cache policy to avoid vacuum causing a + * full cache eviction. + */ + if (vacuum_buffer_hack) + vacuum_buffer_hack_active = true; + + /* * Loop to process each selected relation. */ foreach(cur, vrl) *************** *** 320,325 **** --- 331,341 ---- } } } + + /* + * Change back to normal buffer cache policy. + */ + vacuum_buffer_hack_active = false; /* * Finish up processing. diff -crN ../src.orig/backend/storage/buffer/bufmgr.c ./backend/storage/buffer/bufmgr.c *** ../src.orig/backend/storage/buffer/bufmgr.c Thu Oct 30 10:17:38 2003 --- ./backend/storage/buffer/bufmgr.c Thu Oct 30 10:44:10 2003 *************** *** 64,69 **** --- 64,72 ---- bool zero_damaged_pages = false; + extern bool vacuum_buffer_hack_active; + + static void WaitIO(BufferDesc *buf); static void StartBufferIO(BufferDesc *buf, bool forInput); static void TerminateBufferIO(BufferDesc *buf); *************** *** 205,210 **** --- 208,222 ---- StartBufferIO(bufHdr, false); LWLockRelease(BufMgrLock); } + } + else + { + /* The block was not found in the buffer cache. If we are in + * vacuum buffer cache strategy mode, mark that this buffers + * content was caused by vacuum. + */ + if (vacuum_buffer_hack_active) + bufHdr->flags |= BM_READ_BY_VACUUM; } /* diff -crN ../src.orig/backend/storage/buffer/freelist.c ./backend/storage/buffer/freelist.c *** ../src.orig/backend/storage/buffer/freelist.c Thu Oct 30 10:17:38 2003 --- ./backend/storage/buffer/freelist.c Thu Oct 30 12:38:42 2003 *************** *** 71,79 **** #endif /* BMTRACE */ IsNotInQueue(bf); ! /* change bf so it points to inFrontOfNew and its successor */ ! bf->freePrev = SharedFreeList->freePrev; ! bf->freeNext = Free_List_Descriptor; /* insert new into chain */ BufferDescriptors[bf->freeNext].freePrev = bf->buf_id; --- 71,93 ---- #endif /* BMTRACE */ IsNotInQueue(bf); ! if ((bf->flags & BM_READ_BY_VACUUM) != 0) ! { ! /* in the case the buffer was read or created by vacuum, ! * add it to the end of the queue so that GetFreeBuffer() ! * will return it next again. ! */ ! bf->freePrev = Free_List_Descriptor; ! bf->freeNext = SharedFreeList->freeNext; ! ! bf->flags &= ~BM_READ_BY_VACUUM; ! } ! else ! { ! /* change bf so it points to inFrontOfNew and its successor */ ! bf->freePrev = SharedFreeList->freePrev; ! bf->freeNext = Free_List_Descriptor; ! } /* insert new into chain */ BufferDescriptors[bf->freeNext].freePrev = bf->buf_id; diff -crN ../src.orig/backend/tcop/postgres.c ./backend/tcop/postgres.c *** ../src.orig/backend/tcop/postgres.c Thu Oct 30 10:17:39 2003 --- ./backend/tcop/postgres.c Thu Oct 30 10:25:07 2003 *************** *** 69,74 **** --- 69,77 ---- extern int optind; extern char *optarg; + extern bool vacuum_buffer_hack; + extern bool vacuum_buffer_hack_active; + char *debug_query_string; /* for pgmonitor and * log_min_error_statement */ *************** *** 1874,1879 **** --- 1877,1888 ---- for (;;) { + /* + * Reset the vacuum buffer hack active flag, could be left + * true if a vacuum got aborted. + */ + vacuum_buffer_hack_active = false; + /* * Release storage left over from prior query cycle, and create a * new query input buffer in the cleared QueryContext. diff -crN ../src.orig/include/storage/buf_internals.h ./include/storage/buf_internals.h *** ../src.orig/include/storage/buf_internals.h Thu Oct 30 10:17:43 2003 --- ./include/storage/buf_internals.h Thu Oct 30 10:29:56 2003 *************** *** 41,46 **** --- 41,47 ---- #define BM_IO_ERROR (1 << 6) #define BM_JUST_DIRTIED (1 << 7) #define BM_PIN_COUNT_WAITER (1 << 8) + #define BM_READ_BY_VACUUM (1 << 9) typedef bits16 BufFlags;