forked from huawei/openGauss-server
rollback standby archive
This commit is contained in:
parent
aedb48e7e1
commit
d31aeb6bbf
|
|
@ -59,7 +59,7 @@ bool open_join_children = true;
|
|||
bool will_shutdown = false;
|
||||
|
||||
/* hard-wired binary version number */
|
||||
const uint32 GRAND_VERSION_NUM = 92299;
|
||||
const uint32 GRAND_VERSION_NUM = 92298;
|
||||
|
||||
const uint32 MATVIEW_VERSION_NUM = 92213;
|
||||
const uint32 PARTIALPUSH_VERSION_NUM = 92087;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include "storage/latch.h"
|
||||
#include "storage/pg_shmem.h"
|
||||
#include "storage/pmsignal.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/ps_status.h"
|
||||
|
||||
|
|
@ -60,7 +59,6 @@
|
|||
#include "pgxc/pgxc.h"
|
||||
#include "replication/obswalreceiver.h"
|
||||
#include "replication/walreceiver.h"
|
||||
#include "access/xlogreader.h"
|
||||
/* ----------
|
||||
* Timer definitions.
|
||||
* ----------
|
||||
|
|
@ -91,20 +89,6 @@
|
|||
|
||||
#define ARCHIVE_BUF_SIZE (1024 * 1024)
|
||||
|
||||
/*
|
||||
* Timeout interval for sending the status of the archive thread on the standby node
|
||||
*/
|
||||
#define UPDATE_STATUS_WAIT 3000
|
||||
|
||||
/* the status of archiver on standby */
|
||||
#define ARCHIVE_ON true
|
||||
#define ARCHIVE_OFF false
|
||||
|
||||
#define STANDBY_ARCHIVE_XLOG_UPGRADE_VERSION 92299
|
||||
|
||||
/* the interval of sending archive status is 1s. */
|
||||
#define SEND_ARCHIVE_STATUS_INTERVAL 1000000L
|
||||
|
||||
NON_EXEC_STATIC void PgArchiverMain();
|
||||
static void pgarch_exit(SIGNAL_ARGS);
|
||||
static void ArchSigHupHandler(SIGNAL_ARGS);
|
||||
|
|
@ -117,7 +101,6 @@ static bool pgarch_archiveXlog(char* xlog);
|
|||
static bool pgarch_readyXlog(char* xlog, int xlog_length);
|
||||
static void pgarch_archiveDone(const char* xlog);
|
||||
static void pgarch_archiveRoachForPitrStandby();
|
||||
static void CreateArchiveReadyFile();
|
||||
static bool pgarch_archiveRoachForPitrMaster(XLogRecPtr targetLsn);
|
||||
static bool pgarch_archiveRoachForCoordinator(XLogRecPtr targetLsn);
|
||||
static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn);
|
||||
|
|
@ -125,11 +108,6 @@ typedef bool(*doArchive)(XLogRecPtr);
|
|||
static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun);
|
||||
static void archKill(int code, Datum arg);
|
||||
static void initLastTaskLsn();
|
||||
static bool SendArchiveThreadStatusInternal(bool is_archive_activited);
|
||||
static void SendArchiveThreadStatus(bool status);
|
||||
static bool NotifyPrimaryArchiverActived(ThreadId* last_walrcv_pid, bool* sent_archive_status);
|
||||
static void NotifyPrimaryArchiverShutdown(bool sent_archive_status);
|
||||
static void ChangeArchiveTaskStatus2Done(const char* xlog);
|
||||
|
||||
AlarmCheckResult DataInstArchChecker(Alarm* alarm, AlarmAdditionalParam* additionalParam)
|
||||
{
|
||||
|
|
@ -241,7 +219,6 @@ NON_EXEC_STATIC void PgArchiverMain()
|
|||
*/
|
||||
init_ps_display("archiver process", "", "", "");
|
||||
setObsArchLatch(&t_thrd.arch.mainloop_latch);
|
||||
SetStandbyArchLatch(&t_thrd.arch.mainloop_latch);
|
||||
initLastTaskLsn();
|
||||
pgarch_MainLoop();
|
||||
|
||||
|
|
@ -337,8 +314,6 @@ static void pgarch_MainLoop(void)
|
|||
gettimeofday(&last_copy_time, NULL);
|
||||
bool time_to_stop = false;
|
||||
doArchive fun = NULL;
|
||||
bool sent_archive_status = false;
|
||||
ThreadId last_walrcv_pid = 0;
|
||||
|
||||
/*
|
||||
* We run the copy loop immediately upon entry, in case there are
|
||||
|
|
@ -370,7 +345,6 @@ static void pgarch_MainLoop(void)
|
|||
t_thrd.arch.got_SIGHUP = false;
|
||||
ProcessConfigFile(PGC_SIGHUP);
|
||||
if (!XLogArchivingActive()) {
|
||||
NotifyPrimaryArchiverShutdown(sent_archive_status);
|
||||
ereport(LOG, (errmsg("PgArchiver exit")));
|
||||
return;
|
||||
}
|
||||
|
|
@ -393,26 +367,12 @@ static void pgarch_MainLoop(void)
|
|||
}
|
||||
load_server_mode();
|
||||
if (IsServerModeStandby()) {
|
||||
/*
|
||||
* this step was used by standby to notify primary the archive thread is actived
|
||||
*/
|
||||
if (obs_archive_slot == NULL && t_thrd.proc->workingVersionNum >= STANDBY_ARCHIVE_XLOG_UPGRADE_VERSION &&
|
||||
!NotifyPrimaryArchiverActived(&last_walrcv_pid, &sent_archive_status)) {
|
||||
pg_usleep(SEND_ARCHIVE_STATUS_INTERVAL);
|
||||
continue;
|
||||
}
|
||||
/* if we should do pitr archive, for standby */
|
||||
volatile unsigned int *pitr_task_status = &g_instance.archive_obs_cxt.pitr_task_status;
|
||||
if (unlikely(pg_atomic_read_u32(pitr_task_status) == PITR_TASK_GET)) {
|
||||
pgarch_archiveRoachForPitrStandby();
|
||||
pg_atomic_write_u32(pitr_task_status, PITR_TASK_DONE);
|
||||
}
|
||||
|
||||
/* if we should do archive by standby, we should create a .ready file*/
|
||||
volatile unsigned int* arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
if (unlikely(pg_atomic_read_u32(arch_task_status) == ARCH_TASK_GET)) {
|
||||
CreateArchiveReadyFile();
|
||||
}
|
||||
}
|
||||
|
||||
/* Do what we're here for */
|
||||
|
|
@ -466,7 +426,7 @@ static void pgarch_MainLoop(void)
|
|||
wait_interval = t_thrd.arch.task_wait_interval;
|
||||
last_time = t_thrd.arch.last_arch_time;
|
||||
} else {
|
||||
wait_interval = IsServerModeStandby() ? t_thrd.arch.task_wait_interval : PGARCH_AUTOWAKE_INTERVAL;
|
||||
wait_interval = PGARCH_AUTOWAKE_INTERVAL;
|
||||
last_time = TIME_GET_MILLISEC(last_copy_time);
|
||||
}
|
||||
gettimeofday(&curtime, NULL);
|
||||
|
|
@ -504,15 +464,6 @@ static void pgarch_MainLoop(void)
|
|||
* SIGUSR2.
|
||||
*/
|
||||
} while (PostmasterIsAlive() && XLogArchivingActive() && !time_to_stop);
|
||||
|
||||
/*
|
||||
* This step don't need to check the version number, because we have checked the version in the loop.
|
||||
*
|
||||
* If the version number is bigger than STANDBY_ARCHIVE_XLOG_UPGRADE_VERSION and we notify the primary successfully
|
||||
* in the loop, the sent_archive_status will be set to true. We don't need to send the archive status when
|
||||
* the sent_archive_status is false, so we don't need to check the version number in this step.
|
||||
*/
|
||||
NotifyPrimaryArchiverShutdown(sent_archive_status);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -566,9 +517,6 @@ static void pgarch_ArchiverCopyLoop(void)
|
|||
if (pgarch_archiveXlog(xlog)) {
|
||||
/* successful */
|
||||
pgarch_archiveDone(xlog);
|
||||
|
||||
/* archive xlog on standby success, we need to change the status of archive task. */
|
||||
ChangeArchiveTaskStatus2Done(xlog);
|
||||
break; /* out of inner retry loop */
|
||||
} else {
|
||||
if (++failures >= NUM_ARCHIVE_RETRIES) {
|
||||
|
|
@ -987,43 +935,6 @@ static void pgarch_archiveRoachForPitrStandby()
|
|||
}
|
||||
}
|
||||
|
||||
static void CreateArchiveReadyFile()
|
||||
{
|
||||
XLogRecPtr targetLsn = g_instance.archive_standby_cxt.archive_task.targetLsn;
|
||||
if (!XlogFileIsExisted(t_thrd.proc_cxt.DataDir, targetLsn, DEFAULT_TIMELINE_ID)) {
|
||||
ereport(WARNING, (errmsg("CreateArchiveReadyFile: the %X/%X is not exists, skipping",
|
||||
(uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
volatile unsigned int* arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
if (likely(pg_atomic_read_u32(arch_task_status) == ARCH_TASK_GET)) {
|
||||
pg_memory_barrier();
|
||||
g_instance.archive_standby_cxt.arch_finish_result = true;
|
||||
pg_atomic_write_u32(arch_task_status, ARCH_TASK_DONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
char xlogfname[MAXFNAMELEN];
|
||||
ereport(LOG, (errmsg("CreateArchiveReadyFile %X/%X", (uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
|
||||
XLogSegNo xlogSegno = 0;
|
||||
XLByteToSeg(targetLsn, xlogSegno);
|
||||
if (xlogSegno == InvalidXLogSegPtr) {
|
||||
g_instance.archive_standby_cxt.arch_finish_result = false;
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid Lsn: %lu", targetLsn)));
|
||||
}
|
||||
XLogFileName(xlogfname, DEFAULT_TIMELINE_ID, xlogSegno);
|
||||
|
||||
char tempPath[PATH_MAX] = {0};
|
||||
char srcPath[PATH_MAX + 1] = {0};
|
||||
int rc = snprintf_s(tempPath, PATH_MAX, PATH_MAX - 1, XLOGDIR "/%s", xlogfname);
|
||||
securec_check_ss(rc, "\0", "\0");
|
||||
char* retVal = realpath(tempPath, srcPath);
|
||||
if (retVal == NULL) {
|
||||
ereport(WARNING, (errmsg_internal("realpath src %s failed:%m\n", tempPath)));
|
||||
} else {
|
||||
XLogArchiveNotify(xlogfname);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pgarch_archiveRoachForPitrMaster
|
||||
* choose a walsender to send archive command
|
||||
|
|
@ -1181,88 +1092,3 @@ static void initLastTaskLsn()
|
|||
(uint32)(t_thrd.arch.pitr_task_last_lsn))));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to send the status of archiver
|
||||
*/
|
||||
static void SendArchiveThreadStatus(bool status)
|
||||
{
|
||||
if (!WalRcvIsOnline()) {
|
||||
return;
|
||||
}
|
||||
while(!SendArchiveThreadStatusInternal(status)) {
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("Notifing primary to update archive status is failed.")));
|
||||
pg_usleep(SEND_ARCHIVE_STATUS_INTERVAL);
|
||||
}
|
||||
ereport(LOG, (errmsg("Notifing primary to update archive status is success.")));
|
||||
}
|
||||
|
||||
static bool SendArchiveThreadStatusInternal(bool is_archive_activited)
|
||||
{
|
||||
ResetLatch(&t_thrd.arch.mainloop_latch);
|
||||
g_instance.archive_standby_cxt.archive_enabled = is_archive_activited;
|
||||
(void)gs_signal_send(g_instance.pid_cxt.WalReceiverPID, SIGUSR2);
|
||||
g_instance.archive_standby_cxt.arch_latch = &t_thrd.arch.mainloop_latch;
|
||||
int rc = WaitLatch(&t_thrd.arch.mainloop_latch,
|
||||
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
|
||||
(long)(UPDATE_STATUS_WAIT));
|
||||
if (rc & WL_POSTMASTER_DEATH) {
|
||||
gs_thread_exit(1);
|
||||
}
|
||||
if (rc & WL_TIMEOUT) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NotifyPrimaryArchiverActived(ThreadId* last_walrcv_pid, bool* sent_archive_status)
|
||||
{
|
||||
if (WalRcvIsOnline()) {
|
||||
/* last_walrcv_pid is used to check whether the primary node is switched over. */
|
||||
if (!(*sent_archive_status) || *last_walrcv_pid != g_instance.pid_cxt.WalReceiverPID) {
|
||||
SendArchiveThreadStatus(ARCHIVE_ON);
|
||||
*sent_archive_status = true;
|
||||
*last_walrcv_pid = g_instance.pid_cxt.WalReceiverPID;
|
||||
return true;
|
||||
}
|
||||
if (*sent_archive_status) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*sent_archive_status = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void NotifyPrimaryArchiverShutdown(bool sent_archive_status)
|
||||
{
|
||||
if (sent_archive_status) {
|
||||
SendArchiveThreadStatus(ARCHIVE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
static void ChangeArchiveTaskStatus2Done(const char* xlog)
|
||||
{
|
||||
if (IsServerModeStandby()) {
|
||||
char fname[MAXFNAMELEN];
|
||||
int segno = 0;
|
||||
XLogRecPtr targetLsn = g_instance.archive_standby_cxt.archive_task.targetLsn;
|
||||
XLByteToSeg(targetLsn, segno);
|
||||
XLogFileName(fname, DEFAULT_TIMELINE_ID, segno);
|
||||
if (strcmp(xlog, fname) != 0) {
|
||||
/*
|
||||
* The archived xlog is not the xlog required by the archive task.
|
||||
* Therefore, the archived xlog cannot be returned to the primary.
|
||||
*/
|
||||
ereport(LOG, (errmsg("\"%s\" is not archived target, no reply is sent", xlog)));
|
||||
return;
|
||||
}
|
||||
volatile unsigned int *arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
if (unlikely(pg_atomic_read_u32(arch_task_status) == ARCH_TASK_GET)) {
|
||||
pg_memory_barrier();
|
||||
g_instance.archive_standby_cxt.arch_finish_result = true;
|
||||
pg_atomic_write_u32(arch_task_status, ARCH_TASK_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -313,6 +313,10 @@ char g_bbox_dump_path[1024] = {0};
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define WalRcvIsOnline() \
|
||||
((g_instance.pid_cxt.WalReceiverPID != 0 && t_thrd.walreceiverfuncs_cxt.WalRcv && \
|
||||
t_thrd.walreceiverfuncs_cxt.WalRcv->isRuning))
|
||||
|
||||
#define DataRcvIsOnline() \
|
||||
((IS_DN_DUMMY_STANDYS_MODE() ? (g_instance.pid_cxt.DataReceiverPID != 0 && t_thrd.datareceiver_cxt.DataRcv && \
|
||||
t_thrd.datareceiver_cxt.DataRcv->isRuning) \
|
||||
|
|
@ -2791,6 +2795,7 @@ static int ServerLoop(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have lost the stats collector, try to start a new one */
|
||||
if (g_instance.pid_cxt.PgStatPID == 0 && (pmState == PM_RUN || pmState == PM_HOT_STANDBY) && !dummyStandbyMode)
|
||||
g_instance.pid_cxt.PgStatPID = pgstat_start();
|
||||
|
|
@ -4867,6 +4872,7 @@ static void reaper(SIGNAL_ARGS)
|
|||
#define LOOPHEADER() (exitstatus = (long)(intptr_t)status)
|
||||
|
||||
gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL);
|
||||
ReplicationSlot *obs_slot = NULL;
|
||||
ereport(DEBUG4, (errmsg_internal("reaping dead processes")));
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -5412,8 +5418,13 @@ static void reaper(SIGNAL_ARGS)
|
|||
LogChildExit(LOG, _("archiver process"), pid, exitstatus);
|
||||
|
||||
if (XLogArchivingActive()) {
|
||||
if (pmState == PM_RUN || pmState == PM_HOT_STANDBY || pmState == PM_RECOVERY) {
|
||||
if (pmState == PM_RUN) {
|
||||
g_instance.pid_cxt.PgArchPID = pgarch_start();
|
||||
}else if (pmState == PM_HOT_STANDBY) {
|
||||
obs_slot = getObsReplicationSlot();
|
||||
if (obs_slot != NULL) {
|
||||
g_instance.pid_cxt.PgArchPID = pgarch_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -490,24 +490,6 @@ static void knl_g_archive_obs_init(knl_g_archive_obs_context *archive_obs_cxt)
|
|||
INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), sizeof(ReplicationSlot));
|
||||
}
|
||||
|
||||
static void knl_g_archive_standby_init(knl_g_archive_standby_context* archive_standby_cxt)
|
||||
{
|
||||
Assert(archive_standby_cxt != NULL);
|
||||
errno_t rc = memset_s(archive_standby_cxt, sizeof(knl_g_archive_standby_context), 0, sizeof(knl_g_archive_standby_context));
|
||||
securec_check(rc, "\0", "\0");
|
||||
archive_standby_cxt->arch_task_status = 0;
|
||||
archive_standby_cxt->arch_finish_result = false;
|
||||
archive_standby_cxt->need_to_send_archive_status = false;
|
||||
|
||||
/* we don't need to use this parameter, but we should init it. */
|
||||
archive_standby_cxt->archive_task.sub_term = -1;
|
||||
archive_standby_cxt->archive_task.term = 0;
|
||||
archive_standby_cxt->archive_task.targetLsn = 0;
|
||||
|
||||
archive_standby_cxt->archive_enabled = false;
|
||||
archive_standby_cxt->arch_latch = NULL;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MOT
|
||||
static void knl_g_mot_init(knl_g_mot_context* mot_cxt)
|
||||
{
|
||||
|
|
@ -592,7 +574,6 @@ void knl_instance_init()
|
|||
knl_g_wal_init(&g_instance.wal_cxt);
|
||||
knl_g_oid_nodename_cache_init(&g_instance.oid_nodename_cache);
|
||||
knl_g_archive_obs_init(&g_instance.archive_obs_cxt);
|
||||
knl_g_archive_standby_init(&g_instance.archive_standby_cxt);
|
||||
knl_g_hypo_init(&g_instance.hypo_cxt);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -532,8 +532,9 @@ static void XLogFlushCore(XLogRecPtr WriteRqstPtr);
|
|||
static void XLogSelfFlush(void);
|
||||
static void XLogSelfFlushWithoutStatus(int numHitsOnStartPage, XLogRecPtr CurrPos, int currLRC);
|
||||
|
||||
static void XLogArchiveNotify(const char *xlog);
|
||||
static void XLogArchiveNotifySeg(XLogSegNo segno);
|
||||
static bool HasBeenArchivedOnHaMode(const char* xlog);
|
||||
static bool XLogArchiveCheckDone(const char *xlog);
|
||||
static bool XLogArchiveIsBusy(const char *xlog);
|
||||
static bool XLogArchiveIsReady(const char *xlog);
|
||||
static void XLogArchiveCleanup(const char *xlog);
|
||||
|
|
@ -2325,7 +2326,7 @@ static uint64 XLogRecPtrToBytePos(XLogRecPtr ptr)
|
|||
* and the archiver then knows to archive XLOGDIR/0000000100000001000000C6,
|
||||
* then when complete, rename it to 0000000100000001000000C6.done
|
||||
*/
|
||||
void XLogArchiveNotify(const char *xlog)
|
||||
static void XLogArchiveNotify(const char *xlog)
|
||||
{
|
||||
char archiveStatusPath[MAXPGPATH];
|
||||
FILE *fd = NULL;
|
||||
|
|
@ -2430,20 +2431,12 @@ void XLogArchiveForceDone(const char *xlog)
|
|||
* The reason we do things this way is so that if the original attempt to
|
||||
* create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
|
||||
*/
|
||||
bool XLogArchiveCheckDone(const char *xlog)
|
||||
static bool XLogArchiveCheckDone(const char *xlog)
|
||||
{
|
||||
char archiveStatusPath[MAXPGPATH];
|
||||
struct stat stat_buf;
|
||||
errno_t errorno = EOK;
|
||||
|
||||
/* Only the primary need this step to check this xlog has been archived on standby.
|
||||
* If this xlog has been archived by all standby which start up the archive thread,
|
||||
* we should check weather the primary (if primary start up the archive s)
|
||||
*/
|
||||
if (!HasBeenArchivedOnHaMode(xlog)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Always deletable if archiving is off or in recovery process. Archiving is always disabled on standbys. */
|
||||
if (!XLogArchivingActive() || RecoveryInProgress()) {
|
||||
return true;
|
||||
|
|
@ -2475,66 +2468,6 @@ bool XLogArchiveCheckDone(const char *xlog)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool HasBeenArchivedOnHaMode(const char* xlog)
|
||||
{
|
||||
/*
|
||||
* Generally, the validity of the xlog transferred from the upper layer has been verified.
|
||||
* Therefore, if the length of the xlog name transferred is greater than the standard length
|
||||
* of the xlog name (24 characters), the transferred file is a .backup file.
|
||||
* Therefore, if the xlog name contains more than 24 characters, return true directly.
|
||||
*/
|
||||
if (strlen(xlog) > XLOG_NAME_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
|
||||
load_server_mode();
|
||||
int mode = t_thrd.xlog_cxt.server_mode;
|
||||
XLogRecPtr minium_lsn = PG_UINT64_MAX;
|
||||
|
||||
for (int i = 0; mode == PRIMARY_MODE && i < g_instance.attr.attr_storage.max_wal_senders; i++) {
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
volatile WalSnd* walsnd = &t_thrd.walsender_cxt.WalSndCtl->walsnds[i];
|
||||
if (walsnd == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SpinLockAcquire(&walsnd->mutex);
|
||||
if (IsValidArchiverStandby((WalSnd*)walsnd) &&
|
||||
walsnd->arch_task_last_lsn != 0 && walsnd->arch_task_last_lsn < minium_lsn) {
|
||||
minium_lsn = walsnd->arch_task_last_lsn;
|
||||
}
|
||||
SpinLockRelease(&walsnd->mutex);
|
||||
}
|
||||
|
||||
if (mode == STANDBY_MODE && XLogArchivingActive()) {
|
||||
XLogRecPtr target_lsn = g_instance.archive_standby_cxt.archive_task.targetLsn;
|
||||
minium_lsn = target_lsn;
|
||||
}
|
||||
|
||||
if (minium_lsn == PG_UINT64_MAX) {
|
||||
return true;
|
||||
}
|
||||
char minium_archived_xlog_name[MAXFNAMELEN];
|
||||
XLogSegNo xlogSegno = 0;
|
||||
XLByteToSeg(minium_lsn, xlogSegno);
|
||||
XLogFileName(minium_archived_xlog_name, DEFAULT_TIMELINE_ID, xlogSegno);
|
||||
|
||||
if (mode == STANDBY_MODE) {
|
||||
/*
|
||||
* targetLsn or start_point may be the xlog to be archived. Therefore,
|
||||
* the value of targetLsn or start_point must be smaller than minium_archived_xlog_name
|
||||
* to ensure that the xlog has been archived.
|
||||
*/
|
||||
return strcmp(xlog, minium_archived_xlog_name) < 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the input xlog name is smaller than or equal to the minium_archived_xlog_name,
|
||||
* we can confirm that the xlog has been archived by all standby nodes.
|
||||
*/
|
||||
return strcmp(xlog, minium_archived_xlog_name) <= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XLogArchiveIsBusy
|
||||
*
|
||||
|
|
|
|||
|
|
@ -631,14 +631,10 @@ bool SyncRepGetSyncRecPtr(XLogRecPtr *receivePtr, XLogRecPtr *writePtr, XLogRecP
|
|||
* or there are not enough synchronous standbys.
|
||||
* but in a particular scenario, when most_available_sync is true, primary only wait the alive sync standbys
|
||||
* if list_length(sync_standbys) doesn't satisfy t_thrd.syncrep_cxt.SyncRepConfig->num_sync.
|
||||
*
|
||||
* All synchronous standbys are allowed to disconnect from the host
|
||||
* only when the maximum available mode is on
|
||||
*/
|
||||
if ((!(*am_sync) && check_am_sync) || t_thrd.syncrep_cxt.SyncRepConfig == NULL ||
|
||||
(!t_thrd.walsender_cxt.WalSndCtl->most_available_sync &&
|
||||
list_length(sync_standbys) < t_thrd.syncrep_cxt.SyncRepConfig->num_sync) ||
|
||||
(t_thrd.walsender_cxt.WalSndCtl->most_available_sync && list_length(sync_standbys) == 0)) {
|
||||
list_length(sync_standbys) < t_thrd.syncrep_cxt.SyncRepConfig->num_sync)) {
|
||||
list_free(sync_standbys);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ static void XLogWalRcvWrite(WalRcvCtlBlock *walrcb, char *buf, Size nbytes, XLog
|
|||
* would otherwise have to reopen this file to fsync it later
|
||||
*/
|
||||
if (recvFile >= 0) {
|
||||
char xlogfname[MAXFNAMELEN];
|
||||
|
||||
/*
|
||||
* XLOG segment files will be re-read by recovery in startup
|
||||
* process soon, so we don't advise the OS to release cache
|
||||
|
|
@ -150,15 +152,12 @@ static void XLogWalRcvWrite(WalRcvCtlBlock *walrcb, char *buf, Size nbytes, XLog
|
|||
errmsg("could not close log file %s: %m",
|
||||
XLogFileNameP(t_thrd.xlog_cxt.ThisTimeLineID, recvSegNo))));
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
/*
|
||||
* Create .done file forcibly to prevent the restored segment from
|
||||
* being archived again later.
|
||||
*/
|
||||
char xlogfname[MAXFNAMELEN];
|
||||
XLogFileName(xlogfname, recvFileTLI, recvSegNo);
|
||||
XLogArchiveForceDone(xlogfname);
|
||||
#endif
|
||||
}
|
||||
recvFile = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -87,8 +87,6 @@ bool wal_catchup = false;
|
|||
|
||||
#define TEMP_CONF_FILE "postgresql.conf.bak"
|
||||
|
||||
#define MAX_PATH 256
|
||||
|
||||
const char *g_reserve_param[RESERVE_SIZE] = {
|
||||
"application_name",
|
||||
"archive_command",
|
||||
|
|
@ -169,7 +167,6 @@ static void WalRcvSigHupHandler(SIGNAL_ARGS);
|
|||
static void WalRcvShutdownHandler(SIGNAL_ARGS);
|
||||
static void WalRcvQuickDieHandler(SIGNAL_ARGS);
|
||||
static void sigusr1_handler(SIGNAL_ARGS);
|
||||
static void sigusr2_handler(SIGNAL_ARGS);
|
||||
static void ConfigFileTimer(void);
|
||||
static bool ProcessConfigFileMessage(char *buf, Size len);
|
||||
static void firstSynchStandbyFile(void);
|
||||
|
|
@ -178,12 +175,8 @@ static TimestampTz GetHeartbeatLastReplyTimestamp();
|
|||
static bool WalRecCheckTimeOut(TimestampTz nowtime, TimestampTz last_recv_timestamp, bool ping_sent);
|
||||
static void WalRcvRefreshPercentCountStartLsn(XLogRecPtr currentMaxLsn, XLogRecPtr currentDoneLsn);
|
||||
static void ProcessArchiveXlogMessage(const ArchiveXlogMessage* archive_xlog_message);
|
||||
static void ProcessStandbyArchiveXlogMessage(const ArchiveXlogMessage* archive_xlog_message);
|
||||
static void WalRecvSendArchiveXlogResponse();
|
||||
static void WalRecvSendArchiveXlogResult2Standby();
|
||||
static void SendArchiveStatus(bool status);
|
||||
static void ProcessArchiveStatusResponse(ArchiveStatusResponseMessage* response);
|
||||
static XLogRecPtr InitArchiveStartPoint();
|
||||
|
||||
void ProcessWalRcvInterrupts(void)
|
||||
{
|
||||
/*
|
||||
|
|
@ -306,15 +299,6 @@ void setObsArchLatch(const Latch* latch)
|
|||
SpinLockRelease(&walrcv->mutex);
|
||||
}
|
||||
|
||||
void SetStandbyArchLatch(const Latch* latch)
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv;
|
||||
SpinLockAcquire(&walrcv->mutex);
|
||||
walrcv->arch_latch = (Latch *)latch;
|
||||
SpinLockRelease(&walrcv->mutex);
|
||||
}
|
||||
|
||||
static void wakeupObsArchLatch()
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
|
|
@ -326,17 +310,6 @@ static void wakeupObsArchLatch()
|
|||
SpinLockRelease(&walrcv->mutex);
|
||||
}
|
||||
|
||||
static void wakeupArchLatch()
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv;
|
||||
SpinLockAcquire(&walrcv->mutex);
|
||||
if (walrcv->obsArchLatch != NULL) {
|
||||
SetLatch(walrcv->arch_latch);
|
||||
}
|
||||
SpinLockRelease(&walrcv->mutex);
|
||||
}
|
||||
|
||||
void RefuseConnect()
|
||||
{
|
||||
WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv;
|
||||
|
|
@ -404,20 +377,6 @@ void WalRcvrProcessData(TimestampTz *last_recv_timestamp, bool *ping_sent)
|
|||
pg_atomic_write_u32(pitr_task_status, PITR_TASK_NONE);
|
||||
}
|
||||
|
||||
/* send archive status to primary */
|
||||
if (g_instance.archive_standby_cxt.need_to_send_archive_status) {
|
||||
g_instance.archive_standby_cxt.need_to_send_archive_status = false;
|
||||
SendArchiveStatus(g_instance.archive_standby_cxt.archive_enabled);
|
||||
}
|
||||
|
||||
/* response the result of archive to primary */
|
||||
volatile unsigned int* arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
if (unlikely(pg_atomic_read_u32(arch_task_status) == ARCH_TASK_DONE)) {
|
||||
WalRecvSendArchiveXlogResult2Standby();
|
||||
pg_memory_barrier();
|
||||
pg_atomic_write_u32(arch_task_status, ARCH_TASK_NONE);
|
||||
}
|
||||
|
||||
if (!WalRcvWriterInProgress())
|
||||
ereport(FATAL, (errmsg("terminating walreceiver process due to the death of walrcvwriter")));
|
||||
|
||||
|
|
@ -593,7 +552,7 @@ void WalReceiverMain(void)
|
|||
(void)gspqsignal(SIGALRM, SIG_IGN);
|
||||
(void)gspqsignal(SIGPIPE, SIG_IGN);
|
||||
(void)gspqsignal(SIGUSR1, sigusr1_handler);
|
||||
(void)gspqsignal(SIGUSR2, sigusr2_handler);
|
||||
(void)gspqsignal(SIGUSR2, SIG_IGN);
|
||||
|
||||
/* Reset some signals that are accepted by postmaster but not here */
|
||||
(void)gspqsignal(SIGCHLD, SIG_DFL);
|
||||
|
|
@ -918,18 +877,6 @@ static void sigusr1_handler(SIGNAL_ARGS)
|
|||
errno = save_errno;
|
||||
}
|
||||
|
||||
static void sigusr2_handler(SIGNAL_ARGS) {
|
||||
/* get sigusr2 */
|
||||
int save_errno = errno;
|
||||
gs_signal_setmask(&t_thrd.libpq_cxt.BlockSig, NULL);
|
||||
/*
|
||||
* sending archive status to the primary in this step
|
||||
*/
|
||||
g_instance.archive_standby_cxt.need_to_send_archive_status = true;
|
||||
gs_signal_setmask(&t_thrd.libpq_cxt.UnBlockSig, NULL);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/* Wal receiver is shut down? */
|
||||
bool WalRcvIsShutdown(void)
|
||||
{
|
||||
|
|
@ -1085,25 +1032,6 @@ static void XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len)
|
|||
ProcessArchiveXlogMessage(&archiveXLogMessage);
|
||||
break;
|
||||
}
|
||||
case 'n' : /* process the archive task message sent by primary */
|
||||
{
|
||||
ArchiveXlogMessage archiveXLogMessage;
|
||||
CHECK_MSG_SIZE(len, ArchiveXlogMessage, "invalid ArchiveXlogMessage message received from primary");
|
||||
/* memcpy is required here for alignment reasons */
|
||||
errorno = memcpy_s(&archiveXLogMessage, sizeof(ArchiveXlogMessage), buf, sizeof(ArchiveXlogMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
ProcessStandbyArchiveXlogMessage(&archiveXLogMessage);
|
||||
break;
|
||||
}
|
||||
case 'S': /* send the status of the archive thread on standby */
|
||||
{
|
||||
ArchiveStatusResponseMessage response;
|
||||
CHECK_MSG_SIZE(len, ArchiveStatusResponseMessage, "invalid ArchiveStatusResponseMessage message received from primary");
|
||||
errorno = memcpy_s(&response, sizeof(ArchiveStatusResponseMessage), buf, sizeof(ArchiveStatusResponseMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
ProcessArchiveStatusResponse(&response);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||
errmsg_internal("invalid replication message type %c", type)));
|
||||
|
|
@ -1950,36 +1878,6 @@ static void ProcessArchiveXlogMessage(const ArchiveXlogMessage* archive_xlog_mes
|
|||
wakeupObsArchLatch();
|
||||
}
|
||||
|
||||
/*
|
||||
* Process ProcessStandbyArchiveXlogMessage received from primary sender, message type is 'n'.
|
||||
*/
|
||||
static void ProcessStandbyArchiveXlogMessage(const ArchiveXlogMessage* archive_xlog_message)
|
||||
{
|
||||
ereport(LOG, (errmsg("ProcessStandbyArchiveXlogMessage: get archive xlog message :%X/%X",
|
||||
(uint32)(archive_xlog_message->targetLsn >> 32), (uint32)(archive_xlog_message->targetLsn))));
|
||||
errno_t errorno = EOK;
|
||||
volatile unsigned int* arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
unsigned int expected = ARCH_TASK_NONE;
|
||||
int failed_times = 0;
|
||||
while (pg_atomic_compare_exchange_u32(arch_task_status, &expected, ARCH_TASK_GET) == false) {
|
||||
/* some task arrived before last task done if expected not equal to NONE */
|
||||
expected = ARCH_TASK_NONE;
|
||||
pg_usleep(ARCHIVE_XLOG_DELAY); // sleep 0.01s
|
||||
if (failed_times++ >= GET_ARCHIVE_XLOG_RETRY_MAX) {
|
||||
ereport(WARNING, (errmsg("get archive xlog message :%X/%X, but not finished",
|
||||
(uint32)(archive_xlog_message->targetLsn >> 32),
|
||||
(uint32)(archive_xlog_message->targetLsn))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
errorno = memcpy_s(&g_instance.archive_standby_cxt.archive_task,
|
||||
sizeof(ArchiveXlogMessage) + 1,
|
||||
archive_xlog_message,
|
||||
sizeof(ArchiveXlogMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
wakeupArchLatch();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send switchover request message to primary, indicating the current time.
|
||||
*/
|
||||
|
|
@ -2016,30 +1914,19 @@ static void XLogWalRcvSendSwitchRequest(void)
|
|||
*/
|
||||
static void WalRecvSendArchiveXlogResponse()
|
||||
{
|
||||
char buf[sizeof(ArchiveXlogResponseMessage) + 1];
|
||||
ArchiveXlogResponseMessage reply;
|
||||
char buf[sizeof(ArchiveXlogResponseMeeeage) + 1];
|
||||
ArchiveXlogResponseMeeeage reply;
|
||||
errno_t errorno = EOK;
|
||||
reply.pitr_result = g_instance.archive_obs_cxt.pitr_finish_result;
|
||||
reply.targetLsn = g_instance.archive_obs_cxt.archive_task.targetLsn;
|
||||
XLogSegNo segno = 0;
|
||||
char lastoff[MAXFNAMELEN];
|
||||
XLByteToSeg(reply.targetLsn, segno);
|
||||
XLogFileName(lastoff, reply.targetLsn, segno);
|
||||
if (!reply.pitr_result) {
|
||||
reply.archive_result = ARCHIVE_FAILED;
|
||||
} else if (XLogArchiveCheckDone(lastoff)) {
|
||||
reply.archive_result = ARCHIVE_SUCCESS;
|
||||
} else {
|
||||
reply.archive_result = ARCHIVE_SKIP;
|
||||
}
|
||||
|
||||
buf[0] = 'a';
|
||||
errorno = memcpy_s(&buf[1],
|
||||
sizeof(ArchiveXlogResponseMessage),
|
||||
sizeof(ArchiveXlogResponseMeeeage),
|
||||
&reply,
|
||||
sizeof(ArchiveXlogResponseMessage));
|
||||
sizeof(ArchiveXlogResponseMeeeage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
libpqrcv_send(buf, sizeof(ArchiveXlogResponseMessage) + 1);
|
||||
libpqrcv_send(buf, sizeof(ArchiveXlogResponseMeeeage) + 1);
|
||||
|
||||
ereport(LOG,
|
||||
(errmsg("WalRecvSendArchiveXlogResponse %d %X/%X", reply.pitr_result,
|
||||
|
|
@ -2047,30 +1934,6 @@ static void WalRecvSendArchiveXlogResponse()
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Send archive xlog result message to primary.
|
||||
*/
|
||||
static void WalRecvSendArchiveXlogResult2Standby()
|
||||
{
|
||||
char buf[sizeof(ArchiveXlogResponseMessage) + 1];
|
||||
ArchiveXlogResponseMessage reply;
|
||||
errno_t errorno = EOK;
|
||||
reply.pitr_result = g_instance.archive_standby_cxt.arch_finish_result;
|
||||
reply.targetLsn = g_instance.archive_standby_cxt.archive_task.targetLsn;
|
||||
buf[0] = 'n';
|
||||
errorno = memcpy_s(&buf[1],
|
||||
sizeof(ArchiveXlogResponseMessage),
|
||||
&reply,
|
||||
sizeof(ArchiveXlogResponseMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
libpqrcv_send(buf, sizeof(ArchiveXlogResponseMessage) + 1);
|
||||
const char* archive_result_string = ((reply.pitr_result) ? "success" : "fail");
|
||||
ereport(LOG,
|
||||
(errmsg("WalRecvSendArchiveXlogResult2Standby archive_result:%s archive_lsn:%X/%X", archive_result_string,
|
||||
(uint32)(reply.targetLsn >> 32), (uint32)(reply.targetLsn))));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* process switchover response message from primary.
|
||||
*/
|
||||
|
|
@ -2878,77 +2741,3 @@ static void WalRcvRefreshPercentCountStartLsn(XLogRecPtr currentMaxLsn, XLogRecP
|
|||
WalRcvSetPercentCountStartLsn(currentDoneLsn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SendArchiveStatus
|
||||
* This function is used to notify the primary of
|
||||
* whether archiving is enabled for standby.
|
||||
*
|
||||
* If the value of status is true, archiving is enabled for the standby node.
|
||||
* Otherwise, archiving is disabled.
|
||||
*
|
||||
* The targetLsn is the minimum lsn which is not archived.
|
||||
*/
|
||||
static void SendArchiveStatus(bool status)
|
||||
{
|
||||
char buf[sizeof(ArchiveStatusMessage) + 1];
|
||||
ArchiveStatusMessage message;
|
||||
errno_t errorno = EOK;
|
||||
message.is_archive_activied = status;
|
||||
XLogRecPtr start_point = InitArchiveStartPoint();
|
||||
const char* status_string = status ? "on" : "off";
|
||||
ereport(LOG, (errmsg("the archive thread status is %s, and the start point of lsn is %X/%X",
|
||||
status_string, (uint32)(start_point >> 32), (uint32)start_point)));
|
||||
message.startLsn = start_point;
|
||||
buf[0] = 'S';
|
||||
errorno = memcpy_s(&buf[1],
|
||||
sizeof(ArchiveStatusMessage),
|
||||
&message,
|
||||
sizeof(ArchiveStatusMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
volatile unsigned int* arch_task_status = &g_instance.archive_standby_cxt.arch_task_status;
|
||||
pg_atomic_write_u32(arch_task_status, ARCH_TASK_NONE);
|
||||
libpqrcv_send(buf, sizeof(ArchiveStatusMessage) + 1);
|
||||
}
|
||||
|
||||
static void ProcessArchiveStatusResponse(ArchiveStatusResponseMessage* response)
|
||||
{
|
||||
ereport(LOG, (errmsg("get updating archive status response")));
|
||||
bool is_success = response->is_set_status_success;
|
||||
if (is_success) {
|
||||
SetLatch(g_instance.archive_standby_cxt.arch_latch);
|
||||
} else {
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("it is failed to notify the primary that updating the archive status of standby")));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* InitArchiveStartPoint is used to find a start point which is the standby should check
|
||||
*/
|
||||
static XLogRecPtr InitArchiveStartPoint()
|
||||
{
|
||||
XLogRecPtr flushPtr = t_thrd.walreceiverfuncs_cxt.WalRcv->walRcvCtlBlock->flushPtr;
|
||||
XLogRecPtr targetLsn = flushPtr - XLogSegSize;
|
||||
|
||||
/*
|
||||
* Start from the previous xlog file of the flushptr.
|
||||
* If the xlog file exists, it traverses backwards until the xlog file is archived.
|
||||
* The next file is the oldest xlog file that has not been archived.
|
||||
*/
|
||||
while (XlogFileIsExisted(t_thrd.proc_cxt.DataDir, targetLsn, DEFAULT_TIMELINE_ID)) {
|
||||
int errorno = 0;
|
||||
XLogSegNo segno = 0;
|
||||
char lastoff[MAXFNAMELEN];
|
||||
XLByteToSeg(targetLsn, segno);
|
||||
errorno = snprintf_s(lastoff, MAXFNAMELEN, MAXFNAMELEN - 1, "%08X%08X%08X", t_thrd.xlog_cxt.ThisTimeLineID,
|
||||
(uint32)((segno) / XLogSegmentsPerXLogId), (uint32)((segno) % XLogSegmentsPerXLogId));
|
||||
|
||||
if (XLogArchiveCheckDone(lastoff)) {
|
||||
return targetLsn + XLogSegSize;
|
||||
}
|
||||
targetLsn -= XLogSegSize;
|
||||
}
|
||||
return targetLsn + XLogSegSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,8 +116,6 @@ long g_logical_slot_sleep_time = 0;
|
|||
|
||||
#define AmWalSenderToDummyStandby() (t_thrd.walsender_cxt.MyWalSnd->sendRole == SNDROLE_PRIMARY_DUMMYSTANDBY)
|
||||
#define AmWalSenderOnDummyStandby() (t_thrd.walsender_cxt.MyWalSnd->sendRole == SNDROLE_DUMMYSTANDBY_STANDBY)
|
||||
#define TIME_GET_MILLISEC(t) (((long)(t).tv_sec * 1000) + ((long)(t).tv_usec) / 1000)
|
||||
#define WAIT_FOR_ARCHIVE_TIME 10000L
|
||||
|
||||
/*
|
||||
* calculate catchup late every 1000ms
|
||||
|
|
@ -219,14 +217,7 @@ static void WalSndSetPercentCountStartLsn(XLogRecPtr startLsn);
|
|||
static void WalSndRefreshPercentCountStartLsn(XLogRecPtr currentMaxLsn, XLogRecPtr currentDoneLsn);
|
||||
static void set_xlog_location(ServerMode local_role, XLogRecPtr* sndWrite, XLogRecPtr* sndFlush, XLogRecPtr* sndReplay);
|
||||
static void ProcessArchiveFeedbackMessage(void);
|
||||
static void ProcessStandbyArchiveFeedbackMessage(void);
|
||||
static void WalSndArchiveXlog(XLogRecPtr targetLsn, int sub_term);
|
||||
static void WalSndSendArchiveLsn2Standby(XLogRecPtr targetLsn);
|
||||
static void ArchiveXlogOnStandby(XLogRecPtr targetLsn);
|
||||
static void SendLsn2Standby(XLogRecPtr targetLsn);
|
||||
static void CheckStandbyFinishArchive(XLogRecPtr targetLsn);
|
||||
static void ProcessArchiveStatusMessage();
|
||||
static void ResponseArchiveStatusMessage();
|
||||
static void CalCatchupRate();
|
||||
|
||||
char *DataDir = ".";
|
||||
|
|
@ -2108,15 +2099,6 @@ static void ProcessStandbyMessage(void)
|
|||
case 'a':
|
||||
ProcessArchiveFeedbackMessage();
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
ProcessStandbyArchiveFeedbackMessage();
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
ProcessArchiveStatusMessage();
|
||||
break;
|
||||
|
||||
default:
|
||||
ereport(COMMERROR,
|
||||
(errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unexpected message type \"%d\"", msgtype)));
|
||||
|
|
@ -2553,9 +2535,9 @@ static void ProcessStandbySwitchRequestMessage(void)
|
|||
static void ProcessArchiveFeedbackMessage(void)
|
||||
{
|
||||
volatile WalSnd *walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
ArchiveXlogResponseMessage reply;
|
||||
ArchiveXlogResponseMeeeage reply;
|
||||
/* Decipher the reply message */
|
||||
pq_copymsgbytes(t_thrd.walsender_cxt.reply_message, (char*)&reply, sizeof(ArchiveXlogResponseMessage));
|
||||
pq_copymsgbytes(t_thrd.walsender_cxt.reply_message, (char*)&reply, sizeof(ArchiveXlogResponseMeeeage));
|
||||
ereport(LOG,
|
||||
(errmsg("ProcessArchiveFeedbackMessage %d %X/%X", reply.pitr_result,
|
||||
(uint32)(reply.targetLsn >> 32), (uint32)(reply.targetLsn))));
|
||||
|
|
@ -2574,59 +2556,6 @@ static void ProcessArchiveFeedbackMessage(void)
|
|||
SetLatch(walsnd->arch_latch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the feedback to check is the standby archive successful
|
||||
*/
|
||||
static void ProcessStandbyArchiveFeedbackMessage(void)
|
||||
{
|
||||
volatile WalSnd *walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
ArchiveXlogResponseMessage reply;
|
||||
/* Decipher the reply message */
|
||||
pq_copymsgbytes(t_thrd.walsender_cxt.reply_message, (char*)&reply, sizeof(ArchiveXlogResponseMessage));
|
||||
if (reply.pitr_result && reply.archive_result == ARCHIVE_SKIP) {
|
||||
ereport(WARNING,
|
||||
(errmsg("ProcessArchiveFeedbackMessage: %X/%X has been removed in the standby, skip it.",
|
||||
(uint32)(reply.targetLsn >> 32), (uint32)(reply.targetLsn))));
|
||||
} else {
|
||||
ereport(LOG,
|
||||
(errmsg("ProcessArchiveFeedbackMessage %d %X/%X", reply.pitr_result,
|
||||
(uint32)(reply.targetLsn >> 32), (uint32)(reply.targetLsn))));
|
||||
}
|
||||
walsnd->arch_finish_result = reply.pitr_result;
|
||||
walsnd->archive_target_lsn = reply.targetLsn;
|
||||
}
|
||||
|
||||
static void ProcessArchiveStatusMessage()
|
||||
{
|
||||
volatile WalSnd *walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
ArchiveStatusMessage message;
|
||||
pq_copymsgbytes(t_thrd.walsender_cxt.reply_message, (char*)&message, sizeof(ArchiveStatusMessage));
|
||||
walsnd->is_start_archive = message.is_archive_activied;
|
||||
if (message.startLsn == 0) {
|
||||
XLogRecPtr receivePtr;
|
||||
XLogRecPtr writePtr;
|
||||
XLogRecPtr flushPtr;
|
||||
XLogRecPtr replayPtr;
|
||||
bool amSync = false;
|
||||
bool got_recptr = false;
|
||||
got_recptr = SyncRepGetSyncRecPtr(&receivePtr, &writePtr, &flushPtr, &replayPtr, &amSync, false);
|
||||
if (got_recptr) {
|
||||
walsnd->arch_task_last_lsn = flushPtr;
|
||||
} else {
|
||||
ereport(ERROR,
|
||||
(errmsg("ProcessArchiveStatusMessage failed when call SyncRepGetSyncRecPtr")));
|
||||
}
|
||||
}
|
||||
|
||||
if (walsnd->arch_task_last_lsn < message.startLsn) {
|
||||
walsnd->arch_task_last_lsn = message.startLsn;
|
||||
}
|
||||
ereport(LOG,
|
||||
(errmsg("ProcessArchiveStatusMessage: reset last task lsn to %X/%X",
|
||||
(uint32)(walsnd->arch_task_last_lsn >> 32), (uint32)(walsnd->arch_task_last_lsn))));
|
||||
ResponseArchiveStatusMessage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the limit for sleep_count, it is based on sleep time.
|
||||
*/
|
||||
|
|
@ -3203,42 +3132,6 @@ static int WalSndLoop(WalSndSendDataCallback send_data)
|
|||
/* Check for input from the client */
|
||||
ProcessRepliesIfAny();
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
/* Only the primary can send the archive lsn to standby */
|
||||
load_server_mode();
|
||||
if (t_thrd.xlog_cxt.server_mode == PRIMARY_MODE && IsValidArchiverStandby(t_thrd.walsender_cxt.MyWalSnd)) {
|
||||
XLogRecPtr receivePtr;
|
||||
XLogRecPtr writePtr;
|
||||
XLogRecPtr flushPtr;
|
||||
XLogRecPtr replayPtr;
|
||||
bool amSync = false;
|
||||
bool got_recptr = false;
|
||||
List* sync_standbys = SyncRepGetSyncStandbys(&amSync);
|
||||
int standby_nums = list_length(sync_standbys);
|
||||
list_free(sync_standbys);
|
||||
got_recptr = SyncRepGetSyncRecPtr(&receivePtr, &writePtr, &flushPtr, &replayPtr, &amSync, false);
|
||||
if (got_recptr) {
|
||||
ArchiveXlogOnStandby(flushPtr);
|
||||
} else if (t_thrd.syncrep_cxt.SyncRepConfig == NULL ||
|
||||
u_sess->attr.attr_storage.guc_synchronous_commit <= SYNCHRONOUS_COMMIT_LOCAL_FLUSH ||
|
||||
(t_thrd.walsender_cxt.WalSndCtl->most_available_sync && standby_nums == 0)) {
|
||||
/*
|
||||
* This step is used to deal with the situation that synchronous standbys are not set.
|
||||
*/
|
||||
ArchiveXlogOnStandby(t_thrd.walsender_cxt.MyWalSnd->flush);
|
||||
} else {
|
||||
ereport(WARNING, (errcode(ERRCODE_WARNING),
|
||||
errmsg("ArchiveXlogOnStandby failed when call SyncRepGetSyncRecPtr")));
|
||||
}
|
||||
}
|
||||
|
||||
volatile unsigned int *standby_archive_flag = &t_thrd.walsender_cxt.MyWalSnd->standby_archive_flag;
|
||||
if (unlikely(pg_atomic_read_u32(standby_archive_flag) == 1)) {
|
||||
WalSndSendArchiveLsn2Standby(t_thrd.walsender_cxt.MyWalSnd->arch_task_lsn);
|
||||
pg_atomic_write_u32(standby_archive_flag, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Walsender first startup, send a keepalive to standby, no need reply. */
|
||||
if (first_startup) {
|
||||
WalSndKeepalive(false);
|
||||
|
|
@ -3710,12 +3603,6 @@ static void InitWalSnd(void)
|
|||
walsnd->replSender = false;
|
||||
walsnd->peer_role = UNKNOWN_MODE;
|
||||
walsnd->peer_state = NORMAL_STATE;
|
||||
walsnd->is_start_archive = false;
|
||||
walsnd->archive_target_lsn = 0;
|
||||
walsnd->arch_task_last_lsn = 0;
|
||||
walsnd->arch_finish_result = false;
|
||||
walsnd->has_sent_arch_lsn = false;
|
||||
walsnd->last_send_lsn_time = 0;
|
||||
walsnd->channel_get_replc = 0;
|
||||
rc = memset_s((void *)&walsnd->receive, sizeof(XLogRecPtr), 0, sizeof(XLogRecPtr));
|
||||
securec_check(rc, "", "");
|
||||
|
|
@ -5159,31 +5046,6 @@ static void WalSndArchiveXlog(XLogRecPtr targetLsn, int sub_term)
|
|||
(void)pq_putmessage_noblock('d', t_thrd.walsender_cxt.output_xlog_message, sizeof(ArchiveXlogMessage) + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* send archive lsn to standby
|
||||
*/
|
||||
static void WalSndSendArchiveLsn2Standby(XLogRecPtr targetLsn)
|
||||
{
|
||||
ArchiveXlogMessage archive_message;
|
||||
errno_t errorno = EOK;
|
||||
ereport(LOG,
|
||||
(errmsg("WalSndSendArchiveLsn2Standby %X/%X", (uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
|
||||
archive_message.targetLsn = targetLsn;
|
||||
|
||||
/* Prepend with the message type and send it. */
|
||||
t_thrd.walsender_cxt.output_xlog_message[0] = 'n';
|
||||
errorno = memcpy_s(t_thrd.walsender_cxt.output_xlog_message + 1,
|
||||
sizeof(ArchiveXlogMessage) + WS_MAX_SEND_SIZE,
|
||||
&archive_message,
|
||||
sizeof(ArchiveXlogMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
(void)pq_putmessage_noblock('d', t_thrd.walsender_cxt.output_xlog_message, sizeof(ArchiveXlogMessage) + 1);
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
t_thrd.walsender_cxt.MyWalSnd->last_send_lsn_time = TIME_GET_MILLISEC(tv);
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't currently used for anything. Monitoring tools might be
|
||||
* interested in the future, and we'll need something like this in the
|
||||
|
|
@ -5623,106 +5485,6 @@ XLogSegNo WalGetSyncCountWindow(void)
|
|||
return (XLogSegNo)(uint32)u_sess->attr.attr_storage.wal_keep_segments;
|
||||
}
|
||||
|
||||
static void ArchiveXlogOnStandby(XLogRecPtr flushLsn)
|
||||
{
|
||||
/* Check whether the active node is connected to the standby node. */
|
||||
volatile WalSnd* walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
|
||||
/*
|
||||
* Check whether the size of the newly archived xlog file is greater than that of the last archived xlog file.
|
||||
* If the size is greater than the xlog size, the system sends an archive LSN to the standby node for archiving.
|
||||
*/
|
||||
if ((flushLsn - walsnd->arch_task_last_lsn ) > XLogSegSize) {
|
||||
XLogRecPtr targetLsn;
|
||||
targetLsn = Min(walsnd->arch_task_last_lsn + XLogSegSize -
|
||||
(walsnd->arch_task_last_lsn % XLogSegSize) - 1,
|
||||
flushLsn);
|
||||
if (walsnd->arch_task_last_lsn == targetLsn) {
|
||||
targetLsn = Min(targetLsn + XLogSegSize, flushLsn);
|
||||
}
|
||||
if (!walsnd->has_sent_arch_lsn) {
|
||||
SendLsn2Standby(targetLsn);
|
||||
} else {
|
||||
CheckStandbyFinishArchive(targetLsn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SendLsn2Standby
|
||||
*
|
||||
* Sending the lsn which is need to be archived by standby.
|
||||
* It will return true if send archive lsn successful.
|
||||
*/
|
||||
static void SendLsn2Standby(XLogRecPtr targetLsn)
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
volatile WalSnd* walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
if (walsnd == NULL) {
|
||||
/* send failed, walsnd is null */
|
||||
return;
|
||||
}
|
||||
ereport(LOG,
|
||||
(errmsg("the lsn which is ready to be sent is: \"%X/%X\"",
|
||||
(uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
walsnd->has_sent_arch_lsn = true;
|
||||
if (!XLogRecPtrIsInvalid(walsnd->flush) && XLByteLE(targetLsn, walsnd->flush)) {
|
||||
walsnd->arch_task_lsn = targetLsn;
|
||||
pg_atomic_write_u32(&walsnd->standby_archive_flag, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CheckStandbyFinishArchive
|
||||
*
|
||||
* check the targetLsn and g_instance.archive_obs_cxt.archive_task.targetLsn for deal message with wrong order
|
||||
*/
|
||||
static void CheckStandbyFinishArchive(XLogRecPtr targetLsn)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
volatile WalSnd* walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
long time_diff = (long)TIME_GET_MILLISEC(tv) - walsnd->last_send_lsn_time;
|
||||
if (walsnd->arch_finish_result == false && time_diff > WAIT_FOR_ARCHIVE_TIME) {
|
||||
walsnd->has_sent_arch_lsn = false;
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("transaction xlog file \"%X/%X\" could not be archived: try again",
|
||||
(uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
return;
|
||||
}
|
||||
if (walsnd->arch_finish_result == true) {
|
||||
/* reset result flag */
|
||||
if (XLByteEQ(walsnd->archive_target_lsn, targetLsn)) {
|
||||
walsnd->arch_finish_result = false;
|
||||
walsnd->arch_task_last_lsn = targetLsn;
|
||||
ereport(LOG, (errmsg("the archive time is %.2lf seconds,last archive lsn change to \"%X/%X\"",
|
||||
((double)time_diff / 1000), (uint32)(targetLsn >> 32), (uint32)(targetLsn))));
|
||||
}
|
||||
walsnd->has_sent_arch_lsn = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void ResponseArchiveStatusMessage()
|
||||
{
|
||||
char msgbuf[sizeof(ArchiveStatusResponseMessage) + 1];
|
||||
msgbuf[0] = 'S';
|
||||
ArchiveStatusResponseMessage response;
|
||||
volatile WalSnd *walsnd = t_thrd.walsender_cxt.MyWalSnd;
|
||||
errno_t errorno = EOK;
|
||||
|
||||
if (walsnd == NULL)
|
||||
return;
|
||||
|
||||
ereport(LOG,(errmsg("sending archive status response message")));
|
||||
|
||||
/* Prepend with the message type and send it. */
|
||||
response.is_set_status_success = true;
|
||||
errorno = memcpy_s(&msgbuf[1], sizeof(ArchiveStatusResponseMessage),
|
||||
&response, sizeof(ArchiveStatusResponseMessage));
|
||||
securec_check(errorno, "\0", "\0");
|
||||
(void)pq_putmessage_noblock('d', msgbuf, sizeof(ArchiveStatusResponseMessage) + 1);
|
||||
}
|
||||
/*
|
||||
* Calculate catchup rate of standby to estimate how long
|
||||
* the standby will be caught up with primary.
|
||||
|
|
@ -5753,17 +5515,3 @@ static void CalCatchupRate() {
|
|||
}
|
||||
SpinLockRelease(&walsnd->mutex);
|
||||
}
|
||||
|
||||
/* Check whether the standby node corresponding to the walsnd is a valid standby node for xlog archiving. */
|
||||
bool IsValidArchiverStandby(WalSnd* walsnd)
|
||||
{
|
||||
if (walsnd == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (walsnd->pid != 0 && ((walsnd->sendRole & SNDROLE_PRIMARY_STANDBY) == walsnd->sendRole) &&
|
||||
walsnd->is_start_archive) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -474,10 +474,6 @@ bool CheckForForceFinishRedoTrigger(TermFileData *term_file);
|
|||
|
||||
extern XLogRecPtr XlogRemoveSegPrimary;
|
||||
|
||||
void XLogArchiveNotify(const char *xlog);
|
||||
|
||||
bool XLogArchiveCheckDone(const char *xlog);
|
||||
|
||||
/* File path names (all relative to $PGDATA) */
|
||||
#define BACKUP_LABEL_FILE "backup_label"
|
||||
#define DISABLE_CONN_FILE "disable_conn_file"
|
||||
|
|
|
|||
|
|
@ -737,25 +737,6 @@ typedef struct knl_g_archive_obs_context {
|
|||
int sync_walsender_term;
|
||||
} knl_g_archive_obs_context;
|
||||
|
||||
typedef struct knl_g_archive_standby_context {
|
||||
/*
|
||||
* walreceiver set when get task from walsender
|
||||
* 0 for no task
|
||||
* 1 walreceive get task from walsender and set it for archive thread
|
||||
* 2 archive thread set when task is done
|
||||
*/
|
||||
volatile unsigned int arch_task_status;
|
||||
|
||||
/* archive thread set when archive done*/
|
||||
bool arch_finish_result;
|
||||
|
||||
/* for standby */
|
||||
ArchiveXlogMessage archive_task;
|
||||
bool need_to_send_archive_status;
|
||||
bool archive_enabled;
|
||||
Latch* arch_latch;
|
||||
} knl_g_archive_standby_context;
|
||||
|
||||
#ifdef ENABLE_MOT
|
||||
typedef struct knl_g_mot_context {
|
||||
JitExec::JitExecMode jitExecMode;
|
||||
|
|
@ -861,7 +842,6 @@ typedef struct knl_instance_context {
|
|||
knl_g_barrier_creator_context barrier_creator_cxt;
|
||||
knl_g_oid_nodename_mapping_cache oid_nodename_cache;
|
||||
knl_g_archive_obs_context archive_obs_cxt;
|
||||
knl_g_archive_standby_context archive_standby_cxt;
|
||||
struct HTAB* ngroup_hash_table;
|
||||
knl_g_hypo_context hypo_cxt;
|
||||
} knl_instance_context;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "knl/knl_guc.h"
|
||||
#include "knl/knl_session.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "replication/walprotocol.h"
|
||||
#include "storage/lock/s_lock.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "storage/latch.h"
|
||||
|
|
|
|||
|
|
@ -51,11 +51,6 @@ typedef enum ReplicationType {
|
|||
#define IS_DN_DUMMY_STANDYS_MODE() (g_instance.attr.attr_storage.replication_type == RT_WITH_DUMMY_STANDBY)
|
||||
#define IS_DN_WITHOUT_STANDBYS_MODE() (g_instance.attr.attr_storage.replication_type == RT_WITHOUT_STANDBY)
|
||||
|
||||
#define WalRcvIsOnline() \
|
||||
((g_instance.pid_cxt.WalReceiverPID != 0 && t_thrd.walreceiverfuncs_cxt.WalRcv && \
|
||||
t_thrd.walreceiverfuncs_cxt.WalRcv->isRuning))
|
||||
|
||||
|
||||
/*
|
||||
* We use a simple state machine to control startup, shutdown, and
|
||||
* crash recovery (which is rather like shutdown followed by startup).
|
||||
|
|
|
|||
|
|
@ -142,32 +142,13 @@ typedef struct ArchiveXlogMessage {
|
|||
} ArchiveXlogMessage;
|
||||
|
||||
/*
|
||||
* Refence :ArchiveXlogResponseMessage
|
||||
* Refence :ArchiveXlogResponseMeeeage
|
||||
*/
|
||||
typedef struct ArchiveXlogResponseMessage {
|
||||
typedef struct ArchiveXlogResponseMeeeage {
|
||||
bool pitr_result;
|
||||
XLogRecPtr targetLsn;
|
||||
unsigned int archive_result;
|
||||
} ArchiveXlogResponseMessage;
|
||||
} ArchiveXlogResponseMeeeage;
|
||||
|
||||
/* the result type of archive task */
|
||||
typedef enum {
|
||||
ARCHIVE_SUCCESS = 0,
|
||||
ARCHIVE_SKIP,
|
||||
ARCHIVE_FAILED
|
||||
} ARCH_RESULT_STATUS;
|
||||
|
||||
/*
|
||||
* Refence :ArchiveStatusMessage
|
||||
*/
|
||||
typedef struct ArchiveStatusMessage {
|
||||
bool is_archive_activied;
|
||||
XLogRecPtr startLsn;
|
||||
} ArchiveStatusMessage;
|
||||
|
||||
typedef struct ArchiveStatusResponseMessage {
|
||||
bool is_set_status_success;
|
||||
} ArchiveStatusResponseMessage;
|
||||
/*
|
||||
* Keepalive message from primary (message type 'k'). (lowercase k)
|
||||
* This is wrapped within a CopyData message at the FE/BE protocol level.
|
||||
|
|
@ -192,12 +173,6 @@ typedef enum {
|
|||
PITR_TASK_DONE
|
||||
} PITR_TASK_STATUS;
|
||||
|
||||
typedef enum {
|
||||
ARCH_TASK_NONE = 0,
|
||||
ARCH_TASK_GET,
|
||||
ARCH_TASK_DONE
|
||||
} ARCH_TASK_STATUS;
|
||||
|
||||
/*
|
||||
* switchover response message from primary (message type 'p'). This is wrapped within
|
||||
* a CopyData message at the FE/BE protocol level.
|
||||
|
|
|
|||
|
|
@ -193,11 +193,6 @@ typedef struct WalRcvData {
|
|||
char lastRecoveredBarrierId[MAX_BARRIER_ID_LENGTH];
|
||||
XLogRecPtr lastRecoveredBarrierLSN;
|
||||
Latch* obsArchLatch;
|
||||
bool archive_enabled;
|
||||
Latch* arch_latch;
|
||||
bool arch_finish_result;
|
||||
volatile unsigned int arch_task_status;
|
||||
ArchiveXlogMessage archive_task;
|
||||
} WalRcvData;
|
||||
|
||||
typedef struct WalReceiverFunc {
|
||||
|
|
@ -272,7 +267,6 @@ extern void set_failover_host_conninfo_for_dummy(const char *remote_host, int re
|
|||
extern void get_failover_host_conninfo_for_dummy(int *repl);
|
||||
extern void set_wal_rcv_write_rec_ptr(XLogRecPtr rec_ptr);
|
||||
extern void setObsArchLatch(const Latch* latch);
|
||||
extern void SetStandbyArchLatch(const Latch* latch);
|
||||
|
||||
|
||||
static inline void WalRcvCtlAcquireExitLock(void)
|
||||
|
|
|
|||
|
|
@ -60,8 +60,6 @@ extern bool WalSndAllInProgress(int type);
|
|||
extern bool WalSndQuorumInProgress(int type);
|
||||
extern XLogSegNo WalGetSyncCountWindow(void);
|
||||
|
||||
bool IsValidArchiverStandby(WalSnd* walsnd);
|
||||
|
||||
/*
|
||||
* Remember that we want to wakeup walsenders later
|
||||
*
|
||||
|
|
|
|||
|
|
@ -120,18 +120,6 @@ typedef struct WalSnd {
|
|||
LogCtrlData log_ctrl;
|
||||
unsigned int archive_flag;
|
||||
Latch* arch_latch;
|
||||
bool is_start_archive;
|
||||
unsigned int standby_archive_flag;
|
||||
XLogRecPtr archive_target_lsn;
|
||||
XLogRecPtr arch_task_last_lsn;
|
||||
bool arch_finish_result;
|
||||
|
||||
/*
|
||||
* has_sent_arch_lsn indicates whether the walsnd has sent the archive location,
|
||||
* and last_send_time is used to record the time when the archive location is sent last time.
|
||||
*/
|
||||
bool has_sent_arch_lsn;
|
||||
long last_send_lsn_time;
|
||||
|
||||
/*
|
||||
* lastCalTime is last time calculating catchupRate, and lastCalWrite
|
||||
|
|
|
|||
|
|
@ -51,5 +51,4 @@ llt_single/sql_llt_coverage
|
|||
llt_single/sequence_llt_coverage
|
||||
llt_single/temp_table_stop
|
||||
llt_single/text_search
|
||||
llt_single/xlog_redo
|
||||
llt_single/archive
|
||||
llt_single/xlog_redo
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
source ./standby_env.sh
|
||||
|
||||
function test_1()
|
||||
{
|
||||
check_instance
|
||||
stop_standby
|
||||
gs_guc set -D $standby_data_dir -c "archive_mode = on"
|
||||
gs_guc set -D $standby_data_dir -c "archive_dest = $standby_data_dir/archive_directory"
|
||||
start_standby
|
||||
#create table1
|
||||
gsql -d $db -p $dn1_primary_port -c "DROP TABLE if exists mpp_test1; CREATE TABLE mpp_test1(id INT);"
|
||||
for i in $(seq 1 10000)
|
||||
do
|
||||
gsql -d $db -p $dn1_primary_port -c "insert into mpp_test1 values($i);"
|
||||
done
|
||||
|
||||
stop_primary
|
||||
stop_standby
|
||||
|
||||
cp $standby_data_dir/archive_directory/* $primary_data_dir/pg_xlog
|
||||
cp $standby_data_dir/archive_directory/* $standby_data_dir/pg_xlog
|
||||
start_primary
|
||||
start_standby
|
||||
check_standby_startup
|
||||
}
|
||||
Loading…
Reference in New Issue