···11open Capnp_rpc.Std
22open Eio.Std
33+module API = Schema.Storage.MakeRPC (Capnp_rpc)
3445module Storage :
56 Bellairs.Storage
66- with type file = [ `File_e62ce624f782d37e ] Capability.t
77- and type dir = [ `Directory_8e98f5ea254aace5 ] Capability.t = struct
88- module API = Schema.Storage.MakeRPC (Capnp_rpc)
99-77+ with type file = API.Client.File.t Capability.t
88+ and type dir = API.Client.Directory.t Capability.t = struct
109 type file = API.Client.File.t Capability.t
1110 type dir = API.Client.Directory.t Capability.t
1211 type entry = { name : string; file : file }
···1817 | Some file -> { name; file }
1918 | None -> failwith "missing entry.file"
20192121- let todo msg = failwith ("Storage." ^ msg)
2222-2320 let list t =
2421 let open API.Client.Directory.List in
2522 let request = Capability.Request.create_no_args () in
···2724 let entries = Results.entries_get_list results in
2825 List.map entry entries
29263030- let create _ = todo "create"
3131- let open_ _ = todo "open"
3232- let delete _ = todo "delete"
3333- let size _ = todo "size"
3434- let read ?off:_ ?len:_ _ = todo "read"
2727+ let create t name =
2828+ let open API.Client.Directory.Create in
2929+ let request, params = Capability.Request.create Params.init_pointer in
3030+ Params.name_set params name;
3131+ let results = Capability.call_for_value_exn t method_id request in
3232+ match Results.file_get results with
3333+ | Some file -> file
3434+ | None -> failwith "create: no file returned"
3535+3636+ let open_ t name =
3737+ let open API.Client.Directory.Open in
3838+ let request, params = Capability.Request.create Params.init_pointer in
3939+ Params.name_set params name;
4040+ let results = Capability.call_for_value_exn t method_id request in
4141+ match Results.file_get results with
4242+ | Some file -> file
4343+ | None -> failwith "open: no file returned"
4444+4545+ let delete t name =
4646+ let open API.Client.Directory.Delete in
4747+ let request, params = Capability.Request.create Params.init_pointer in
4848+ Params.name_set params name;
4949+ let _ = Capability.call_for_value_exn t method_id request in
5050+ ()
5151+5252+ let size t =
5353+ let open API.Client.File.Size in
5454+ let request = Capability.Request.create_no_args () in
5555+ let results = Capability.call_for_value_exn t method_id request in
5656+ Stdint.Int64.of_uint64 (Results.size_get results)
5757+5858+ let read ?off ?len t =
5959+ let open API.Client.File.Read in
6060+ let request, params = Capability.Request.create Params.init_pointer in
6161+ let () =
6262+ match off with
6363+ | None -> ()
6464+ | Some off -> Params.off_set params (Stdint.Int64.to_uint64 off)
6565+ in
6666+ let () =
6767+ match len with
6868+ | None -> ()
6969+ | Some len -> Params.len_set params (Stdint.Int64.to_uint64 len)
7070+ in
7171+ let results = Capability.call_for_value_exn t method_id request in
7272+ Results.data_get results
3573end
36743737-let ls net uri =
7575+let connect net uri f =
3876 Switch.run @@ fun sw ->
3977 let client_vat = Capnp_rpc_unix.client_only_vat ~sw net in
4040- let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in
4141- let entries = Capnp_rpc_unix.with_cap_exn sr Storage.list in
4242- List.iter (fun { Storage.name; _ } -> Fmt.pr "- %s\n" name) entries
7878+ let client = Capnp_rpc_unix.Vat.import_exn client_vat uri in
7979+ Capnp_rpc_unix.with_cap_exn client f
8080+8181+let pp_file ppf file = Fmt.pf ppf "[%a]" Capnp_rpc.Capability.pp file
8282+8383+let pp_entry ppf entry =
8484+ Fmt.pf ppf "%s:%a" entry.Storage.name pp_file entry.file
8585+8686+let ls net uri =
8787+ connect net uri @@ fun dir ->
8888+ let entries = Storage.list dir in
8989+ Printf.printf "total %d:\n" (List.length entries);
9090+ List.iter (Fmt.pr "- %a\n" pp_entry) entries;
9191+ Fmt.pr "%!"
9292+9393+let create net uri name =
9494+ connect net uri @@ fun dir ->
9595+ let file = Storage.create dir name in
9696+ Fmt.pr "Created file '%s': %a\n" name pp_file file
9797+9898+let open_file net uri name =
9999+ connect net uri @@ fun dir ->
100100+ let file = Storage.open_ dir name in
101101+ Fmt.pr "Opened file '%s': %a\n" name pp_file file
102102+103103+let delete net uri name =
104104+ connect net uri @@ fun dir ->
105105+ Storage.delete dir name;
106106+ Fmt.pr "Deleted file '%s'\n" name
107107+108108+let size net uri name =
109109+ connect net uri @@ fun dir ->
110110+ let file = Storage.open_ dir name in
111111+ let size = Storage.size file in
112112+ Fmt.pr "Size of '%s': %Ld bytes\n" name size
113113+114114+let read net addr name offset length =
115115+ connect net addr @@ fun dir ->
116116+ let file = Storage.open_ dir name in
117117+ let data = Storage.read ?off:offset ?len:length file in
118118+ Printf.printf "Contents of '%s':\n%s\n" name data
4311944120open Cmdliner
45121···51127 let i = Arg.info [] ~docv:"ADDR" ~doc:"Address of server (capnp://...)" in
52128 Arg.(required @@ pos 0 (some Capnp_rpc_unix.sturdy_uri) None i)
53129130130+let name_arg =
131131+ let i = Arg.info [] ~docv:"NAME" ~doc:"Name of the file" in
132132+ Arg.(required @@ pos 1 (some string) None i)
133133+134134+let offset_arg =
135135+ let i =
136136+ Arg.info [ "o"; "offset" ] ~docv:"OFFSET"
137137+ ~doc:"Offset from where to start reading (default: 0)"
138138+ in
139139+ Arg.(value @@ opt (some int64) None i)
140140+141141+let length_arg =
142142+ let i =
143143+ Arg.info [ "l"; "length" ] ~docv:"LENGTH"
144144+ ~doc:"Number of bytes to read (default: all)"
145145+ in
146146+ Arg.(value @@ opt (some int64) None i)
147147+54148let ls_cmd env =
5555- let doc = "run the client" in
149149+ let doc = "List files in the directory" in
56150 let info = Cmd.info "ls" ~doc in
57151 Cmd.v info Term.(const (ls env#net) $ connect_addr)
581525959-let () = exit @@ Eio_main.run @@ fun env -> Cmd.eval (ls_cmd env)
153153+let create_cmd env =
154154+ let doc = "Create a new file" in
155155+ let info = Cmd.info "create" ~doc in
156156+ Cmd.v info Term.(const (create env#net) $ connect_addr $ name_arg)
157157+158158+let open_cmd env =
159159+ let doc = "Open an existing file and show its ID" in
160160+ let info = Cmd.info "open" ~doc in
161161+ Cmd.v info Term.(const (open_file env#net) $ connect_addr $ name_arg)
162162+163163+let delete_cmd env =
164164+ let doc = "Delete a file" in
165165+ let info = Cmd.info "delete" ~doc in
166166+ Cmd.v info Term.(const (delete env#net) $ connect_addr $ name_arg)
167167+168168+let size_cmd env =
169169+ let doc = "Get the size of a file" in
170170+ let info = Cmd.info "size" ~doc in
171171+ Cmd.v info Term.(const (size env#net) $ connect_addr $ name_arg)
172172+173173+let read_cmd env =
174174+ let doc = "Read the contents of a file" in
175175+ let info = Cmd.info "read" ~doc in
176176+ Cmd.v info
177177+ Term.(
178178+ const (read env#net) $ connect_addr $ name_arg $ offset_arg $ length_arg)
179179+180180+let main_cmd env =
181181+ let doc = "Bellairs Storage Client" in
182182+ let info = Cmd.info "bellairs" ~doc in
183183+ Cmd.group info
184184+ [
185185+ ls_cmd env;
186186+ create_cmd env;
187187+ open_cmd env;
188188+ delete_cmd env;
189189+ size_cmd env;
190190+ read_cmd env;
191191+ ]
192192+193193+let () = exit @@ Eio_main.run @@ fun env -> Cmd.eval (main_cmd env)
+32-10
mvp/ocaml/server/server.ml
···66module API = Schema.Storage.MakeRPC (Capnp_rpc)
77open Capnp_rpc.Std
8899-let todo msg = failwith ("TODO: " ^ msg)
1010-119module Impl : sig
1210 include Bellairs.Storage
1311···2826 let _ = create tbl "bar" in
2927 tbl
30283131- let open_ (files : dir) name =
3232- try Hashtbl.find files name with Not_found -> failwith "file not found"
3333-2929+ let open_ (files : dir) name = Hashtbl.find files name
3430 let delete files name = Hashtbl.remove files name
35313632 let read ?(off = 0L) ?(len = Int64.max_int) file =
···8581 Directory.local
8682 @@ object
8783 inherit Directory.service
8888- method create_impl _ = todo "create_impl"
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
89959096 method list_impl _ release_param_caps =
9197 let open Directory.List in
···94100 Service.Response.create Results.init_pointer
95101 in
96102 let entries = Impl.list dir in
9797-98103 let entries_array =
99104 Results.entries_init results (List.length entries)
100105 in
···105110 API.Builder.Directory.Entry.file_set entry
106111 (Some (File.local e.Impl.file)))
107112 entries;
108108-109113 Service.return response
110114111111- method open_impl _ = todo "open_impl"
112112- method delete_impl _ = todo "delete_impl"
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
113135 end
114136end
115137