1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

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.
This commit is contained in:
Alvaro Herrera
2011-09-28 11:32:38 -03:00
parent 1a00c0ef53
commit 09e196e453
4 changed files with 95 additions and 60 deletions

View File

@@ -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 */

View File

@@ -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.
*
* This can be called directly from clog.c, for reasons explained there.
* SlruScanDirectory callback
* This callback reports true if there's any segment prior to the one
* containing the page passed as "data".
*/
bool
SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
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.
*
* Note that the ordering in which the directory is scanned is not guaranteed.
*
* Note that no locking is applied.
*/
bool
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;
}