WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

[Xen-API] [PATCH] add new modules to stdext

To: xen-api@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-API] [PATCH] add new modules to stdext
From: David Scott <dave.scott@xxxxxxxxxxxxx>
Date: Wed, 21 Jul 2010 23:29:33 +0100
Delivery-date: Wed, 21 Jul 2010 15:41:41 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.4.3
# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1279751355 -3600
# Node ID 542efa53c3e25342a175ead7f9327b972f976820
# Parent  ad151dc6eb4578f098df793e92498a9ba1a9ec3a
Add new modules: lazyList, extentlistSet, set_test to stdext

lazyList contains a simple lazy list implementation.
extentlistSet contains a Set implementation where elements are stored as a list 
of (start, length) pairs
set_test contains functions to test a set implementation

extentlistset_test contains test cases for extentlistSet using set_test.

Signed-off-by: David Scott <dave.scott@xxxxxxxxxxxxx>

diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/Makefile
--- a/stdext/Makefile   Mon Jul 12 08:33:28 2010 +0100
+++ b/stdext/Makefile   Wed Jul 21 23:29:15 2010 +0100
@@ -22,12 +22,13 @@
 
 STDEXT_OBJS = fun opt listext filenameext stringext arrayext hashtblext 
pervasiveext threadext ring \
        qring fring bigbuffer unixext range vIO trie config date encodings fe 
fecomms \
-       forkhelpers gzip sha1sum zerocheck base64 backtrace tar mapext os either
+       forkhelpers gzip sha1sum zerocheck base64 backtrace tar mapext os 
either \
+       lazyList extentlistSet set_test
 
 INTF = $(foreach obj, $(STDEXT_OBJS),$(obj).cmi)
 LIBS = stdext.cma stdext.cmxa
 
-PROGRAMS = base64pp fe_cli fe_test
+PROGRAMS = base64pp fe_cli fe_test extentlistset_test
 
 DOCDIR = /myrepos/xen-api-libs.hg/doc
 
@@ -46,6 +47,9 @@
 fe_test: fe_test.ml all libstdext_stubs.a
        ocamlfind $(OCAMLOPT) $(OCAMLOPTFLAGS) unix.cmxa ../uuid/uuid.cmxa 
../rpc-light/rpc.cmx ../rpc-light/jsonrpc.cmx stdext.cmxa -linkpkg -I ../uuid 
-o $@ $< -ccopt -L.
 
+extentlistset_test: extentlistset_test.ml all libstdext_stubs.a
+       ocamlfind $(OCAMLOPT) $(OCAMLOPTFLAGS) unix.cmxa stdext.cmxa -linkpkg 
-o $@ $< -ccopt -L.
+
 stdext.cmxa: libstdext_stubs.a $(foreach obj,$(STDEXT_OBJS),$(obj).cmx)
        $(OCAMLOPT) $(OCAMLOPTFLAGS) -a -o $@ -cclib -lstdext_stubs $(foreach 
obj,$(STDEXT_OBJS),$(obj).cmx)
 
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/extentlistSet.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/extentlistSet.ml   Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,106 @@
+
+module type Number = sig
+       type t
+       val zero: t
+       val add : t -> t -> t
+       val sub : t -> t -> t
+end
+
+module ExtentlistSet (A : Number) =
+struct
+       type extent = A.t * A.t
+       type t = extent list
+
+       let ($+) = A.add
+       let ($-) = A.sub
+
+       let empty = []
+
+       let sort list : t =
+               List.sort (fun x y -> compare (fst x) (fst y)) list
+
+       let remove_zeroes = List.filter (fun (_, y) -> y <> A.zero)
+
+       let union (list1: t) (list2: t) : t =
+               let combined = sort (list1 @ list2) in
+               let rec inner l acc =
+                       match l with
+                               | (s1,e1)::(s2,e2)::ls ->
+                                       let extent1_end = s1 $+ e1 in
+                                       if extent1_end < s2 then
+                                               inner ((s2,e2)::ls) 
((s1,e1)::acc)
+                                       else
+                                               let extent2_end = s2 $+ e2 in
+                                               if extent1_end > extent2_end 
then
+                                                       inner ((s1,e1)::ls) acc
+                                               else
+                                                       inner ((s1,s2 $+ e2 $- 
s1)::ls) acc
+                               | (s1,e1)::[] -> (s1,e1)::acc
+                               | [] -> []
+               in List.rev (inner combined [])
+
+       let intersection (list1: t) (list2: t) =
+               let rec inner l1 l2 acc =
+                       match (l1,l2) with
+                               | (s1,e1)::l1s , (s2,e2)::l2s ->
+                                       if s1 > s2 then inner l2 l1 acc else
+                                               if s1 $+ e1 < s2 then inner l1s 
l2 acc else
+                                                       if s1 < s2 then inner 
((s2,e1 $+ s1 $- s2)::l1s) l2 acc else
+                                                               (* s1=s2 *)
+                                                               if e1 < e2 then
+                                                                       inner 
l1s ((s2 $+ e1,e2 $- e1)::l2s) ((s1,e1)::acc)
+                                                               else if e1 > e2 
then
+                                                                       inner 
((s1 $+ e2,e1 $- e2)::l1s) l2s ((s2,e2)::acc)
+                                                               else (* e1=e2 *)
+                                                                       inner 
l1s l2s ((s1,e1)::acc)
+                               | _ -> List.rev acc
+               in
+               remove_zeroes(inner list1 list2 [])
+
+       let difference (list1: t) (list2: t) : t =
+               let rec inner l1 l2 acc =
+                       match (l1,l2) with
+                               | (s1,e1)::l1s , (s2,e2)::l2s ->
+                                       if s1<s2 then begin
+                                               if s1 $+ e1 > s2 then
+                                                       inner ((s2,s1 $+ e1 $- 
s2)::l1s) l2 ((s1,s2 $- s1)::acc)
+                                               else
+                                                       inner l1s l2 
((s1,e1)::acc)
+                                       end else if s1>s2 then begin
+                                               if s2 $+ e2 > s1 then
+                                                       inner l1 ((s1,s2 $+ e2 
$- s1)::l2s) acc
+                                               else
+                                                       inner l1 l2s acc
+                                       end else begin
+                                               (* s1=s2 *)
+                                               if e1 > e2 then
+                                                       inner ((s1 $+ e2,e1 $- 
e2)::l1s) l2s acc
+                                               else if e1 < e2 then
+                                                       inner l1s ((s2 $+ e1,e2 
$- e1)::l2s) acc
+                                               else
+                                                       inner l1s l2s acc
+                                       end
+                               | l1s, [] -> (List.rev acc) @ l1s
+                               | [], _ -> List.rev acc
+               in
+               remove_zeroes(inner list1 list2 [])
+
+       let of_list (list: extent list) : t =
+               let l = sort list in
+               let rec inner ls acc =
+                       match ls with
+                               | (s1,e1)::(s2,e2)::rest ->
+                                       (* extents should be non-overlapping *)
+                                       if s1 $+ e1 > s2 then failwith "Bad 
list"
+                                       (* adjacent extents should be coalesced 
*)
+                                       else if s1 $+ e1=s2 then inner ((s1,e1 
$+ e2)::rest) acc
+                                       else inner ((s2,e2)::rest) 
((s1,e1)::acc)
+                               | (s1,e1)::[] -> List.rev ((s1,e1)::acc)
+                               | [] -> List.rev acc
+               in
+               inner l []
+
+       let fold_left = List.fold_left
+
+       let to_list x = x
+end
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/extentlistSet.mli
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/extentlistSet.mli  Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,27 @@
+(** A module to represent sets of elements as (start, length) pairs. *)
+
+(** Elements must be 'Numbers': *)
+module type Number = sig 
+       type t 
+       val zero: t
+       val add : t -> t -> t 
+       val sub : t -> t -> t 
+
+end
+
+(** Representation of a Set *)
+module ExtentlistSet: functor (A : Number) -> sig
+       type extent = A.t * A.t
+       type t
+
+       val empty : t
+
+       val union : t -> t -> t
+       val intersection : t -> t -> t
+       val difference : t -> t -> t
+
+       val of_list : extent list -> t
+       val to_list : t -> extent list
+       val fold_left : ('a -> extent -> 'a) -> 'a -> t -> 'a
+end
+
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/extentlistset_test.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/extentlistset_test.ml      Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,92 @@
+(* We will check if a list of set equalities hold over random inputs *)
+
+open Set_test
+
+(* We test using the integer domain only. *)
+module Intextentlist = ExtentlistSet.ExtentlistSet(struct 
+  type t=int 
+  let zero=0 
+  let add=(+) 
+  let sub=(-) 
+end)
+open Intextentlist
+
+(* Sets are finite, up to cardinality [size] *)
+let size = 1000
+
+module Tests = SetEqualities(struct
+       type t = Intextentlist.t
+       let universe = of_list [(0, size)]
+       let (+) = union
+       let (^) = intersection
+       let (-) = difference
+
+       let not x = universe - x
+       let (=) x y = (x - y = empty) && (y - x = empty)
+       let extent_to_string (s, l) = Printf.sprintf "(%d, %d)" s l
+       let to_string xs = String.concat ", " (List.map extent_to_string 
(to_list xs))
+end)
+(* Given a triple of inputs, check that all the set equalities hold *)
+let one (a, b, c) = List.iter (fun f -> f a b c) Tests.all
+
+open LazyList
+
+(** [make p s e] return an extentlist starting at [s], ending before [e] where
+    an integer x is covered by the extentlist iff [p x] *)
+let make p s e =
+  let rec ints acc a b = if a < b then ints (a :: acc) (a + 1) b else acc in
+  of_list (List.fold_left (fun acc x -> if p x then (x, 1)::acc else acc) [] 
(ints [] s e))
+
+(* A lazy-list of random triples (a, b, c)*)
+let random_inputs =    
+  let one () = make (fun _ -> Random.bool ()) 0 (size - 1) in
+  (* Create triples of random inputs for the checker *)
+  let three () = one (), one (), one () in
+  let rec f () = lazy (Cons(three (), f ())) in
+  f ()
+
+let _ = 
+  let n = 1000 in
+  iter (fun _ -> ()) (take n (map one random_inputs));
+  Printf.printf "%d random sets of maximum size %d checked.\n" n size
+
+type run = 
+  | Empty of int
+  | Full of int
+let to_run_list xs = 
+  let rec inner acc index = function
+       | [] -> acc
+       | (x, y) :: xs -> inner (Full y :: (Empty (x - index)) :: acc) (x + y) 
xs in  let map f xs = 
+       let rec inner acc f = function
+         | [] -> acc
+         | (x :: xs) -> inner ((f x)::acc) f xs in
+         inner [] f xs in
+
+       List.rev (inner [] 0 xs)
+
+let _ =
+  (* vhds have max size of 2 TiB, in 2 MiB blocks => 2**20 blocks *)
+  (* The BAT consists of up to 2**20 blocks in any order *)
+  (* Worst case for us is as many singleton blocks as possible, which *)
+  (* can't be coalesced because they don't have neighbours. The maximum *)
+  (* number of blocks is achieved with the allocation pattern 10101010... *)
+  (* i.e. 2**19 singleton blocks. *)
+
+  (* As a bitmap we would have 2**19 / 2**3 = 2**16 bytes (64kbit) *)
+  let worst_case = make (fun x -> x mod 2 = 1) 0 (1024*1024/2/12) in
+  let hex (a, b) = Printf.sprintf "%x,%x" a b in
+  let to_string xs = "[" ^ (String.concat ";" (Listext.List.map_tr hex xs)) ^ 
"]" in
+
+
+  Printf.printf "generated\n";
+       let x = to_list worst_case in
+Printf.printf "got a list\n";
+         let y = Listext.List.map_tr hex x in
+Printf.printf "got lots of strings\n";
+  let s = to_string (to_list worst_case) in
+  Printf.printf "Extent size=%d\n" (String.length s);
+       let string_of_run = function
+         | Empty x -> Printf.sprintf "-%d" x
+         | Full x -> Printf.sprintf "+%d" x in
+       let s' = String.concat ";" (Listext.List.map_tr string_of_run 
(to_run_list x)) in
+         Printf.printf "Runs size=%d\n" (String.length s')
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/lazyList.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/lazyList.ml        Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,20 @@
+(* A lazy-list implementation *)
+
+type 'a elt =
+       | Empty
+       | Cons of 'a * 'a t
+and 'a t = 'a elt lazy_t
+
+let rec map f xs = lazy(match Lazy.force xs with
+       | Empty -> Empty
+       | Cons(x, xs) -> Cons(f x, map f xs))
+       
+let rec take n xs = lazy(match n, Lazy.force xs with
+       | 0, _ -> Empty
+       | n, Empty -> raise Not_found
+       | n, Cons(x, xs) -> Cons(x, take (n - 1) xs)) 
+       
+let rec iter f xs = match Lazy.force xs with
+       | Empty -> ()
+       | Cons(x, xs) -> f x; iter f xs
+
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/lazyList.mli
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/lazyList.mli       Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,16 @@
+(** A lazy-list *)
+
+(** A forced lazy list element *)
+type 'a elt = Empty | Cons of 'a * 'a t
+
+(** A lazy list *)
+and 'a t = 'a elt lazy_t
+
+(** [map f xs] returns the list [f 1; f 2; ...; f n] *)
+val map : ('a -> 'b) -> 'a t -> 'b t
+
+(** [take n xs] returns the list truncated to the first [n] elements *)
+val take : int -> 'a t -> 'a t
+
+(** [iter f xs] applies every list element to [f] *)
+val iter : ('a -> 'b) -> 'a t -> unit
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/set_test.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/set_test.ml        Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,31 @@
+module type Set = sig
+  type t
+  val (+): t -> t -> t (* union *)
+  val (^): t -> t -> t (* intersection *)
+  val (-): t -> t -> t (* difference *)
+  val not: t -> t      (* complement *)
+  val (=): t -> t -> bool
+
+  val to_string: t -> string
+end
+
+module SetEqualities(S: Set) = struct
+  open S
+
+  let w txt f a b c = 
+       if Pervasives.not(f a b c)
+       then failwith (Printf.sprintf "%s a=%s b=%s c=%s" txt (S.to_string a) 
(S.to_string b) (S.to_string c))
+         
+  let all = [
+       w "commutative_1" (fun a b _ -> a + b = b + a);
+       w "commutative_2" (fun a b _ -> a ^ b = b ^ a);
+       w "associative_1" (fun a b c -> (a + b) + c = a + (b + c));
+       w "associative_2" (fun a b c -> (a ^ b) ^ c = a ^ (b ^ c));
+       w "distributive_1" (fun a b c -> a + (b ^ c) = (a + b) ^ (a + c));
+       w "distributive_2" (fun a b c -> a ^ (b + c) = (a ^ b) + (a ^ c));
+       w "complement_1" (fun a _ _ -> not (not a) = a);
+       w "demorgan_1" (fun a b _ -> not (a + b) = (not a) ^ (not b));
+       w "demorgan_2" (fun a b _ -> not (a ^ b) = (not a) + (not b));
+  ]
+end
+
diff -r ad151dc6eb45 -r 542efa53c3e2 stdext/set_test.mli
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stdext/set_test.mli       Wed Jul 21 23:29:15 2010 +0100
@@ -0,0 +1,15 @@
+module type Set =
+  sig
+    type t
+    val ( + ) : t -> t -> t
+    val ( ^ ) : t -> t -> t
+    val ( - ) : t -> t -> t
+    val not : t -> t
+    val ( = ) : t -> t -> bool
+    val to_string : t -> string
+  end
+module SetEqualities :
+  functor (S : Set) ->
+    sig
+      val all : (S.t -> S.t -> S.t -> unit) list
+    end
diff -r ad151dc6eb45 -r 542efa53c3e2 xapi-libs.spec
--- a/xapi-libs.spec    Mon Jul 12 08:33:28 2010 +0100
+++ b/xapi-libs.spec    Wed Jul 21 23:29:15 2010 +0100
@@ -69,7 +69,7 @@
    /opt/xensource/libexec/pciutil
    /opt/xensource/libexec/sexprpp
    /opt/xensource/libexec/xmlpp
-
+   /opt/xensource/libexec/extentlistset_test
 
 %files devel
 %defattr(-,root,root,-)
@@ -180,6 +180,9 @@
    /usr/lib/ocaml/stdext/dllstdext_stubs.so
    /usr/lib/ocaml/stdext/encodings.cmi
    /usr/lib/ocaml/stdext/encodings.cmx
+   /usr/lib/ocaml/stdext/extentlistSet.cmi
+   /usr/lib/ocaml/stdext/extentlistSet.cmx
+   /usr/lib/ocaml/stdext/extentlistset_test.cmx
    /usr/lib/ocaml/stdext/fe.cmi
    /usr/lib/ocaml/stdext/fe.cmx
    /usr/lib/ocaml/stdext/fecomms.cmi
@@ -197,6 +200,8 @@
    /usr/lib/ocaml/stdext/hashtblext.cmi
    /usr/lib/ocaml/stdext/hashtblext.cmx
    /usr/lib/ocaml/stdext/libstdext_stubs.a
+   /usr/lib/ocaml/stdext/lazyList.cmi
+   /usr/lib/ocaml/stdext/lazyList.cmx
    /usr/lib/ocaml/stdext/listext.cmi
    /usr/lib/ocaml/stdext/listext.cmx
    /usr/lib/ocaml/stdext/mapext.cmi
@@ -211,6 +216,8 @@
    /usr/lib/ocaml/stdext/range.cmx
    /usr/lib/ocaml/stdext/ring.cmi
    /usr/lib/ocaml/stdext/ring.cmx
+   /usr/lib/ocaml/stdext/set_test.cmi
+   /usr/lib/ocaml/stdext/set_test.cmx
    /usr/lib/ocaml/stdext/sha1sum.cmi
    /usr/lib/ocaml/stdext/sha1sum.cmx
    /usr/lib/ocaml/stdext/stdext.a
 stdext/Makefile              |    8 ++-
 stdext/extentlistSet.ml      |  106 +++++++++++++++++++++++++++++++++++++++++++
 stdext/extentlistSet.mli     |   27 ++++++++++
 stdext/extentlistset_test.ml |   92 +++++++++++++++++++++++++++++++++++++
 stdext/lazyList.ml           |   20 ++++++++
 stdext/lazyList.mli          |   16 ++++++
 stdext/set_test.ml           |   31 ++++++++++++
 stdext/set_test.mli          |   15 ++++++
 xapi-libs.spec               |    9 +++-
 9 files changed, 321 insertions(+), 3 deletions(-)


Attachment: xen-api-libs.hg.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-API] [PATCH] add new modules to stdext, David Scott <=