diff options
Diffstat (limited to 'src/backend/access/transam/slru.c')
-rw-r--r-- | src/backend/access/transam/slru.c | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 901a5e57da7..d1bfd9570c1 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -41,7 +41,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.32 2005/12/06 18:10:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.33 2005/12/06 23:08:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,11 +87,13 @@ * until control returns to SimpleLruFlush(). This data structure remembers * which files are open. */ +#define MAX_FLUSH_BUFFERS 16 + typedef struct SlruFlushData { - int num_files; /* # files actually open */ - int fd[NUM_SLRU_BUFFERS]; /* their FD's */ - int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */ + int num_files; /* # files actually open */ + int fd[MAX_FLUSH_BUFFERS]; /* their FD's */ + int segno[MAX_FLUSH_BUFFERS]; /* their log seg#s */ } SlruFlushData; /* @@ -150,25 +152,38 @@ static int SlruSelectLRUPage(SlruCtl ctl, int pageno); */ Size -SimpleLruShmemSize(void) +SimpleLruShmemSize(int nslots) { - /* we assume NUM_SLRU_BUFFERS isn't so large as to risk overflow */ - return BUFFERALIGN(sizeof(SlruSharedData)) + BLCKSZ * NUM_SLRU_BUFFERS; + Size sz; + + /* we assume nslots isn't so large as to risk overflow */ + sz = MAXALIGN(sizeof(SlruSharedData)); + sz += MAXALIGN(nslots * sizeof(char *)); /* page_buffer[] */ + sz += MAXALIGN(nslots * sizeof(SlruPageStatus)); /* page_status[] */ + sz += MAXALIGN(nslots * sizeof(bool)); /* page_dirty[] */ + sz += MAXALIGN(nslots * sizeof(int)); /* page_number[] */ + sz += MAXALIGN(nslots * sizeof(int)); /* page_lru_count[] */ + sz += MAXALIGN(nslots * sizeof(LWLockId)); /* buffer_locks[] */ + + return BUFFERALIGN(sz) + BLCKSZ * nslots; } void -SimpleLruInit(SlruCtl ctl, const char *name, +SimpleLruInit(SlruCtl ctl, const char *name, int nslots, LWLockId ctllock, const char *subdir) { SlruShared shared; bool found; - shared = (SlruShared) ShmemInitStruct(name, SimpleLruShmemSize(), &found); + shared = (SlruShared) ShmemInitStruct(name, + SimpleLruShmemSize(nslots), + &found); if (!IsUnderPostmaster) { /* Initialize locks and shared memory area */ - char *bufptr; + char *ptr; + Size offset; int slotno; Assert(!found); @@ -177,19 +192,37 @@ SimpleLruInit(SlruCtl ctl, const char *name, shared->ControlLock = ctllock; - bufptr = (char *) shared + BUFFERALIGN(sizeof(SlruSharedData)); + shared->num_slots = nslots; + + shared->cur_lru_count = 0; + + /* shared->latest_page_number will be set later */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + ptr = (char *) shared; + offset = MAXALIGN(sizeof(SlruSharedData)); + shared->page_buffer = (char **) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(char *)); + shared->page_status = (SlruPageStatus *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(SlruPageStatus)); + shared->page_dirty = (bool *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(bool)); + shared->page_number = (int *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(int)); + shared->page_lru_count = (int *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(int)); + shared->buffer_locks = (LWLockId *) (ptr + offset); + offset += MAXALIGN(nslots * sizeof(LWLockId)); + ptr += BUFFERALIGN(offset); + + for (slotno = 0; slotno < nslots; slotno++) { - shared->page_buffer[slotno] = bufptr; + shared->page_buffer[slotno] = ptr; shared->page_status[slotno] = SLRU_PAGE_EMPTY; shared->page_dirty[slotno] = false; shared->page_lru_count[slotno] = 0; shared->buffer_locks[slotno] = LWLockAssign(); - bufptr += BLCKSZ; + ptr += BLCKSZ; } - - /* shared->latest_page_number will be set later */ } else Assert(found); @@ -394,7 +427,7 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid) LWLockAcquire(shared->ControlLock, LW_SHARED); /* See if page is already in a buffer */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_number[slotno] == pageno && shared->page_status[slotno] != SLRU_PAGE_EMPTY && @@ -643,9 +676,20 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) if (fdata) { - fdata->fd[fdata->num_files] = fd; - fdata->segno[fdata->num_files] = segno; - fdata->num_files++; + if (fdata->num_files < MAX_FLUSH_BUFFERS) + { + fdata->fd[fdata->num_files] = fd; + fdata->segno[fdata->num_files] = segno; + fdata->num_files++; + } + else + { + /* + * In the unlikely event that we exceed MAX_FLUSH_BUFFERS, + * fall back to treating it as a standalone write. + */ + fdata = NULL; + } } } @@ -797,7 +841,7 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno) int best_page_number; /* See if page already has a buffer assigned */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_number[slotno] == pageno && shared->page_status[slotno] != SLRU_PAGE_EMPTY) @@ -830,7 +874,7 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno) best_delta = -1; bestslot = 0; /* no-op, just keeps compiler quiet */ best_page_number = 0; /* ditto */ - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { int this_delta; int this_page_number; @@ -908,7 +952,7 @@ SimpleLruFlush(SlruCtl ctl, bool checkpoint) LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE); - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { SimpleLruWritePage(ctl, slotno, &fdata); @@ -990,7 +1034,7 @@ restart:; return; } - for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + for (slotno = 0; slotno < shared->num_slots; slotno++) { if (shared->page_status[slotno] == SLRU_PAGE_EMPTY) continue; |