[libvirt] [PATCH 1/2] python: cleanup vcpu related binding APIs
Michal Privoznik
mprivozn at redhat.com
Thu Sep 27 13:51:06 UTC 2012
On 26.09.2012 19:33, Guannan Ren wrote:
> libvirt_virDomainGetVcpus: add error handling, return -1 instead of None
> libvirt_virDomainPinVcpu and libvirt_virDomainPinVcpuFlags:
> make use of libvirt_boolUnwrap
>
> Set bitmap according to these values which are contained in given
> argument of vcpu tuple and turn off these bit corresponding to
> missing vcpus in argument tuple
>
> The original way ignored the error info from PyTuple_GetItem
> if index is out of range.
> "IndexError: tuple index out of range"
> The error message will only be raised on next command in interactive mode.
> ---
> python/libvirt-override.c | 171 +++++++++++++++++++++++++++++++++-------------
> 1 file changed, 123 insertions(+), 48 deletions(-)
>
> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
> index 25f9d3f..b69f5cf 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -1333,9 +1333,11 @@ cleanup:
>
> static PyObject *
> libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
> - PyObject *args) {
> + PyObject *args)
> +{
> virDomainPtr domain;
> PyObject *pyobj_domain, *pyretval = NULL, *pycpuinfo = NULL, *pycpumap = NULL;
> + PyObject *error = NULL;
You are not setting this variable before every 'goto cleanup;' and I
think it should be done. Or is it okay to return NULL?
> virNodeInfo nodeinfo;
> virDomainInfo dominfo;
> virVcpuInfoPtr cpuinfo = NULL;
> @@ -1352,29 +1354,33 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
> i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo);
> LIBVIRT_END_ALLOW_THREADS;
> if (i_retval < 0)
> - return VIR_PY_NONE;
> + return VIR_PY_INT_FAIL;
>
> LIBVIRT_BEGIN_ALLOW_THREADS;
> i_retval = virDomainGetInfo(domain, &dominfo);
> LIBVIRT_END_ALLOW_THREADS;
> if (i_retval < 0)
> - return VIR_PY_NONE;
> + return VIR_PY_INT_FAIL;
>
> if (VIR_ALLOC_N(cpuinfo, dominfo.nrVirtCpu) < 0)
> - return VIR_PY_NONE;
> + return PyErr_NoMemory();
>
> cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
> if (xalloc_oversized(dominfo.nrVirtCpu, cpumaplen) ||
> - VIR_ALLOC_N(cpumap, dominfo.nrVirtCpu * cpumaplen) < 0)
> + VIR_ALLOC_N(cpumap, dominfo.nrVirtCpu * cpumaplen) < 0) {
> + error = PyErr_NoMemory();
> goto cleanup;
> + }
>
> LIBVIRT_BEGIN_ALLOW_THREADS;
> i_retval = virDomainGetVcpus(domain,
> cpuinfo, dominfo.nrVirtCpu,
> cpumap, cpumaplen);
> LIBVIRT_END_ALLOW_THREADS;
> - if (i_retval < 0)
> + if (i_retval < 0) {
> + error = VIR_PY_INT_FAIL;
> goto cleanup;
> + }
>
> /* convert to a Python tuple of long objects */
> if ((pyretval = PyTuple_New(2)) == NULL)
> @@ -1386,13 +1392,43 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
>
> for (i = 0 ; i < dominfo.nrVirtCpu ; i++) {
> PyObject *info = PyTuple_New(4);
> + PyObject *item = NULL;
> + bool itemError = true;
> +
> if (info == NULL)
> goto cleanup;
> - PyTuple_SetItem(info, 0, PyInt_FromLong((long)cpuinfo[i].number));
> - PyTuple_SetItem(info, 1, PyInt_FromLong((long)cpuinfo[i].state));
> - PyTuple_SetItem(info, 2, PyLong_FromLongLong((long long)cpuinfo[i].cpuTime));
> - PyTuple_SetItem(info, 3, PyInt_FromLong((long)cpuinfo[i].cpu));
> - PyList_SetItem(pycpuinfo, i, info);
> + do {
> + if ((item = PyInt_FromLong((long)cpuinfo[i].number)) == NULL)
> + break;
> + else if ((PyTuple_SetItem(info, 0, item)) < 0)
> + break;
> +
> + if ((item = PyInt_FromLong((long)cpuinfo[i].state)) == NULL)
> + break;
> + else if (PyTuple_SetItem(info, 1, item) < 0)
> + break;
> +
> + if ((item = PyLong_FromLongLong((long long)cpuinfo[i].cpuTime)) == NULL)
> + break;
> + else if (PyTuple_SetItem(info, 2, item) < 0)
> + break;
> +
> + if ((item = PyInt_FromLong((long)cpuinfo[i].cpu)) == NULL)
> + break;
> + else if (PyTuple_SetItem(info, 3, item) < 0)
> + break;
> +
> + if (PyList_SetItem(pycpuinfo, i, info) < 0)
> + break;
> +
> + itemError = false;
> + } while (0);
> +
> + if (itemError) {
> + Py_DECREF(info);
> + Py_XDECREF(item);
> + goto cleanup;
> + }
No. I know python bindings code are mess but this won't make it any
better. First of all:
if (cond1)
code_block;
else if (cond2)
the_very_same_codeblock;
can be joined like this:
if (cond1 || cond2)
code_block;
Second - drop the do { } while(0) and use a label instead:
if (cond1 || cond2)
goto label;
This label can in this special case be at the end of the parent for
loop; However, there needs to be 'continue' just before the label so the
for loop doesn't execute the label itself.
> }
> for (i = 0 ; i < dominfo.nrVirtCpu ; i++) {
> PyObject *info = PyTuple_New(VIR_NODEINFO_MAXCPUS(nodeinfo));
> @@ -1400,36 +1436,52 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
> if (info == NULL)
> goto cleanup;
> for (j = 0 ; j < VIR_NODEINFO_MAXCPUS(nodeinfo) ; j++) {
> - PyTuple_SetItem(info, j, PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen, i, j)));
> + PyObject *item = NULL;
> + if ((item = PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen, i, j))) == NULL) {
> + Py_DECREF(info);
> + goto cleanup;
> + } else if (PyTuple_SetItem(info, j, item) < 0) {
> + Py_DECREF(info);
> + Py_DECREF(item);
> + goto cleanup;
Again, join this if () else if; you probably need to use
Py_XDECREF(item) then.
> + }
> + }
> + if (PyList_SetItem(pycpumap, i, info) < 0) {
> + Py_DECREF(info);
> + goto cleanup;
> }
> - PyList_SetItem(pycpumap, i, info);
> }
> - PyTuple_SetItem(pyretval, 0, pycpuinfo);
> - PyTuple_SetItem(pyretval, 1, pycpumap);
> + if (PyTuple_SetItem(pyretval, 0, pycpuinfo) < 0)
> + goto cleanup;
> +
> + if (PyTuple_SetItem(pyretval, 1, pycpumap) < 0)
> + goto cleanup;
And again a candidate for joining.
>
> VIR_FREE(cpuinfo);
> VIR_FREE(cpumap);
>
> return pyretval;
>
> - cleanup:
> +cleanup:
> VIR_FREE(cpuinfo);
> VIR_FREE(cpumap);
> Py_XDECREF(pyretval);
> Py_XDECREF(pycpuinfo);
> Py_XDECREF(pycpumap);
> - return VIR_PY_NONE;
> + return error;
> }
>
>
> static PyObject *
> libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED,
> - PyObject *args) {
> + PyObject *args)
> +{
> virDomainPtr domain;
> - PyObject *pyobj_domain, *pycpumap, *truth;
> + PyObject *pyobj_domain, *pycpumap;
> + PyObject *ret = NULL;
> virNodeInfo nodeinfo;
> unsigned char *cpumap;
> - int cpumaplen, i, vcpu;
> + int cpumaplen, i, j, vcpu, tuple_size;
> int i_retval;
>
> if (!PyArg_ParseTuple(args, (char *)"OiO:virDomainPinVcpu",
> @@ -1445,37 +1497,50 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED,
>
> cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
> if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
> - return VIR_PY_INT_FAIL;
> + return PyErr_NoMemory();
> +
> + tuple_size = PyTuple_Size(pycpumap);
> + if (tuple_size == -1)
> + goto cleanup;
>
> - truth = PyBool_FromLong(1);
> - for (i = 0 ; i < VIR_NODEINFO_MAXCPUS(nodeinfo) ; i++) {
> + for (i = 0; i < tuple_size; i++) {
> PyObject *flag = PyTuple_GetItem(pycpumap, i);
> - if (flag == truth)
> - VIR_USE_CPU(cpumap, i);
> - else
> - VIR_UNUSE_CPU(cpumap, i);
> + bool b;
> +
> + if (!flag || libvirt_boolUnwrap(flag, &b) < 0)
> + goto cleanup;
> +
> + (b) ? VIR_USE_CPU(cpumap, i) : VIR_UNUSE_CPU(cpumap, i);
Well, in libvirt we prefer 'if (b) ...' rather than this.
> }
>
> + for (j = 0; j < VIR_NODEINFO_MAXCPUS(nodeinfo) - i; j++)
> + VIR_UNUSE_CPU(cpumap, i + j);
> +
This would be more readable as:
for (; i < VIR_NODEINFO_MAXCPUS(nodeinfo); i++)
VIR_UNUSE_CPU(cpumap, i);
The 'j' variable can be then dropped.
> LIBVIRT_BEGIN_ALLOW_THREADS;
> i_retval = virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen);
> LIBVIRT_END_ALLOW_THREADS;
> - Py_DECREF(truth);
> - VIR_FREE(cpumap);
>
> - if (i_retval < 0)
> - return VIR_PY_INT_FAIL;
> + if (i_retval < 0) {
> + ret = VIR_PY_INT_FAIL;
> + goto cleanup;
> + }
> + ret = VIR_PY_INT_SUCCESS;
>
> - return VIR_PY_INT_SUCCESS;
> +cleanup:
> + VIR_FREE(cpumap);
> + return ret;
> }
>
> static PyObject *
> libvirt_virDomainPinVcpuFlags(PyObject *self ATTRIBUTE_UNUSED,
> - PyObject *args) {
> + PyObject *args)
> +{
> virDomainPtr domain;
> - PyObject *pyobj_domain, *pycpumap, *truth;
> + PyObject *pyobj_domain, *pycpumap;
> + PyObject *ret = NULL;
> virNodeInfo nodeinfo;
> unsigned char *cpumap;
> - int cpumaplen, i, vcpu;
> + int cpumaplen, i, j, vcpu, tuple_size;
> unsigned int flags;
> int i_retval;
>
> @@ -1492,27 +1557,37 @@ libvirt_virDomainPinVcpuFlags(PyObject *self ATTRIBUTE_UNUSED,
>
> cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
> if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
> - return VIR_PY_INT_FAIL;
> + return PyErr_NoMemory();
> +
> + tuple_size = PyTuple_Size(pycpumap);
> + if (tuple_size == -1)
> + goto cleanup;
>
> - truth = PyBool_FromLong(1);
> - for (i = 0 ; i < VIR_NODEINFO_MAXCPUS(nodeinfo) ; i++) {
> + for (i = 0; i < tuple_size; i++) {
> PyObject *flag = PyTuple_GetItem(pycpumap, i);
> - if (flag == truth)
> - VIR_USE_CPU(cpumap, i);
> - else
> - VIR_UNUSE_CPU(cpumap, i);
> + bool b;
> +
> + if (!flag || libvirt_boolUnwrap(flag, &b) < 0)
> + goto cleanup;
> +
> + (b) ? VIR_USE_CPU(cpumap, i) : VIR_UNUSE_CPU(cpumap, i);
same applies here
> }
>
> + for (j = 0; j < VIR_NODEINFO_MAXCPUS(nodeinfo) - i; j++)
> + VIR_UNUSE_CPU(cpumap, i + j);
> +
and here
> LIBVIRT_BEGIN_ALLOW_THREADS;
> i_retval = virDomainPinVcpuFlags(domain, vcpu, cpumap, cpumaplen, flags);
> LIBVIRT_END_ALLOW_THREADS;
> - Py_DECREF(truth);
> - VIR_FREE(cpumap);
> -
> - if (i_retval < 0)
> - return VIR_PY_INT_FAIL;
> + if (i_retval < 0) {
> + ret = VIR_PY_INT_FAIL;
> + goto cleanup;
> + }
> + ret = VIR_PY_INT_SUCCESS;
>
> - return VIR_PY_INT_SUCCESS;
> +cleanup:
> + VIR_FREE(cpumap);
> + return ret;
> }
>
> static PyObject *
>
Michal
More information about the libvir-list
mailing list