* Wait for synchronous replication, if requested by user. * * Initially backends start in state SYNC_REP_NOT_WAITING and then * change that state to SYNC_REP_WAITING before adding ourselves * to the wait queue. During SyncRepWakeQueue() a WALSender changes * the state to SYNC_REP_WAIT_COMPLETE once replication is confirmed. * This backend then resets its state to SYNC_REP_NOT_WAITING. * *
| 183 | * autofailover. |
| 184 | */ |
| 185 | void |
| 186 | SyncRepWaitForLSN(XLogRecPtr lsn, bool commit) |
| 187 | { |
| 188 | char *new_status = NULL; |
| 189 | const char *old_status; |
| 190 | int mode; |
| 191 | #ifndef USE_INTERNAL_FTS |
| 192 | bool wal_all_streaming = false; |
| 193 | #endif |
| 194 | /* |
| 195 | * This should be called while holding interrupts during a transaction |
| 196 | * commit to prevent the follow-up shared memory queue cleanups to be |
| 197 | * influenced by external interruptions. |
| 198 | */ |
| 199 | Assert(InterruptHoldoffCount > 0); |
| 200 | |
| 201 | Assert(!am_walsender); |
| 202 | elogif(debug_walrepl_syncrep, LOG, |
| 203 | "syncrep wait -- This backend's commit LSN for syncrep is %X/%X.", |
| 204 | LSN_FORMAT_ARGS(lsn)); |
| 205 | |
| 206 | /* |
| 207 | * Fast exit if user has not requested sync replication, or there are no |
| 208 | * sync replication standby names defined. |
| 209 | * |
| 210 | * Since this routine gets called every commit time, it's important to |
| 211 | * exit quickly if sync replication is not requested. So we check |
| 212 | * WalSndCtl->sync_standbys_defined flag without the lock and exit |
| 213 | * immediately if it's false. If it's true, we need to check it again |
| 214 | * later while holding the lock, to check the flag and operate the sync |
| 215 | * rep queue atomically. This is necessary to avoid the race condition |
| 216 | * described in SyncRepUpdateSyncStandbysDefined(). On the other hand, if |
| 217 | * it's false, the lock is not necessary because we don't touch the queue. |
| 218 | */ |
| 219 | if (!SyncRepRequested() || |
| 220 | (!IS_QUERY_DISPATCHER() && !((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_defined)) |
| 221 | return; |
| 222 | |
| 223 | /* Cap the level for anything other than commit to remote flush only. */ |
| 224 | if (commit) |
| 225 | mode = SyncRepWaitMode; |
| 226 | else |
| 227 | mode = Min(SyncRepWaitMode, SYNC_REP_WAIT_FLUSH); |
| 228 | |
| 229 | Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks))); |
| 230 | Assert(WalSndCtl != NULL); |
| 231 | |
| 232 | LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); |
| 233 | Assert(MyProc->syncRepState == SYNC_REP_NOT_WAITING); |
| 234 | |
| 235 | /* |
| 236 | * GPDB special behavior: if the master/coordinator doesn't configure a standby, |
| 237 | * or the standby is down, or the connection between the master/coordinator and standby |
| 238 | * is broken, the xlog will not be synchronized to the standby before the key |
| 239 | * operations(PREPARE/COMMIT_PREPARED/COMMIT) continues. The only benefit is that |
| 240 | * when the network is unstable, the transaction will not be blocked. |
| 241 | */ |
| 242 | if (IS_QUERY_DISPATCHER()) |
no test coverage detected