[libvirt] [PATCH 1/4] virsh: Move job watch code to a separate function

Michal Privoznik mprivozn at redhat.com
Tue Dec 20 15:21:08 UTC 2011


called do_watch_job. This can be later used in other
job oriented commands like dump, save, managedsave
to report progress and allow user to cancel via ^C.
---
 tools/virsh.c |  187 ++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 113 insertions(+), 74 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index 583ec6d..5f9a9ff 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -394,6 +394,27 @@ static char *editWriteToTempFile (vshControl *ctl, const char *doc);
 static int   editFile (vshControl *ctl, const char *filename);
 static char *editReadBackFile (vshControl *ctl, const char *filename);
 
+/* Typedefs, function prototypes for job progress reporting.
+ * There are used by some long lingering commands like
+ * migrate, dump, save, managedsave.
+ */
+typedef struct __vshCtrlData {
+    vshControl *ctl;
+    const vshCmd *cmd;
+    int writefd;
+} vshCtrlData;
+
+typedef void (*jobWatchTimeoutFunc) (vshControl *ctl, virDomainPtr dom);
+
+static bool
+do_watch_job(vshControl *ctl,
+             virDomainPtr dom,
+             bool verbose,
+             int pipe_fd,
+             int timeout,
+             jobWatchTimeoutFunc timeout_func,
+             const char *label);
+
 static void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
 #define vshMalloc(_ctl, _sz)    _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
 
@@ -5720,12 +5741,6 @@ static const vshCmdOptDef opts_migrate[] = {
     {NULL, 0, 0, NULL}
 };
 
-typedef struct __vshCtrlData {
-    vshControl *ctl;
-    const vshCmd *cmd;
-    int writefd;
-} vshCtrlData;
-
 static void
 doMigrate (void *opaque)
 {
@@ -5858,75 +5873,44 @@ print_job_progress(const char *label, unsigned long long remaining,
     fflush(stderr);
 }
 
+static void
+on_migration_timeout(vshControl *ctl,
+                     virDomainPtr dom)
+{
+    vshDebug(ctl, VSH_ERR_DEBUG, "suspend the domain "
+             "when migration timeouts\n");
+    virDomainSuspend(dom);
+}
+
 static bool
-cmdMigrate (vshControl *ctl, const vshCmd *cmd)
+do_watch_job(vshControl *ctl,
+             virDomainPtr dom,
+             bool verbose,
+             int pipe_fd,
+             int timeout,
+             jobWatchTimeoutFunc timeout_func,
+             const char *label)
 {
-    virDomainPtr dom = NULL;
-    int p[2] = {-1, -1};
-    int ret = -1;
-    bool functionReturn = false;
-    virThread workerThread;
-    struct pollfd pollfd;
-    char retchar;
     struct sigaction sig_action;
     struct sigaction old_sig_action;
-    virDomainJobInfo jobinfo;
-    bool verbose = false;
-    int timeout = 0;
+    struct pollfd pollfd;
     struct timeval start, curr;
-    bool live_flag = false;
-    vshCtrlData data;
+    virDomainJobInfo jobinfo;
+    int ret = -1;
+    char retchar;
+    bool functionReturn = false;
     sigset_t sigmask, oldsigmask;
 
     sigemptyset(&sigmask);
     sigaddset(&sigmask, SIGINT);
 
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    if (vshCommandOptBool (cmd, "verbose"))
-        verbose = true;
-
-    if (vshCommandOptBool (cmd, "live"))
-        live_flag = true;
-    if (vshCommandOptInt(cmd, "timeout", &timeout) > 0) {
-        if (! live_flag) {
-            vshError(ctl, "%s", _("migrate: Unexpected timeout for offline migration"));
-            goto cleanup;
-        }
-
-        if (timeout < 1) {
-            vshError(ctl, "%s", _("migrate: Invalid timeout"));
-            goto cleanup;
-        }
-
-        /* Ensure that we can multiply by 1000 without overflowing. */
-        if (timeout > INT_MAX / 1000) {
-            vshError(ctl, "%s", _("migrate: Timeout is too big"));
-            goto cleanup;
-        }
-    }
-
-    if (pipe(p) < 0)
-        goto cleanup;
-
-    data.ctl = ctl;
-    data.cmd = cmd;
-    data.writefd = p[1];
-
-    if (virThreadCreate(&workerThread,
-                        true,
-                        doMigrate,
-                        &data) < 0)
-        goto cleanup;
-
     intCaught = 0;
     sig_action.sa_sigaction = vshCatchInt;
     sig_action.sa_flags = SA_SIGINFO;
     sigemptyset(&sig_action.sa_mask);
     sigaction(SIGINT, &sig_action, &old_sig_action);
 
-    pollfd.fd = p[0];
+    pollfd.fd = pipe_fd;
     pollfd.events = POLLIN;
     pollfd.revents = 0;
 
@@ -5935,18 +5919,16 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
 repoll:
         ret = poll(&pollfd, 1, 500);
         if (ret > 0) {
-            if (saferead(p[0], &retchar, sizeof(retchar)) > 0) {
-                if (retchar == '0') {
-                    functionReturn = true;
+            if (pollfd.revents & POLLIN &&
+                saferead(pipe_fd, &retchar, sizeof(retchar)) > 0 &&
+                retchar == '0') {
                     if (verbose) {
                         /* print [100 %] */
-                        print_job_progress("Migration", 0, 1);
+                        print_job_progress(label, 0, 1);
                     }
-                } else
-                    functionReturn = false;
-            } else
-                functionReturn = false;
-            break;
+                    break;
+            }
+            goto cleanup;
         }
 
         if (ret < 0) {
@@ -5957,17 +5939,16 @@ repoll:
                 } else
                     goto repoll;
             }
-            functionReturn = false;
-            break;
+            goto cleanup;
         }
 
         GETTIMEOFDAY(&curr);
         if ( timeout && ((int)(curr.tv_sec - start.tv_sec)  * 1000 + \
                          (int)(curr.tv_usec - start.tv_usec) / 1000) > timeout * 1000 ) {
             /* suspend the domain when migration timeouts. */
-            vshDebug(ctl, VSH_ERR_DEBUG,
-                     "suspend the domain when migration timeouts\n");
-            virDomainSuspend(dom);
+            vshDebug(ctl, VSH_ERR_DEBUG, "%s timeout", label);
+            if (timeout_func)
+                (timeout_func)(ctl, dom);
             timeout = 0;
         }
 
@@ -5976,12 +5957,70 @@ repoll:
             ret = virDomainGetJobInfo(dom, &jobinfo);
             pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
             if (ret == 0)
-                print_job_progress("Migration", jobinfo.dataRemaining,
+                print_job_progress(label, jobinfo.dataRemaining,
                                    jobinfo.dataTotal);
         }
     }
 
+    functionReturn = true;
+
+cleanup:
     sigaction(SIGINT, &old_sig_action, NULL);
+    return functionReturn;
+}
+
+static bool
+cmdMigrate (vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom = NULL;
+    int p[2] = {-1, -1};
+    virThread workerThread;
+    bool verbose = false;
+    bool functionReturn = false;
+    int timeout = 0;
+    bool live_flag = false;
+    vshCtrlData data;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if (vshCommandOptBool (cmd, "verbose"))
+        verbose = true;
+
+    if (vshCommandOptBool (cmd, "live"))
+        live_flag = true;
+    if (vshCommandOptInt(cmd, "timeout", &timeout) > 0) {
+        if (! live_flag) {
+            vshError(ctl, "%s", _("migrate: Unexpected timeout for offline migration"));
+            goto cleanup;
+        }
+
+        if (timeout < 1) {
+            vshError(ctl, "%s", _("migrate: Invalid timeout"));
+            goto cleanup;
+        }
+
+        /* Ensure that we can multiply by 1000 without overflowing. */
+        if (timeout > INT_MAX / 1000) {
+            vshError(ctl, "%s", _("migrate: Timeout is too big"));
+            goto cleanup;
+        }
+    }
+
+    if (pipe(p) < 0)
+        goto cleanup;
+
+    data.ctl = ctl;
+    data.cmd = cmd;
+    data.writefd = p[1];
+
+    if (virThreadCreate(&workerThread,
+                        true,
+                        doMigrate,
+                        &data) < 0)
+        goto cleanup;
+    functionReturn = do_watch_job(ctl, dom, verbose, p[0], timeout,
+                                  on_migration_timeout, "Migration");
 
     virThreadJoin(&workerThread);
 
-- 
1.7.3.4




More information about the libvir-list mailing list