summaryrefslogtreecommitdiff
path: root/src/backend/utils/init/miscinit.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-10 17:26:44 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-10 17:27:15 -0400
commitc9b0cbe98bd783e24a8c4d8d8ac472a494b81292 (patch)
tree1d4459d614fe104efa5c8d6881b5ef347a523b11 /src/backend/utils/init/miscinit.c
parent85642ec00b5e0c58d2504b10c079693b8fb28cc5 (diff)
Support having multiple Unix-domain sockets per postmaster.
Replace unix_socket_directory with unix_socket_directories, which is a list of socket directories, and adjust postmaster's code to allow zero or more Unix-domain sockets to be created. This is mostly a straightforward change, but since the Unix sockets ought to be created after the TCP/IP sockets for safety reasons (better chance of detecting a port number conflict), AddToDataDirLockFile needs to be fixed to support out-of-order updates of data directory lockfile lines. That's a change that had been foreseen to be necessary someday anyway. Honza Horak, reviewed and revised by Tom Lane
Diffstat (limited to 'src/backend/utils/init/miscinit.c')
-rw-r--r--src/backend/utils/init/miscinit.c120
1 files changed, 75 insertions, 45 deletions
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index fb376a0d271..775d71f56c5 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -49,8 +49,8 @@
ProcessingMode Mode = InitProcessing;
-/* Note: we rely on this to initialize as zeroes */
-static char socketLockFile[MAXPGPATH];
+/* List of lock files to be removed at proc exit */
+static List *lock_files = NIL;
/* ----------------------------------------------------------------
@@ -628,7 +628,7 @@ GetUserNameFromId(Oid roleid)
* Interlock-file support
*
* These routines are used to create both a data-directory lockfile
- * ($DATADIR/postmaster.pid) and a Unix-socket-file lockfile ($SOCKFILE.lock).
+ * ($DATADIR/postmaster.pid) and Unix-socket-file lockfiles ($SOCKFILE.lock).
* Both kinds of files contain the same info initially, although we can add
* more information to a data-directory lockfile after it's created, using
* AddToDataDirLockFile(). See miscadmin.h for documentation of the contents
@@ -640,32 +640,35 @@ GetUserNameFromId(Oid roleid)
*/
/*
- * proc_exit callback to remove a lockfile.
+ * proc_exit callback to remove lockfiles.
*/
static void
-UnlinkLockFile(int status, Datum filename)
+UnlinkLockFiles(int status, Datum arg)
{
- char *fname = (char *) DatumGetPointer(filename);
+ ListCell *l;
- if (fname != NULL)
+ foreach(l, lock_files)
{
- if (unlink(fname) != 0)
- {
- /* Should we complain if the unlink fails? */
- }
- free(fname);
+ char *curfile = (char *) lfirst(l);
+
+ unlink(curfile);
+ /* Should we complain if the unlink fails? */
}
+ /* Since we're about to exit, no need to reclaim storage */
+ lock_files = NIL;
}
/*
* Create a lockfile.
*
- * filename is the name of the lockfile to create.
+ * filename is the path name of the lockfile to create.
* amPostmaster is used to determine how to encode the output PID.
+ * socketDir is the Unix socket directory path to include (possibly empty).
* isDDLock and refName are used to determine what error message to produce.
*/
static void
CreateLockFile(const char *filename, bool amPostmaster,
+ const char *socketDir,
bool isDDLock, const char *refName)
{
int fd;
@@ -891,12 +894,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
DataDir,
(long) MyStartTime,
PostPortNumber,
-#ifdef HAVE_UNIX_SOCKETS
- (*UnixSocketDir != '\0') ? UnixSocketDir : DEFAULT_PGSOCKET_DIR
-#else
- ""
-#endif
- );
+ socketDir);
errno = 0;
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
@@ -934,9 +932,14 @@ CreateLockFile(const char *filename, bool amPostmaster,
}
/*
- * Arrange for automatic removal of lockfile at proc_exit.
+ * Arrange to unlink the lock file(s) at proc_exit. If this is the
+ * first one, set up the on_proc_exit function to do it; then add this
+ * lock file to the list of files to unlink.
*/
- on_proc_exit(UnlinkLockFile, PointerGetDatum(strdup(filename)));
+ if (lock_files == NIL)
+ on_proc_exit(UnlinkLockFiles, 0);
+
+ lock_files = lappend(lock_files, pstrdup(filename));
}
/*
@@ -945,41 +948,50 @@ CreateLockFile(const char *filename, bool amPostmaster,
* When this is called, we must have already switched the working
* directory to DataDir, so we can just use a relative path. This
* helps ensure that we are locking the directory we should be.
+ *
+ * Note that the socket directory path line is initially written as empty.
+ * postmaster.c will rewrite it upon creating the first Unix socket.
*/
void
CreateDataDirLockFile(bool amPostmaster)
{
- CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, true, DataDir);
+ CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, "", true, DataDir);
}
/*
* Create a lockfile for the specified Unix socket file.
*/
void
-CreateSocketLockFile(const char *socketfile, bool amPostmaster)
+CreateSocketLockFile(const char *socketfile, bool amPostmaster,
+ const char *socketDir)
{
char lockfile[MAXPGPATH];
snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
- CreateLockFile(lockfile, amPostmaster, false, socketfile);
- /* Save name of lockfile for TouchSocketLockFile */
- strcpy(socketLockFile, lockfile);
+ CreateLockFile(lockfile, amPostmaster, socketDir, false, socketfile);
}
/*
- * TouchSocketLockFile -- mark socket lock file as recently accessed
+ * TouchSocketLockFiles -- mark socket lock files as recently accessed
*
- * This routine should be called every so often to ensure that the lock file
- * has a recent mod or access date. That saves it
+ * This routine should be called every so often to ensure that the socket
+ * lock files have a recent mod or access date. That saves them
* from being removed by overenthusiastic /tmp-directory-cleaner daemons.
* (Another reason we should never have put the socket file in /tmp...)
*/
void
-TouchSocketLockFile(void)
+TouchSocketLockFiles(void)
{
- /* Do nothing if we did not create a socket... */
- if (socketLockFile[0] != '\0')
+ ListCell *l;
+
+ foreach(l, lock_files)
{
+ char *socketLockFile = (char *) lfirst(l);
+
+ /* No need to touch the data directory lock file, we trust */
+ if (strcmp(socketLockFile, DIRECTORY_LOCK_FILE) == 0)
+ continue;
+
/*
* utime() is POSIX standard, utimes() is a common alternative; if we
* have neither, fall back to actually reading the file (which only
@@ -1011,8 +1023,10 @@ TouchSocketLockFile(void)
* Add (or replace) a line in the data directory lock file.
* The given string should not include a trailing newline.
*
- * Caution: this erases all following lines. In current usage that is OK
- * because lines are added in order. We could improve it if needed.
+ * Note: because we don't truncate the file, if we were to rewrite a line
+ * with less data than it had before, there would be garbage after the last
+ * line. We don't ever actually do that, so not worth adding another kernel
+ * call to cover the possibility.
*/
void
AddToDataDirLockFile(int target_line, const char *str)
@@ -1020,8 +1034,10 @@ AddToDataDirLockFile(int target_line, const char *str)
int fd;
int len;
int lineno;
- char *ptr;
- char buffer[BLCKSZ];
+ char *srcptr;
+ char *destptr;
+ char srcbuffer[BLCKSZ];
+ char destbuffer[BLCKSZ];
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
if (fd < 0)
@@ -1032,7 +1048,7 @@ AddToDataDirLockFile(int target_line, const char *str)
DIRECTORY_LOCK_FILE)));
return;
}
- len = read(fd, buffer, sizeof(buffer) - 1);
+ len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
if (len < 0)
{
ereport(LOG,
@@ -1042,36 +1058,50 @@ AddToDataDirLockFile(int target_line, const char *str)
close(fd);
return;
}
- buffer[len] = '\0';
+ srcbuffer[len] = '\0';
/*
- * Skip over lines we are not supposed to rewrite.
+ * Advance over lines we are not supposed to rewrite, then copy them
+ * to destbuffer.
*/
- ptr = buffer;
+ srcptr = srcbuffer;
for (lineno = 1; lineno < target_line; lineno++)
{
- if ((ptr = strchr(ptr, '\n')) == NULL)
+ if ((srcptr = strchr(srcptr, '\n')) == NULL)
{
elog(LOG, "bogus data in \"%s\"", DIRECTORY_LOCK_FILE);
close(fd);
return;
}
- ptr++;
+ srcptr++;
}
+ memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
+ destptr = destbuffer + (srcptr - srcbuffer);
/*
* Write or rewrite the target line.
*/
- snprintf(ptr, buffer + sizeof(buffer) - ptr, "%s\n", str);
+ snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
+ destptr += strlen(destptr);
+
+ /*
+ * If there are more lines in the old file, append them to destbuffer.
+ */
+ if ((srcptr = strchr(srcptr, '\n')) != NULL)
+ {
+ srcptr++;
+ snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
+ srcptr);
+ }
/*
* And rewrite the data. Since we write in a single kernel call, this
* update should appear atomic to onlookers.
*/
- len = strlen(buffer);
+ len = strlen(destbuffer);
errno = 0;
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
- (int) write(fd, buffer, len) != len)
+ (int) write(fd, destbuffer, len) != len)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)