]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
virsh: Move job watch code to a separate function
authorMichal Privoznik <mprivozn@redhat.com>
Tue, 20 Dec 2011 13:04:28 +0000 (14:04 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 22 Dec 2011 10:05:15 +0000 (11:05 +0100)
called vshWatchJob. 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

index ed9e1b75c9a318aa0521a31b8d560099c9960647..a1317e896ebb3f92ce6bf3cfc8662882be61afb8 100644 (file)
@@ -395,6 +395,29 @@ 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,
+                                     void *opaque);
+
+static bool
+vshWatchJob(vshControl *ctl,
+            virDomainPtr dom,
+            bool verbose,
+            int pipe_fd,
+            int timeout,
+            jobWatchTimeoutFunc timeout_func,
+            void *opaque,
+            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__)
 
@@ -5881,12 +5904,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)
 {
@@ -6019,75 +6036,46 @@ print_job_progress(const char *label, unsigned long long remaining,
     fflush(stderr);
 }
 
+static void
+vshMigrationTimeout(vshControl *ctl,
+                    virDomainPtr dom,
+                    void *opaque ATTRIBUTE_UNUSED)
+{
+    vshDebug(ctl, VSH_ERR_DEBUG, "suspending the domain, "
+             "since migration timed out\n");
+    virDomainSuspend(dom);
+}
+
 static bool
-cmdMigrate (vshControl *ctl, const vshCmd *cmd)
+vshWatchJob(vshControl *ctl,
+            virDomainPtr dom,
+            bool verbose,
+            int pipe_fd,
+            int timeout,
+            jobWatchTimeoutFunc timeout_func,
+            void *opaque,
+            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;
 
@@ -6096,18 +6084,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) {
@@ -6118,17 +6104,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, opaque);
             timeout = 0;
         }
 
@@ -6137,12 +6122,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 = vshWatchJob(ctl, dom, verbose, p[0], timeout,
+                                 vshMigrationTimeout, NULL, _("Migration"));
 
     virThreadJoin(&workerThread);