Parcourir la source

qdevice: Initial port to use pr-poll-loop

Only qdevice_instance_wait_for_initial_heuristics_exec_result is ported
for now.

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse il y a 5 ans
Parent
commit
7a4e9c59ee

+ 3 - 1
qdevices/Makefile.am

@@ -143,7 +143,9 @@ corosync_qdevice_SOURCES = corosync-qdevice.c \
                            process-list.h process-list.c \
                            qdevice-net-heuristics.c qdevice-net-heuristics.h \
                            qdevice-heuristics-result-notifier.c qdevice-heuristics-result-notifier.h \
-                           log.c log.h
+                           log.c log.h pr-poll-loop.c pr-poll-loop.h \
+                           qdevice-pr-poll-loop-cb.c qdevice-pr-poll-loop-cb.h \
+                           qdevice-pr-poll-loop.c qdevice-pr-poll-loop.h
 
 corosync_qdevice_tool_SOURCES = corosync-qdevice-tool.c unix-socket.c unix-socket.h dynar.c dynar.h \
                                 dynar-str.c dynar-str.h utils.c utils.h

+ 8 - 1
qdevices/corosync-qdevice.c

@@ -47,6 +47,8 @@
 #include "qdevice-ipc.h"
 #include "qdevice-log.h"
 #include "qdevice-model.h"
+#include "qdevice-pr-poll-loop.h"
+#include "qdevice-pr-poll-loop-cb.h"
 #include "qdevice-votequorum.h"
 #include "utils.h"
 
@@ -257,13 +259,18 @@ main(int argc, char * const argv[])
 		return (EXIT_FAILURE);
 	}
 
+	log(LOG_DEBUG, "Registering main poll loop callbacks");
+	if (qdevice_pr_poll_loop_cb_register(&instance) != 0) {
+		return (EXIT_FAILURE);
+	}
+
 	log(LOG_DEBUG, "Waiting for ring id");
 	if (qdevice_votequorum_wait_for_ring_id(&instance) != 0) {
 		return (EXIT_FAILURE);
 	}
 
 	log(LOG_DEBUG, "Waiting for initial heuristics exec result");
-	if (qdevice_instance_wait_for_initial_heuristics_exec_result(&instance) != 0) {
+	if (qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(&instance) != 0) {
 		return (EXIT_FAILURE);
 	}
 

+ 2 - 156
qdevices/qdevice-instance.c

@@ -39,10 +39,6 @@
 #include "qdevice-config.h"
 #include "qdevice-instance.h"
 #include "qdevice-heuristics-exec-list.h"
-/*TODO Remove this 3 line includes when porting on pr-poll-loop */
-#include "qdevice-heuristics.h"
-#include "qdevice-heuristics-cmd.h"
-#include "qdevice-votequorum.h"
 #include "qdevice-model.h"
 #include "utils.h"
 
@@ -57,6 +53,7 @@ qdevice_instance_init(struct qdevice_instance *instance,
 
 	instance->vq_last_poll = ((time_t) -1);
 	instance->advanced_settings = advanced_settings;
+	pr_poll_loop_init(&instance->main_poll_loop);
 
 	return (0);
 }
@@ -66,6 +63,7 @@ qdevice_instance_destroy(struct qdevice_instance *instance)
 {
 
 	node_list_free(&instance->config_node_list);
+	pr_poll_loop_destroy(&instance->main_poll_loop);
 
 	return (0);
 }
@@ -298,155 +296,3 @@ qdevice_instance_configure_from_cmap(struct qdevice_instance *instance)
 
 	return (0);
 }
-
-#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);
-}

+ 13 - 1
qdevices/qdevice-instance.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -47,6 +47,7 @@
 #include "qdevice-heuristics.h"
 #include "qdevice-model-type.h"
 #include "node-list.h"
+#include "pr-poll-loop.h"
 #include "unix-socket-ipc.h"
 
 #ifdef __cplusplus
@@ -118,6 +119,17 @@ struct qdevice_instance {
 	int sync_in_progress;
 
 	struct qdevice_heuristics_instance heuristics_instance;
+
+	struct pr_poll_loop main_poll_loop;
+
+	/*
+	 * Set by poll handler when votequorum connection is closed
+	 */
+	int votequorum_closed;
+	/*
+	 * Set by poll handler when one of the heuristics pipes becomes closed
+	 */
+	int heuristics_closed;
 };
 
 extern int	qdevice_instance_init(struct qdevice_instance *instance,

+ 190 - 0
qdevices/qdevice-pr-poll-loop-cb.c

@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log.h"
+#include "qdevice-heuristics-cmd.h"
+#include "qdevice-heuristics-log.h"
+#include "qdevice-pr-poll-loop-cb.h"
+#include "qdevice-votequorum.h"
+
+static int
+heuristics_pipe_log_recv_read_cb(int fd, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+	int res;
+
+	res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+	if (res == -1) {
+		instance->heuristics_closed = 1;
+		return (-1);
+	}
+
+	return (0);
+}
+
+/*
+ * Callback is shared for all heuristics pipes
+ */
+static int
+heuristics_pipe_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+
+	instance->heuristics_closed = 1;
+
+	/*
+	 * Closed pipe doesn't mean return of PR_POLL_READ. To display
+	 * better log message, we call read log as if POLLIN would
+	 * be set. Ignore error code because loop closes anyway.
+	 */
+	(void)qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+	log(LOG_DEBUG, "POLL_ERR (%u) on heuristics pipe. "
+	     "Disconnecting.",  revents);
+
+	return (-1);
+}
+
+static int
+heuristics_pipe_cmd_recv_read_cb(int fd, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+	int res;
+
+	res = qdevice_heuristics_cmd_read_from_pipe(&instance->heuristics_instance);
+	if (res == -1) {
+		instance->heuristics_closed = 1;
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+heuristics_pipe_cmd_send_set_events_cb(int fd, short *events, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+	int res;
+
+	res = -1;
+
+	if (!send_buffer_list_empty(&instance->heuristics_instance.cmd_out_buffer_list)) {
+		*events |= POLLOUT;
+		res = 0;
+	}
+
+	return (res);
+}
+
+static int
+heuristics_pipe_cmd_send_write_cb(int fd, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+	int res;
+
+	res = qdevice_heuristics_cmd_write(&instance->heuristics_instance);
+	if (res == -1) {
+		instance->heuristics_closed = 1;
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+votequorum_read_cb(int fd, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+	int res;
+
+	res = qdevice_votequorum_dispatch(instance);
+	if (res == -1) {
+		instance->votequorum_closed = 1;
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+votequorum_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+	struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+
+	instance->votequorum_closed = 1;
+
+	log(LOG_DEBUG, "POLL_ERR (%u) on corosync socket. "
+	     "Disconnecting.",  revents);
+
+	return (-1);
+}
+
+int
+qdevice_pr_poll_loop_cb_register(struct qdevice_instance *instance)
+{
+
+	if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_log_recv,
+	    POLLIN, NULL, heuristics_pipe_log_recv_read_cb, NULL, heuristics_pipe_err_cb,
+	    instance, NULL) != 0) {
+		log(LOG_ERR, "Can't add heuristics log pipe to main poll loop");
+
+		return (-1);
+	}
+
+	if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_cmd_recv,
+	    POLLIN, NULL, heuristics_pipe_cmd_recv_read_cb, NULL, heuristics_pipe_err_cb,
+	    instance, NULL) != 0) {
+		log(LOG_ERR, "Can't add heuristics cmd recv pipe to main poll loop");
+
+		return (-1);
+	}
+
+	if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_cmd_send,
+	    0, heuristics_pipe_cmd_send_set_events_cb, NULL,
+	    heuristics_pipe_cmd_send_write_cb, heuristics_pipe_err_cb,
+	    instance, NULL) != 0) {
+		log(LOG_ERR, "Can't add heuristics cmd send pipe to main poll loop");
+
+		return (-1);
+	}
+
+	if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->votequorum_poll_fd,
+	    POLLIN, NULL, votequorum_read_cb, NULL, votequorum_err_cb,
+	    instance, NULL) != 0) {
+		log(LOG_ERR, "Can't add votequorum fd to main poll loop");
+
+		return (-1);
+	}
+
+	return (0);
+}

+ 50 - 0
qdevices/qdevice-pr-poll-loop-cb.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_PR_POLL_LOOP_CB_H_
+#define _QDEVICE_PR_POLL_LOOP_CB_H_
+
+#include "qdevice-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int		qdevice_pr_poll_loop_cb_register(struct qdevice_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_PR_POLL_LOOP_CB_H_ */

+ 89 - 0
qdevices/qdevice-pr-poll-loop.c

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log.h"
+#include "qdevice-pr-poll-loop.h"
+#include "timer-list.h"
+
+static int
+wait_for_initial_heuristics_exec_result_timeout_timer_cb(void *data1, void *data2)
+{
+	int *timeout_called = (int *)data1;
+
+	*timeout_called = 1;
+
+	return (0);
+}
+
+int
+qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(struct qdevice_instance *instance)
+{
+	struct timer_list_entry *timeout_timer;
+	int timeout_called;
+	int poll_res;
+	PRUint32 timeout;
+
+	timeout_called = 0;
+
+	/*
+	 * We know this is never larger than QDEVICE_DEFAULT_HEURISTICS_MAX_TIMEOUT * 2
+	 */
+	timeout = (PRUint32)instance->heuristics_instance.sync_timeout * 2;
+
+	timeout_timer = timer_list_add(pr_poll_loop_get_timer_list(&instance->main_poll_loop),
+	    timeout, wait_for_initial_heuristics_exec_result_timeout_timer_cb,
+	    &timeout_called, NULL);
+
+	while ((poll_res = pr_poll_loop_exec(&instance->main_poll_loop)) == 0 &&
+	    !instance->vq_node_list_initial_heuristics_finished &&
+	    !timeout_called) {
+	}
+
+	if (poll_res == -2) {
+		log(LOG_CRIT, "Initial heuristics exec result poll failed - internal error");
+		return (-1);
+	} else if (poll_res == -3) {
+		log_nss(LOG_CRIT, "Initial heuristics exec result poll failed - PR_Poll error");
+		return (-1);
+	}
+
+	if (timeout_called) {
+		log(LOG_ERR, "Timeout waiting for initial heuristics exec result");
+		return (-1);
+	}
+
+	timer_list_delete(pr_poll_loop_get_timer_list(&instance->main_poll_loop), timeout_timer);
+
+	return (poll_res);
+}

+ 51 - 0
qdevices/qdevice-pr-poll-loop.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_PR_POLL_LOOP_H_
+#define _QDEVICE_PR_POLL_LOOP_H_
+
+#include "qdevice-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int		qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(
+    struct qdevice_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_PR_POLL_LOOP_H_ */