X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=libvirt%2Flibvirt_c.c;h=c5680267980b296d8fe1a1bc637ac07ab754ff4c;hb=a0e7843645253be00956b5382242791fe126eb28;hp=f896097ed2e7e062d8975e2925032731be63ff19;hpb=0e09861c06a0c274bcfdacceaee347f8aaa969cb;p=virt-top.git diff --git a/libvirt/libvirt_c.c b/libvirt/libvirt_c.c index f896097..c568026 100644 --- a/libvirt/libvirt_c.c +++ b/libvirt/libvirt_c.c @@ -1,6 +1,20 @@ /* OCaml bindings for libvirt. * (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc. * http://libvirt.org/ + * + * 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 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" @@ -20,6 +34,7 @@ #include #include #include +#include static char *Optstring_val (value strv); typedef value (*Val_ptr_t) (void *); @@ -28,6 +43,21 @@ static value Val_opt (void *ptr, Val_ptr_t Val_ptr); static value _raise_virterror (virConnectPtr conn, const char *fn); static value Val_virterror (virErrorPtr err); +/* Use this around synchronous libvirt API calls to release the OCaml + * lock, allowing other threads to run simultaneously. 'code' must not + * perform any caml_* calls, run any OCaml code, or raise any exception. + * http://web.archive.org/web/20030521020915/http://caml.inria.fr/archives/200106/msg00199.html + */ +#define NONBLOCKING(code) \ + do { \ + caml_enter_blocking_section (); \ + code; \ + caml_leave_blocking_section (); \ + } while (0) + +/* Check error condition from a libvirt function, and automatically raise + * an exception if one is found. + */ #define CHECK_ERROR(cond, conn, fn) \ do { if (cond) _raise_virterror (conn, fn); } while (0) @@ -102,6 +132,16 @@ extern int virDomainSetSchedulerParameters (virDomainPtr domain, int nparams) __attribute__((weak)); #endif +#ifdef HAVE_VIRNODEGETFREEMEMORY +extern unsigned long long virNodeGetFreeMemory (virConnectPtr conn) + __attribute__((weak)); +#endif +#ifdef HAVE_VIRNODEGETCELLSFREEMEMORY +extern int virNodeGetCellsFreeMemory (virConnectPtr conn, + unsigned long long *freeMems, + int startCell, int maxCells) + __attribute__((weak)); +#endif #endif /* HAVE_WEAK_SYMBOLS */ /*----------------------------------------------------------------------*/ @@ -116,7 +156,7 @@ ocaml_libvirt_get_version (value driverv, value unit) int r; typeVer_ptr = driver ? &typeVer : NULL; - r = virGetVersion (&libVer, driver, typeVer_ptr); + NONBLOCKING (r = virGetVersion (&libVer, driver, typeVer_ptr)); CHECK_ERROR (r == -1, NULL, "virGetVersion"); rv = caml_alloc_tuple (2); @@ -212,7 +252,7 @@ ocaml_libvirt_connect_open (value namev, value unit) const char *name = Optstring_val (namev); virConnectPtr conn; - conn = virConnectOpen (name); + NONBLOCKING (conn = virConnectOpen (name)); CHECK_ERROR (!conn, NULL, "virConnectOpen"); rv = Val_connect (conn); @@ -228,7 +268,7 @@ ocaml_libvirt_connect_open_readonly (value namev, value unit) const char *name = Optstring_val (namev); virConnectPtr conn; - conn = virConnectOpenReadOnly (name); + NONBLOCKING (conn = virConnectOpenReadOnly (name)); CHECK_ERROR (!conn, NULL, "virConnectOpen"); rv = Val_connect (conn); @@ -243,7 +283,7 @@ ocaml_libvirt_connect_close (value connv) virConnectPtr conn = Connect_val (connv); int r; - r = virConnectClose (conn); + NONBLOCKING (r = virConnectClose (conn)); CHECK_ERROR (r == -1, conn, "virConnectClose"); /* So that we don't double-free in the finalizer: */ @@ -260,7 +300,7 @@ ocaml_libvirt_connect_get_type (value connv) virConnectPtr conn = Connect_val (connv); const char *r; - r = virConnectGetType (conn); + NONBLOCKING (r = virConnectGetType (conn)); CHECK_ERROR (!r, conn, "virConnectGetType"); rv = caml_copy_string (r); @@ -275,7 +315,7 @@ ocaml_libvirt_connect_get_version (value connv) unsigned long hvVer; int r; - r = virConnectGetVersion (conn, &hvVer); + NONBLOCKING (r = virConnectGetVersion (conn, &hvVer)); CHECK_ERROR (r == -1, conn, "virConnectGetVersion"); CAMLreturn (Val_int (hvVer)); @@ -291,7 +331,7 @@ ocaml_libvirt_connect_get_hostname (value connv) char *r; WEAK_SYMBOL_CHECK (virConnectGetHostname); - r = virConnectGetHostname (conn); + NONBLOCKING (r = virConnectGetHostname (conn)); CHECK_ERROR (!r, conn, "virConnectGetHostname"); rv = caml_copy_string (r); @@ -312,7 +352,7 @@ ocaml_libvirt_connect_get_uri (value connv) char *r; WEAK_SYMBOL_CHECK (virConnectGetURI); - r = virConnectGetURI (conn); + NONBLOCKING (r = virConnectGetURI (conn)); CHECK_ERROR (!r, conn, "virConnectGetURI"); rv = caml_copy_string (r); @@ -331,7 +371,7 @@ ocaml_libvirt_connect_get_max_vcpus (value connv, value typev) const char *type = Optstring_val (typev); int r; - r = virConnectGetMaxVcpus (conn, type); + NONBLOCKING (r = virConnectGetMaxVcpus (conn, type)); CHECK_ERROR (r == -1, conn, "virConnectGetMaxVcpus"); CAMLreturn (Val_int (r)); @@ -346,7 +386,7 @@ ocaml_libvirt_connect_list_domains (value connv, value iv) int i = Int_val (iv); int ids[i], r; - r = virConnectListDomains (conn, ids, i); + NONBLOCKING (r = virConnectListDomains (conn, ids, i)); CHECK_ERROR (r == -1, conn, "virConnectListDomains"); rv = caml_alloc (r, 0); @@ -363,7 +403,7 @@ ocaml_libvirt_connect_num_of_domains (value connv) virConnectPtr conn = Connect_val (connv); int r; - r = virConnectNumOfDomains (conn); + NONBLOCKING (r = virConnectNumOfDomains (conn)); CHECK_ERROR (r == -1, conn, "virConnectNumOfDomains"); CAMLreturn (Val_int (r)); @@ -377,7 +417,7 @@ ocaml_libvirt_connect_get_capabilities (value connv) virConnectPtr conn = Connect_val (connv); char *r; - r = virConnectGetCapabilities (conn); + NONBLOCKING (r = virConnectGetCapabilities (conn)); CHECK_ERROR (!r, conn, "virConnectGetCapabilities"); rv = caml_copy_string (r); @@ -393,7 +433,7 @@ ocaml_libvirt_connect_num_of_defined_domains (value connv) virConnectPtr conn = Connect_val (connv); int r; - r = virConnectNumOfDefinedDomains (conn); + NONBLOCKING (r = virConnectNumOfDefinedDomains (conn)); CHECK_ERROR (r == -1, conn, "virConnectNumOfDefinedDomains"); CAMLreturn (Val_int (r)); @@ -409,7 +449,7 @@ ocaml_libvirt_connect_list_defined_domains (value connv, value iv) char *names[i]; int r; - r = virConnectListDefinedDomains (conn, names, i); + NONBLOCKING (r = virConnectListDefinedDomains (conn, names, i)); CHECK_ERROR (r == -1, conn, "virConnectListDefinedDomains"); rv = caml_alloc (r, 0); @@ -429,7 +469,7 @@ ocaml_libvirt_connect_num_of_networks (value connv) virConnectPtr conn = Connect_val (connv); int r; - r = virConnectNumOfNetworks (conn); + NONBLOCKING (r = virConnectNumOfNetworks (conn)); CHECK_ERROR (r == -1, conn, "virConnectNumOfNetworks"); CAMLreturn (Val_int (r)); @@ -445,7 +485,7 @@ ocaml_libvirt_connect_list_networks (value connv, value iv) char *names[i]; int r; - r = virConnectListNetworks (conn, names, i); + NONBLOCKING (r = virConnectListNetworks (conn, names, i)); CHECK_ERROR (r == -1, conn, "virConnectListNetworks"); rv = caml_alloc (r, 0); @@ -465,7 +505,7 @@ ocaml_libvirt_connect_num_of_defined_networks (value connv) virConnectPtr conn = Connect_val (connv); int r; - r = virConnectNumOfDefinedNetworks (conn); + NONBLOCKING (r = virConnectNumOfDefinedNetworks (conn)); CHECK_ERROR (r == -1, conn, "virConnectNumOfDefinedNetworks"); CAMLreturn (Val_int (r)); @@ -481,7 +521,7 @@ ocaml_libvirt_connect_list_defined_networks (value connv, value iv) char *names[i]; int r; - r = virConnectListDefinedNetworks (conn, names, i); + NONBLOCKING (r = virConnectListDefinedNetworks (conn, names, i)); CHECK_ERROR (r == -1, conn, "virConnectListDefinedNetworks"); rv = caml_alloc (r, 0); @@ -503,7 +543,7 @@ ocaml_libvirt_connect_get_node_info (value connv) virNodeInfo info; int r; - r = virNodeGetInfo (conn, &info); + NONBLOCKING (r = virNodeGetInfo (conn, &info)); CHECK_ERROR (r == -1, conn, "virNodeGetInfo"); rv = caml_alloc (8, 0); @@ -520,6 +560,55 @@ ocaml_libvirt_connect_get_node_info (value connv) } CAMLprim value +ocaml_libvirt_connect_node_get_free_memory (value connv) +{ +#ifdef HAVE_VIRNODEGETFREEMEMORY + CAMLparam1 (connv); + CAMLlocal1 (rv); + virConnectPtr conn = Connect_val (connv); + unsigned long long r; + + WEAK_SYMBOL_CHECK (virNodeGetFreeMemory); + NONBLOCKING (r = virNodeGetFreeMemory (conn)); + CHECK_ERROR (r == 0, conn, "virNodeGetFreeMemory"); + + rv = caml_copy_int64 ((int64) r); + CAMLreturn (rv); +#else + NOT_SUPPORTED ("virNodeGetFreeMemory"); +#endif +} + +CAMLprim value +ocaml_libvirt_connect_node_get_cells_free_memory (value connv, + value startv, value maxv) +{ +#ifdef HAVE_VIRNODEGETCELLSFREEMEMORY + CAMLparam3 (connv, startv, maxv); + CAMLlocal2 (rv, iv); + virConnectPtr conn = Connect_val (connv); + int start = Int_val (startv); + int max = Int_val (maxv); + int r, i; + unsigned long long freemems[max]; + + WEAK_SYMBOL_CHECK (virNodeGetCellsFreeMemory); + NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max)); + CHECK_ERROR (r == -1, conn, "virNodeGetCellsFreeMemory"); + + rv = caml_alloc (r, 0); + for (i = 0; i < r; ++i) { + iv = caml_copy_int64 ((int64) freemems[i]); + Store_field (rv, i, iv); + } + + CAMLreturn (rv); +#else + NOT_SUPPORTED ("virNodeGetCellsFreeMemory"); +#endif +} + +CAMLprim value ocaml_libvirt_domain_create_linux (value connv, value xmlv) { CAMLparam2 (connv, xmlv); @@ -528,7 +617,7 @@ ocaml_libvirt_domain_create_linux (value connv, value xmlv) char *xml = String_val (xmlv); virDomainPtr r; - r = virDomainCreateLinux (conn, xml, 0); + NONBLOCKING (r = virDomainCreateLinux (conn, xml, 0)); CHECK_ERROR (!r, conn, "virDomainCreateLinux"); rv = Val_domain (r, connv); @@ -544,7 +633,7 @@ ocaml_libvirt_domain_lookup_by_id (value connv, value iv) int i = Int_val (iv); virDomainPtr r; - r = virDomainLookupByID (conn, i); + NONBLOCKING (r = virDomainLookupByID (conn, i)); CHECK_ERROR (!r, conn, "virDomainLookupByID"); rv = Val_domain (r, connv); @@ -560,7 +649,7 @@ ocaml_libvirt_domain_lookup_by_uuid (value connv, value uuidv) char *uuid = String_val (uuidv); virDomainPtr r; - r = virDomainLookupByUUID (conn, (unsigned char *) uuid); + NONBLOCKING (r = virDomainLookupByUUID (conn, (unsigned char *) uuid)); CHECK_ERROR (!r, conn, "virDomainLookupByUUID"); rv = Val_domain (r, connv); @@ -576,7 +665,7 @@ ocaml_libvirt_domain_lookup_by_uuid_string (value connv, value uuidv) char *uuid = String_val (uuidv); virDomainPtr r; - r = virDomainLookupByUUIDString (conn, uuid); + NONBLOCKING (r = virDomainLookupByUUIDString (conn, uuid)); CHECK_ERROR (!r, conn, "virDomainLookupByUUIDString"); rv = Val_domain (r, connv); @@ -592,7 +681,7 @@ ocaml_libvirt_domain_lookup_by_name (value connv, value namev) char *name = String_val (namev); virDomainPtr r; - r = virDomainLookupByName (conn, name); + NONBLOCKING (r = virDomainLookupByName (conn, name)); CHECK_ERROR (!r, conn, "virDomainLookupByName"); rv = Val_domain (r, connv); @@ -607,7 +696,7 @@ ocaml_libvirt_domain_destroy (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainDestroy (dom); + NONBLOCKING (r = virDomainDestroy (dom)); CHECK_ERROR (r == -1, conn, "virDomainDestroy"); /* So that we don't double-free in the finalizer: */ @@ -624,7 +713,7 @@ ocaml_libvirt_domain_free (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainFree (dom); + NONBLOCKING (r = virDomainFree (dom)); CHECK_ERROR (r == -1, conn, "virDomainFree"); /* So that we don't double-free in the finalizer: */ @@ -641,7 +730,7 @@ ocaml_libvirt_domain_suspend (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainSuspend (dom); + NONBLOCKING (r = virDomainSuspend (dom)); CHECK_ERROR (r == -1, conn, "virDomainSuspend"); CAMLreturn (Val_unit); @@ -655,7 +744,7 @@ ocaml_libvirt_domain_resume (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainResume (dom); + NONBLOCKING (r = virDomainResume (dom)); CHECK_ERROR (r == -1, conn, "virDomainResume"); CAMLreturn (Val_unit); @@ -670,7 +759,7 @@ ocaml_libvirt_domain_save (value domv, value pathv) char *path = String_val (pathv); int r; - r = virDomainSave (dom, path); + NONBLOCKING (r = virDomainSave (dom, path)); CHECK_ERROR (r == -1, conn, "virDomainSave"); CAMLreturn (Val_unit); @@ -684,7 +773,7 @@ ocaml_libvirt_domain_restore (value connv, value pathv) char *path = String_val (pathv); int r; - r = virDomainRestore (conn, path); + NONBLOCKING (r = virDomainRestore (conn, path)); CHECK_ERROR (r == -1, conn, "virDomainRestore"); CAMLreturn (Val_unit); @@ -699,7 +788,7 @@ ocaml_libvirt_domain_core_dump (value domv, value pathv) char *path = String_val (pathv); int r; - r = virDomainCoreDump (dom, path, 0); + NONBLOCKING (r = virDomainCoreDump (dom, path, 0)); CHECK_ERROR (r == -1, conn, "virDomainCoreDump"); CAMLreturn (Val_unit); @@ -713,7 +802,7 @@ ocaml_libvirt_domain_shutdown (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainShutdown (dom); + NONBLOCKING (r = virDomainShutdown (dom)); CHECK_ERROR (r == -1, conn, "virDomainShutdown"); CAMLreturn (Val_unit); @@ -727,7 +816,7 @@ ocaml_libvirt_domain_reboot (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainReboot (dom, 0); + NONBLOCKING (r = virDomainReboot (dom, 0)); CHECK_ERROR (r == -1, conn, "virDomainReboot"); CAMLreturn (Val_unit); @@ -742,7 +831,7 @@ ocaml_libvirt_domain_get_name (value domv) virConnectPtr conn = Connect_domv (domv); const char *r; - r = virDomainGetName (dom); + NONBLOCKING (r = virDomainGetName (dom)); CHECK_ERROR (!r, conn, "virDomainGetName"); rv = caml_copy_string (r); @@ -759,7 +848,7 @@ ocaml_libvirt_domain_get_uuid (value domv) unsigned char uuid[VIR_UUID_BUFLEN]; int r; - r = virDomainGetUUID (dom, uuid); + NONBLOCKING (r = virDomainGetUUID (dom, uuid)); CHECK_ERROR (r == -1, conn, "virDomainGetUUID"); rv = caml_copy_string ((char *) uuid); @@ -776,7 +865,7 @@ ocaml_libvirt_domain_get_uuid_string (value domv) char uuid[VIR_UUID_STRING_BUFLEN]; int r; - r = virDomainGetUUIDString (dom, uuid); + NONBLOCKING (r = virDomainGetUUIDString (dom, uuid)); CHECK_ERROR (r == -1, conn, "virDomainGetUUIDString"); rv = caml_copy_string (uuid); @@ -791,7 +880,7 @@ ocaml_libvirt_domain_get_id (value domv) virConnectPtr conn = Connect_domv (domv); unsigned int r; - r = virDomainGetID (dom); + NONBLOCKING (r = virDomainGetID (dom)); /* There's a bug in libvirt which means that if you try to get * the ID of a defined-but-not-running domain, it returns -1, * and there's no way to distinguish that from an error. @@ -810,7 +899,7 @@ ocaml_libvirt_domain_get_os_type (value domv) virConnectPtr conn = Connect_domv (domv); char *r; - r = virDomainGetOSType (dom); + NONBLOCKING (r = virDomainGetOSType (dom)); CHECK_ERROR (!r, conn, "virDomainGetOSType"); rv = caml_copy_string (r); @@ -827,7 +916,7 @@ ocaml_libvirt_domain_get_max_memory (value domv) virConnectPtr conn = Connect_domv (domv); unsigned long r; - r = virDomainGetMaxMemory (dom); + NONBLOCKING (r = virDomainGetMaxMemory (dom)); CHECK_ERROR (r == 0 /* [sic] */, conn, "virDomainGetMaxMemory"); rv = caml_copy_int64 (r); @@ -843,7 +932,7 @@ ocaml_libvirt_domain_set_max_memory (value domv, value memv) unsigned long mem = Int64_val (memv); int r; - r = virDomainSetMaxMemory (dom, mem); + NONBLOCKING (r = virDomainSetMaxMemory (dom, mem)); CHECK_ERROR (r == -1, conn, "virDomainSetMaxMemory"); CAMLreturn (Val_unit); @@ -858,7 +947,7 @@ ocaml_libvirt_domain_set_memory (value domv, value memv) unsigned long mem = Int64_val (memv); int r; - r = virDomainSetMemory (dom, mem); + NONBLOCKING (r = virDomainSetMemory (dom, mem)); CHECK_ERROR (r == -1, conn, "virDomainSetMemory"); CAMLreturn (Val_unit); @@ -874,7 +963,7 @@ ocaml_libvirt_domain_get_info (value domv) virDomainInfo info; int r; - r = virDomainGetInfo (dom, &info); + NONBLOCKING (r = virDomainGetInfo (dom, &info)); CHECK_ERROR (r == -1, conn, "virDomainGetInfo"); rv = caml_alloc (5, 0); @@ -896,7 +985,7 @@ ocaml_libvirt_domain_get_xml_desc (value domv) virConnectPtr conn = Connect_domv (domv); char *r; - r = virDomainGetXMLDesc (dom, 0); + NONBLOCKING (r = virDomainGetXMLDesc (dom, 0)); CHECK_ERROR (!r, conn, "virDomainGetXMLDesc"); rv = caml_copy_string (r); @@ -916,7 +1005,7 @@ ocaml_libvirt_domain_get_scheduler_type (value domv) int nparams; WEAK_SYMBOL_CHECK (virDomainGetSchedulerType); - r = virDomainGetSchedulerType (dom, &nparams); + NONBLOCKING (r = virDomainGetSchedulerType (dom, &nparams)); CHECK_ERROR (!r, conn, "virDomainGetSchedulerType"); rv = caml_alloc_tuple (2); @@ -942,7 +1031,7 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv) int r, i; WEAK_SYMBOL_CHECK (virDomainGetSchedulerParameters); - r = virDomainGetSchedulerParameters (dom, params, &nparams); + NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams)); CHECK_ERROR (r == -1, conn, "virDomainGetSchedulerParameters"); rv = caml_alloc (nparams, 0); @@ -1035,7 +1124,7 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv) } WEAK_SYMBOL_CHECK (virDomainSetSchedulerParameters); - r = virDomainSetSchedulerParameters (dom, params, nparams); + NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams)); CHECK_ERROR (r == -1, conn, "virDomainSetSchedulerParameters"); CAMLreturn (Val_unit); @@ -1053,7 +1142,7 @@ ocaml_libvirt_domain_define_xml (value connv, value xmlv) char *xml = String_val (xmlv); virDomainPtr r; - r = virDomainDefineXML (conn, xml); + NONBLOCKING (r = virDomainDefineXML (conn, xml)); CHECK_ERROR (!r, conn, "virDomainDefineXML"); rv = Val_domain (r, connv); @@ -1068,7 +1157,7 @@ ocaml_libvirt_domain_undefine (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainUndefine (dom); + NONBLOCKING (r = virDomainUndefine (dom)); CHECK_ERROR (r == -1, conn, "virDomainUndefine"); CAMLreturn (Val_unit); @@ -1082,7 +1171,7 @@ ocaml_libvirt_domain_create (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainCreate (dom); + NONBLOCKING (r = virDomainCreate (dom)); CHECK_ERROR (r == -1, conn, "virDomainCreate"); CAMLreturn (Val_unit); @@ -1096,7 +1185,7 @@ ocaml_libvirt_domain_get_autostart (value domv) virConnectPtr conn = Connect_domv (domv); int r, autostart; - r = virDomainGetAutostart (dom, &autostart); + NONBLOCKING (r = virDomainGetAutostart (dom, &autostart)); CHECK_ERROR (r == -1, conn, "virDomainGetAutostart"); CAMLreturn (autostart ? Val_true : Val_false); @@ -1110,7 +1199,7 @@ ocaml_libvirt_domain_set_autostart (value domv, value autostartv) virConnectPtr conn = Connect_domv (domv); int r, autostart = autostartv == Val_true ? 1 : 0; - r = virDomainSetAutostart (dom, autostart); + NONBLOCKING (r = virDomainSetAutostart (dom, autostart)); CHECK_ERROR (r == -1, conn, "virDomainSetAutostart"); CAMLreturn (Val_unit); @@ -1124,7 +1213,7 @@ ocaml_libvirt_domain_set_vcpus (value domv, value nvcpusv) virConnectPtr conn = Connect_domv (domv); int r, nvcpus = Int_val (nvcpusv); - r = virDomainSetVcpus (dom, nvcpus); + NONBLOCKING (r = virDomainSetVcpus (dom, nvcpus)); CHECK_ERROR (r == -1, conn, "virDomainSetVcpus"); CAMLreturn (Val_unit); @@ -1141,7 +1230,7 @@ ocaml_libvirt_domain_pin_vcpu (value domv, value vcpuv, value cpumapv) int vcpu = Int_val (vcpuv); int r; - r = virDomainPinVcpu (dom, vcpu, cpumap, maplen); + NONBLOCKING (r = virDomainPinVcpu (dom, vcpu, cpumap, maplen)); CHECK_ERROR (r == -1, conn, "virDomainPinVcpu"); CAMLreturn (Val_unit); @@ -1163,7 +1252,7 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv) memset (info, 0, sizeof (virVcpuInfo) * maxinfo); memset (cpumaps, 0, maxinfo * maplen); - r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen); + NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen)); CHECK_ERROR (r == -1, conn, "virDomainPinVcpu"); /* Copy the virVcpuInfo structures. */ @@ -1197,7 +1286,7 @@ ocaml_libvirt_domain_get_max_vcpus (value domv) virConnectPtr conn = Connect_domv (domv); int r; - r = virDomainGetMaxVcpus (dom); + NONBLOCKING (r = virDomainGetMaxVcpus (dom)); CHECK_ERROR (r == -1, conn, "virDomainGetMaxVcpus"); CAMLreturn (Val_int (r)); @@ -1212,7 +1301,7 @@ ocaml_libvirt_domain_attach_device (value domv, value xmlv) char *xml = String_val (xmlv); int r; - r = virDomainAttachDevice (dom, xml); + NONBLOCKING (r = virDomainAttachDevice (dom, xml)); CHECK_ERROR (r == -1, conn, "virDomainAttachDevice"); CAMLreturn (Val_unit); @@ -1227,7 +1316,7 @@ ocaml_libvirt_domain_detach_device (value domv, value xmlv) char *xml = String_val (xmlv); int r; - r = virDomainDetachDevice (dom, xml); + NONBLOCKING (r = virDomainDetachDevice (dom, xml)); CHECK_ERROR (r == -1, conn, "virDomainDetachDevice"); CAMLreturn (Val_unit); @@ -1263,7 +1352,7 @@ ocaml_libvirt_domain_migrate_native (value domv, value dconnv, value flagsv, val bandwidth = Int_val (Field (optbandwidthv, 0)); WEAK_SYMBOL_CHECK (virDomainMigrate); - r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth); + NONBLOCKING (r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth)); CHECK_ERROR (!r, conn, "virDomainMigrate"); rv = Val_domain (r, dconnv); @@ -1296,7 +1385,7 @@ ocaml_libvirt_domain_block_stats (value domv, value pathv) int r; WEAK_SYMBOL_CHECK (virDomainBlockStats); - r = virDomainBlockStats (dom, path, &stats, sizeof stats); + NONBLOCKING (r = virDomainBlockStats (dom, path, &stats, sizeof stats)); CHECK_ERROR (r == -1, conn, "virDomainBlockStats"); rv = caml_alloc (5, 0); @@ -1325,7 +1414,7 @@ ocaml_libvirt_domain_interface_stats (value domv, value pathv) int r; WEAK_SYMBOL_CHECK (virDomainInterfaceStats); - r = virDomainInterfaceStats (dom, path, &stats, sizeof stats); + NONBLOCKING (r = virDomainInterfaceStats (dom, path, &stats, sizeof stats)); CHECK_ERROR (r == -1, conn, "virDomainInterfaceStats"); rv = caml_alloc (8, 0); @@ -1353,7 +1442,7 @@ ocaml_libvirt_network_lookup_by_name (value connv, value namev) char *name = String_val (namev); virNetworkPtr r; - r = virNetworkLookupByName (conn, name); + NONBLOCKING (r = virNetworkLookupByName (conn, name)); CHECK_ERROR (!r, conn, "virNetworkLookupByName"); rv = Val_network (r, connv); @@ -1369,7 +1458,7 @@ ocaml_libvirt_network_lookup_by_uuid (value connv, value uuidv) char *uuid = String_val (uuidv); virNetworkPtr r; - r = virNetworkLookupByUUID (conn, (unsigned char *) uuid); + NONBLOCKING (r = virNetworkLookupByUUID (conn, (unsigned char *) uuid)); CHECK_ERROR (!r, conn, "virNetworkLookupByUUID"); rv = Val_network (r, connv); @@ -1385,7 +1474,7 @@ ocaml_libvirt_network_lookup_by_uuid_string (value connv, value uuidv) char *uuid = String_val (uuidv); virNetworkPtr r; - r = virNetworkLookupByUUIDString (conn, uuid); + NONBLOCKING (r = virNetworkLookupByUUIDString (conn, uuid)); CHECK_ERROR (!r, conn, "virNetworkLookupByUUIDString"); rv = Val_network (r, connv); @@ -1401,7 +1490,7 @@ ocaml_libvirt_network_create_xml (value connv, value xmlv) char *xml = String_val (xmlv); virNetworkPtr r; - r = virNetworkCreateXML (conn, xml); + NONBLOCKING (r = virNetworkCreateXML (conn, xml)); CHECK_ERROR (!r, conn, "virNetworkCreateXML"); rv = Val_network (r, connv); @@ -1417,7 +1506,7 @@ ocaml_libvirt_network_define_xml (value connv, value xmlv) char *xml = String_val (xmlv); virNetworkPtr r; - r = virNetworkDefineXML (conn, xml); + NONBLOCKING (r = virNetworkDefineXML (conn, xml)); CHECK_ERROR (!r, conn, "virNetworkDefineXML"); rv = Val_network (r, connv); @@ -1432,7 +1521,7 @@ ocaml_libvirt_network_undefine (value netv) virConnectPtr conn = Connect_netv (netv); int r; - r = virNetworkUndefine (net); + NONBLOCKING (r = virNetworkUndefine (net)); CHECK_ERROR (r == -1, conn, "virNetworkUndefine"); CAMLreturn (Val_unit); @@ -1446,7 +1535,7 @@ ocaml_libvirt_network_create (value netv) virConnectPtr conn = Connect_netv (netv); int r; - r = virNetworkCreate (net); + NONBLOCKING (r = virNetworkCreate (net)); CHECK_ERROR (r == -1, conn, "virNetworkCreate"); CAMLreturn (Val_unit); @@ -1460,7 +1549,7 @@ ocaml_libvirt_network_destroy (value netv) virConnectPtr conn = Connect_netv (netv); int r; - r = virNetworkDestroy (net); + NONBLOCKING (r = virNetworkDestroy (net)); CHECK_ERROR (r == -1, conn, "virNetworkDestroy"); /* So that we don't double-free in the finalizer: */ @@ -1477,7 +1566,7 @@ ocaml_libvirt_network_free (value netv) virConnectPtr conn = Connect_netv (netv); int r; - r = virNetworkFree (net); + NONBLOCKING (r = virNetworkFree (net)); CHECK_ERROR (r == -1, conn, "virNetworkFree"); /* So that we don't double-free in the finalizer: */ @@ -1495,7 +1584,7 @@ ocaml_libvirt_network_get_name (value netv) virConnectPtr conn = Connect_netv (netv); const char *r; - r = virNetworkGetName (net); + NONBLOCKING (r = virNetworkGetName (net)); CHECK_ERROR (!r, conn, "virNetworkGetName"); rv = caml_copy_string (r); @@ -1512,7 +1601,7 @@ ocaml_libvirt_network_get_uuid (value netv) unsigned char uuid[VIR_UUID_BUFLEN]; int r; - r = virNetworkGetUUID (net, uuid); + NONBLOCKING (r = virNetworkGetUUID (net, uuid)); CHECK_ERROR (r == -1, conn, "virNetworkGetUUID"); rv = caml_copy_string ((char *) uuid); @@ -1529,7 +1618,7 @@ ocaml_libvirt_network_get_uuid_string (value netv) char uuid[VIR_UUID_STRING_BUFLEN]; int r; - r = virNetworkGetUUIDString (net, uuid); + NONBLOCKING (r = virNetworkGetUUIDString (net, uuid)); CHECK_ERROR (r == -1, conn, "virNetworkGetUUIDString"); rv = caml_copy_string (uuid); @@ -1545,7 +1634,7 @@ ocaml_libvirt_network_get_xml_desc (value netv) virConnectPtr conn = Connect_netv (netv); char *r; - r = virNetworkGetXMLDesc (net, 0); + NONBLOCKING (r = virNetworkGetXMLDesc (net, 0)); CHECK_ERROR (!r, conn, "virNetworkGetXMLDesc"); rv = caml_copy_string (r); @@ -1562,7 +1651,7 @@ ocaml_libvirt_network_get_bridge_name (value netv) virConnectPtr conn = Connect_netv (netv); char *r; - r = virNetworkGetBridgeName (net); + NONBLOCKING (r = virNetworkGetBridgeName (net)); CHECK_ERROR (!r, conn, "virNetworkGetBridgeName"); rv = caml_copy_string (r); @@ -1578,7 +1667,7 @@ ocaml_libvirt_network_get_autostart (value netv) virConnectPtr conn = Connect_netv (netv); int r, autostart; - r = virNetworkGetAutostart (net, &autostart); + NONBLOCKING (r = virNetworkGetAutostart (net, &autostart)); CHECK_ERROR (r == -1, conn, "virNetworkGetAutostart"); CAMLreturn (autostart ? Val_true : Val_false); @@ -1592,7 +1681,7 @@ ocaml_libvirt_network_set_autostart (value netv, value autostartv) virConnectPtr conn = Connect_netv (netv); int r, autostart = autostartv == Val_true ? 1 : 0; - r = virNetworkSetAutostart (net, autostart); + NONBLOCKING (r = virNetworkSetAutostart (net, autostart)); CHECK_ERROR (r == -1, conn, "virNetworkSetAutostart"); CAMLreturn (Val_unit); @@ -1722,6 +1811,72 @@ _raise_virterror (virConnectPtr conn, const char *fn) CAMLreturn (Val_unit); } +/* Convert the virErrorNumber, virErrorDomain and virErrorLevel enums + * into values (longs because they are variants in OCaml). + * + * The enum values are part of the libvirt ABI so they cannot change, + * which means that we can convert these numbers directly into + * OCaml variants (which use the same ordering) very fast. + * + * The tricky part here is when we are linked to a newer version of + * libvirt than the one we were compiled against. If the newer libvirt + * generates an error code which we don't know about then we need + * to convert it into VIR_*_UNKNOWN (code). + */ + +#define MAX_VIR_CODE 44 /* VIR_ERR_INVALID_MAC */ +#define MAX_VIR_DOMAIN 16 /* VIR_FROM_STATS_LINUX */ +#define MAX_VIR_LEVEL VIR_ERR_ERROR + +static inline value +Val_err_number (virErrorNumber code) +{ + CAMLparam0 (); + CAMLlocal1 (rv); + + if (0 <= code && code <= MAX_VIR_CODE) + rv = Val_int (code); + else { + rv = caml_alloc (1, 0); /* VIR_ERR_UNKNOWN (code) */ + Store_field (rv, 0, Val_int (code)); + } + + CAMLreturn (rv); +} + +static inline value +Val_err_domain (virErrorDomain code) +{ + CAMLparam0 (); + CAMLlocal1 (rv); + + if (0 <= code && code <= MAX_VIR_DOMAIN) + rv = Val_int (code); + else { + rv = caml_alloc (1, 0); /* VIR_FROM_UNKNOWN (code) */ + Store_field (rv, 0, Val_int (code)); + } + + CAMLreturn (rv); +} + +static inline value +Val_err_level (virErrorLevel code) +{ + CAMLparam0 (); + CAMLlocal1 (rv); + + if (0 <= code && code <= MAX_VIR_LEVEL) + rv = Val_int (code); + else { + rv = caml_alloc (1, 0); /* VIR_ERR_UNKNOWN_LEVEL (code) */ + Store_field (rv, 0, Val_int (code)); + } + + CAMLreturn (rv); +} + +/* Convert a virterror to a value. */ static value Val_virterror (virErrorPtr err) { @@ -1729,11 +1884,11 @@ Val_virterror (virErrorPtr err) CAMLlocal3 (rv, connv, optv); rv = caml_alloc (12, 0); - Store_field (rv, 0, Val_int (err->code)); - Store_field (rv, 1, Val_int (err->domain)); + Store_field (rv, 0, Val_err_number (err->code)); + Store_field (rv, 1, Val_err_domain (err->domain)); Store_field (rv, 2, Val_opt (err->message, (Val_ptr_t) caml_copy_string)); - Store_field (rv, 3, Val_int (err->level)); + Store_field (rv, 3, Val_err_level (err->level)); /* conn, dom and net fields, all optional */ if (err->conn) {