* Wait for any slot's connection to have query results, consume the results, * and update the slot's status as appropriate. Returns true on success, * false on cancellation, on error, or if no slots are connected. */
| 195 | * false on cancellation, on error, or if no slots are connected. |
| 196 | */ |
| 197 | static bool |
| 198 | wait_on_slots(ParallelSlotArray *sa) |
| 199 | { |
| 200 | int i; |
| 201 | fd_set slotset; |
| 202 | int maxFd = 0; |
| 203 | PGconn *cancelconn = NULL; |
| 204 | |
| 205 | /* We must reconstruct the fd_set for each call to select_loop */ |
| 206 | FD_ZERO(&slotset); |
| 207 | |
| 208 | for (i = 0; i < sa->numslots; i++) |
| 209 | { |
| 210 | int sock; |
| 211 | |
| 212 | /* We shouldn't get here if we still have slots without connections */ |
| 213 | Assert(sa->slots[i].connection != NULL); |
| 214 | |
| 215 | sock = PQsocket(sa->slots[i].connection); |
| 216 | |
| 217 | /* |
| 218 | * We don't really expect any connections to lose their sockets after |
| 219 | * startup, but just in case, cope by ignoring them. |
| 220 | */ |
| 221 | if (sock < 0) |
| 222 | continue; |
| 223 | |
| 224 | /* Keep track of the first valid connection we see. */ |
| 225 | if (cancelconn == NULL) |
| 226 | cancelconn = sa->slots[i].connection; |
| 227 | |
| 228 | FD_SET(sock, &slotset); |
| 229 | if (sock > maxFd) |
| 230 | maxFd = sock; |
| 231 | } |
| 232 | |
| 233 | /* |
| 234 | * If we get this far with no valid connections, processing cannot |
| 235 | * continue. |
| 236 | */ |
| 237 | if (cancelconn == NULL) |
| 238 | return false; |
| 239 | |
| 240 | SetCancelConn(sa->slots->connection); |
| 241 | i = select_loop(maxFd, &slotset); |
| 242 | ResetCancelConn(); |
| 243 | |
| 244 | /* failure? */ |
| 245 | if (i < 0) |
| 246 | return false; |
| 247 | |
| 248 | for (i = 0; i < sa->numslots; i++) |
| 249 | { |
| 250 | int sock; |
| 251 | |
| 252 | sock = PQsocket(sa->slots[i].connection); |
| 253 | |
| 254 | if (sock >= 0 && FD_ISSET(sock, &slotset)) |
no test coverage detected