Teach CreateSlotOnDisk to try to clean up after previous failures.
authorRobert Haas <rhaas@postgresql.org>
Thu, 30 Jan 2014 18:24:46 +0000 (13:24 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 30 Jan 2014 18:24:46 +0000 (13:24 -0500)
src/backend/replication/slot.c

index 17d026711c2e5af2aebe086c7e35b48f7e177f93..306ad9a21d540a925a86eae317afb86c1c2d24cf 100644 (file)
@@ -739,6 +739,7 @@ CreateSlotOnDisk(ReplicationSlot *slot)
 {
        char            tmppath[MAXPGPATH];
        char            path[MAXPGPATH];
+       struct stat     st;
 
        /*
         * No need to take out the io_in_progress_lock, nobody else can see this
@@ -749,17 +750,29 @@ CreateSlotOnDisk(ReplicationSlot *slot)
        sprintf(path, "pg_replslot/%s", NameStr(slot->data.name));
        sprintf(tmppath, "pg_replslot/%s.tmp", NameStr(slot->data.name));
 
+       /*
+        * It's just barely possible that some previous effort to create or
+        * drop a slot with this name left a temp directory lying around.
+        * If that seems to be the case, try to remove it.  If the rmtree()
+        * fails, we'll error out at the mkdir() below, so we don't bother
+        * checking success.
+        */
+       if (stat(tmppath, &st) == 0 && S_ISDIR(st.st_mode))
+               rmtree(tmppath, true);
+
+       /* Create and fsync the temporary slot directory. */
        if (mkdir(tmppath, S_IRWXU) < 0)
                ereport(ERROR,
                                (errcode_for_file_access(),
                                 errmsg("could not create directory \"%s\": %m",
                                                tmppath)));
-
        fsync_fname(tmppath, true);
 
+       /* Write the actual state file. */
        slot->dirty = true; /* signal that we really need to write */
        SaveSlotToPath(slot, tmppath, ERROR);
 
+       /* Rename the directory into place. */
        if (rename(tmppath, path) != 0)
                ereport(ERROR,
                                (errcode_for_file_access(),