[libvirt] [PATCHv5 0/4] Outline of rewriting vbox Driver

Fix some problems in last patch. Includes: * Re-manage the patches in a better order, move some symbol definitions into the proper patch. * Make the API in vboxUniformedAPI hierarchical. So when more apis introduced into the uniformed api, it wouldn't go to a mess. * Rewrite the vboxDomainSave in a better way. Taowei (4): Define vboxUniformedAPI Implement vboxInitialize and vboxDomainSave Implement uniformed api for each vbox version Install vboxUniformedAPI po/POTFILES.in | 1 + src/Makefile.am | 4 +- src/vbox/vbox_common.c | 183 +++++++++++++++ src/vbox/vbox_common.h | 151 ++++++++++++ src/vbox/vbox_driver.c | 22 +- src/vbox/vbox_tmpl.c | 504 ++++++++++++++++++++++++----------------- src/vbox/vbox_uniformed_api.h | 211 +++++++++++++++++ 7 files changed, 868 insertions(+), 208 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_uniformed_api.h -- 1.7.9.5

The vboxUniformedAPI is reconstructed. Introducing structs like vboxUniformedIObject, vboxUniformedIProgress (and so on) to make the vboxUniformedAPI more regular. --- src/Makefile.am | 3 +- src/vbox/vbox_uniformed_api.h | 194 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/vbox/vbox_uniformed_api.h diff --git a/src/Makefile.am b/src/Makefile.am index 2b9ac61..c1e3f45 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -673,7 +673,8 @@ VBOX_DRIVER_SOURCES = \ vbox/vbox_V4_2.c vbox/vbox_CAPI_v4_2.h \ vbox/vbox_V4_2_20.c vbox/vbox_CAPI_v4_2_20.h \ vbox/vbox_V4_3.c vbox/vbox_CAPI_v4_3.h \ - vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h + vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h \ + vbox/vbox_uniformed_api.h VBOX_DRIVER_EXTRA_DIST = \ vbox/vbox_tmpl.c vbox/README \ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h new file mode 100644 index 0000000..ca41ec3 --- /dev/null +++ b/src/vbox/vbox_uniformed_api.h @@ -0,0 +1,194 @@ +/* + * Copyright 2014, Taowei Luo (uaedante@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef VBOX_UNIFORMED_API_H +# define VBOX_UNIFORMED_API_H + +# include "internal.h" + +/* This file may be used in three place. That is vbox_tmpl.c, + * vbox_common.c and vbox_driver.c. The vboxUniformedAPI and some + * types used for vboxUniformedAPI is defined here. + * + * The vbox_tmpl.c is the only place where the driver knows the inside + * architecture of those vbox structs(vboxObj, vboxSession, + * pFuncs, vboxCallback and vboxQueue). The file should be included + * after the currect vbox_CAPI_v*.h, then we can use the vbox structs + * in vboxGlobalData. The vbox_tmpl.c should implement functions + * defined in vboxUniformedAPI. + * + * In vbox_driver.c, it is used to define the struct vboxUniformedAPI. + * The vbox_driver.c collects vboxUniformedAPI for all versions. + * Then vboxRegister calls the vboxRegisterUniformedAPI to register. + * Note: In vbox_driver.c, the vbox structs in vboxGlobalData is + * defined by vbox_CAPI_v2.2.h. + * + * The vbox_common.c, it is used to generate common codes for all vbox + * versions. Bacause the same member varible's offset in a vbox struct + * may change between different vbox versions. The vbox_common.c + * shouldn't directly use struct's member varibles defined in + * vbox_CAPI_v*.h. To make things safety, we include the + * vbox_common.h in vbox_common.c. In this case, we treat structs + * defined by vbox as a void*. The common codes don't concern about + * the inside of this structs(actually, we can't, in the common level). + * With the help of vboxUniformed API, we call VirtualBox's API and + * implement the vbox driver in a high level. + * + * In conclusion: + * * In vbox_tmpl.c, this file is included after vbox_CAPI_v*.h + * * In vbox_driver.c, this file is included after vbox_glue.h + * * In vbox_common.c, this file is included after vbox_common.h + * + */ + +/* Extracted define from vbox_tmpl.c */ + +# ifdef WIN32 +struct _vboxIID_v2_x_WIN32 { + /* IID is represented by a GUID value. */ + GUID value; +}; +# endif /* !WIN32 */ + +struct _vboxIID_v2_x { + /* IID is represented by a pointer to a nsID. */ + nsID *value; + + /* backing is used in cases where we need to create or copy an IID. + * We cannot allocate memory that can be freed by ComUnallocMem. + * Therefore, we use this stack allocated nsID instead. */ + nsID backing; +}; + +struct _vboxIID_v3_x { + /* IID is represented by a UTF-16 encoded UUID in string form. */ + PRUnichar *value; + + /* owner indicates if we own the value and need to free it. */ + bool owner; +}; + +typedef union { +# ifdef WIN32 + struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; +# endif /* !WIN32 */ + struct _vboxIID_v2_x vboxIID_v2_x; + struct _vboxIID_v3_x vboxIID_v3_x; +} vboxIIDUnion; + +typedef union { + nsresult uResultCode; + PRInt32 resultCode; +} resultCodeUnion; + +typedef struct { + virMutex lock; + unsigned long version; + + virCapsPtr caps; + virDomainXMLOptionPtr xmlopt; + + IVirtualBox *vboxObj; + ISession *vboxSession; + + /** Our version specific API table pointer. */ + PCVBOXXPCOM pFuncs; + + /* The next is used when VBOX_API_VERSION > 2002000 */ + /* Async event handling */ + virObjectEventStatePtr domainEvents; + int fdWatch; +# if defined(VBOX_API_VERSION) && VBOX_API_VERSION > 2002000 && VBOX_API_VERSION <= 3002000 + /* IVirtualBoxCallback is used in VirtualBox 3.x only */ + IVirtualBoxCallback *vboxCallback; +# else /* VBOX_API_VERSION == 2002000 || VBOX_API_VERSION > 3002000 or VBOX_API_VERSION undefined */ + void *vboxCallback; +# endif /* VBOX_API_VERSION == 2002000 || VBOX_API_VERSION > 3002000 or VBOX_API_VERSION undefined */ + + +# if defined(VBOX_API_VERSION) && VBOX_API_VERSION > 2002000 + nsIEventQueue *vboxQueue; +# else /* VBOX_API_VERSION == 2002000 or undefined */ + void *vboxQueue; +# endif /* VBOX_API_VERSION == 2002000 or undefined */ + int volatile vboxCallBackRefCount; + + /* pointer back to the connection */ + virConnectPtr conn; + +} vboxGlobalData; + +/* vboxUniformedAPI gives vbox_common.c a uniformed layer to see + * vbox API. + */ + +/* Functions for vboxIID */ +typedef struct { + void (*initializeVboxIID)(vboxIIDUnion *iidu); + void (*vboxIIDUnalloc)(vboxGlobalData *data, vboxIIDUnion *iidu); + void (*vboxIIDFromUUID)(vboxGlobalData *data, vboxIIDUnion *iidu, const unsigned char *uuid); + void (*DEBUGIID)(const char *msg, vboxIIDUnion *iidu); +} vboxUniformedIID; + +/* Functions for IObject */ +typedef struct { + nsresult (*GetMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); +} vboxUniformedIObject; + +/* Functions for ISession */ +typedef struct { + nsresult (*OpenExisting)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); + nsresult (*GetConsole)(ISession *session, IConsole **console); + nsresult (*Close)(ISession *session); +} vboxUniformedISession; + +/* Functions for IConsole */ +typedef struct { + nsresult (*SaveState)(IConsole *console, IProgress **progress); +} vboxUniformedIConsole; + +/* Functions for IProgress */ +typedef struct { + nsresult (*WaitForCompletion)(IProgress *progress, PRInt32 timeout); + nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); +} vboxUniformedIProgress; + +/* Functions for nsISupports */ +typedef struct { + nsresult (*Release)(void *Ihandle); +} vboxUniformednsISupports; + +typedef struct { + /* vbox API version */ + uint32_t APIVersion; + uint32_t XPCOMCVersion; + /* vbox APIs */ + int (*pfnInitialize)(vboxGlobalData *data); + int (*initializeFWatch)(vboxGlobalData *data); + vboxUniformedIID UIID; + vboxUniformedIObject UIObject; + vboxUniformedISession UISession; + vboxUniformedIConsole UIConsole; + vboxUniformedIProgress UIProgress; + vboxUniformednsISupports nsUISupports; + /* vbox API features */ + bool fWatchNeedInitialize; + bool getMachineForSession; +} vboxUniformedAPI; + +#endif /* VBOX_UNIFORMED_API_H */ -- 1.7.9.5

I moved vbox_common to the second patch, and the modification of vbox_tmpl.c into the third one. The benefit is that we will no longer leave functions defined in *.h but not implemented or functions used without definition. Moreover, the code style in vboxDomainSave is managed in a better way. --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/vbox/vbox_common.c | 153 +++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_common.h | 151 ++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_uniformed_api.h | 3 + 5 files changed, 309 insertions(+) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 31a8381..8c1b712 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -213,6 +213,7 @@ src/util/virxml.c src/vbox/vbox_MSCOMGlue.c src/vbox/vbox_XPCOMCGlue.c src/vbox/vbox_driver.c +src/vbox/vbox_common.c src/vbox/vbox_snapshot_conf.c src/vbox/vbox_tmpl.c src/vmware/vmware_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index c1e3f45..7a935e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -674,6 +674,7 @@ VBOX_DRIVER_SOURCES = \ vbox/vbox_V4_2_20.c vbox/vbox_CAPI_v4_2_20.h \ vbox/vbox_V4_3.c vbox/vbox_CAPI_v4_3.h \ vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h \ + vbox/vbox_common.c vbox/vbox_common.h \ vbox/vbox_uniformed_api.h VBOX_DRIVER_EXTRA_DIST = \ diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c new file mode 100644 index 0000000..3f95abb --- /dev/null +++ b/src/vbox/vbox_common.c @@ -0,0 +1,153 @@ +/* + * Copyright 2014, Taowei Luo (uaedante@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <unistd.h> + +#include "internal.h" +#include "datatypes.h" +#include "domain_conf.h" +#include "domain_event.h" +#include "virlog.h" + +#include "vbox_common.h" +#include "vbox_uniformed_api.h" + +/* Common codes for vbox driver. With the definitions in vbox_common.h, + * it treats vbox structs as a void*. Though vboxUniformedAPI + * it call vbox functions. This file is a high level implement about + * the vbox driver. + */ + +#define VIR_FROM_THIS VIR_FROM_VBOX + +VIR_LOG_INIT("vbox.vbox_common"); + +#define RC_SUCCEEDED(rc) NS_SUCCEEDED(rc.resultCode) +#define RC_FAILED(rc) NS_FAILED(rc.resultCode) + +#define VBOX_RELEASE(arg) \ + do { \ + if (arg) { \ + gVBoxAPI.nsUISupports.Release((void *)arg); \ + (arg) = NULL; \ + } \ + } while (0) + +#define VBOX_OBJECT_CHECK(conn, type, value) \ +vboxGlobalData *data = conn->privateData;\ +type ret = value;\ +if (!data->vboxObj) {\ + return ret;\ +} + +/* global vbox API, used for all common codes. */ +static vboxUniformedAPI gVBoxAPI; + +static int openSessionForMachine(vboxGlobalData *data, vboxIIDUnion *iid, const unsigned char *dom_uuid, + IMachine **machine, bool checkflag) +{ + gVBoxAPI.UIID.vboxIIDFromUUID(data, iid, dom_uuid); + if (!checkflag || gVBoxAPI.getMachineForSession) { + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + if (NS_FAILED(gVBoxAPI.UIObject.GetMachine(data, iid, machine))) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return -1; + } + } + return 0; +} + +int vboxInitialize(vboxGlobalData *data) +{ + if (gVBoxAPI.pfnInitialize(data) != 0) + goto cleanup; + + if (gVBoxAPI.fWatchNeedInitialize && gVBoxAPI.initializeFWatch(data) != 0) + goto cleanup; + + if (data->vboxObj == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("IVirtualBox object is null")); + goto cleanup; + } + + if (data->vboxSession == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("ISession object is null")); + goto cleanup; + } + + return 0; + + cleanup: + return -1; +} + +int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IConsole *console = NULL; + vboxIIDUnion iid; + IMachine *machine = NULL; + IProgress *progress = NULL; + resultCodeUnion resultCode; + nsresult rc; + + gVBoxAPI.UIID.initializeVboxIID(&iid); + /* VirtualBox currently doesn't support saving to a file + * at a location other then the machine folder and thus + * setting path to ATTRIBUTE_UNUSED for now, will change + * this behaviour once get the VirtualBox API in right + * shape to do this + */ + + /* Open a Session for the machine */ + if (openSessionForMachine(data, &iid, dom->uuid, &machine, true) < 0) + goto cleanup; + + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_FAILED(rc) || !console) + goto freeSession; + + rc = gVBoxAPI.UIConsole.SaveState(console, &progress); + if (!progress) + goto freeSession; + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_SUCCEEDED(resultCode)) + ret = 0; + + freeSession: + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + gVBoxAPI.UIID.DEBUGIID("UUID of machine being saved:", &iid); + VBOX_RELEASE(machine); + VBOX_RELEASE(console); + VBOX_RELEASE(progress); + gVBoxAPI.UIID.vboxIIDUnalloc(data, &iid); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h new file mode 100644 index 0000000..bf0d106 --- /dev/null +++ b/src/vbox/vbox_common.h @@ -0,0 +1,151 @@ +/* + * Copyright 2014, Taowei Luo (uaedante@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef VBOX_COMMON_H +# define VBOX_COMMON_H + +# ifdef ___VirtualBox_CXPCOM_h +# error this file should not be included after vbox_CAPI_v*.h +# endif + +# include "internal.h" +# include <stddef.h> +# include "wchar.h" + +/* This file extracts some symbols defined in + * vbox_CAPI_v*.h. It tells the vbox_common.c + * how to treat with this symbols. This file + * can't be included with files such as + * vbox_CAPI_v*.h, or it would casue multiple + * definitions. + * + * You can see the more informations in vbox_api.h + */ + +/* Copied definitions from vbox_CAPI_*.h. + * We must MAKE SURE these codes are compatible. */ + +typedef unsigned char PRUint8; +# if (defined(HPUX) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus < 199707L) \ + || (defined(SCO) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus == 1L) +typedef char PRInt8; +# else +typedef signed char PRInt8; +# endif + +# define PR_INT8_MAX 127 +# define PR_INT8_MIN (-128) +# define PR_UINT8_MAX 255U + +typedef unsigned short PRUint16; +typedef short PRInt16; + +# define PR_INT16_MAX 32767 +# define PR_INT16_MIN (-32768) +# define PR_UINT16_MAX 65535U + +typedef unsigned int PRUint32; +typedef int PRInt32; +# define PR_INT32(x) x +# define PR_UINT32(x) x ## U + +# define PR_INT32_MAX PR_INT32(2147483647) +# define PR_INT32_MIN (-PR_INT32_MAX - 1) +# define PR_UINT32_MAX PR_UINT32(4294967295) + +typedef long PRInt64; +typedef unsigned long PRUint64; +typedef int PRIntn; +typedef unsigned int PRUintn; + +typedef double PRFloat64; +typedef size_t PRSize; + +typedef ptrdiff_t PRPtrdiff; + +typedef unsigned long PRUptrdiff; + +typedef PRIntn PRBool; + +# define PR_TRUE 1 +# define PR_FALSE 0 + +typedef PRUint8 PRPackedBool; + +/* +** Status code used by some routines that have a single point of failure or +** special status return. +*/ +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +# ifndef __PRUNICHAR__ +# define __PRUNICHAR__ +# if defined(WIN32) || defined(XP_MAC) +typedef wchar_t PRUnichar; +# else +typedef PRUint16 PRUnichar; +# endif +# endif + +typedef long PRWord; +typedef unsigned long PRUword; + +# define nsnull 0 +typedef PRUint32 nsresult; + +# if defined(__GNUC__) && (__GNUC__ > 2) +# define NS_LIKELY(x) (__builtin_expect((x), 1)) +# define NS_UNLIKELY(x) (__builtin_expect((x), 0)) +# else +# define NS_LIKELY(x) (x) +# define NS_UNLIKELY(x) (x) +# endif + +# define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000)) +# define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000))) + +/** + * An "interface id" which can be used to uniquely identify a given + * interface. + * A "unique identifier". This is modeled after OSF DCE UUIDs. + */ + +struct nsID { + PRUint32 m0; + PRUint16 m1; + PRUint16 m2; + PRUint8 m3[8]; +}; + +typedef struct nsID nsID; +typedef nsID nsIID; + +/* Simplied definitions in vbox_CAPI_*.h */ + +typedef void const *PCVBOXXPCOM; +typedef void IVirtualBox; +typedef void ISession; +typedef void IVirtualBoxCallback; +typedef void nsIEventQueue; +typedef void IConsole; +typedef void IMachine; +typedef void IProgress; + +#endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index ca41ec3..39b034d 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -191,4 +191,7 @@ typedef struct { bool getMachineForSession; } vboxUniformedAPI; +int vboxInitialize(vboxGlobalData *data); +int vboxDomainSave(virDomainPtr dom, const char *path); + #endif /* VBOX_UNIFORMED_API_H */ -- 1.7.9.5

Implement uniformed api in vbox_tmpl.c, for each vbox version. Diff to the v4: Because the C forbid struct assignment in initialization (which may cause error: 'initializer element is not constant'). So the vbox**InstallUniformedAPI is introduced as the way to install vboxAPI is changed. --- src/vbox/vbox_tmpl.c | 504 ++++++++++++++++++++++++----------------- src/vbox/vbox_uniformed_api.h | 12 + 2 files changed, 313 insertions(+), 203 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 4ba9ad7..86c5357 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -89,7 +89,7 @@ /* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */ #include "vbox_glue.h" - +#include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -189,7 +189,7 @@ if (strUtf16) {\ #define DEBUGUUID(msg, iid) \ {\ - VIR_DEBUG(msg ": {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",\ + VIR_DEBUG("%s: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", msg,\ (unsigned)(iid)->m0,\ (unsigned)(iid)->m1,\ (unsigned)(iid)->m2,\ @@ -203,56 +203,6 @@ if (strUtf16) {\ (unsigned)(iid)->m3[7]);\ }\ -typedef struct { - virMutex lock; - unsigned long version; - - virCapsPtr caps; - virDomainXMLOptionPtr xmlopt; - - IVirtualBox *vboxObj; - ISession *vboxSession; - - /** Our version specific API table pointer. */ - PCVBOXXPCOM pFuncs; - -#if VBOX_API_VERSION == 2002000 - -} vboxGlobalData; - -#else /* !(VBOX_API_VERSION == 2002000) */ - - /* Async event handling */ - virObjectEventStatePtr domainEvents; - int fdWatch; - -# if VBOX_API_VERSION <= 3002000 - /* IVirtualBoxCallback is used in VirtualBox 3.x only */ - IVirtualBoxCallback *vboxCallback; -# endif /* VBOX_API_VERSION <= 3002000 */ - - nsIEventQueue *vboxQueue; - int volatile vboxCallBackRefCount; - - /* pointer back to the connection */ - virConnectPtr conn; - -} vboxGlobalData; - -/* g_pVBoxGlobalData has to be global variable, - * there is no other way to make the callbacks - * work other then having g_pVBoxGlobalData as - * global, because the functions namely AddRef, - * Release, etc consider it as global and you - * can't change the function definition as it - * is XPCOM nsISupport::* function and it expects - * them that way - */ - -static vboxGlobalData *g_pVBoxGlobalData = NULL; - -#endif /* !(VBOX_API_VERSION == 2002000) */ - #if VBOX_API_VERSION < 4000000 # define VBOX_OBJECT_GET_MACHINE(/* in */ iid_value, /* out */ machine) \ @@ -283,6 +233,56 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL; #endif /* VBOX_API_VERSION >= 4000000 */ +#if VBOX_API_VERSION == 2002000 + +# ifdef WIN32 + +typedef struct _vboxIID_v2_x_WIN32 vboxIID; +typedef struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; + +# define VBOX_IID_INITIALIZER { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } + +# define IID_MEMBER(name) (iidu->vboxIID_v2_x_WIN32.name) + +# else /* !WIN32 */ + +typedef struct _vboxIID_v2_x vboxIID; +typedef struct _vboxIID_v2_x vboxIID_v2_x; + +# define VBOX_IID_INITIALIZER { NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } + +# define IID_MEMBER(name) (iidu->vboxIID_v2_x.name) + +# endif /* !WIN32 */ + +#else /* VBOX_API_VERSION != 2002000 */ + +typedef struct _vboxIID_v3_x vboxIID; +typedef struct _vboxIID_v3_x vboxIID_v3_x; + +# define VBOX_IID_INITIALIZER { NULL, true } + +# define IID_MEMBER(name) (iidu->vboxIID_v3_x.name) + +#endif /* VBOX_API_VERSION != 2002000 */ + +/* g_pVBoxGlobalData has to be global variable, + * there is no other way to make the callbacks + * work other then having g_pVBoxGlobalData as + * global, because the functions namely AddRef, + * Release, etc consider it as global and you + * can't change the function definition as it + * is XPCOM nsISupport::* function and it expects + * them that way + */ + +#if VBOX_API_VERSION > 2002000 + +static vboxGlobalData *g_pVBoxGlobalData = NULL; + +#endif /* !(VBOX_API_VERSION == 2002000) */ + + static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); static int vboxDomainCreate(virDomainPtr dom); static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); @@ -383,16 +383,6 @@ static void nsIDFromChar(nsID *iid, const unsigned char *uuid) # ifdef WIN32 -typedef struct _vboxIID_v2_x_WIN32 vboxIID; -typedef struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; - -struct _vboxIID_v2_x_WIN32 { - /* IID is represented by a GUID value. */ - GUID value; -}; - -# define VBOX_IID_INITIALIZER { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } - static void vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, vboxIID_v2_x_WIN32 *iid ATTRIBUTE_UNUSED) @@ -401,6 +391,13 @@ vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, } static void +_vboxIIDUnalloc(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iid ATTRIBUTE_UNUSED) +{ + /* Nothing to free */ +} + +static void vboxIIDToUUID_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid, unsigned char *uuid) { nsIDtoChar(uuid, (nsID *)&iid->value); @@ -415,6 +412,13 @@ vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, nsIDFromChar((nsID *)&iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x_WIN32(data, &iidu->vboxIID_v2_x_WIN32, uuid); +} + static bool vboxIIDIsEqual_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid1, vboxIID_v2_x_WIN32 *iid2) { @@ -432,6 +436,7 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, memcpy(&iid->value, &items[idx], sizeof(GUID)); } + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x_WIN32(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x_WIN32(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x_WIN32(data, iid, uuid) @@ -440,22 +445,8 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, vboxIIDFromArrayItem_v2_x_WIN32(data, iid, array, idx) # define DEBUGIID(msg, iid) DEBUGUUID(msg, (nsID *)&(iid)) -# else /* !WIN32 */ -typedef struct _vboxIID_v2_x vboxIID; -typedef struct _vboxIID_v2_x vboxIID_v2_x; - -struct _vboxIID_v2_x { - /* IID is represented by a pointer to a nsID. */ - nsID *value; - - /* backing is used in cases where we need to create or copy an IID. - * We cannot allocate memory that can be freed by ComUnallocMem. - * Therefore, we use this stack allocated nsID instead. */ - nsID backing; -}; - -# define VBOX_IID_INITIALIZER { NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } +# else /* !WIN32 */ static void vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) @@ -472,6 +463,12 @@ vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v2_x(data, &iidu->vboxIID_v2_x); +} + +static void vboxIIDToUUID_v2_x(vboxIID_v2_x *iid, unsigned char *uuid) { nsIDtoChar(uuid, iid->value); @@ -489,6 +486,13 @@ vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, nsIDFromChar(iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x(data, &iidu->vboxIID_v2_x, uuid); +} + static bool vboxIIDIsEqual_v2_x(vboxIID_v2_x *iid1, vboxIID_v2_x *iid2) { @@ -506,6 +510,7 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, memcpy(iid->value, array->items[idx], sizeof(nsID)); } + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x(data, iid, uuid) @@ -514,23 +519,11 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, vboxIIDFromArrayItem_v2_x(data, iid, array, idx) # define DEBUGIID(msg, iid) DEBUGUUID(msg, iid) + # endif /* !WIN32 */ #else /* VBOX_API_VERSION != 2002000 */ -typedef struct _vboxIID_v3_x vboxIID; -typedef struct _vboxIID_v3_x vboxIID_v3_x; - -struct _vboxIID_v3_x { - /* IID is represented by a UTF-16 encoded UUID in string form. */ - PRUnichar *value; - - /* owner indicates if we own the value and need to free it. */ - bool owner; -}; - -# define VBOX_IID_INITIALIZER { NULL, true } - static void vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) { @@ -543,6 +536,12 @@ vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v3_x(data, &iidu->vboxIID_v3_x); +} + +static void vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, unsigned char *uuid) { @@ -568,6 +567,13 @@ vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, data->pFuncs->pfnUtf8ToUtf16(utf8, &iid->value); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v3_x(data, &iidu->vboxIID_v3_x, uuid); +} + static bool vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1, vboxIID_v3_x *iid2) @@ -606,6 +612,7 @@ vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, vboxIIDFromArrayItem_v3_x(data, iid, array, idx) # define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16) + # if VBOX_API_VERSION >= 3001000 /** @@ -826,6 +833,210 @@ static PRUnichar *PRUnicharFromInt(int n) { #endif /* !(VBOX_API_VERSION == 2002000) */ +/* Begin of vboxUniformedAPI */ + +static int _pfnInitialize(vboxGlobalData *data) +{ + data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); + if (data->pFuncs == NULL) + return -1; +#if VBOX_XPCOMC_VERSION == 0x00010000U + data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession); +#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ + data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession); +#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ + return 0; +} + +static int +_initializeFWatch(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) + /* No event queue functionality in 2.2.* as of now */ + VIR_WARN("There is no fWatch initical in current version"); +#else /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + /* Initialize the fWatch needed for Event Callbacks */ + data->fdWatch = -1; + data->pFuncs->pfnGetEventQueue(&data->vboxQueue); + if (data->vboxQueue == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("nsIEventQueue object is null")); + return -1; + } +#endif /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + return 0; +} + +static nsresult +_sessionGetConsole(ISession *session, IConsole **console) +{ + return session->vtbl->GetConsole(session, console); +} + +static nsresult +_consoleSaveState(IConsole *console, IProgress **progress) +{ + return console->vtbl->SaveState(console, progress); +} + +static nsresult +_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) +{ + return progress->vtbl->WaitForCompletion(progress, timeout); +} + +static nsresult _nsisupportsRelease(void *Ihandle) +{ + /* It is safety to convert a pointer from IVirtual(or structs + * like this) to nsISupports*/ + nsISupports *nsi = (nsISupports *)Ihandle; + return nsi->vtbl->Release(nsi); +} + +#if VBOX_API_VERSION == 2002000 + +static nsresult +_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +{ + return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode); +} + +static void _initializeVboxIID(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); +} + +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ +# ifdef WIN32 + DEBUGUUID(msg, (nsID *)&IID_MEMBER(value)); +# else /* !WIN32 */ + DEBUGUUID(msg, IID_MEMBER(value)); +# endif /* !WIN32 */ +} + +#else /* VBOX_API_VERSION != 2002000 */ + +static nsresult +_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +{ + return progress->vtbl->GetResultCode(progress, &resultCode->resultCode); +} + +static void _initializeVboxIID(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); + IID_MEMBER(owner) = true; +} + +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ + DEBUGPRUnichar(msg, IID_MEMBER(value)); +} + +#endif /* VBOX_API_VERSION != 2002000 */ + +#if VBOX_API_VERSION < 4000000 + +static nsresult +_objectGetMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->GetMachine(data->vboxObj, IID_MEMBER(value), machine); +} + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +{ + return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->Close(session); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_objectGetMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->FindMachine(data->vboxObj, IID_MEMBER(value), machine); +} + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->UnlockMachine(session); +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + +static vboxUniformedIID _UIID = { + .initializeVboxIID = _initializeVboxIID, + .vboxIIDUnalloc = _vboxIIDUnalloc, + .vboxIIDFromUUID = _vboxIIDFromUUID, + .DEBUGIID = _DEBUGIID, +}; + +static vboxUniformedIObject _UIObject = { + .GetMachine = _objectGetMachine, +}; + +static vboxUniformedISession _UISession = { + .OpenExisting = _sessionOpenExisting, + .Close = _sessionClose, + .GetConsole = _sessionGetConsole, +}; + +static vboxUniformedIConsole _UIConsole = { + .SaveState = _consoleSaveState, +}; + +static vboxUniformedIProgress _UIProgress = { + .WaitForCompletion = _progressWaitForCompletion, + .GetResultCode = _progressGetResultCode, +}; + +static vboxUniformednsISupports _nsUISupports = { + .Release = _nsisupportsRelease, +}; + +void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) +{ + pVBoxAPI->APIVersion = VBOX_API_VERSION; + pVBoxAPI->XPCOMCVersion = VBOX_XPCOMC_VERSION; + pVBoxAPI->pfnInitialize = _pfnInitialize; + pVBoxAPI->initializeFWatch = _initializeFWatch; + pVBoxAPI->UIID = _UIID; + pVBoxAPI->UIObject = _UIObject; + pVBoxAPI->UISession = _UISession; + pVBoxAPI->UIConsole = _UIConsole; + pVBoxAPI->UIProgress = _UIProgress; + pVBoxAPI->nsUISupports = _nsUISupports; +#if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) + /* No event queue functionality in 2.2.* as of now */ + pVBoxAPI->fWatchNeedInitialize = 0; +#else /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + pVBoxAPI->fWatchNeedInitialize = 1; +#endif /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + +#if VBOX_API_VERSION >= 4000000 + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + pVBoxAPI->getMachineForSession = 1; +#else /* VBOX_API_VERSION < 4000000 */ + pVBoxAPI->getMachineForSession = 0; +#endif /* VBOX_API_VERSION < 4000000 */ +} + +/* End of vboxUniformedAPI and Begin of common codes */ + static PRUnichar * vboxSocketFormatAddrUtf16(vboxGlobalData *data, virSocketAddrPtr addr) { @@ -915,58 +1126,6 @@ static virCapsPtr vboxCapsInit(void) return NULL; } -static int -vboxInitialize(vboxGlobalData *data) -{ - data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); - - if (data->pFuncs == NULL) - goto cleanup; - -#if VBOX_XPCOMC_VERSION == 0x00010000U - data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession); -#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ - data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, - ISESSION_IID_STR, &data->vboxSession); - -# if VBOX_API_VERSION == 2002000 - - /* No event queue functionality in 2.2.* as of now */ - -# else /* !(VBOX_API_VERSION == 2002000) */ - - /* Initial the fWatch needed for Event Callbacks */ - data->fdWatch = -1; - - data->pFuncs->pfnGetEventQueue(&data->vboxQueue); - - if (data->vboxQueue == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("nsIEventQueue object is null")); - goto cleanup; - } - -# endif /* !(VBOX_API_VERSION == 2002000) */ -#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ - - if (data->vboxObj == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("IVirtualBox object is null")); - goto cleanup; - } - - if (data->vboxSession == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ISession object is null")); - goto cleanup; - } - - return 0; - - cleanup: - return -1; -} - static int vboxExtractVersion(vboxGlobalData *data) { int ret = -1; @@ -2093,67 +2252,6 @@ vboxDomainGetState(virDomainPtr dom, return ret; } -static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - - /* VirtualBox currently doesn't support saving to a file - * at a location other then the machine folder and thus - * setting path to ATTRIBUTE_UNUSED for now, will change - * this behaviour once get the VirtualBox API in right - * shape to do this - */ - - /* Open a Session for the machine */ - vboxIIDFromUUID(&iid, dom->uuid); -#if VBOX_API_VERSION >= 4000000 - /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return -1; - } -#endif - - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (NS_SUCCEEDED(rc) && console) { - IProgress *progress = NULL; - - console->vtbl->SaveState(console, &progress); - - if (progress) { -#if VBOX_API_VERSION == 2002000 - nsresult resultCode; -#else - PRInt32 resultCode; -#endif - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_SUCCEEDED(resultCode)) { - ret = 0; - } - VBOX_RELEASE(progress); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } - - DEBUGIID("UUID of machine being saved:", iid.value); - - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 39b034d..a052a0f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -194,4 +194,16 @@ typedef struct { int vboxInitialize(vboxGlobalData *data); int vboxDomainSave(virDomainPtr dom, const char *path); +/* Version specified functions for installing uniformed API */ +void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox30InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox31InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox32InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox40InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox41InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox42InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox42_20InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox43InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vbox43_4InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); + #endif /* VBOX_UNIFORMED_API_H */ -- 1.7.9.5

Install vboxUniformedAPI in the new way. With the prototype: void vboxRegisterUniformedAPI(uint32_t uVersion); And leave the install job to the vbox_common.c --- src/vbox/vbox_common.c | 30 ++++++++++++++++++++++++++++++ src/vbox/vbox_driver.c | 22 ++++++++++++++++++---- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 3f95abb..12b3e33 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -75,6 +75,36 @@ static int openSessionForMachine(vboxGlobalData *data, vboxIIDUnion *iid, const return 0; } +void vboxRegisterUniformedAPI(uint32_t uVersion) +{ + /* Install gVBoxAPI according to the vbox API version. + * This function don't check the validation of the + * uVersion, it assumes the vboxRegister will do this + * job. + */ + if (uVersion >= 2001052 && uVersion < 2002051) { + vbox22InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 2002051 && uVersion < 3000051) { + vbox30InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 3000051 && uVersion < 3001051) { + vbox31InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 3001051 && uVersion < 3002051) { + vbox32InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 3002051 && uVersion < 4000051) { + vbox40InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 4000051 && uVersion < 4001051) { + vbox41InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 4001051 && uVersion < 4002020) { + vbox42InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 4002020 && uVersion < 4002051) { + vbox42_20InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 4002051 && uVersion < 4003004) { + vbox43InstallUniformedAPI(&gVBoxAPI); + } else if (uVersion >= 4003004 && uVersion < 4003051) { + vbox43_4InstallUniformedAPI(&gVBoxAPI); + } +} + int vboxInitialize(vboxGlobalData *data) { if (gVBoxAPI.pfnInitialize(data) != 0) diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 7d004b2..0b71a5a 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -39,6 +39,9 @@ #include "vbox_glue.h" #include "virerror.h" #include "virutil.h" +#include "domain_event.h" +#include "domain_conf.h" +#include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -144,10 +147,10 @@ int vboxRegister(void) networkDriver = &vbox42NetworkDriver; storageDriver = &vbox42StorageDriver; } else if (uVersion >= 4002020 && uVersion < 4002051) { - VIR_DEBUG("VirtualBox API version: 4.2.20 or higher"); - driver = &vbox42_20Driver; - networkDriver = &vbox42_20NetworkDriver; - storageDriver = &vbox42_20StorageDriver; + VIR_DEBUG("VirtualBox API version: 4.2.20 or higher"); + driver = &vbox42_20Driver; + networkDriver = &vbox42_20NetworkDriver; + storageDriver = &vbox42_20StorageDriver; } else if (uVersion >= 4002051 && uVersion < 4003004) { VIR_DEBUG("VirtualBox API version: 4.3"); driver = &vbox43Driver; @@ -161,6 +164,17 @@ int vboxRegister(void) } else { VIR_DEBUG("Unsupported VirtualBox API version: %u", uVersion); } + /* Register vboxUniformedAPI. The dummy driver will not + * use vboxAPI, so the register step is only for validate + * vbox API versions. + * When the vbox driver is fully redesigned, and there is no + * vbox**Driver or vbox**NetworkDriver or vbox**StorageDriver any + * more, the registerAPI function will handle all jobs in this + * vboxRegister (eg. API version check, return a dummy driver + * for unsupported version). + * But the current design is a solution for compatibility. + */ + vboxRegisterUniformedAPI(uVersion); } else { VIR_DEBUG("VBoxCGlueInit failed, using dummy driver"); } diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index a052a0f..8aede4c 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -206,4 +206,6 @@ void vbox42_20InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); void vbox43InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); void vbox43_4InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); +void vboxRegisterUniformedAPI(uint32_t uVersion); + #endif /* VBOX_UNIFORMED_API_H */ -- 1.7.9.5

On 02.07.2014 18:53, Taowei wrote:
Fix some problems in last patch. Includes: * Re-manage the patches in a better order, move some symbol definitions into the proper patch. * Make the API in vboxUniformedAPI hierarchical. So when more apis introduced into the uniformed api, it wouldn't go to a mess. * Rewrite the vboxDomainSave in a better way.
Taowei (4): Define vboxUniformedAPI Implement vboxInitialize and vboxDomainSave Implement uniformed api for each vbox version Install vboxUniformedAPI
po/POTFILES.in | 1 + src/Makefile.am | 4 +- src/vbox/vbox_common.c | 183 +++++++++++++++ src/vbox/vbox_common.h | 151 ++++++++++++ src/vbox/vbox_driver.c | 22 +- src/vbox/vbox_tmpl.c | 504 ++++++++++++++++++++++++----------------- src/vbox/vbox_uniformed_api.h | 211 +++++++++++++++++ 7 files changed, 868 insertions(+), 208 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_uniformed_api.h
Okay, all the patches works for me. I think you can start rewriting more APIs. Michal
participants (2)
-
Michal Privoznik
-
Taowei