On a quest for agency in Bellairs

Initial version of 'share'

Still quite broken at the moment

+3
mvp/ocaml/bellairs_intf.ml
···
val size : file -> int64
val read : ?off:int64 -> ?len:int64 -> file -> string
val write : ?off:int64 -> ?len:int64 -> file -> string -> unit
+
+
(* FIXME: not totally sure if that should be here *)
+
val share : file -> Uri.t
end
module type Sigs = sig
+10 -11
mvp/ocaml/client/client.ml
···
Capnp_rpc_unix.with_cap_exn client f
let pp_name ppf name = Fmt.pf ppf "%a" Fmt.(styled `Bold string) name
-
-
let pp_entry ppf { Storage.name; file } =
-
Fmt.pf ppf "%a:%a" pp_name name Capability.pp file
+
let pp_uri ppf id = Fmt.pf ppf "%a" Fmt.(styled `Yellow Uri.pp) id
+
let pp_entry ppf { Storage.name; _ } = Fmt.pf ppf "%a" pp_name name
let ls net () uri =
connect net uri @@ fun dir ->
···
Storage.write file data;
Fmt.pr "%a is created.\n%!" pp_name name
-
let open_file net () uri name =
+
let share net () uri name =
connect net uri @@ fun dir ->
-
let _file = Storage.open_ dir name in
-
Fmt.pr "%a: <raw>.\n%!" pp_name name
+
Capability.with_ref (Storage.open_ dir name) @@ fun file ->
+
let uri = Storage.share file in
+
Fmt.pr "%a\n%!" pp_uri uri
let delete net () uri name =
connect net uri @@ fun dir ->
···
Term.(
const (create env#net) $ setup_log $ connect_addr $ name_arg $ data_arg)
-
let open_cmd env =
+
let share_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) $ setup_log $ connect_addr $ name_arg)
+
let info = Cmd.info "share" ~doc in
+
Cmd.v info Term.(const (share env#net) $ setup_log $ connect_addr $ name_arg)
let delete_cmd env =
let doc = "Delete a file" in
···
[
ls_cmd env;
create_cmd env;
-
open_cmd env;
+
share_cmd env;
delete_cmd env;
size_cmd env;
read_cmd env;
+7 -2
mvp/ocaml/client/storage.ml
···
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
-
()
+
Capability.call_for_unit_exn t method_id request
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 share t =
+
let open API.Client.File.Share in
+
let request = Capability.Request.create_no_args () in
+
let results = Capability.call_for_value_exn t method_id request in
+
Uri.of_string (Results.uri_get results)
let opt_set f params = function
| None -> ()
+2 -2
mvp/ocaml/server/directory.ml
···
open Capnp_rpc.Std
module API = Schema.Storage.MakeRPC (Capnp_rpc)
-
let local sr dir =
+
let local dir =
let module Directory = API.Service.Directory in
-
Capnp_rpc.Persistence.with_sturdy_ref sr Directory.local
+
Directory.local
@@ object
inherit Directory.service
+2 -5
mvp/ocaml/server/directory.mli
···
-
open Capnp_rpc
open Bellairs
+
open Capnp_rpc
-
val local :
-
API.Service.Directory.t Sturdy_ref.t ->
-
Impl.dir ->
-
API.Service.Directory.t Capability.t
+
val local : Impl.dir -> API.Service.Directory.t Capability.t
+10 -2
mvp/ocaml/server/file.ml
···
-
open Capnp_rpc.Std
open Bellairs
+
open Capnp_rpc.Std
let int64_of_uint64 n =
match Stdint.Int64.of_uint64 n with -1L -> None | i -> Some i
···
let local file =
let module File = API.Service.File in
File.local
-
@@ object
+
@@ object (self)
inherit File.service
+
+
method share_impl _params release_param_caps =
+
let open File.Share in
+
release_param_caps ();
+
let response, results = Service.Response.create Results.init_pointer in
+
let uri = Capnp_rpc.Persistence.save_exn (File.local self) in
+
Results.uri_set results (Uri.to_string uri);
+
Service.return response
method read_impl params release_param_caps =
let open File.Read in
+1 -1
mvp/ocaml/server/file.mli
···
-
open Capnp_rpc
open Bellairs
+
open Capnp_rpc
val local : Impl.file -> API.Service.File.t Capability.t
+10 -12
mvp/ocaml/server/impl.ml
···
in-memory database *)
type file = { mutable content : string }
-
type dir = (string, file) Hashtbl.t
+
type dir = { files : (string, file) Hashtbl.t }
type entry = { name : string; file : file }
-
let create files name =
+
let create { files } name =
let file = { content = "" } 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 root () = { files = Hashtbl.create 10 }
+
let open_ dir name = Hashtbl.find dir.files name
+
let delete dir name = Hashtbl.remove dir.files name
let read ?(off = 0L) ?len file =
let content_len = String.length file.content in
···
let size file = Int64.of_int (String.length file.content)
-
let list files =
-
Hashtbl.fold (fun name file acc -> { name; file } :: acc) files []
+
let list dir =
+
Hashtbl.fold (fun name file acc -> { name; file } :: acc) dir.files []
+
+
(* this is done in another layer *)
+
let share _ = assert false
+1 -4
mvp/ocaml/server/server.ml
···
let services = Restorer.Table.create ~sw make_sturdy in
let restore = Restorer.of_table services in
let root_id = Capnp_rpc_unix.Vat_config.derived_id config "root" in
-
let root =
-
let sr = Capnp_rpc_net.Restorer.Table.sturdy_ref services root_id in
-
Directory.local sr (Impl.root ())
-
in
+
let root = Directory.local (Impl.root ()) in
Restorer.Table.add services root_id root;
let vat = Capnp_rpc_unix.serve ~sw ~restore config in
match Capnp_rpc_unix.Cap_file.save_service vat root_id cap_file with
+6 -4
mvp/schema/storage.capnp
···
interface File {
# Represents a file in the filesystem
-
size @0 () -> (size :UInt64);
-
# Returns the size of the file in bytes
-
-
read @1 (off :UInt64 = 0, len :UInt64 = 0xffffffffffffffff) -> (data :Data);
+
read @0 (off :UInt64 = 0, len :UInt64 = 0xffffffffffffffff) -> (data :Data);
# Reads data from the file, optionally starting at offset and reading up to len bytes
# Default is to read the entire file
+
size @1 () -> (size :UInt64);
+
# Returns the size of the file in bytes
+
write @2 (off :UInt64 = 0, len :UInt64 = 0xffffffffffffffff, data :Data) -> ();
# Write data to the file, optionally starting at offset and reading up to len bytes
# Default is to write the entire file
+
+
share @3 () -> (uri: Text);
}