diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2011-09-28 11:32:38 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2011-10-04 14:03:23 -0300 |
commit | 09e196e4539a70c51e828abcfe48dee3efd312d8 (patch) | |
tree | a229e227e0e4db185606acafbbd3e8c3c12171aa /src/backend/access | |
parent | 1a00c0ef5368bb7b8ddcb3cf279df36577918ac4 (diff) | |
download | postgresql-09e196e4539a70c51e828abcfe48dee3efd312d8.tar.gz postgresql-09e196e4539a70c51e828abcfe48dee3efd312d8.zip |
Use callbacks in SlruScanDirectory for the actual action
Previously, the code assumed that the only possible action to take was
to delete files behind a certain cutoff point. The async notify code
was already a crock: it used a different "pagePrecedes" function for
truncation than for regular operation. By allowing it to pass a
callback to SlruScanDirectory it can do cleanly exactly what it needs to
do.
The clog.c code also had its own use for SlruScanDirectory, which is
made a bit simpler with this.
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/transam/clog.c | 2 | ||||
-rw-r--r-- | src/backend/access/transam/slru.c | 104 |
2 files changed, 77 insertions, 29 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 3a6c39164ce..ee645f7bd47 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -606,7 +606,7 @@ TruncateCLOG(TransactionId oldestXact) cutoffPage = TransactionIdToPage(oldestXact); /* Check to see if there's any files that could be removed */ - if (!SlruScanDirectory(ClogCtl, cutoffPage, false)) + if (!SlruScanDirectory(ClogCtl, SlruScanDirCbReportPresence, &cutoffPage)) return; /* nothing to remove */ /* Write XLOG record and flush XLOG to disk */ diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 69e5245beba..4b838a0dfeb 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -132,6 +132,8 @@ static bool SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid); static int SlruSelectLRUPage(SlruCtl ctl, int pageno); +static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, + int segpage, void *data); /* * Initialization of shared memory @@ -1137,33 +1139,84 @@ restart:; LWLockRelease(shared->ControlLock); /* Now we can remove the old segment(s) */ - (void) SlruScanDirectory(ctl, cutoffPage, true); + (void) SlruScanDirectory(ctl, SlruScanDirCbDeleteCutoff, &cutoffPage); } /* - * SimpleLruTruncate subroutine: scan directory for removable segments. - * Actually remove them iff doDeletions is true. Return TRUE iff any - * removable segments were found. Note: no locking is needed. + * SlruScanDirectory callback + * This callback reports true if there's any segment prior to the one + * containing the page passed as "data". + */ +bool +SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data) +{ + int cutoffPage = *(int *) data; + + cutoffPage -= cutoffPage % SLRU_PAGES_PER_SEGMENT; + + if (ctl->PagePrecedes(segpage, cutoffPage)) + return true; /* found one; don't iterate any more */ + + return false; /* keep going */ +} + +/* + * SlruScanDirectory callback. + * This callback deletes segments prior to the one passed in as "data". + */ +static bool +SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, int segpage, void *data) +{ + char path[MAXPGPATH]; + int cutoffPage = *(int *) data; + + if (ctl->PagePrecedes(segpage, cutoffPage)) + { + snprintf(path, MAXPGPATH, "%s/%s", ctl->Dir, filename); + ereport(DEBUG2, + (errmsg("removing file \"%s\"", path))); + unlink(path); + } + + return false; /* keep going */ +} + +/* + * SlruScanDirectory callback. + * This callback deletes all segments. + */ +bool +SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int segpage, void *data) +{ + char path[MAXPGPATH]; + + snprintf(path, MAXPGPATH, "%s/%s", ctl->Dir, filename); + ereport(DEBUG2, + (errmsg("removing file \"%s\"", path))); + unlink(path); + + return false; /* keep going */ +} + +/* + * Scan the SimpleLRU directory and apply a callback to each file found in it. + * + * If the callback returns true, the scan is stopped. The last return value + * from the callback is returned. * - * This can be called directly from clog.c, for reasons explained there. + * Note that the ordering in which the directory is scanned is not guaranteed. + * + * Note that no locking is applied. */ bool -SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions) +SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data) { - bool found = false; DIR *cldir; struct dirent *clde; int segno; int segpage; - char path[MAXPGPATH]; - - /* - * The cutoff point is the start of the segment containing cutoffPage. - * (This is redundant when called from SimpleLruTruncate, but not when - * called directly from clog.c.) - */ - cutoffPage -= cutoffPage % SLRU_PAGES_PER_SEGMENT; - + bool retval; + cldir = AllocateDir(ctl->Dir); while ((clde = ReadDir(cldir, ctl->Dir)) != NULL) { @@ -1172,20 +1225,15 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions) { segno = (int) strtol(clde->d_name, NULL, 16); segpage = segno * SLRU_PAGES_PER_SEGMENT; - if (ctl->PagePrecedes(segpage, cutoffPage)) - { - found = true; - if (doDeletions) - { - snprintf(path, MAXPGPATH, "%s/%s", ctl->Dir, clde->d_name); - ereport(DEBUG2, - (errmsg("removing file \"%s\"", path))); - unlink(path); - } - } + + elog(DEBUG2, "SlruScanDirectory invoking callback on %s/%s", + ctl->Dir, clde->d_name); + retval = callback(ctl, clde->d_name, segpage, data); + if (retval) + break; } } FreeDir(cldir); - return found; + return retval; } |