<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-07-02 17:12 GMT+08:00 Michal Privoznik <span dir="ltr"><<a href="mailto:mprivozn@redhat.com" target="_blank">mprivozn@redhat.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class=""><div class="h5">On <a href="tel:26.06.2014%2015" value="+12606201415" target="_blank">26.06.2014 15</a>:51, Taowei wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
In vbox_common.c:<br>
vboxInitialize and vboxDomainSave are rewrited with vboxUniformedAPI.<br>
<br>
In vbox_common.h<br>
Some common definitions in vbox_CAPI_v*.h are directly extracted to<br>
this file. Some other incompatible defintions are simplified here. So we<br>
can write common code with it.<br>
<br>
---<br>
  po/POTFILES.in         |    1 +<br>
  src/Makefile.am        |    1 +<br>
  src/vbox/vbox_common.c |  150 ++++++++++++++++++++++++++++++<u></u>+++++++++++++++++<br>
  src/vbox/vbox_common.h |  151 ++++++++++++++++++++++++++++++<u></u>++++++++++++++++++<br>
  4 files changed, 303 insertions(+)<br>
  create mode 100644 src/vbox/vbox_common.c<br>
  create mode 100644 src/vbox/vbox_common.h<br>
<br>
diff --git a/po/POTFILES.in b/po/POTFILES.in<br>
index 31a8381..8c1b712 100644<br>
--- a/po/POTFILES.in<br>
+++ b/po/POTFILES.in<br>
@@ -213,6 +213,7 @@ src/util/virxml.c<br>
  src/vbox/vbox_MSCOMGlue.c<br>
  src/vbox/vbox_XPCOMCGlue.c<br>
  src/vbox/vbox_driver.c<br>
+src/vbox/vbox_common.c<br>
  src/vbox/vbox_snapshot_conf.c<br>
  src/vbox/vbox_tmpl.c<br>
  src/vmware/vmware_conf.c<br>
diff --git a/src/Makefile.am b/src/Makefile.am<br>
index c1e3f45..7a935e5 100644<br>
--- a/src/Makefile.am<br>
+++ b/src/Makefile.am<br>
@@ -674,6 +674,7 @@ VBOX_DRIVER_SOURCES =                                               \<br>
        vbox/vbox_V4_2_20.c vbox/vbox_CAPI_v4_2_20.h                    \<br>
        vbox/vbox_V4_3.c vbox/vbox_CAPI_v4_3.h                  \<br>
        vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h              \<br>
+       vbox/vbox_common.c vbox/vbox_common.h                   \<br>
        vbox/vbox_uniformed_api.h<br>
<br>
  VBOX_DRIVER_EXTRA_DIST =                                      \<br>
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c<br>
new file mode 100644<br>
index 0000000..27211a0<br>
--- /dev/null<br>
+++ b/src/vbox/vbox_common.c<br>
@@ -0,0 +1,150 @@<br>
+/*<br>
+ * Copyright 2014, Taowei Luo (<a href="mailto:uaedante@gmail.com" target="_blank">uaedante@gmail.com</a>)<br>
+ *<br>
+ * This library is free software; you can redistribute it and/or<br>
+ * modify it under the terms of the GNU Lesser General Public<br>
+ * License as published by the Free Software Foundation; either<br>
+ * version 2.1 of the License, or (at your option) any later version.<br>
+ *<br>
+ * This library is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+ * Lesser General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU Lesser General Public<br>
+ * License along with this library.  If not, see<br>
+ * <<a href="http://www.gnu.org/licenses/" target="_blank">http://www.gnu.org/licenses/</a>><u></u>.<br>
+ */<br>
+<br>
+#include <config.h><br>
+<br>
+#include <unistd.h><br>
+<br>
+#include "internal.h"<br>
+#include "datatypes.h"<br>
+#include "domain_conf.h"<br>
+#include "domain_event.h"<br>
+#include "virlog.h"<br>
+<br>
+#include "vbox_common.h"<br>
+#include "vbox_uniformed_api.h"<br>
+<br>
+/* Common codes for vbox driver. With the definitions in vbox_common.h,<br>
+ * it treats vbox structs as a void*. Though vboxUniformedAPI<br>
+ * it call vbox functions. This file is a high level implement about<br>
+ * the vbox driver.<br>
+ */<br>
+<br>
+#define VIR_FROM_THIS VIR_FROM_VBOX<br>
+<br>
+VIR_LOG_INIT("vbox.vbox_<u></u>common");<br>
+<br>
+#define RC_SUCCEEDED(rc) NS_SUCCEEDED(rc.resultCode)<br>
+#define RC_FAILED(rc) NS_FAILED(rc.resultCode)<br>
+<br>
+#define VBOX_RELEASE(arg)                                                     \<br>
+    do {                                                                      \<br>
+        if (arg) {                                                            \<br>
+            pVBoxAPI->nsisupportsRelease((<u></u>void *)arg);                        \<br>
+            (arg) = NULL;                                                     \<br>
+        }                                                                     \<br>
+    } while (0)<br>
+<br>
+#define VBOX_OBJECT_CHECK(conn, type, value) \<br>
+vboxGlobalData *data = conn->privateData;\<br>
+type ret = value;\<br>
+if (!data->vboxObj) {\<br>
+    return ret;\<br>
+}<br>
+<br>
+static vboxUniformedAPI *pVBoxAPI;<br>
+<br>
+void vboxRegisterUniformedAPI(<u></u>vboxUniformedAPI *vboxAPI)<br>
+{<br>
+    VIR_DEBUG("VirtualBox Uniformed API has been registered");<br>
+    pVBoxAPI = vboxAPI;<br>
+}<br>
+<br>
+int vboxInitialize(vboxGlobalData *data)<br>
+{<br>
+    if (pVBoxAPI->pfnInitialize(data) != 0)<br>
+        goto cleanup;<br>
+<br>
+    if (pVBoxAPI-><u></u>fWatchNeedInitialize && pVBoxAPI->initializeFWatch(<u></u>data) != 0)<br>
+        goto cleanup;<br>
+<br>
+    if (data->vboxObj == NULL) {<br>
+        virReportError(VIR_ERR_<u></u>INTERNAL_ERROR, "%s",<br>
+                       _("IVirtualBox object is null"));<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    if (data->vboxSession == NULL) {<br>
+        virReportError(VIR_ERR_<u></u>INTERNAL_ERROR, "%s",<br>
+                       _("ISession object is null"));<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    return 0;<br>
+<br>
+ cleanup:<br>
+    return -1;<br>
+}<br>
+<br>
+int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED)<br>
+{<br>
+    VBOX_OBJECT_CHECK(dom->conn, int, -1);<br>
+    IConsole *console    = NULL;<br>
+    vboxIIDUnion iid;<br>
+    IMachine *machine = NULL;<br>
+    nsresult rc;<br>
+<br>
+    pVBoxAPI->initializeVboxIID(&<u></u>iid);<br>
+    /* VirtualBox currently doesn't support saving to a file<br>
+     * at a location other then the machine folder and thus<br>
+     * setting path to ATTRIBUTE_UNUSED for now, will change<br>
+     * this behaviour once get the VirtualBox API in right<br>
+     * shape to do this<br>
+     */<br>
+<br>
</blockquote>
<br></div></div>
This down here ..<div class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    /* Open a Session for the machine */<br>
+    pVBoxAPI->vboxIIDFromUUID(<u></u>data, &iid, dom->uuid);<br>
+    if (pVBoxAPI-><u></u>getMachineForSession) {<br>
+        /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */<br>
+        rc = pVBoxAPI->objectGetMachine(<u></u>data, &iid, &machine);<br>
+        if (NS_FAILED(rc)) {<br>
+            virReportError(VIR_ERR_NO_<u></u>DOMAIN, "%s",<br>
+                           _("no domain with matching uuid"));<br>
+            return -1;<br>
+        }<br>
+    }<br>
</blockquote>
<br></div>
.. I guess is going to be used fairly frequently, so maybe it can be turned into a separate function.<div class=""><br></div></blockquote><div>pVBoxAPI->vboxIIDFromUUID(<u></u>data, &iid, dom->uuid); </div><div>
rc = pVBoxAPI->objectGetMachine(<u></u>data, &iid, &machine);<br>        if (NS_FAILED(rc)) {<br>            virReportError(VIR_ERR_NO_<u></u>DOMAIN, "%s",<br>                           _("no domain with matching uuid"));<br>
            return -1;<br>        }<br></div><div>This part indeed be used frequently, but some places check the flag getMachineForSession while other places don't.</div><div>So the prototype would be this:</div><div>
<br></div><div>int openSessionForMachine(vboxGlobaldata *data, vboxIID *iid, unsigned char* dom_uuid, IMachine *machine, bool checkflag);</div><div><br></div><div>Is this okay (or too complex)?</div><div><br></div><div>Meanwhile, When NS_FAILED(rc), some functions returned -1 (like this one), but some else goto the cleanup and unalloc the</div>
<div>vboxIID, I perfer to make all NS_FAILED(rc) goto cleanup, what's your opinion?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class="">
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+    rc = pVBoxAPI->sessionOpenExisting(<u></u>data, &iid, machine);<br>
+    if (NS_SUCCEEDED(rc)) {<br>
+        rc = pVBoxAPI->sessionGetConsole(<u></u>data->vboxSession, &console);<br>
+        if (NS_SUCCEEDED(rc) && console) {<br>
+            IProgress *progress = NULL;<br>
+<br>
+            pVBoxAPI->consoleSaveState(<u></u>console, &progress);<br>
+<br>
+            if (progress) {<br>
+                resultCodeUnion resultCode;<br>
+<br>
+                pVBoxAPI-><u></u>progressWaitForCompletion(<u></u>progress, -1);<br>
+                pVBoxAPI-><u></u>progressGetResultCode(<u></u>progress, &resultCode);<br>
+                if (RC_SUCCEEDED(resultCode)) {<br>
+                    ret = 0;<br>
+                }<br>
+                VBOX_RELEASE(progress);<br>
+            }<br>
+            VBOX_RELEASE(console);<br>
+        }<br>
+        pVBoxAPI->sessionClose(data-><u></u>vboxSession);<br>
+    }<br>
</blockquote>
<br></div>
I find this still distant to the rest of our code. I mean, we use this pattern:<br>
<br>
  if (func() < 0)<br>
    goto cleanup;<br>
<br>
  rc = func2();<br>
  if (rc < 0)<br>
    goto cleanup;<br>
<br>
So maybe we can use the same here:<div class=""><br>
<br>
  rc = pVBoxAPI->sessionOpenExisting(<u></u>data, &iid, machine);<br></div>
  if (NS_FAILED(rc) < 0)<br>
    goto cleanup;<div class=""><br>
<br>
  rc = pVBoxAPI->sessionGetConsole(<u></u>data->vboxSession, &console);<br></div>
  if (NS_FAILED(rc) < 0)<br>
    goto cleanup;<br>
<br>
  ...<br>
<br>
  ret = 0;<br>
 cleanup:<br>
  VBOX_RELEASE(progress);<br>
  VBOX_RELEASE(console);<br>
  pVBoxAPI->sessionClose(data-><u></u>vboxSession);<br>
  ...<br>
  return ret;<div><div class="h5"><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+    pVBoxAPI->DEBUGIID("UUID of machine being saved:", &iid);<br>
+<br>
+    VBOX_RELEASE(machine);<br>
+    pVBoxAPI->vboxIIDUnalloc(data, &iid);<br>
+    return ret;<br>
+}<br>
diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h<br>
new file mode 100644<br>
index 0000000..bf0d106<br>
--- /dev/null<br>
+++ b/src/vbox/vbox_common.h<br>
@@ -0,0 +1,151 @@<br>
+/*<br>
+ * Copyright 2014, Taowei Luo (<a href="mailto:uaedante@gmail.com" target="_blank">uaedante@gmail.com</a>)<br>
+ *<br>
+ * This library is free software; you can redistribute it and/or<br>
+ * modify it under the terms of the GNU Lesser General Public<br>
+ * License as published by the Free Software Foundation; either<br>
+ * version 2.1 of the License, or (at your option) any later version.<br>
+ *<br>
+ * This library is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+ * Lesser General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU Lesser General Public<br>
+ * License along with this library.  If not, see<br>
+ * <<a href="http://www.gnu.org/licenses/" target="_blank">http://www.gnu.org/licenses/</a>><u></u>.<br>
+ */<br>
+<br>
+#ifndef VBOX_COMMON_H<br>
+# define VBOX_COMMON_H<br>
+<br>
+# ifdef ___VirtualBox_CXPCOM_h<br>
+#  error this file should not be included after vbox_CAPI_v*.h<br>
+# endif<br>
+<br>
+# include "internal.h"<br>
+# include <stddef.h><br>
+# include "wchar.h"<br>
+<br>
+/* This file extracts some symbols defined in<br>
+ * vbox_CAPI_v*.h. It tells the vbox_common.c<br>
+ * how to treat with this symbols. This file<br>
+ * can't be included with files such as<br>
+ * vbox_CAPI_v*.h, or it would casue multiple<br>
+ * definitions.<br>
+ *<br>
+ * You can see the more informations in vbox_api.h<br>
+ */<br>
+<br>
+/* Copied definitions from vbox_CAPI_*.h.<br>
+ * We must MAKE SURE these codes are compatible. */<br>
+<br>
+typedef unsigned char PRUint8;<br>
+# if (defined(HPUX) && defined(__cplusplus) \<br>
+     && !defined(__GNUC__) && __cplusplus < 199707L) \<br>
+    || (defined(SCO) && defined(__cplusplus) \<br>
+        && !defined(__GNUC__) && __cplusplus == 1L)<br>
+typedef char PRInt8;<br>
+# else<br>
+typedef signed char PRInt8;<br>
+# endif<br>
+<br>
+# define PR_INT8_MAX 127<br>
+# define PR_INT8_MIN (-128)<br>
+# define PR_UINT8_MAX 255U<br>
+<br>
+typedef unsigned short PRUint16;<br>
+typedef short PRInt16;<br>
+<br>
+# define PR_INT16_MAX 32767<br>
+# define PR_INT16_MIN (-32768)<br>
+# define PR_UINT16_MAX 65535U<br>
</blockquote>
<br></div></div>
Are these really necessary? I know we already have them, I'm just asking.<div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+typedef unsigned int PRUint32;<br>
+typedef int PRInt32;<br>
+# define PR_INT32(x)  x<br>
+# define PR_UINT32(x) x ## U<br>
+<br>
+# define PR_INT32_MAX PR_INT32<a href="tel:%282147483647" value="+12147483647" target="_blank">(2147483647</a>)<br>
+# define PR_INT32_MIN (-PR_INT32_MAX - 1)<br>
+# define PR_UINT32_MAX PR_UINT32(4294967295)<br>
+<br>
+typedef long PRInt64;<br>
+typedef unsigned long PRUint64;<br>
+typedef int PRIntn;<br>
+typedef unsigned int PRUintn;<br>
+<br>
+typedef double          PRFloat64;<br>
+typedef size_t PRSize;<br>
+<br>
+typedef ptrdiff_t PRPtrdiff;<br>
+<br>
+typedef unsigned long PRUptrdiff;<br>
+<br>
+typedef PRIntn PRBool;<br>
+<br>
+# define PR_TRUE 1<br>
+# define PR_FALSE 0<br>
+<br>
+typedef PRUint8 PRPackedBool;<br>
+<br>
+/*<br>
+** Status code used by some routines that have a single point of failure or<br>
+** special status return.<br>
+*/<br>
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;<br>
+<br>
+# ifndef __PRUNICHAR__<br>
+#  define __PRUNICHAR__<br>
+#  if defined(WIN32) || defined(XP_MAC)<br>
+typedef wchar_t PRUnichar;<br>
+#  else<br>
+typedef PRUint16 PRUnichar;<br>
+#  endif<br>
+# endif<br>
+<br>
+typedef long PRWord;<br>
+typedef unsigned long PRUword;<br>
+<br>
+# define nsnull 0<br>
+typedef PRUint32 nsresult;<br>
+<br>
+# if defined(__GNUC__) && (__GNUC__ > 2)<br>
+#  define NS_LIKELY(x)    (__builtin_expect((x), 1))<br>
+#  define NS_UNLIKELY(x)  (__builtin_expect((x), 0))<br>
+# else<br>
+#  define NS_LIKELY(x)    (x)<br>
+#  define NS_UNLIKELY(x)  (x)<br>
+# endif<br>
+<br>
+# define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000))<br>
+# define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))<br>
</blockquote>
<br></div></div>
Wow, I didn't know we are using likely and unlikely in libvirt.<div class=""><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+/**<br>
+ * An "interface id" which can be used to uniquely identify a given<br>
+ * interface.<br>
+ * A "unique identifier". This is modeled after OSF DCE UUIDs.<br>
+ */<br>
+<br>
+struct nsID {<br>
+  PRUint32 m0;<br>
+  PRUint16 m1;<br>
+  PRUint16 m2;<br>
+  PRUint8 m3[8];<br>
+};<br>
+<br>
+typedef struct nsID nsID;<br>
+typedef nsID nsIID;<br>
+<br>
+/* Simplied definitions in vbox_CAPI_*.h */<br>
+<br>
+typedef void const *PCVBOXXPCOM;<br>
+typedef void IVirtualBox;<br>
+typedef void ISession;<br>
+typedef void IVirtualBoxCallback;<br>
+typedef void nsIEventQueue;<br>
+typedef void IConsole;<br>
+typedef void IMachine;<br>
+typedef void IProgress;<br>
+<br>
+#endif /* VBOX_COMMON_H */<br>
<br>
</blockquote>
<br>
</div></div></blockquote></div><br></div></div>