···11+open Capnp_rpc.Std
22+module API = Schema.Storage.MakeRPC (Capnp_rpc)
33+44+let local dir =
55+ let module Directory = API.Service.Directory in
66+ Directory.local
77+ @@ object
88+ inherit Directory.service
99+1010+ method create_impl params release_param_caps =
1111+ let open Directory.Create in
1212+ let name = Params.name_get params in
1313+ release_param_caps ();
1414+ let response, results = Service.Response.create Results.init_pointer in
1515+ let file = Impl.create dir name in
1616+ let file_cap = File.local file in
1717+ (* TODO: add persistence *)
1818+ Results.file_set results (Some file_cap);
1919+ Service.return response
2020+2121+ method list_impl _ release_param_caps =
2222+ let open Directory.List in
2323+ release_param_caps ();
2424+ let response, results = Service.Response.create Results.init_pointer in
2525+ let entries = Impl.list dir in
2626+ let entries_array =
2727+ Results.entries_init results (List.length entries)
2828+ in
2929+ List.iteri
3030+ (fun i e ->
3131+ let entry = Capnp.Array.get entries_array i in
3232+ API.Builder.Directory.Entry.name_set entry e.Impl.name;
3333+ API.Builder.Directory.Entry.file_set entry
3434+ (Some (File.local e.Impl.file)))
3535+ entries;
3636+ Service.return response
3737+3838+ method open_impl params release_param_caps =
3939+ let open Directory.Open in
4040+ let name = Params.name_get params in
4141+ release_param_caps ();
4242+ let response, results = Service.Response.create Results.init_pointer in
4343+ try
4444+ let file = Impl.open_ dir name in
4545+ Results.file_set results (Some (File.local file));
4646+ Service.return response
4747+ with Not_found -> Service.fail "File '%s' not found" name
4848+4949+ method delete_impl params release_param_caps =
5050+ let open Directory.Delete in
5151+ let name = Params.name_get params in
5252+ release_param_caps ();
5353+ let response = Service.Response.create_empty () in
5454+ Impl.delete dir name;
5555+ Service.return response
5656+ end
+3
mvp/ocaml/server/directory.mli
···11+open Capnp_rpc.Std
22+33+val local : Impl.dir -> API.Service.Directory.t Capability.t
+26
mvp/ocaml/server/file.ml
···11+open Capnp_rpc.Std
22+33+let local file =
44+ let module File = API.Service.File in
55+ File.local
66+ @@ object
77+ inherit File.service
88+99+ method read_impl params release_param_caps =
1010+ let open File.Read in
1111+ let off = Stdint.Int64.of_uint64 (Params.off_get params) in
1212+ let len = Stdint.Int64.of_uint64 (Params.len_get params) in
1313+ release_param_caps ();
1414+ let response, results = Service.Response.create Results.init_pointer in
1515+ let data = Impl.read file ~off ~len in
1616+ Results.data_set results data;
1717+ Service.return response
1818+1919+ method size_impl _ release_param_caps =
2020+ let open File.Size in
2121+ release_param_caps ();
2222+ let response, results = Service.Response.create Results.init_pointer in
2323+ let size = Stdint.Int64.to_uint64 (Impl.size file) in
2424+ Results.size_set results size;
2525+ Service.return response
2626+ end
+3
mvp/ocaml/server/file.mli
···11+open Capnp_rpc.Std
22+33+val local : Impl.file -> API.Service.File.t Capability.t
+31
mvp/ocaml/server/impl.ml
···11+type file = { content : string; size : int64 }
22+type dir = (string, file) Hashtbl.t
33+type entry = { name : string; file : file }
44+55+let create files name =
66+ let file = { content = ""; size = 0L } in
77+ Hashtbl.add files name file;
88+ file
99+1010+let root () =
1111+ let tbl = Hashtbl.create 10 in
1212+ let _ = create tbl "foo" in
1313+ let _ = create tbl "bar" in
1414+ tbl
1515+1616+let open_ (files : dir) name = Hashtbl.find files name
1717+let delete files name = Hashtbl.remove files name
1818+1919+let read ?(off = 0L) ?(len = Int64.max_int) file =
2020+ let content_len = String.length file.content in
2121+ let off = Int64.to_int off in
2222+ let len = Int64.to_int len in
2323+ let off = max 0 (min off content_len) in
2424+ let max_len = content_len - off in
2525+ let len = if len >= max_len then max_len else len in
2626+ String.sub file.content off len
2727+2828+let size file = file.size
2929+3030+let list files =
3131+ Hashtbl.fold (fun name file acc -> { name; file } :: acc) files []
+3
mvp/ocaml/server/impl.mli
···11+include Bellairs.Storage
22+33+val root : unit -> dir
+3-135
mvp/ocaml/server/server.ml
···3344let cap_file = "storage.cap"
5566-module API = Schema.Storage.MakeRPC (Capnp_rpc)
77-open Capnp_rpc.Std
88-99-module Impl : sig
1010- include Bellairs.Storage
1111-1212- val root : unit -> dir
1313-end = struct
1414- type file = { content : string; size : int64 }
1515- type dir = (string, file) Hashtbl.t
1616- type entry = { name : string; file : file }
1717-1818- let create files name =
1919- let file = { content = ""; size = 0L } in
2020- Hashtbl.add files name file;
2121- file
2222-2323- let root () =
2424- let tbl = Hashtbl.create 10 in
2525- let _ = create tbl "foo" in
2626- let _ = create tbl "bar" in
2727- tbl
2828-2929- let open_ (files : dir) name = Hashtbl.find files name
3030- let delete files name = Hashtbl.remove files name
3131-3232- let read ?(off = 0L) ?(len = Int64.max_int) file =
3333- let content_len = String.length file.content in
3434- let off = Int64.to_int off in
3535- let len = Int64.to_int len in
3636- let off = max 0 (min off content_len) in
3737- let max_len = content_len - off in
3838- let len = if len >= max_len then max_len else len in
3939- String.sub file.content off len
4040-4141- let size file = file.size
4242-4343- let list files =
4444- Hashtbl.fold (fun name file acc -> { name; file } :: acc) files []
4545-end
4646-4747-module File = struct
4848- let local file =
4949- let module File = API.Service.File in
5050- File.local
5151- @@ object
5252- inherit File.service
5353-5454- method read_impl params release_param_caps =
5555- let open File.Read in
5656- let off = Stdint.Int64.of_uint64 (Params.off_get params) in
5757- let len = Stdint.Int64.of_uint64 (Params.len_get params) in
5858- release_param_caps ();
5959- let response, results =
6060- Service.Response.create Results.init_pointer
6161- in
6262- let data = Impl.read file ~off ~len in
6363- Results.data_set results data;
6464- Service.return response
6565-6666- method size_impl _ release_param_caps =
6767- let open File.Size in
6868- release_param_caps ();
6969- let response, results =
7070- Service.Response.create Results.init_pointer
7171- in
7272- let size = Stdint.Int64.to_uint64 (Impl.size file) in
7373- Results.size_set results size;
7474- Service.return response
7575- end
7676-end
7777-7878-module Directory = struct
7979- let local dir =
8080- let module Directory = API.Service.Directory in
8181- Directory.local
8282- @@ object
8383- inherit Directory.service
8484-8585- method create_impl params release_param_caps =
8686- let open Directory.Create in
8787- let name = Params.name_get params in
8888- release_param_caps ();
8989- let response, results =
9090- Service.Response.create Results.init_pointer
9191- in
9292- let file = Impl.create dir name in
9393- Results.file_set results (Some (File.local file));
9494- Service.return response
9595-9696- method list_impl _ release_param_caps =
9797- let open Directory.List in
9898- release_param_caps ();
9999- let response, results =
100100- Service.Response.create Results.init_pointer
101101- in
102102- let entries = Impl.list dir in
103103- let entries_array =
104104- Results.entries_init results (List.length entries)
105105- in
106106- List.iteri
107107- (fun i e ->
108108- let entry = Capnp.Array.get entries_array i in
109109- API.Builder.Directory.Entry.name_set entry e.Impl.name;
110110- API.Builder.Directory.Entry.file_set entry
111111- (Some (File.local e.Impl.file)))
112112- entries;
113113- Service.return response
114114-115115- method open_impl params release_param_caps =
116116- let open Directory.Open in
117117- let name = Params.name_get params in
118118- release_param_caps ();
119119- let response, results =
120120- Service.Response.create Results.init_pointer
121121- in
122122- try
123123- let file = Impl.open_ dir name in
124124- Results.file_set results (Some (File.local file));
125125- Service.return response
126126- with Not_found -> Service.fail "File '%s' not found" name
127127-128128- method delete_impl params release_param_caps =
129129- let open Directory.Delete in
130130- let name = Params.name_get params in
131131- release_param_caps ();
132132- let response = Service.Response.create_empty () in
133133- Impl.delete dir name;
134134- Service.return response
135135- end
136136-end
137137-1386let serve config =
1397 Switch.run @@ fun sw ->
140140- let service_id = Capnp_rpc_unix.Vat_config.derived_id config "main" in
141141- let restore = Restorer.single service_id (Directory.local (Impl.root ())) in
88+ let root_id = Capnp_rpc_unix.Vat_config.derived_id config "root" in
99+ let restore = Restorer.single root_id (Directory.local (Impl.root ())) in
14210 let vat = Capnp_rpc_unix.serve ~sw ~restore config in
143143- match Capnp_rpc_unix.Cap_file.save_service vat service_id cap_file with
1111+ match Capnp_rpc_unix.Cap_file.save_service vat root_id cap_file with
14412 | Error (`Msg m) -> failwith m
14513 | Ok () ->
14614 traceln "Server running. Connect using %S." cap_file;