* libvirt/libvirt.mli, libvirt/libvirt.ml: New error numbers
[virt-top.git] / libvirt / libvirt_c.c
index f896097..a2bb1ad 100644 (file)
@@ -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"
@@ -102,6 +116,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 */
 
 /*----------------------------------------------------------------------*/
@@ -520,6 +544,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);
+  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);
+  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);
@@ -1722,6 +1795,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 +1868,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) {