Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e4e2e2a

Browse files
committed
Online upgrade
1 parent b1c1aa5 commit e4e2e2a

File tree

8 files changed

+110
-27
lines changed

8 files changed

+110
-27
lines changed

src/backend/libpq/pqcomm.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,17 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
503503
closesocket(fd);
504504
continue;
505505
}
506+
if ((setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
507+
(char *) &one, sizeof(one))) == -1)
508+
{
509+
ereport(LOG,
510+
(errcode_for_socket_access(),
511+
/* translator: first %s is IPv4, IPv6, or Unix */
512+
errmsg("setsockopt(SO_REUSEADDR) failed for %s address \"%s\": %m",
513+
familyDesc, addrDesc)));
514+
closesocket(fd);
515+
continue;
516+
}
506517
}
507518
#endif
508519

src/backend/port/sysv_shmem.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
125125
IpcMemoryId shmid;
126126
void *requestedAddress = NULL;
127127
void *memAddress;
128-
128+
int mode = IPC_CREAT | IPC_EXCL | IPCProtection;
129129
/*
130130
* Normally we just pass requestedAddress = NULL to shmat(), allowing the
131131
* system to choose where the segment gets mapped. But in an EXEC_BACKEND
@@ -143,14 +143,16 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
143143
if (pg_shmem_addr)
144144
requestedAddress = (void *) strtoul(pg_shmem_addr, NULL, 0);
145145
}
146+
if (IsOnlineUpgrade)
147+
{
148+
mode &= ~IPC_EXCL;
149+
}
146150
#endif
147151

148-
shmid = shmget(memKey, size, IPC_CREAT | IPC_EXCL | IPCProtection);
149-
152+
shmid = shmget(memKey, size, mode);
150153
if (shmid < 0)
151154
{
152155
int shmget_errno = errno;
153-
154156
/*
155157
* Fail quietly if error indicates a collision with existing segment.
156158
* One would expect EEXIST, given that we said IPC_EXCL, but perhaps
@@ -175,7 +177,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
175177
*/
176178
if (shmget_errno == EINVAL)
177179
{
178-
shmid = shmget(memKey, 0, IPC_CREAT | IPC_EXCL | IPCProtection);
180+
shmid = shmget(memKey, 0, mode);
179181

180182
if (shmid < 0)
181183
{
@@ -216,7 +218,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
216218
(errmsg("could not create shared memory segment: %m"),
217219
errdetail("Failed system call was shmget(key=%lu, size=%zu, 0%o).",
218220
(unsigned long) memKey, size,
219-
IPC_CREAT | IPC_EXCL | IPCProtection),
221+
mode),
220222
(shmget_errno == EINVAL) ?
221223
errhint("This error usually means that PostgreSQL's request for a shared memory "
222224
"segment exceeded your kernel's SHMMAX parameter, or possibly that "
@@ -241,7 +243,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
241243
}
242244

243245
/* Register on-exit routine to delete the new segment */
244-
on_shmem_exit(IpcMemoryDelete, Int32GetDatum(shmid));
246+
//on_shmem_exit(IpcMemoryDelete, Int32GetDatum(shmid));
245247

246248
/* OK, should be able to attach to the segment */
247249
memAddress = shmat(shmid, requestedAddress, PG_SHMAT_FLAGS);
@@ -752,6 +754,11 @@ PGSharedMemoryCreate(Size size,
752754

753755
/* Initialize new segment. */
754756
hdr = (PGShmemHeader *) memAddress;
757+
758+
*shim = hdr;
759+
if (IsOnlineUpgrade)
760+
return hdr;
761+
755762
hdr->creatorPID = getpid();
756763
hdr->magic = PGShmemMagic;
757764
hdr->dsm_control = 0;
@@ -765,7 +772,6 @@ PGSharedMemoryCreate(Size size,
765772
*/
766773
hdr->totalsize = size;
767774
hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
768-
*shim = hdr;
769775

770776
/* Save info for possible future use */
771777
UsedShmemSegAddr = memAddress;
@@ -806,7 +812,7 @@ PGSharedMemoryReAttach(void)
806812
void *origUsedShmemSegAddr = UsedShmemSegAddr;
807813

808814
Assert(UsedShmemSegAddr != NULL);
809-
Assert(IsUnderPostmaster);
815+
Assert(IsUnderPostmaster || IsOnlineUpgrade);
810816

811817
#ifdef __CYGWIN__
812818
/* cygipc (currently) appears to not detach on exec. */

src/backend/postmaster/postmaster.c

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ static void pmdie(SIGNAL_ARGS);
391391
static void reaper(SIGNAL_ARGS);
392392
static void sigusr1_handler(SIGNAL_ARGS);
393393
static void startup_die(SIGNAL_ARGS);
394-
static void dummy_handler(SIGNAL_ARGS);
394+
static void upgrade_handler(SIGNAL_ARGS);
395395
static void StartupPacketTimeoutHandler(void);
396396
static void CleanupBackend(int pid, int exitstatus);
397397
static bool CleanupBackgroundWorker(int pid, int exitstatus);
@@ -560,6 +560,48 @@ int postmaster_alive_fds[2] = {-1, -1};
560560
HANDLE PostmasterHandle;
561561
#endif
562562

563+
static void
564+
UpgradePostgres(void)
565+
{
566+
char* PostmasterArgs[] = {"/home/knizhnik/postgresql/dist/bin/postgres", "-U", "-D", "." ,NULL};
567+
BackendParameters param;
568+
FILE *fp;
569+
570+
if (!save_backend_variables(&param, NULL))
571+
return; /* log made by save_backend_variables */
572+
573+
/* Open file */
574+
fp = AllocateFile("postmaster.params", PG_BINARY_W);
575+
if (!fp)
576+
{
577+
ereport(LOG,
578+
(errcode_for_file_access(),
579+
errmsg("could not create file \"postmaster.params\": %m")));
580+
return;
581+
}
582+
583+
if (fwrite(&param, sizeof(param), 1, fp) != 1)
584+
{
585+
ereport(LOG,
586+
(errcode_for_file_access(),
587+
errmsg("could not write to file \"postmaster.params\": %m")));
588+
FreeFile(fp);
589+
return;
590+
}
591+
592+
/* Release file */
593+
if (FreeFile(fp))
594+
{
595+
ereport(LOG,
596+
(errcode_for_file_access(),
597+
errmsg("could not write to file \"postmaster.params\": %m")));
598+
return;
599+
}
600+
601+
elog(LOG, "Upgrade postgres");
602+
execv(PostmasterArgs[0], PostmasterArgs);
603+
}
604+
563605
/*
564606
* Postmaster main entry point
565607
*/
@@ -634,9 +676,10 @@ PostmasterMain(int argc, char *argv[])
634676
pqsignal(SIGPIPE, SIG_IGN); /* ignored */
635677
pqsignal_no_restart(SIGUSR1, sigusr1_handler); /* message from child
636678
* process */
637-
pqsignal_no_restart(SIGUSR2, dummy_handler); /* unused, reserve for
679+
pqsignal_no_restart(SIGUSR2, upgrade_handler); /* unused, reserve for
638680
* children */
639681
pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
682+
pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
640683

641684
/*
642685
* No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We
@@ -669,13 +712,16 @@ PostmasterMain(int argc, char *argv[])
669712
* tcop/postgres.c (the option sets should not conflict) and with the
670713
* common help() function in main/main.c.
671714
*/
672-
while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1)
715+
while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:UW:-:")) != -1)
673716
{
674717
switch (opt)
675718
{
676719
case 'B':
677720
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
678721
break;
722+
case 'U':
723+
IsOnlineUpgrade = true;
724+
break;
679725

680726
case 'b':
681727
/* Undocumented flag used for binary upgrades */
@@ -853,6 +899,10 @@ PostmasterMain(int argc, char *argv[])
853899
ExitPostmaster(1);
854900
}
855901

902+
if (IsOnlineUpgrade)
903+
read_backend_variables("postmaster.params", NULL);
904+
905+
856906
/*
857907
* Locate the proper configuration files and data directory, and read
858908
* postgresql.conf for the first time.
@@ -950,7 +1000,8 @@ PostmasterMain(int argc, char *argv[])
9501000
* so it must happen before opening sockets so that at exit, the socket
9511001
* lockfiles go away after CloseServerPorts runs.
9521002
*/
953-
CreateDataDirLockFile(true);
1003+
if (!IsOnlineUpgrade)
1004+
CreateDataDirLockFile(true);
9541005

9551006
/*
9561007
* Read the control file (for error checking and config info).
@@ -991,12 +1042,16 @@ PostmasterMain(int argc, char *argv[])
9911042
* Now that loadable modules have had their chance to register background
9921043
* workers, calculate MaxBackends.
9931044
*/
994-
InitializeMaxBackends();
1045+
if (!IsOnlineUpgrade)
1046+
InitializeMaxBackends();
9951047

9961048
/*
9971049
* Set up shared memory and semaphores.
9981050
*/
999-
reset_shared();
1051+
if (IsOnlineUpgrade)
1052+
PGSharedMemoryReAttach();
1053+
else
1054+
reset_shared();
10001055

10011056
/*
10021057
* Estimate number of openable files. This must happen after setting up
@@ -4980,6 +5035,10 @@ SubPostmasterMain(int argc, char *argv[])
49805035
/* And run the backend */
49815036
BackendRun(&port); /* does not return */
49825037
}
5038+
if (strcmp(argv[1], "--forkpostmaster") == 0)
5039+
{
5040+
InitShmemAccess(UsedShmemSegAddr);
5041+
}
49835042
if (strcmp(argv[1], "--forkboot") == 0)
49845043
{
49855044
/* Restore basic shared memory pointers */
@@ -5296,8 +5355,9 @@ startup_die(SIGNAL_ARGS)
52965355
* tcop/postgres.c.)
52975356
*/
52985357
static void
5299-
dummy_handler(SIGNAL_ARGS)
5358+
upgrade_handler(SIGNAL_ARGS)
53005359
{
5360+
UpgradePostgres();
53015361
}
53025362

53035363
/*
@@ -6079,10 +6139,12 @@ save_backend_variables(BackendParameters *param, Port *port,
60796139
HANDLE childProcess, pid_t childPid)
60806140
#endif
60816141
{
6082-
memcpy(&param->port, port, sizeof(Port));
6083-
if (!write_inheritable_socket(&param->portsocket, port->sock, childPid))
6084-
return false;
6085-
6142+
if (port)
6143+
{
6144+
memcpy(&param->port, port, sizeof(Port));
6145+
if (!write_inheritable_socket(&param->portsocket, port->sock, childPid))
6146+
return false;
6147+
}
60866148
strlcpy(param->DataDir, DataDir, MAXPGPATH);
60876149

60886150
memcpy(&param->ListenSocket, &ListenSocket, sizeof(ListenSocket));
@@ -6316,9 +6378,11 @@ read_backend_variables(char *id, Port *port)
63166378
static void
63176379
restore_backend_variables(BackendParameters *param, Port *port)
63186380
{
6319-
memcpy(port, &param->port, sizeof(Port));
6320-
read_inheritable_socket(&port->sock, &param->portsocket);
6321-
6381+
if (port)
6382+
{
6383+
memcpy(port, &param->port, sizeof(Port));
6384+
read_inheritable_socket(&port->sock, &param->portsocket);
6385+
}
63226386
SetDataDir(param->DataDir);
63236387

63246388
memcpy(&ListenSocket, &param->ListenSocket, sizeof(ListenSocket));

src/backend/storage/ipc/ipci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ CreateSharedMemoryAndSemaphores(void)
194194
/*
195195
* Set up shared memory allocation mechanism
196196
*/
197-
if (!IsUnderPostmaster)
197+
if (!IsUnderPostmaster && !IsOnlineUpgrade)
198198
InitShmemAllocation();
199199

200200
/*

src/backend/storage/ipc/shmem.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
383383
/* Must be trying to create/attach to ShmemIndex itself */
384384
Assert(strcmp(name, "ShmemIndex") == 0);
385385

386-
if (IsUnderPostmaster)
386+
if (IsUnderPostmaster || IsOnlineUpgrade)
387387
{
388388
/* Must be initializing a (non-standalone) backend */
389389
Assert(shmemseghdr->index != NULL);

src/backend/utils/init/globals.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pid_t PostmasterPid = 0;
108108
bool IsPostmasterEnvironment = false;
109109
bool IsUnderPostmaster = false;
110110
bool IsBinaryUpgrade = false;
111+
bool IsOnlineUpgrade = false;
111112
bool IsBackgroundWorker = false;
112113

113114
bool ExitOnAnyError = false;

src/common/exec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ find_my_exec(const char *argv0, char *retpath)
169169
* Since no explicit path was supplied, the user must have been relying on
170170
* PATH. We'll search the same PATH.
171171
*/
172+
path = getenv("PATH");
173+
Assert(path != NULL);
172174
if ((path = getenv("PATH")) && *path)
173175
{
174176
char *startp = NULL,
@@ -195,7 +197,6 @@ find_my_exec(const char *argv0, char *retpath)
195197
join_path_components(retpath, retpath, argv0);
196198
}
197199
canonicalize_path(retpath);
198-
199200
switch (validate_exec(retpath))
200201
{
201202
case 0: /* found ok */
@@ -210,7 +211,6 @@ find_my_exec(const char *argv0, char *retpath)
210211
}
211212
} while (*endp);
212213
}
213-
214214
log_error(errcode(ERRCODE_UNDEFINED_FILE),
215215
_("could not find a \"%s\" to execute"), argv0);
216216
return -1;

src/include/miscadmin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ extern PGDLLIMPORT bool IsPostmasterEnvironment;
150150
extern PGDLLIMPORT bool IsUnderPostmaster;
151151
extern PGDLLIMPORT bool IsBackgroundWorker;
152152
extern PGDLLIMPORT bool IsBinaryUpgrade;
153+
extern PGDLLIMPORT bool IsOnlineUpgrade;
153154

154155
extern PGDLLIMPORT bool ExitOnAnyError;
155156

0 commit comments

Comments
 (0)