--- /dev/null
+From 99ba7e0eae5ea7567aded458ab63c5984ed43191 Mon Sep 17 00:00:00 2001
+From: Hu Tao <hutao@cn.fujitsu.com>
+Date: Wed, 9 May 2012 16:48:31 +0800
+Subject: [PATCH] Add Libvirt.Domain.get_cpu_stats_total.
+
+Original patch by Hu Tao.
+
+RWMJ modified the patch to split this into two functions
+(old get_cpu_stats and new get_cpu_stats_total). Apart
+from that split, the code is identical.
+---
+ examples/.depend | 12 +++---
+ examples/get_cpu_stats.ml | 48 +++++++++++++-----------
+ libvirt/.depend | 12 +++---
+ libvirt/libvirt.ml | 1 +
+ libvirt/libvirt.mli | 6 ++-
+ libvirt/libvirt_c_oneoffs.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 134 insertions(+), 34 deletions(-)
+
+diff --git a/examples/.depend b/examples/.depend
+index f58db3d..3d955f9 100644
+--- a/examples/.depend
++++ b/examples/.depend
+@@ -1,6 +1,6 @@
+-get_cpu_stats.cmo: ../libvirt/libvirt.cmi
+-get_cpu_stats.cmx: ../libvirt/libvirt.cmx
+-list_domains.cmo: ../libvirt/libvirt.cmi
+-list_domains.cmx: ../libvirt/libvirt.cmx
+-node_info.cmo: ../libvirt/libvirt.cmi
+-node_info.cmx: ../libvirt/libvirt.cmx
++node_info.cmo : ../libvirt/libvirt.cmi
++node_info.cmx : ../libvirt/libvirt.cmx
++get_cpu_stats.cmo : ../libvirt/libvirt.cmi
++get_cpu_stats.cmx : ../libvirt/libvirt.cmx
++list_domains.cmo : ../libvirt/libvirt.cmi
++list_domains.cmx : ../libvirt/libvirt.cmx
+diff --git a/examples/get_cpu_stats.ml b/examples/get_cpu_stats.ml
+index d7a8d0c..10b3840 100644
+--- a/examples/get_cpu_stats.ml
++++ b/examples/get_cpu_stats.ml
+@@ -18,32 +18,38 @@ let () =
+ let domname = Sys.argv.(1) in
+
+ let conn = C.connect_readonly () in
+-
+- let nr_pcpus =
+- let info = C.get_node_info conn in
+- C.maxcpus_of_node_info info in
+-
+- let stats =
+- let dom = D.lookup_by_name conn domname in
+- D.get_cpu_stats dom in
++ let dom = D.lookup_by_name conn domname in
++ let stats = D.get_cpu_stats dom in
++ let total_stats = D.get_cpu_stats_total dom in
++
++ let print_params n params =
++ List.iter (
++ fun (name, value) ->
++ printf " %s=" name;
++ match value with
++ | D.TypedFieldInt32 i -> printf "%ld" i
++ | D.TypedFieldUInt32 i -> printf "%ld" i
++ | D.TypedFieldInt64 i -> printf "%Ld" i
++ | D.TypedFieldUInt64 i -> printf "%Ld" i
++ | D.TypedFieldFloat f -> printf "%g" f
++ | D.TypedFieldBool b -> printf "%b" b
++ | D.TypedFieldString s -> printf "%S" s
++ ) params in
+
+ Array.iteri (
+ fun n params ->
+ printf "pCPU %d:" n;
+- List.iter (
+- fun (name, value) ->
+- printf " %s=" name;
+- match value with
+- | D.TypedFieldInt32 i -> printf "%ld" i
+- | D.TypedFieldUInt32 i -> printf "%ld" i
+- | D.TypedFieldInt64 i -> printf "%Ld" i
+- | D.TypedFieldUInt64 i -> printf "%Ld" i
+- | D.TypedFieldFloat f -> printf "%g" f
+- | D.TypedFieldBool b -> printf "%b" b
+- | D.TypedFieldString s -> printf "%S" s
+- ) params;
++ print_params n params;
+ printf "\n"
+- ) stats
++ ) stats;
++
++ Array.iteri (
++ fun n params ->
++ printf "total:";
++ print_params n params;
++ printf "\n"
++ ) total_stats
++
+ with
+ Libvirt.Virterror err ->
+ eprintf "error: %s\n" (Libvirt.Virterror.to_string err)
+diff --git a/libvirt/.depend b/libvirt/.depend
+index 3f2297e..7d32e13 100644
+--- a/libvirt/.depend
++++ b/libvirt/.depend
+@@ -1,6 +1,6 @@
+-libvirt.cmi:
+-libvirt_version.cmi:
+-libvirt.cmo: libvirt.cmi
+-libvirt.cmx: libvirt.cmi
+-libvirt_version.cmo: libvirt_version.cmi
+-libvirt_version.cmx: libvirt_version.cmi
++libvirt_version.cmi :
++libvirt.cmi :
++libvirt_version.cmo : libvirt_version.cmi
++libvirt_version.cmx : libvirt_version.cmi
++libvirt.cmo : libvirt.cmi
++libvirt.cmx : libvirt.cmi
+diff --git a/libvirt/libvirt.ml b/libvirt/libvirt.ml
+index 07542a9..2997b0b 100644
+--- a/libvirt/libvirt.ml
++++ b/libvirt/libvirt.ml
+@@ -418,6 +418,7 @@ struct
+ 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 -> typed_param list array = "ocaml_libvirt_domain_get_cpu_stats"
++ external get_cpu_stats_total : [>`R] t -> typed_param list array = "ocaml_libvirt_domain_get_cpu_stats_total"
+ 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 5a288c0..020be59 100644
+--- a/libvirt/libvirt.mli
++++ b/libvirt/libvirt.mli
+@@ -560,7 +560,11 @@ sig
+ of the array and bitmap returned from this function.
+ *)
+ val get_cpu_stats : [>`R] t -> typed_param list array
+- (** [get_pcpu_stats dom] returns the physical CPU stats
++ (** [get_cpu_stats dom] returns the per-CPU physical CPU stats
++ for a domain. See the libvirt documentation for details.
++ *)
++ val get_cpu_stats_total : [>`R] t -> typed_param list array
++ (** [get_cpu_stats dom] returns the total physical CPU stats
+ for a domain. See the libvirt documentation for details.
+ *)
+ val get_max_vcpus : [>`R] t -> int
+diff --git a/libvirt/libvirt_c_oneoffs.c b/libvirt/libvirt_c_oneoffs.c
+index 70cf96f..2a1850f 100644
+--- a/libvirt/libvirt_c_oneoffs.c
++++ b/libvirt/libvirt_c_oneoffs.c
+@@ -638,6 +638,95 @@ ocaml_libvirt_domain_get_cpu_stats (value domv)
+ #endif
+ }
+
++CAMLprim value
++ocaml_libvirt_domain_get_cpu_stats_total (value domv)
++{
++#ifdef HAVE_VIRDOMAINGETCPUSTATS
++ CAMLparam1 (domv);
++ CAMLlocal5 (cpustats, param_head, param_node, typed_param, typed_param_value);
++ CAMLlocal1 (v);
++ virDomainPtr dom = Domain_val (domv);
++ virConnectPtr conn = Connect_domv (domv);
++ virTypedParameterPtr params;
++ int r, nparams, j, pos;
++
++ /* get total information */
++ NONBLOCKING (nparams = virDomainGetCPUStats(dom, NULL, 0, -1, 1, 0));
++ CHECK_ERROR (nparams < 0, conn, "virDomainGetCPUStats");
++
++ if ((params = malloc(sizeof(*params) * nparams)) == NULL)
++ caml_failwith ("virDomainGetCPUStats: malloc");
++
++ cpustats = caml_alloc (1, 0); /* cpustats: array of params(list of typed_param) */
++
++ NONBLOCKING (r = virDomainGetCPUStats(dom, params, nparams, -1, 1, 0));
++ CHECK_ERROR (r < 0, conn, "virDomainGetCPUStats");
++
++ param_head = Val_emptylist;
++ if (params[nparams].type != 0) {
++ for (j = r - 1; j >= 0; j--) {
++ pos = j;
++
++ 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);
++ v = caml_copy_int32 (params[pos].value.i);
++ break;
++ case VIR_TYPED_PARAM_UINT:
++ typed_param_value = caml_alloc (1, 1);
++ v = caml_copy_int32 (params[pos].value.ui);
++ break;
++ case VIR_TYPED_PARAM_LLONG:
++ typed_param_value = caml_alloc (1, 2);
++ v = caml_copy_int64 (params[pos].value.l);
++ break;
++ case VIR_TYPED_PARAM_ULLONG:
++ typed_param_value = caml_alloc (1, 3);
++ v = caml_copy_int64 (params[pos].value.ul);
++ break;
++ case VIR_TYPED_PARAM_DOUBLE:
++ typed_param_value = caml_alloc (1, 4);
++ v = caml_copy_double (params[pos].value.d);
++ break;
++ case VIR_TYPED_PARAM_BOOLEAN:
++ typed_param_value = caml_alloc (1, 5);
++ v = Val_bool (params[pos].value.b);
++ break;
++ case VIR_TYPED_PARAM_STRING:
++ typed_param_value = caml_alloc (1, 6);
++ v = caml_copy_string (params[pos].value.s);
++ free (params[pos].value.s);
++ break;
++ default:
++ /* XXX Memory leak on this path, if there are more
++ * VIR_TYPED_PARAM_STRING past this point in the array.
++ */
++ free (params);
++ caml_failwith ("virDomainGetCPUStats: "
++ "unknown parameter type returned");
++ }
++ Store_field (typed_param_value, 0, v);
++ Store_field (typed_param, 1, typed_param_value);
++ }
++ }
++ Store_field (cpustats, 0, param_head);
++
++ free(params);
++ CAMLreturn (cpustats);
++#else
++ not_supported ("virDomainGetCPUStats");
++#endif
++}
++
+ #ifdef HAVE_WEAK_SYMBOLS
+ #ifdef HAVE_VIRDOMAINMIGRATE
+ extern virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,
+--
+1.7.11.4
+