On a quest for agency in Bellairs

Move things aronund on the server side

Changed files
+132 -137
mvp
+6 -2
mvp/ocaml/client/client.ml
···
open Eio.Std
module API = Schema.Storage.MakeRPC (Capnp_rpc)
+
let pp_file ppf file =
+
let e = Capability.problem file in
+
Fmt.pf ppf "[%a:%a]" Capnp_rpc.Capability.pp file
+
Fmt.(option Capnp_rpc.Exception.pp)
+
e
+
module Storage :
Bellairs.Storage
with type file = API.Client.File.t Capability.t
···
let client_vat = Capnp_rpc_unix.client_only_vat ~sw net in
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
+1
mvp/ocaml/server/API.ml
···
+
include Schema.Storage.MakeRPC (Capnp_rpc)
+56
mvp/ocaml/server/directory.ml
···
+
open Capnp_rpc.Std
+
module API = Schema.Storage.MakeRPC (Capnp_rpc)
+
+
let local dir =
+
let module Directory = API.Service.Directory in
+
Directory.local
+
@@ object
+
inherit Directory.service
+
+
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
+
let file_cap = File.local file in
+
(* TODO: add persistence *)
+
Results.file_set results (Some file_cap);
+
Service.return response
+
+
method list_impl _ release_param_caps =
+
let open Directory.List in
+
release_param_caps ();
+
let response, results = Service.Response.create Results.init_pointer in
+
let entries = Impl.list dir in
+
let entries_array =
+
Results.entries_init results (List.length entries)
+
in
+
List.iteri
+
(fun i e ->
+
let entry = Capnp.Array.get entries_array i in
+
API.Builder.Directory.Entry.name_set entry e.Impl.name;
+
API.Builder.Directory.Entry.file_set entry
+
(Some (File.local e.Impl.file)))
+
entries;
+
Service.return response
+
+
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
+3
mvp/ocaml/server/directory.mli
···
+
open Capnp_rpc.Std
+
+
val local : Impl.dir -> API.Service.Directory.t Capability.t
+26
mvp/ocaml/server/file.ml
···
+
open Capnp_rpc.Std
+
+
let local file =
+
let module File = API.Service.File in
+
File.local
+
@@ object
+
inherit File.service
+
+
method read_impl params release_param_caps =
+
let open File.Read in
+
let off = Stdint.Int64.of_uint64 (Params.off_get params) in
+
let len = Stdint.Int64.of_uint64 (Params.len_get params) in
+
release_param_caps ();
+
let response, results = Service.Response.create Results.init_pointer in
+
let data = Impl.read file ~off ~len in
+
Results.data_set results data;
+
Service.return response
+
+
method size_impl _ release_param_caps =
+
let open File.Size in
+
release_param_caps ();
+
let response, results = Service.Response.create Results.init_pointer in
+
let size = Stdint.Int64.to_uint64 (Impl.size file) in
+
Results.size_set results size;
+
Service.return response
+
end
+3
mvp/ocaml/server/file.mli
···
+
open Capnp_rpc.Std
+
+
val local : Impl.file -> API.Service.File.t Capability.t
+31
mvp/ocaml/server/impl.ml
···
+
type file = { content : string; size : int64 }
+
type dir = (string, file) Hashtbl.t
+
type entry = { name : string; file : file }
+
+
let create files name =
+
let file = { content = ""; size = 0L } in
+
Hashtbl.add files name file;
+
file
+
+
let root () =
+
let tbl = Hashtbl.create 10 in
+
let _ = create tbl "foo" in
+
let _ = create tbl "bar" in
+
tbl
+
+
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 =
+
let content_len = String.length file.content in
+
let off = Int64.to_int off in
+
let len = Int64.to_int len in
+
let off = max 0 (min off content_len) in
+
let max_len = content_len - off in
+
let len = if len >= max_len then max_len else len in
+
String.sub file.content off len
+
+
let size file = file.size
+
+
let list files =
+
Hashtbl.fold (fun name file acc -> { name; file } :: acc) files []
+3
mvp/ocaml/server/impl.mli
···
+
include Bellairs.Storage
+
+
val root : unit -> dir
+3 -135
mvp/ocaml/server/server.ml
···
let cap_file = "storage.cap"
-
module API = Schema.Storage.MakeRPC (Capnp_rpc)
-
open Capnp_rpc.Std
-
-
module Impl : sig
-
include Bellairs.Storage
-
-
val root : unit -> dir
-
end = struct
-
type file = { content : string; size : int64 }
-
type dir = (string, file) Hashtbl.t
-
type entry = { name : string; file : file }
-
-
let create files name =
-
let file = { content = ""; size = 0L } in
-
Hashtbl.add files name file;
-
file
-
-
let root () =
-
let tbl = Hashtbl.create 10 in
-
let _ = create tbl "foo" in
-
let _ = create tbl "bar" in
-
tbl
-
-
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 =
-
let content_len = String.length file.content in
-
let off = Int64.to_int off in
-
let len = Int64.to_int len in
-
let off = max 0 (min off content_len) in
-
let max_len = content_len - off in
-
let len = if len >= max_len then max_len else len in
-
String.sub file.content off len
-
-
let size file = file.size
-
-
let list files =
-
Hashtbl.fold (fun name file acc -> { name; file } :: acc) files []
-
end
-
-
module File = struct
-
let local file =
-
let module File = API.Service.File in
-
File.local
-
@@ object
-
inherit File.service
-
-
method read_impl params release_param_caps =
-
let open File.Read in
-
let off = Stdint.Int64.of_uint64 (Params.off_get params) in
-
let len = Stdint.Int64.of_uint64 (Params.len_get params) in
-
release_param_caps ();
-
let response, results =
-
Service.Response.create Results.init_pointer
-
in
-
let data = Impl.read file ~off ~len in
-
Results.data_set results data;
-
Service.return response
-
-
method size_impl _ release_param_caps =
-
let open File.Size in
-
release_param_caps ();
-
let response, results =
-
Service.Response.create Results.init_pointer
-
in
-
let size = Stdint.Int64.to_uint64 (Impl.size file) in
-
Results.size_set results size;
-
Service.return response
-
end
-
end
-
-
module Directory = struct
-
let local dir =
-
let module Directory = API.Service.Directory in
-
Directory.local
-
@@ object
-
inherit Directory.service
-
-
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
-
release_param_caps ();
-
let response, results =
-
Service.Response.create Results.init_pointer
-
in
-
let entries = Impl.list dir in
-
let entries_array =
-
Results.entries_init results (List.length entries)
-
in
-
List.iteri
-
(fun i e ->
-
let entry = Capnp.Array.get entries_array i in
-
API.Builder.Directory.Entry.name_set entry e.Impl.name;
-
API.Builder.Directory.Entry.file_set entry
-
(Some (File.local e.Impl.file)))
-
entries;
-
Service.return response
-
-
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
-
let serve config =
Switch.run @@ fun sw ->
-
let service_id = Capnp_rpc_unix.Vat_config.derived_id config "main" in
-
let restore = Restorer.single service_id (Directory.local (Impl.root ())) in
+
let root_id = Capnp_rpc_unix.Vat_config.derived_id config "root" in
+
let restore = Restorer.single root_id (Directory.local (Impl.root ())) in
let vat = Capnp_rpc_unix.serve ~sw ~restore config in
-
match Capnp_rpc_unix.Cap_file.save_service vat service_id cap_file with
+
match Capnp_rpc_unix.Cap_file.save_service vat root_id cap_file with
| Error (`Msg m) -> failwith m
| Ok () ->
traceln "Server running. Connect using %S." cap_file;