+
+#define QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS 5
+
+int
+qdevice_instance_wait_for_initial_heuristics_exec_result(struct qdevice_instance *instance)
+{
+ struct pollfd pfds[QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS];
+ int no_pfds;
+ int poll_res;
+ int timeout;
+ int i;
+ int case_processed;
+ int res;
+
+ while (!instance->vq_node_list_initial_heuristics_finished) {
+ no_pfds = 0;
+
+ assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
+ pfds[no_pfds].fd = instance->heuristics_instance.pipe_log_recv;
+ pfds[no_pfds].events = POLLIN;
+ pfds[no_pfds].revents = 0;
+ no_pfds++;
+
+ assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
+ pfds[no_pfds].fd = instance->heuristics_instance.pipe_cmd_recv;
+ pfds[no_pfds].events = POLLIN;
+ pfds[no_pfds].revents = 0;
+ no_pfds++;
+
+ assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
+ pfds[no_pfds].fd = instance->votequorum_poll_fd;
+ pfds[no_pfds].events = POLLIN;
+ pfds[no_pfds].revents = 0;
+ no_pfds++;
+
+ if (!send_buffer_list_empty(&instance->heuristics_instance.cmd_out_buffer_list)) {
+ assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
+ pfds[no_pfds].fd = instance->heuristics_instance.pipe_cmd_send;
+ pfds[no_pfds].events = POLLOUT;
+ pfds[no_pfds].revents = 0;
+ no_pfds++;
+ }
+
+ /*
+ * We know this is never larger than QDEVICE_DEFAULT_HEURISTICS_MAX_TIMEOUT * 2
+ */
+ timeout = (int)instance->heuristics_instance.sync_timeout * 2;
+
+ poll_res = poll(pfds, no_pfds, timeout);
+ if (poll_res > 0) {
+ for (i = 0; i < no_pfds; i++) {
+ if (pfds[i].revents & POLLIN) {
+ case_processed = 0;
+ switch (i) {
+ case 0:
+ case_processed = 1;
+
+ res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+ if (res == -1) {
+ return (-1);
+ }
+ break;
+ case 1:
+ case_processed = 1;
+ res = qdevice_heuristics_cmd_read_from_pipe(&instance->heuristics_instance);
+ if (res == -1) {
+ return (-1);
+ }
+ break;
+ case 2:
+ case_processed = 1;
+ res = qdevice_votequorum_dispatch(instance);
+ if (res == -1) {
+ return (-1);
+ }
+ case 3:
+ /*
+ * Read on heuristics cmd send fs shouldn't happen
+ */
+ break;
+ }
+
+ if (!case_processed) {
+ log(LOG_CRIT, "Unhandled read on poll descriptor %u", i);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (pfds[i].revents & POLLOUT) {
+ case_processed = 0;
+ switch (i) {
+ case 0:
+ case 1:
+ case 2:
+ /*
+ * Write on heuristics log, cmd recv or vq shouldn't happen
+ */
+ break;
+ case 3:
+ case_processed = 1;
+ res = qdevice_heuristics_cmd_write(&instance->heuristics_instance);
+ if (res == -1) {
+ return (-1);
+ }
+ break;
+ }
+
+ if (!case_processed) {
+ log(LOG_CRIT, "Unhandled write on poll descriptor %u", i);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if ((pfds[i].revents & (POLLERR|POLLHUP|POLLNVAL)) &&
+ !(pfds[i].revents & (POLLIN|POLLOUT))) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 3:
+ /*
+ * Closed pipe doesn't mean return of POLLIN. To display
+ * better log message, we call read log as if POLLIN would
+ * be set.
+ */
+ res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+ if (res == -1) {
+ return (-1);
+ }
+
+ log(LOG_ERR, "POLLERR (%u) on heuristics pipe. Exiting",
+ pfds[i].revents);
+ return (-1);
+ break;
+ case 2:
+ log(LOG_ERR, "POLLERR (%u) on corosync socket. Exiting",
+ pfds[i].revents);
+ return (-1);
+ break;
+ }
+ }
+ }
+ } else if (poll_res == 0) {
+ log(LOG_ERR, "Timeout waiting for initial heuristics exec result");
+ return (-1);
+ } else {
+ log_err(LOG_ERR, "Initial heuristics exec result poll failed");
+ return (-1);
+ }
+ }
+
+ return (0);
+}