postgres.git / summary / log / commit / refs

commit    f9b50b7c18c8ce7de1fee59409fe23c58d438190
Author:   Alvaro Herrera <alvherre@alvh.no-ip.org>
Date:     Mon Aug 19 21:48:17 2013 +0000
First released in: 9.4.0, 9.3.0

    Fix removal of files in pgstats directories
    
    Instead of deleting all files in stats_temp_directory and the permanent
    directory on a crash, only remove those files that match the pattern of
    files we actually write in them, to avoid possibly clobbering existing
    unrelated contents of the temporary directory.  Per complaint from Jeff
    Janes, and subsequent discussion, starting at message
    CAMkU=1z9+7RsDODnT4=cDFBRBp8wYQbd_qsLcMtKEf-oFwuOdQ@mail.gmail.com
    
    Also, fix a bug in the same routine to avoid removing files from the
    permanent directory twice (instead of once from that directory and then
    from the temporary directory), also per report from Jeff Janes, in
    message
    CAMkU=1wbk947=-pAosDMX5VC+sQw9W4ttq6RM9rXu=MjNeEQKA@mail.gmail.com


src/backend/postmaster/pgstat.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index a52377fc9db..c16dd036c03 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -563,15 +563,37 @@ pgstat_reset_remove_files(const char *directory) struct dirent *entry; char fname[MAXPGPATH]; - dir = AllocateDir(pgstat_stat_directory); - while ((entry = ReadDir(dir, pgstat_stat_directory)) != NULL) + dir = AllocateDir(directory); + while ((entry = ReadDir(dir, directory)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + int nitems; + Oid tmp_oid; + char tmp_type[8]; + char tmp_rest[2]; + + if (strncmp(entry->d_name, ".", 2) == 0 || + strncmp(entry->d_name, "..", 3) == 0) continue; - /* XXX should we try to ignore files other than the ones we write? */ + /* + * Skip directory entries that don't match the file names we write. + * See get_dbstat_filename for the database-specific pattern. + */ + nitems = sscanf(entry->d_name, "db_%u.%5s%1s", + &tmp_oid, tmp_type, tmp_rest); + if (nitems != 2) + { + nitems = sscanf(entry->d_name, "global.%5s%1s", + tmp_type, tmp_rest); + if (nitems != 1) + continue; + } + + if (strncmp(tmp_type, "tmp", 4) != 0 && + strncmp(tmp_type, "stat", 5) != 0) + continue; - snprintf(fname, MAXPGPATH, "%s/%s", pgstat_stat_directory, + snprintf(fname, MAXPGPATH, "%s/%s", directory, entry->d_name); unlink(fname); } @@ -3631,6 +3653,7 @@ get_dbstat_filename(bool permanent, bool tempname, Oid databaseid, { int printed; + /* NB -- pgstat_reset_remove_files knows about the pattern this uses */ printed = snprintf(filename, len, "%s/db_%u.%s", permanent ? PGSTAT_STAT_PERMANENT_DIRECTORY : pgstat_stat_directory, [parent: 3619a20d3351]