summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2013-08-19 21:48:17 +0000
committerAlvaro Herrera2013-08-19 21:52:52 +0000
commitdb5b49cdd4f481828b227f03b373fbc9bde4301a (patch)
tree890838cb2180513f4f08184d20cde1a5ce3078ef
parent38c69237c21186038f6902373a0f06af1c2f7cfb (diff)
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
-rw-r--r--src/backend/postmaster/pgstat.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index dac5bca78aa..f42f1839c22 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -562,15 +562,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);
}
@@ -3627,6 +3649,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,