* 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. */
| 1099 | * The caller must hold SyncRepLock in exclusive mode. |
| 1100 | */ |
| 1101 | int |
| 1102 | SyncRepWakeQueue(bool all, int mode) |
| 1103 | { |
| 1104 | volatile WalSndCtlData *walsndctl = WalSndCtl; |
| 1105 | PGPROC *proc = NULL; |
| 1106 | PGPROC *thisproc = NULL; |
| 1107 | int numprocs = 0; |
| 1108 | |
| 1109 | Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE); |
| 1110 | Assert(LWLockHeldByMeInMode(SyncRepLock, LW_EXCLUSIVE)); |
| 1111 | Assert(SyncRepQueueIsOrderedByLSN(mode)); |
| 1112 | |
| 1113 | proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]), |
| 1114 | &(WalSndCtl->SyncRepQueue[mode]), |
| 1115 | offsetof(PGPROC, syncRepLinks)); |
| 1116 | |
| 1117 | while (proc) |
| 1118 | { |
| 1119 | /* |
| 1120 | * Assume the queue is ordered by LSN |
| 1121 | */ |
| 1122 | if (!all && walsndctl->lsn[mode] < proc->waitLSN) |
| 1123 | return numprocs; |
| 1124 | |
| 1125 | /* |
| 1126 | * Move to next proc, so we can delete thisproc from the queue. |
| 1127 | * thisproc is valid, proc may be NULL after this. |
| 1128 | */ |
| 1129 | thisproc = proc; |
| 1130 | proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]), |
| 1131 | &(proc->syncRepLinks), |
| 1132 | offsetof(PGPROC, syncRepLinks)); |
| 1133 | |
| 1134 | /* |
| 1135 | * Remove thisproc from queue. |
| 1136 | */ |
| 1137 | SHMQueueDelete(&(thisproc->syncRepLinks)); |
| 1138 | |
| 1139 | /* |
| 1140 | * SyncRepWaitForLSN() reads syncRepState without holding the lock, so |
| 1141 | * make sure that it sees the queue link being removed before the |
| 1142 | * syncRepState change. |
| 1143 | */ |
| 1144 | pg_write_barrier(); |
| 1145 | |
| 1146 | /* |
| 1147 | * Set state to complete; see SyncRepWaitForLSN() for discussion of |
| 1148 | * the various states. |
| 1149 | */ |
| 1150 | thisproc->syncRepState = SYNC_REP_WAIT_COMPLETE; |
| 1151 | |
| 1152 | /* |
| 1153 | * Wake only when we have set state and removed from queue. |
| 1154 | */ |
| 1155 | SetLatch(&(thisproc->procLatch)); |
| 1156 | |
| 1157 | elogif(debug_walrepl_syncrep, LOG, |
| 1158 | "syncrep wakeup queue -- %d procid was removed from syncrep queue. " |
no test coverage detected