On a quest for agency in Bellairs

Add more (broken) code

Changed files
+183 -27
mvp
ocaml
client
server
+151 -17
mvp/ocaml/client/client.ml
···
open Capnp_rpc.Std
open Eio.Std
+
module API = Schema.Storage.MakeRPC (Capnp_rpc)
module Storage :
Bellairs.Storage
-
with type file = [ `File_e62ce624f782d37e ] Capability.t
-
and type dir = [ `Directory_8e98f5ea254aace5 ] Capability.t = struct
-
module API = Schema.Storage.MakeRPC (Capnp_rpc)
-
+
with type file = API.Client.File.t Capability.t
+
and type dir = API.Client.Directory.t Capability.t = struct
type file = API.Client.File.t Capability.t
type dir = API.Client.Directory.t Capability.t
type entry = { name : string; file : file }
···
| Some file -> { name; file }
| None -> failwith "missing entry.file"
-
let todo msg = failwith ("Storage." ^ msg)
-
let list t =
let open API.Client.Directory.List in
let request = Capability.Request.create_no_args () in
···
let entries = Results.entries_get_list results in
List.map entry entries
-
let create _ = todo "create"
-
let open_ _ = todo "open"
-
let delete _ = todo "delete"
-
let size _ = todo "size"
-
let read ?off:_ ?len:_ _ = todo "read"
+
let create t name =
+
let open API.Client.Directory.Create in
+
let request, params = Capability.Request.create Params.init_pointer in
+
Params.name_set params name;
+
let results = Capability.call_for_value_exn t method_id request in
+
match Results.file_get results with
+
| Some file -> file
+
| None -> failwith "create: no file returned"
+
+
let open_ t name =
+
let open API.Client.Directory.Open in
+
let request, params = Capability.Request.create Params.init_pointer in
+
Params.name_set params name;
+
let results = Capability.call_for_value_exn t method_id request in
+
match Results.file_get results with
+
| Some file -> file
+
| None -> failwith "open: no file returned"
+
+
let delete t name =
+
let open API.Client.Directory.Delete in
+
let request, params = Capability.Request.create Params.init_pointer in
+
Params.name_set params name;
+
let _ = Capability.call_for_value_exn t method_id request in
+
()
+
+
let size t =
+
let open API.Client.File.Size in
+
let request = Capability.Request.create_no_args () in
+
let results = Capability.call_for_value_exn t method_id request in
+
Stdint.Int64.of_uint64 (Results.size_get results)
+
+
let read ?off ?len t =
+
let open API.Client.File.Read in
+
let request, params = Capability.Request.create Params.init_pointer in
+
let () =
+
match off with
+
| None -> ()
+
| Some off -> Params.off_set params (Stdint.Int64.to_uint64 off)
+
in
+
let () =
+
match len with
+
| None -> ()
+
| Some len -> Params.len_set params (Stdint.Int64.to_uint64 len)
+
in
+
let results = Capability.call_for_value_exn t method_id request in
+
Results.data_get results
end
-
let ls net uri =
+
let connect net uri f =
Switch.run @@ fun sw ->
let client_vat = Capnp_rpc_unix.client_only_vat ~sw net in
-
let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in
-
let entries = Capnp_rpc_unix.with_cap_exn sr Storage.list in
-
List.iter (fun { Storage.name; _ } -> Fmt.pr "- %s\n" name) entries
+
let client = Capnp_rpc_unix.Vat.import_exn client_vat uri in
+
Capnp_rpc_unix.with_cap_exn client f
+
+
let pp_file ppf file = Fmt.pf ppf "[%a]" Capnp_rpc.Capability.pp file
+
+
let pp_entry ppf entry =
+
Fmt.pf ppf "%s:%a" entry.Storage.name pp_file entry.file
+
+
let ls net uri =
+
connect net uri @@ fun dir ->
+
let entries = Storage.list dir in
+
Printf.printf "total %d:\n" (List.length entries);
+
List.iter (Fmt.pr "- %a\n" pp_entry) entries;
+
Fmt.pr "%!"
+
+
let create net uri name =
+
connect net uri @@ fun dir ->
+
let file = Storage.create dir name in
+
Fmt.pr "Created file '%s': %a\n" name pp_file file
+
+
let open_file net uri name =
+
connect net uri @@ fun dir ->
+
let file = Storage.open_ dir name in
+
Fmt.pr "Opened file '%s': %a\n" name pp_file file
+
+
let delete net uri name =
+
connect net uri @@ fun dir ->
+
Storage.delete dir name;
+
Fmt.pr "Deleted file '%s'\n" name
+
+
let size net uri name =
+
connect net uri @@ fun dir ->
+
let file = Storage.open_ dir name in
+
let size = Storage.size file in
+
Fmt.pr "Size of '%s': %Ld bytes\n" name size
+
+
let read net addr name offset length =
+
connect net addr @@ fun dir ->
+
let file = Storage.open_ dir name in
+
let data = Storage.read ?off:offset ?len:length file in
+
Printf.printf "Contents of '%s':\n%s\n" name data
open Cmdliner
···
let i = Arg.info [] ~docv:"ADDR" ~doc:"Address of server (capnp://...)" in
Arg.(required @@ pos 0 (some Capnp_rpc_unix.sturdy_uri) None i)
+
let name_arg =
+
let i = Arg.info [] ~docv:"NAME" ~doc:"Name of the file" in
+
Arg.(required @@ pos 1 (some string) None i)
+
+
let offset_arg =
+
let i =
+
Arg.info [ "o"; "offset" ] ~docv:"OFFSET"
+
~doc:"Offset from where to start reading (default: 0)"
+
in
+
Arg.(value @@ opt (some int64) None i)
+
+
let length_arg =
+
let i =
+
Arg.info [ "l"; "length" ] ~docv:"LENGTH"
+
~doc:"Number of bytes to read (default: all)"
+
in
+
Arg.(value @@ opt (some int64) None i)
+
let ls_cmd env =
-
let doc = "run the client" in
+
let doc = "List files in the directory" in
let info = Cmd.info "ls" ~doc in
Cmd.v info Term.(const (ls env#net) $ connect_addr)
-
let () = exit @@ Eio_main.run @@ fun env -> Cmd.eval (ls_cmd env)
+
let create_cmd env =
+
let doc = "Create a new file" in
+
let info = Cmd.info "create" ~doc in
+
Cmd.v info Term.(const (create env#net) $ connect_addr $ name_arg)
+
+
let open_cmd env =
+
let doc = "Open an existing file and show its ID" in
+
let info = Cmd.info "open" ~doc in
+
Cmd.v info Term.(const (open_file env#net) $ connect_addr $ name_arg)
+
+
let delete_cmd env =
+
let doc = "Delete a file" in
+
let info = Cmd.info "delete" ~doc in
+
Cmd.v info Term.(const (delete env#net) $ connect_addr $ name_arg)
+
+
let size_cmd env =
+
let doc = "Get the size of a file" in
+
let info = Cmd.info "size" ~doc in
+
Cmd.v info Term.(const (size env#net) $ connect_addr $ name_arg)
+
+
let read_cmd env =
+
let doc = "Read the contents of a file" in
+
let info = Cmd.info "read" ~doc in
+
Cmd.v info
+
Term.(
+
const (read env#net) $ connect_addr $ name_arg $ offset_arg $ length_arg)
+
+
let main_cmd env =
+
let doc = "Bellairs Storage Client" in
+
let info = Cmd.info "bellairs" ~doc in
+
Cmd.group info
+
[
+
ls_cmd env;
+
create_cmd env;
+
open_cmd env;
+
delete_cmd env;
+
size_cmd env;
+
read_cmd env;
+
]
+
+
let () = exit @@ Eio_main.run @@ fun env -> Cmd.eval (main_cmd env)
+32 -10
mvp/ocaml/server/server.ml
···
module API = Schema.Storage.MakeRPC (Capnp_rpc)
open Capnp_rpc.Std
-
let todo msg = failwith ("TODO: " ^ msg)
-
module Impl : sig
include Bellairs.Storage
···
let _ = create tbl "bar" in
tbl
-
let open_ (files : dir) name =
-
try Hashtbl.find files name with Not_found -> failwith "file not found"
-
+
let open_ (files : dir) name = Hashtbl.find files name
let delete files name = Hashtbl.remove files name
let read ?(off = 0L) ?(len = Int64.max_int) file =
···
Directory.local
@@ object
inherit Directory.service
-
method create_impl _ = todo "create_impl"
+
+
method create_impl params release_param_caps =
+
let open Directory.Create in
+
let name = Params.name_get params in
+
release_param_caps ();
+
let response, results =
+
Service.Response.create Results.init_pointer
+
in
+
let file = Impl.create dir name in
+
Results.file_set results (Some (File.local file));
+
Service.return response
method list_impl _ release_param_caps =
let open Directory.List in
···
Service.Response.create Results.init_pointer
in
let entries = Impl.list dir in
-
let entries_array =
Results.entries_init results (List.length entries)
in
···
API.Builder.Directory.Entry.file_set entry
(Some (File.local e.Impl.file)))
entries;
-
Service.return response
-
method open_impl _ = todo "open_impl"
-
method delete_impl _ = todo "delete_impl"
+
method open_impl params release_param_caps =
+
let open Directory.Open in
+
let name = Params.name_get params in
+
release_param_caps ();
+
let response, results =
+
Service.Response.create Results.init_pointer
+
in
+
try
+
let file = Impl.open_ dir name in
+
Results.file_set results (Some (File.local file));
+
Service.return response
+
with Not_found -> Service.fail "File '%s' not found" name
+
+
method delete_impl params release_param_caps =
+
let open Directory.Delete in
+
let name = Params.name_get params in
+
release_param_caps ();
+
let response = Service.Response.create_empty () in
+
Impl.delete dir name;
+
Service.return response
end
end