(* The album example: client, server and auxiliary functions *) (* The example is representative of the standard Java RMI benchmarks and examples: remote file servers (in the paper TCY09), album collection (of the paper IYTC09), etc. It is particularly akin to the remote linked list traversal RMI micro-benchmark The code demonstrates extending Chourai with a custom, serializable data type. References: [TCY09] Eli Tilevich, William R. Cook, Yang Jiao. Explicit Batching for Distributed Objects. The 29th IEEE International Conference on Distributed Computing Systems (ICDCS 2009). June 22-26, 2009. http://people.cs.vt.edu/~jiaoyang/paper/icdcs09.pdf [IYTC09] Ali Ibrahim, Yang Jiao, Eli Tilevich, and William R. Cook. Remote Batch Invocation for Compositional Object Services. The 23rd European Conference on Object-Oriented Programming (ECOOP 2009). July 6-10, 2009. http://people.cs.vt.edu/~jiaoyang/paper/ecoop09.pdf *) (* #load "wire.cmo";; *) open Wire;; (* Define the custom data type and `inject' it into our framework *) type album_descr = {album_inode : int; album_max : int} (* The max number of albums in a collection *) ;; (* Implementation of the album interface. These functions will normally be executed by the server. *) let get_album : string -> album_descr = function | "small" -> {album_inode = 0; album_max = 0} | "large" -> {album_inode = 100; album_max = 105} | x -> failwith ("get_album: unknown album: " ^ x) let next_album : album_descr -> album_descr = fun alb -> if alb.album_inode < alb.album_max then {alb with album_inode = succ alb.album_inode} else failwith "next_album: the album collection is exhausted" ;; let get_title : album_descr -> string = function {album_inode = x} -> "Title " ^ string_of_int x let get_rating : album_descr -> int = function {album_inode = x} -> if x mod 2 = 0 then 1 else 10 ;; let delete_album : album_descr -> string = function {album_inode = x} -> "Deleted " ^ string_of_int x ;; (* We use the generic embedding-projection shown later let album_to_wire : album_descr to_wire = fun x -> WComp [WAtom (UInt x.album_inode); WAtom (UInt x.album_max)] ;; let album_from_wire : album_descr from_wire = function | WComp [WAtom (UInt x); WAtom (UInt y)] when x <= y -> Datum {album_inode = x; album_max = y} | w -> Err ("album_from_wire: bad format: " ^ show_wire w) ;; *) let album_iso : (album_descr, (int*int)) iso = {iso_ab = (fun a -> (a.album_inode, a.album_max)); iso_ba = (fun (x,y) -> if x <= y then Datum {album_inode = x; album_max = y} else Err "album_iso: invalid album_descr")} ;; (* Standard boiler-plate. In the future, it could be automatically generated. *) let album_typerep = user_typerep album_iso (tup2_typerep int_typerep int_typerep);; let album_to_wire : album_descr to_wire = gen_to_wire album_typerep;; let album_from_wire : album_descr from_wire = gen_from_wire album_typerep;; let fn_string_album f argw = match string_from_wire argw with | Datum x -> album_to_wire (f x) | Err e -> failwith e ;; let fn_album_string f argw = match album_from_wire argw with | Datum x -> string_to_wire (f x) | Err e -> failwith e ;; let fn_album_int f argw = match album_from_wire argw with | Datum x -> int_to_wire (f x) | Err e -> failwith e ;; let fn_album_album f argw = match album_from_wire argw with | Datum x -> album_to_wire (f x) | Err e -> failwith e ;; let album_registry = [ ("get_album", fn_string_album get_album); ("next_album", fn_album_album next_album); ("get_title", fn_album_string get_title); ("get_rating", fn_album_int get_rating); ("delete_album", fn_album_string delete_album); ] ;;