[libvirt] [PATCH] Add two NUMA tuning python bindings APIs

Guan Nan Ren gren at redhat.com
Thu Jan 19 08:54:51 UTC 2012



----- Original Message -----
From: "Alex Jia" <ajia at redhat.com>
To: "Guan Nan Ren" <gren at redhat.com>
Cc: libvir-list at redhat.com
Sent: Thursday, January 19, 2012 1:39:58 PM
Subject: Re: [libvirt] [PATCH] Add two NUMA tuning python bindings APIs

On 01/19/2012 11:29 AM, Alex Jia wrote:
> On 01/19/2012 09:38 AM, Guan Nan Ren wrote:
>>    Hi
>>
>>       Anybody could give a hand on reviewing this patch,
>>       I appreciate it.
>>       Chinese New Year is coming, best wishes to this community :)
>>
>>    Guannan Ren
> Happy New Year!
>> ----- Original Message -----
>> From: "Guannan Ren"<gren at redhat.com>
>> To: libvir-list at redhat.com
>> Sent: Monday, January 16, 2012 6:58:06 PM
>> Subject: [libvirt] [PATCH] Add two NUMA tuning python bindings APIs
>>
>>          *virDomainSetNumaParameters
>>          *virDomainGetNumaParameters
>> ---
>>   python/libvirt-override-api.xml |   13 +++
>>   python/libvirt-override.c       |  186 
>> +++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 199 insertions(+), 0 deletions(-)
>>
>> diff --git a/python/libvirt-override-api.xml 
>> b/python/libvirt-override-api.xml
>> index 704fee9..e09290c 100644
>> --- a/python/libvirt-override-api.xml
>> +++ b/python/libvirt-override-api.xml
>> @@ -248,6 +248,19 @@
>> <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
>> <arg name='flags' type='int' info='an OR'ed set of 
>> virDomainModificationImpact'/>
>> </function>
>> +<function name='virDomainSetNumaParameters' file='python'>
>> +<info>Change the NUMA tunables</info>
>> +<return type='int' info='-1 in case of error, 0 in case of success.'/>
>> +<arg name='domain' type='virDomainPtr' info='pointer to domain 
>> object'/>
>> +<arg name='params' type='virTypedParameterPtr' info='pointer to 
>> memory tunable objects'/>
A copy-paste error, s/memory/numa/.
>> +<arg name='flags'  type='int' info='an OR'ed set of 
>> virDomainModificationImpact'/>
>> +</function>
>> +<function name='virDomainGetNumaParameters' file='python'>
>> +<info>Get the NUMA parameters</info>
>> +<return type='virTypedParameterPtr' info='the I/O tunables value or 
>> None in case of error'/>
Save as above, s/I/O/numa/.
>> +<arg name='domain' type='virDomainPtr' info='pointer to domain 
>> object'/>
>> +<arg name='flags' type='int' info='an OR'ed set of 
>> virDomainModificationImpact'/>
>> +</function>
>> <function name='virConnectListStoragePools' file='python'>
>> <info>list the storage pools, stores the pointers to the names in 
>> @names</info>
>> <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor 
>> connection'/>
>> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
>> index d2aad0f..27ad1d8 100644
>> --- a/python/libvirt-override.c
>> +++ b/python/libvirt-override.c
>> @@ -1000,6 +1000,190 @@ libvirt_virDomainGetMemoryParameters(PyObject 
>> *self ATTRIBUTE_UNUSED,
>>   }
>>
>>   static PyObject *
>> +libvirt_virDomainSetNumaParameters(PyObject *self ATTRIBUTE_UNUSED,
>> +                                     PyObject *args) {
>> +    virDomainPtr domain;
>> +    PyObject *pyobj_domain, *info;
>> +    int i_retval;
>> +    int nparams = 0, i;
>> +    unsigned int flags;
>> +    virTypedParameterPtr params;
>> +
>> +    if (!PyArg_ParseTuple(args,
>> +                          (char *)"OOi:virDomainSetNumaParameters",
>> +&pyobj_domain,&info,&flags))
>> +        return(NULL);
>> +    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
>> +
>> +    LIBVIRT_BEGIN_ALLOW_THREADS;
>> +    i_retval = virDomainGetNumaParameters(domain, NULL,&nparams, 
>> flags);
>> +    LIBVIRT_END_ALLOW_THREADS;
>> +
>> +    if (i_retval<  0)
>> +        return VIR_PY_INT_FAIL;
>> +
>> +    if ((params = malloc(sizeof(*params)*nparams)) == NULL)
>> +        return VIR_PY_INT_FAIL;
>> +
>> +    LIBVIRT_BEGIN_ALLOW_THREADS;
>> +    i_retval = virDomainGetNumaParameters(domain, params,&nparams, 
>> flags);
>> +    LIBVIRT_END_ALLOW_THREADS;
>> +
>> +    if (i_retval<  0) {
>> +        free(params);
>> +        return VIR_PY_INT_FAIL;
>> +    }
>> +
>> +    /* convert to a Python tuple of long objects */
>> +    for (i = 0; i<  nparams; i++) {
>> +        PyObject *key, *val;
>> +        key = libvirt_constcharPtrWrap(params[i].field);
>> +        val = PyDict_GetItem(info, key);
>> +        Py_DECREF(key);
>> +
>> +        if (val == NULL)
>> +            continue;
>> +
>> +        switch (params[i].type) {
>> +        case VIR_TYPED_PARAM_INT:
>> +            params[i].value.i = (int)PyInt_AS_LONG(val);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_UINT:
>> +            params[i].value.ui = (unsigned int)PyInt_AS_LONG(val);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_LLONG:
>> +            params[i].value.l = (long long)PyLong_AsLongLong(val);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_ULLONG:
>> +            params[i].value.ul = (unsigned long 
>> long)PyLong_AsLongLong(val);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_DOUBLE:
>> +            params[i].value.d = (double)PyFloat_AsDouble(val);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_BOOLEAN:
>> +            {
>> +                /* Hack - Python's definition of Py_True breaks strict
>> +                 * aliasing rules, so can't directly compare
>> +                 */
>> +                PyObject *hacktrue = PyBool_FromLong(1);
>> +                params[i].value.b = hacktrue == val ? 1: 0;
>> +                Py_DECREF(hacktrue);
>> +            }
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_STRING:
>> +            params[i].value.s = PyString_AsString(val);
>> +            break;
>> +
>> +        default:
>> +            free(params);
>> +            return VIR_PY_INT_FAIL;
>> +        }
>> +    }
>> +
>> +    LIBVIRT_BEGIN_ALLOW_THREADS;
>> +    i_retval = virDomainSetNumaParameters(domain, params, nparams, 
>> flags);
>> +    LIBVIRT_END_ALLOW_THREADS;
>> +    if (i_retval<  0) {
>> +        free(params);
>> +        return VIR_PY_INT_FAIL;
>> +    }
>> +
>> +    free(params);
>> +    return VIR_PY_INT_SUCCESS;
>> +}
>> +
>> +static PyObject *
>> +libvirt_virDomainGetNumaParameters(PyObject *self ATTRIBUTE_UNUSED,
>> +                                     PyObject *args) {
>> +    virDomainPtr domain;
>> +    PyObject *pyobj_domain, *info;
>> +    int i_retval;
>> +    int nparams = 0, i;
>> +    unsigned int flags;
>> +    virTypedParameterPtr params;
>> +
>> +    if (!PyArg_ParseTuple(args, (char 
>> *)"Oi:virDomainGetNumaParameters",
>> +&pyobj_domain,&flags))
>> +        return(NULL);
>> +    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
>> +
>> +    LIBVIRT_BEGIN_ALLOW_THREADS;
>> +    i_retval = virDomainGetNumaParameters(domain, NULL,&nparams, 
>> flags);
>> +    LIBVIRT_END_ALLOW_THREADS;
>> +
>> +    if (i_retval<  0)
>> +        return VIR_PY_NONE;
>> +
>> +    if ((params = malloc(sizeof(*params)*nparams)) == NULL)
>> +        return VIR_PY_NONE;
>> +
>> +    LIBVIRT_BEGIN_ALLOW_THREADS;
>> +    i_retval = virDomainGetNumaParameters(domain, params,&nparams, 
>> flags);
>> +    LIBVIRT_END_ALLOW_THREADS;
>> +
>> +    if (i_retval<  0) {
>> +        free(params);
>> +        return VIR_PY_NONE;
>> +    }
>> +
>> +    /* convert to a Python tuple of long objects */
>> +    if ((info = PyDict_New()) == NULL) {
>> +        free(params);
>> +        return VIR_PY_NONE;
>> +    }
>> +
>> +    for (i = 0 ; i<  nparams ; i++) {
>> +        PyObject *key, *val;
>> +
>> +        switch (params[i].type) {
>> +        case VIR_TYPED_PARAM_INT:
>> +            val = PyInt_FromLong((long)params[i].value.i);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_UINT:
>> +            val = PyInt_FromLong((long)params[i].value.ui);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_LLONG:
>> +            val = PyLong_FromLongLong((long long)params[i].value.l);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_ULLONG:
>> +            val = PyLong_FromLongLong((long long)params[i].value.ul);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_DOUBLE:
>> +            val = PyFloat_FromDouble((double)params[i].value.d);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_BOOLEAN:
>> +            val = PyBool_FromLong((long)params[i].value.b);
>> +            break;
>> +
>> +        case VIR_TYPED_PARAM_STRING:
>> +            val = libvirt_constcharPtrWrap(params[i].value.s);
> The above style isn't consistent with previous codes, the 
> libvirt_constcharPtrWrap is
> a wrapper function, it will be better to uniform them.
>
> In addition, the function libvirt_constcharPtrWrap will call 
> PyString_FromString() to
> return a new reference of a string, but the original string memory 
> hasn't been released,
> so original function/caller need to free it, moreover, the 
> libvirt_constcharPtrWrap is
> called in a loop, so you also need to free it in a loop and 'default' 
> branch.

   Hi Alex

     The call to PyString_FromString() will cause Python memory manager 
   to allocate a new string object in Python's private heap rather than
   incrementing a reference to the string in system heap.
     Meanwhile, the function returns the ownership of a new reference(probably
   the first one) to the string object to "val".
     According to the Memory Management doc,"PyDict_SetItem() and friends 
   don’t take over ownership" that means It doesn't increment the reference 
   to the string object.
     So, The object reference returned from the C function that is called from Python
   is returned to the Python program with only one reference. as for the string
   in the system heap, it is release by "free(params)" above the last return.

   Guannan Ren

     
 





More information about the libvir-list mailing list