[libvirt] [PATCH v2 2/2] parallels: login to parallels SDK
Dmitry Guryanov
dguryanov at parallels.com
Thu Sep 11 14:19:23 UTC 2014
On Thursday 11 September 2014 12:09:20 Daniel P. Berrange wrote:
> On Sat, Sep 06, 2014 at 08:28:10PM +0400, Dmitry Guryanov wrote:
> > Add files parallels_sdk.c and parallels_sdk.h for code
> > which works with SDK, so libvirt's code will not mix with
> > dealing with parallels SDK.
> >
> > To use Parallels SDK you must first call PrlApi_InitEx function,
> > and then you will be able to connect to a server with
> > PrlSrv_LoginLocalEx function. When you've done you must call
> > PrlApi_Deinit. So let's call PrlApi_InitEx on first .connectOpen,
> > count number of connections and deinitialize, when this counter
> > becomes zero.
>
> As a general rule, even if we count the open/close calls
> it isn't safe to run deinit functions in libvirt. eg consider
> if libvirt is linked against another program or library that
> also uses the paralllels SDK. Libvirt does not know if the
> other code has stopped using the SDK. So either the reference
> counting must be done in PrlApi_{InitEx,Deinit} functions
> directly, or libvirt should simply not call PrlApi_Deinit
> at all. I'd probably just go with the latter, as I doubt there
> is any real harm to skipping deinit.
>
I can move reference counting to parallels SDK,
> > diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
> > new file mode 100644
> > index 0000000..22afd61
> > --- /dev/null
> > +++ b/src/parallels/parallels_sdk.c
> > @@ -0,0 +1,241 @@
> >
> > +
> > +#define VIR_FROM_THIS VIR_FROM_PARALLELS
>
> The use of this constant here will mean any error message printed
> by libvirt will have a 'Parallels Cloud Server:' prefix on it
>
> > +static void
> > +logPrlErrorHelper(PRL_RESULT err, const char *filename,
> > + const char *funcname, size_t linenr)
> > +{
> > + char *msg1 = NULL, *msg2 = NULL;
> > + PRL_UINT32 len = 0;
> > +
> > + /* Get required buffer length */
> > + PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, NULL, &len);
> > +
> > + if (VIR_ALLOC_N(msg1, len) < 0)
> > + goto out;
> > +
> > + /* get short error description */
> > + PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, msg1, &len);
> > +
> > + PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, NULL, &len);
> > +
> > + if (VIR_ALLOC_N(msg2, len) < 0)
> > + goto out;
> > +
> > + /* get long error description */
> > + PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, msg2, &len);
> > +
> > + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
> > + filename, funcname, linenr,
> > + _("Parallels SDK: %s %s"), msg1, msg2);
>
> So adding 'Parallels SDK' is probably overkill here. I'd suggest
> just us '%s %s' instead.
>
OK, thanks, I'll fix it.
> > +
>
> > + out:
> nit-pick, we tend to use 'cleanup' as a standard label name
>
> > + VIR_FREE(msg1);
> > + VIR_FREE(msg2);
> > +}
> > +
> > +#define logPrlError(code) \
> > + logPrlErrorHelper(code, __FILE__, \
> > + __FUNCTION__, __LINE__)
> > +
> > +static PRL_RESULT
> > +logPrlEventErrorHelper(PRL_HANDLE event, const char *filename,
> > + const char *funcname, size_t linenr)
> > +{
> > + PRL_RESULT ret, retCode;
> > + char *msg1 = NULL, *msg2 = NULL;
> > + PRL_UINT32 len = 0;
> > + int err = -1;
> > +
> > + if ((ret = PrlEvent_GetErrCode(event, &retCode))) {
> > + logPrlError(ret);
> > + return ret;
> > + }
> > +
> > + PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, NULL, &len);
> > +
> > + if (VIR_ALLOC_N(msg1, len) < 0)
> > + goto out;
> > +
> > + PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, msg1, &len);
> > +
> > + PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, NULL, &len);
> > +
> > + if (VIR_ALLOC_N(msg2, len) < 0)
> > + goto out;
> > +
> > + PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, msg2, &len);
> > +
> > + virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
> > + filename, funcname, linenr,
> > + _("Parallels SDK: %s %s"), msg1, msg2);
>
> Same note here.
>
> > + err = 0;
> > +
>
> > + out:
> And here.
>
> > + VIR_FREE(msg1);
> > + VIR_FREE(msg2);
> > +
> > + return err;
> > +}
> > +
> > +#define logPrlEventError(event) \
> > + logPrlEventErrorHelper(event, __FILE__, \
> > + __FUNCTION__, __LINE__)
> > +
> > +static PRL_HANDLE
> > +getJobResultHelper(PRL_HANDLE job, unsigned int timeout,
> > + const char *filename, const char *funcname,
> > + size_t linenr)
> > +{
> > + PRL_RESULT ret, retCode;
> > + PRL_HANDLE result = NULL;
> > +
> > + if ((ret = PrlJob_Wait(job, timeout))) {
> > + logPrlErrorHelper(ret, filename, funcname, linenr);
> > + goto out;
> > + }
> > +
> > + if ((ret = PrlJob_GetRetCode(job, &retCode))) {
> > + logPrlErrorHelper(ret, filename, funcname, linenr);
> > + goto out;
> > + }
> > +
> > + if (retCode) {
> > + PRL_HANDLE err_handle;
> > +
> > + /* Sometimes it's possible to get additional error info. */
> > + if ((ret = PrlJob_GetError(job, &err_handle))) {
> > + logPrlErrorHelper(ret, filename, funcname, linenr);
> > + goto out;
> > + }
> > +
> > + if (logPrlEventErrorHelper(err_handle, filename, funcname,
> > linenr)) + logPrlErrorHelper(retCode, filename, funcname,
> > linenr); +
> > + PrlHandle_Free(err_handle);
> > + } else {
> > + ret = PrlJob_GetResult(job, &result);
> > + if (PRL_FAILED(ret)) {
> > + logPrlErrorHelper(ret, filename, funcname, linenr);
> > + PrlHandle_Free(result);
> > + result = NULL;
> > + goto out;
> > + }
> > + }
> > +
>
> > + out:
> Here
>
> > + PrlHandle_Free(job);
> > + return result;
> > +}
> > +
>
> Regards,
> Daniel
--
Dmitry Guryanov
More information about the libvir-list
mailing list