diff options
Diffstat (limited to 'src/backend/access/transam/slru.c')
-rw-r--r-- | src/backend/access/transam/slru.c | 104 |
1 files changed, 76 insertions, 28 deletions
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; } |