[libvirt] [PATCH 1/1 V4] ocaml-libvirt: add D.get_cpu_stats() API to ocaml-libvirt

Lai Jiangshan laijs at cn.fujitsu.com
Wed Feb 8 08:59:45 UTC 2012


Changed from V3:
	use new virDomainGetCPUStats() libvirt-API.
	use C code to construct the typed_param list array

Acked-by: "Richard W.M. Jones" <rjones at redhat.com>
Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
---
 libvirt/libvirt.ml          |    8 ++++
 libvirt/libvirt.mli         |   11 +++++
 libvirt/libvirt_c_oneoffs.c |   91 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/libvirt/libvirt.ml b/libvirt/libvirt.ml
index fc29264..08c501b 100644
--- a/libvirt/libvirt.ml
+++ b/libvirt/libvirt.ml
@@ -343,6 +343,13 @@ struct
     | SchedFieldInt64 of int64 | SchedFieldUInt64 of int64
     | SchedFieldFloat of float | SchedFieldBool of bool
 
+  type typed_param = string * typed_param_value
+  and typed_param_value =
+    | TypedFieldInt32 of int32 | TypedFieldUInt32 of int32
+    | TypedFieldInt64 of int64 | TypedFieldUInt64 of int64
+    | TypedFieldFloat of float | TypedFieldBool of bool
+    | TypedFieldString of string
+
   type migrate_flag = Live
 
   type memory_flag = Virtual
@@ -419,6 +426,7 @@ struct
   external set_vcpus : [>`W] t -> int -> unit = "ocaml_libvirt_domain_set_vcpus"
   external pin_vcpu : [>`W] t -> int -> string -> unit = "ocaml_libvirt_domain_pin_vcpu"
   external get_vcpus : [>`R] t -> int -> int -> int * vcpu_info array * string = "ocaml_libvirt_domain_get_vcpus"
+  external get_cpu_stats : [>`R] t -> int -> typed_param list array = "ocaml_libvirt_domain_get_cpu_stats"
   external get_max_vcpus : [>`R] t -> int = "ocaml_libvirt_domain_get_max_vcpus"
   external attach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_attach_device"
   external detach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_detach_device"
diff --git a/libvirt/libvirt.mli b/libvirt/libvirt.mli
index 7bda889..31f2ca2 100644
--- a/libvirt/libvirt.mli
+++ b/libvirt/libvirt.mli
@@ -439,6 +439,13 @@ sig
     | SchedFieldInt64 of int64 | SchedFieldUInt64 of int64
     | SchedFieldFloat of float | SchedFieldBool of bool
 
+  type typed_param = string * typed_param_value
+  and typed_param_value =
+    | TypedFieldInt32 of int32 | TypedFieldUInt32 of int32
+    | TypedFieldInt64 of int64 | TypedFieldUInt64 of int64
+    | TypedFieldFloat of float | TypedFieldBool of bool
+    | TypedFieldString of string
+
   type migrate_flag = Live
 
   type memory_flag = Virtual
@@ -586,6 +593,10 @@ sig
 	for a domain.  See the libvirt documentation for details
 	of the array and bitmap returned from this function.
     *)
+  val get_cpu_stats : [>`R] t -> int -> typed_param list array
+    (** [get_pcpu_stats dom nr_pcpu] returns the physic CPU stats
+	for a domain.  See the libvirt documentation for details.
+    *)
   val get_max_vcpus : [>`R] t -> int
     (** Returns the maximum number of vCPUs supported for this domain. *)
   val attach_device : [>`W] t -> xml -> unit
diff --git a/libvirt/libvirt_c_oneoffs.c b/libvirt/libvirt_c_oneoffs.c
index d87dd21..a0c74be 100644
--- a/libvirt/libvirt_c_oneoffs.c
+++ b/libvirt/libvirt_c_oneoffs.c
@@ -604,6 +604,97 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
   CAMLreturn (rv);
 }
 
+CAMLprim value
+ocaml_libvirt_domain_get_cpu_stats (value domv, value nr_pcpusv)
+{
+  CAMLparam2 (domv, nr_pcpusv);
+  CAMLlocal5 (cpustats, param_head, param_node, typed_param, typed_param_value);
+  virDomainPtr dom = Domain_val (domv);
+  virConnectPtr conn = Connect_domv (domv);
+  int nr_pcpus = Int_val (nr_pcpusv);
+  virTypedParameterPtr params;
+  int r, cpu, ncpus, nparams, i, j, pos;
+
+  /* get percpu information */
+  NONBLOCKING (nparams = virDomainGetCPUStats(dom, NULL, 0, -1, 1, 0));
+  CHECK_ERROR (nparams < 0, conn, "virDomainGetCPUStats");
+
+  if ((params = malloc(sizeof(*params) * nparams * 128)) == NULL)
+    caml_failwith ((char *)__FUNCTION__);
+
+  cpustats = caml_alloc (nr_pcpus, 0); /* cpustats: array of params(list of typed_param) */
+  cpu = 0;
+  while (cpu < nr_pcpus) {
+    ncpus = nr_pcpus - cpu > 128 ? 128 : nr_pcpus - cpu;
+
+    NONBLOCKING (r = virDomainGetCPUStats(dom, params, nparams, cpu, ncpus, 0));
+    CHECK_ERROR (r < 0, conn, "virDomainGetCPUStats");
+
+    for (i = 0; i < ncpus; i++) {
+      /* list of typed_param: single linked list of param_nodes */
+      param_head = Val_emptylist; /* param_head: the head param_node of list of typed_param */
+
+      if (params[i * nparams].type == 0) {
+        Store_field(cpustats, cpu + i, param_head);
+        continue;
+      }
+
+      for (j = nparams - 1; j >= 0; j--) {
+        pos = i * nparams + j;
+          if (params[pos].type == 0)
+            continue;
+
+        param_node = caml_alloc(2, 0); /* param_node: typed_param, next param_node */
+        Store_field(param_node, 1, param_head);
+        param_head = param_node;
+
+        typed_param = caml_alloc(2, 0); /* typed_param: field name(string), typed_param_value */
+        Store_field(param_node, 0, typed_param);
+        Store_field(typed_param, 0, caml_copy_string(params[pos].field));
+
+        /* typed_param_value: value with the corresponding type tag */
+        switch(params[pos].type) {
+        case VIR_TYPED_PARAM_INT:
+          typed_param_value = caml_alloc (1, 0);
+          Store_field(typed_param_value, 0, caml_copy_int32(params[pos].value.i));
+          break;
+        case VIR_TYPED_PARAM_UINT:
+          typed_param_value = caml_alloc (1, 1);
+          Store_field(typed_param_value, 0, caml_copy_int32(params[pos].value.ui));
+          break;
+        case VIR_TYPED_PARAM_LLONG:
+          typed_param_value = caml_alloc (1, 2);
+          Store_field(typed_param_value, 0, caml_copy_int64(params[pos].value.l));
+          break;
+        case VIR_TYPED_PARAM_ULLONG:
+          typed_param_value = caml_alloc (1, 3);
+          Store_field(typed_param_value, 0, caml_copy_int64(params[pos].value.ul));
+          break;
+        case VIR_TYPED_PARAM_DOUBLE:
+          typed_param_value = caml_alloc (1, 4);
+          Store_field(typed_param_value, 0, caml_copy_double(params[pos].value.d));
+          break;
+        case VIR_TYPED_PARAM_BOOLEAN:
+          typed_param_value = caml_alloc (1, 5);
+          Store_field(typed_param_value, 0, Int_val(!!(params[pos].value.b)));
+          break;
+        case VIR_TYPED_PARAM_STRING:
+          typed_param_value = caml_alloc (1, 6);
+          Store_field(typed_param_value, 0, caml_copy_string(params[pos].value.s));
+          break;
+        default:
+          free(params);
+          caml_failwith ((char *)__FUNCTION__);
+        }
+        Store_field(typed_param, 1, typed_param_value);
+      }
+      Store_field(cpustats, cpu + i, param_head);
+    }
+    cpu += ncpus;
+  }
+  free(params);
+  CAMLreturn (cpustats);
+}
 #ifdef HAVE_WEAK_SYMBOLS
 #ifdef HAVE_VIRDOMAINMIGRATE
 extern virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,




More information about the libvir-list mailing list