=== Applying patches on top of PostgreSQL commit ID a9afa021e95f2b0ffaaf26f3a27e685f634f4ac9 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Mon Feb 2 07:50:28 UTC 2026 On branch cf/6404 nothing to commit, working tree clean === using 'git am' to apply patch ./v2-0001-Cascade-sync-rep.patch === Applying: Cascade sync rep Implemented cascaded synchronous replication support. The new SyncRepGetSendingSyncRecPtr function in syncrep.c computes replication status values by aggregating positions from synchronous standbys with local server positions. Furthermore, walsender processes can now prompt walreceiver processes for immediate feedback delivery to upstream replication sources. Using index info to reconstruct a base tree... M src/backend/replication/syncrep.c M src/backend/replication/walreceiver.c M src/backend/replication/walsender.c M src/include/access/xlogdefs.h M src/include/replication/syncrep.h M src/include/replication/walsender_private.h Falling back to patching base and 3-way merge... Auto-merging src/include/replication/walsender_private.h Auto-merging src/include/replication/syncrep.h Auto-merging src/include/access/xlogdefs.h Auto-merging src/backend/replication/walsender.c Auto-merging src/backend/replication/walreceiver.c Auto-merging src/backend/replication/syncrep.c === using 'git am' to apply patch ./v2-0002-Refactor-syncrep.patch === Applying: Refactor syncrep The code has been refactored to preserve the semantic sections in syncrep.c. Several functions have been reorganized and moved between different code sections to better align with their usage patterns and improve logical grouping. Using index info to reconstruct a base tree... M src/backend/replication/syncrep.c Falling back to patching base and 3-way merge... Auto-merging src/backend/replication/syncrep.c CONFLICT (content): Merge conflict in src/backend/replication/syncrep.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 Refactor syncrep The code has been refactored to preserve the semantic sections in syncrep.c. Several functions have been reorganized and moved between different code sections to better align with their usage patterns and improve logical grouping. When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Unstaged changes after reset: M src/backend/replication/syncrep.c === using patch(1) to apply patch ./v2-0002-Refactor-syncrep.patch === patching file src/backend/replication/syncrep.c Hunk #2 FAILED at 1077. Hunk #3 succeeded at 1353 (offset -1 lines). 1 out of 3 hunks FAILED -- saving rejects to file src/backend/replication/syncrep.c.rej Unstaged changes after reset: M src/backend/replication/syncrep.c Removing src/backend/replication/syncrep.c.rej === using 'git apply' to apply patch ./v2-0002-Refactor-syncrep.patch === Applied patch to 'src/backend/replication/syncrep.c' with conflicts. U src/backend/replication/syncrep.c diff --cc src/backend/replication/syncrep.c index 100fed96e0e,39d0e1d8d6f..00000000000 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@@ -833,205 -1077,6 +1076,208 @@@ standby_priority_comparator(const void return sa->walsnd_index - sb->walsnd_index; } ++<<<<<<< ours + +/* + * Check if we are in the list of sync standbys, and if so, determine + * priority sequence. Return priority if set, or zero to indicate that + * we are not a potential sync standby. + * + * Compare the parameter SyncRepStandbyNames against the application_name + * for this WALSender, or allow any name if we find a wildcard "*". + */ +static int +SyncRepGetStandbyPriority(void) +{ + const char *standby_name; + int priority; + bool found = false; + + /* + * Since synchronous cascade replication is not allowed, we always set the + * priority of cascading walsender to zero. + */ + + if (!SyncStandbysDefined() || SyncRepConfig == NULL) + return 0; + + standby_name = SyncRepConfig->member_names; + for (priority = 1; priority <= SyncRepConfig->nmembers; priority++) + { + if (pg_strcasecmp(standby_name, application_name) == 0 || + strcmp(standby_name, "*") == 0) + { + found = true; + break; + } + standby_name += strlen(standby_name) + 1; + } + + if (!found) + return 0; + + /* + * In quorum-based sync replication, all the standbys in the list have the + * same priority, one. + */ + return (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY) ? priority : 1; +} + +/* + * Walk the specified queue from head. Set the state of any backends that + * need to be woken, remove them from the queue, and then wake them. + * Pass all = true to wake whole queue; otherwise, just wake up to + * the walsender's LSN. + * + * The caller must hold SyncRepLock in exclusive mode. + */ +static int +SyncRepWakeQueue(bool all, int mode) +{ + volatile WalSndCtlData *walsndctl = WalSndCtl; + int numprocs = 0; + dlist_mutable_iter iter; + + Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE); + Assert(LWLockHeldByMeInMode(SyncRepLock, LW_EXCLUSIVE)); + Assert(SyncRepQueueIsOrderedByLSN(mode)); + + dlist_foreach_modify(iter, &WalSndCtl->SyncRepQueue[mode]) + { + PGPROC *proc = dlist_container(PGPROC, syncRepLinks, iter.cur); + + /* + * Assume the queue is ordered by LSN + */ + if (!all && walsndctl->lsn[mode] < proc->waitLSN) + return numprocs; + + /* + * Remove from queue. + */ + dlist_delete_thoroughly(&proc->syncRepLinks); + + /* + * SyncRepWaitForLSN() reads syncRepState without holding the lock, so + * make sure that it sees the queue link being removed before the + * syncRepState change. + */ + pg_write_barrier(); + + /* + * Set state to complete; see SyncRepWaitForLSN() for discussion of + * the various states. + */ + proc->syncRepState = SYNC_REP_WAIT_COMPLETE; + + /* + * Wake only when we have set state and removed from queue. + */ + SetLatch(&(proc->procLatch)); + + numprocs++; + } + + return numprocs; +} + +/* + * The checkpointer calls this as needed to update the shared + * sync_standbys_status flag, so that backends don't remain permanently wedged + * if synchronous_standby_names is unset. It's safe to check the current value + * without the lock, because it's only ever updated by one process. But we + * must take the lock to change it. + */ +void +SyncRepUpdateSyncStandbysDefined(void) +{ + bool sync_standbys_defined = SyncStandbysDefined(); + + if (sync_standbys_defined != + ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_DEFINED) != 0)) + { + LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); + + /* + * If synchronous_standby_names has been reset to empty, it's futile + * for backends to continue waiting. Since the user no longer wants + * synchronous replication, we'd better wake them up. + */ + if (!sync_standbys_defined) + { + int i; + + for (i = 0; i < NUM_SYNC_REP_WAIT_MODE; i++) + SyncRepWakeQueue(true, i); + } + + /* + * Only allow people to join the queue when there are synchronous + * standbys defined. Without this interlock, there's a race + * condition: we might wake up all the current waiters; then, some + * backend that hasn't yet reloaded its config might go to sleep on + * the queue (and never wake up). This prevents that. + */ + WalSndCtl->sync_standbys_status = SYNC_STANDBY_INIT | + (sync_standbys_defined ? SYNC_STANDBY_DEFINED : 0); + + LWLockRelease(SyncRepLock); + } + else if ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_INIT) == 0) + { + LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); + + /* + * Note that there is no need to wake up the queues here. We would + * reach this path only if SyncStandbysDefined() returns false, or it + * would mean that some backends are waiting with the GUC set. See + * SyncRepWaitForLSN(). + */ + Assert(!SyncStandbysDefined()); + + /* + * Even if there is no sync standby defined, let the readers of this + * information know that the sync standby data has been initialized. + * This can just be done once, hence the previous check on + * SYNC_STANDBY_INIT to avoid useless work. + */ + WalSndCtl->sync_standbys_status |= SYNC_STANDBY_INIT; + + LWLockRelease(SyncRepLock); + } +} + +#ifdef USE_ASSERT_CHECKING +static bool +SyncRepQueueIsOrderedByLSN(int mode) +{ + XLogRecPtr lastLSN; + dlist_iter iter; + + Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE); + + lastLSN = InvalidXLogRecPtr; + + dlist_foreach(iter, &WalSndCtl->SyncRepQueue[mode]) + { + PGPROC *proc = dlist_container(PGPROC, syncRepLinks, iter.cur); + + /* + * Check the queue is ordered by LSN and that multiple procs don't + * have matching LSNs + */ + if (proc->waitLSN <= lastLSN) + return false; + + lastLSN = proc->waitLSN; + } + + return true; +} +#endif + ++======= ++>>>>>>> theirs /* * =========================================================== * Synchronous Replication functions for wal receiver processes