Skip to content

Commit ca93445

Browse files
committed
update Eio httpstore
1 parent 5f67805 commit ca93445

File tree

3 files changed

+105
-36
lines changed

3 files changed

+105
-36
lines changed

zarr-eio/src/storage.ml

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,13 @@ end
136136

137137
module HttpStore = struct
138138
exception Not_implemented
139-
exception Request_failed of string
139+
exception Request_failed of int * string
140140

141141
open Cohttp_eio
142142

143143
let raise_status_error s =
144144
let c = Cohttp.Code.code_of_status s in
145-
let msg = Printf.sprintf "%d: %s" c (Cohttp.Code.reason_phrase_of_code c) in
146-
raise (Request_failed msg)
145+
raise (Request_failed (c, Cohttp.Code.reason_phrase_of_code c))
147146

148147
module IO = struct
149148
module Deferred = Deferred
@@ -160,18 +159,23 @@ module HttpStore = struct
160159
raise (Zarr.Storage.Key_not_found key)
161160
| e -> raise_status_error e
162161

163-
let size t key =
162+
let size t key = try String.length (get t key) with
163+
| Zarr.Storage.Key_not_found _ -> 0
164+
165+
(*let size t key =
164166
Eio.Switch.run @@ fun sw ->
165167
let url = Uri.with_path t.base_url key in
166168
let resp = Client.head ~sw t.client url in
167169
match Http.Response.status resp with
168170
| #Http.Status.success ->
169171
begin match Http.Response.content_length resp with
170172
| Some l -> l
171-
| None -> String.length (get t key)
173+
| None ->
174+
try String.length (get t key) with
175+
| Zarr.Storage.Key_not_found _ -> 0
172176
end
173177
| #Http.Status.client_error as e when e = `Not_found -> Deferred.return 0
174-
| e -> raise_status_error e
178+
| e -> raise_status_error e *)
175179

176180
let is_member t key = if (size t key) = 0 then false else true
177181

@@ -184,19 +188,19 @@ module HttpStore = struct
184188
let size = String.length data in
185189
List.map (read_range ~data ~size) ranges
186190

187-
(*let set t key data =
191+
let set t key data =
188192
Eio.Switch.run @@ fun sw ->
189193
let url = Uri.with_path t.base_url key in
190194
let headers = Http.Header.of_list [("Content-Length", string_of_int (String.length data))] in
191195
let body = Body.of_string data in
192-
let resp, _ = Client.put ~sw ~headers ~body t.client url in
196+
let resp, _ = Client.post ~sw ~headers ~body t.client url in
193197
match Http.Response.status resp with
194198
| #Http.Status.success -> Deferred.return_unit
195199
| e -> raise_status_error e
196200

197201
let set_partial_values t key ?(append=false) rsv =
198-
let* size = size t key in
199-
let* ov = match size with
202+
let size = size t key in
203+
let ov = match size with
200204
| 0 -> Deferred.return String.empty
201205
| _ -> get t key
202206
in
@@ -208,11 +212,15 @@ module HttpStore = struct
208212
Bytes.unsafe_to_string s
209213
in
210214
set t key (List.fold_left f ov rsv)
211-
*)
215+
216+
let erase t key =
217+
Eio.Switch.run @@ fun sw ->
218+
let url = Uri.with_path t.base_url key in
219+
let resp, _ = Client.delete ~sw t.client url in
220+
match Http.Response.status resp with
221+
| #Http.Status.success -> Deferred.return_unit
222+
| e -> raise_status_error e
212223

213-
let set _ = raise Not_implemented
214-
let set_partial_values _ = raise Not_implemented
215-
let erase _ = raise Not_implemented
216224
let erase_prefix _ = raise Not_implemented
217225
let list _ = raise Not_implemented
218226
let list_dir _ = raise Not_implemented

zarr-eio/src/storage.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ end
2323

2424
module HttpStore : sig
2525
exception Not_implemented
26-
exception Request_failed of string
26+
exception Request_failed of int * string
2727
include Zarr.Storage.STORE with module Deferred = Deferred
2828
val with_open :
2929
net:_ Eio.Net.t ->

zarr-eio/test/test_eio.ml

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,31 +152,92 @@ let _ =
152152
test_storage (module FilesystemStore) s;
153153
HttpStore.with_open ~net:env#net (Uri.of_string "http://127.0.0.1:8080") (fun store ->
154154
let module S = Tiny_httpd in
155-
let dir_behavior = S.Dir.Forbidden and download = true and delete = true and upload = true in
156-
let config = S.Dir.config ~dir_behavior ~delete ~upload ~download ()
157-
and addr = "127.0.0.1" and port = 8080 in
158-
let server = S.create ~max_connections:4 ~addr ~port () in
159-
(*let dir = "/home/zoj/dev/zarr-ml/testdata.zarr" in *)
160-
let dir = Sys.getenv "HTTPSTORE_DIR" in
161-
S.Dir.add_dir_path ~config ~dir ~prefix:"" server;
155+
let server = S.create ~max_connections:1000 ~addr:"127.0.0.1" ~port:8080 () in
156+
let dir = tmp_dir in
157+
S.add_route_handler server ~meth:`HEAD S.Route.rest_of_path_urlencoded (fun path _ ->
158+
let fspath = Filename.concat dir path in
159+
match In_channel.(with_open_gen [Open_rdonly] 0o700 fspath length) with
160+
| exception Sys_error e -> S.Response.make_raw ~code:404 e
161+
| s ->
162+
let headers =
163+
[("Content-Length", Int64.to_string s)
164+
;("Content-Type", "application/octet-stream")]
165+
in
166+
let r = S.Response.make_raw ~code:200 "" in
167+
S.Response.update_headers (List.append headers) r
168+
);
169+
S.add_route_handler server ~meth:`GET S.Route.rest_of_path_urlencoded (fun path _ ->
170+
let fspath = Filename.concat dir path in
171+
match In_channel.(with_open_gen [Open_rdonly] 0o700 fspath input_all) with
172+
| exception Sys_error _ -> S.Response.make_raw ~code:404 (Printf.sprintf "%s not found" path)
173+
| s -> S.Response.make_raw ~code:200 s
174+
);
175+
S.add_route_handler server ~meth:`POST S.Route.rest_of_path_urlencoded (fun path req ->
176+
let write oc = Out_channel.(output_string oc req.body; flush oc) in
177+
let fspath = Filename.concat dir path in
178+
Zarr.Util.create_parent_dir fspath 0o700;
179+
let f = [Open_wronly; Open_trunc; Open_creat] in
180+
match Out_channel.(with_open_gen f 0o700 fspath write) with
181+
| exception Sys_error e -> S.Response.make_raw ~code:500 e
182+
| () -> S.Response.make_raw ~code:201 req.body
183+
);
184+
S.add_route_handler server ~meth:`DELETE S.Route.rest_of_path_urlencoded (fun path _ ->
185+
let fspath = Filename.concat dir path in
186+
match Sys.remove fspath with
187+
| exception Sys_error e -> S.Response.make_raw ~code:404 e
188+
| () -> S.Response.make_raw ~code:200 (Printf.sprintf "%s deleted successfully" path)
189+
);
162190
let _ = Thread.create S.run server in
163-
let gnode = Node.Group.of_path "/some/group" in
191+
let gnode = Node.Group.root in
192+
let attrs = `Assoc [("questions", `String "answer")] in
193+
HttpStore.Group.create ~attrs store gnode;
194+
let exists = HttpStore.Group.exists store gnode in
195+
assert_equal ~printer:string_of_bool true exists;
164196
let meta = HttpStore.Group.metadata store gnode in
165-
assert_equal ~printer:Metadata.Group.show Metadata.Group.default meta;
166-
let anode = Node.Array.of_path "/some/group/another" in
197+
assert_equal ~printer:Yojson.Safe.show attrs (Metadata.Group.attributes meta);
198+
let exists = HttpStore.Array.exists store Node.Array.(gnode / "non-member") in
199+
assert_equal ~printer:string_of_bool false exists;
200+
201+
let cfg =
202+
{chunk_shape = [|2; 5; 5|]
203+
;index_location = End
204+
;index_codecs = [`Bytes LE]
205+
;codecs = [`Transpose [|2; 0; 1|]; `Bytes BE]} in
206+
let anode = Node.Array.(gnode / "arrnode") in
167207
let slice = [|R [|0; 5|]; I 10; R [|0; 10|]|] in
168-
let _ = HttpStore.Array.read store anode slice Complex32 in
169-
assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.hierarchy store);
170-
assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.Group.create store (Node.Group.of_path "/blah"));
171-
(*assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.Group.children store gnode);
172-
assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.Array.rename store anode "newname"); *)
173-
(*assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.Array.reshape store anode [|1;1;1|]); *)
174-
assert_raises (HttpStore.Not_implemented) (fun () -> HttpStore.clear store);
208+
let bigger_slice = [|R [|0; 6|]; L [|9; 10|] ; R [|0; 11|]|] in
209+
HttpStore.Array.create
210+
~codecs:[`ShardingIndexed cfg] ~shape:[|100; 100; 50|] ~chunks:[|10; 15; 20|]
211+
Complex32 Complex.one anode store;
212+
let exp = Ndarray.init Complex32 [|6; 1; 11|] (Fun.const Complex.one) in
213+
let got = HttpStore.Array.read store anode slice Complex32 in
214+
assert_equal exp got;
215+
Ndarray.fill exp Complex.{re=2.0; im=0.};
216+
HttpStore.Array.write store anode slice exp;
217+
let got = HttpStore.Array.read store anode slice Complex32 in
218+
(* test if a bigger slice containing new elements can be read from store *)
219+
let _ = HttpStore.Array.read store anode bigger_slice Complex32 in
220+
assert_equal exp got;
221+
(* test writing a bigger slice to store *)
222+
HttpStore.Array.write store anode bigger_slice @@ Ndarray.init Complex32 [|7; 2; 12|] (Fun.const Complex.{re=0.; im=3.0});
223+
let got = HttpStore.Array.read store anode slice Complex32 in
224+
Ndarray.fill exp Complex.{re=0.; im=3.0};
225+
assert_equal exp got;
226+
let nshape = [|25; 28; 10|] in
227+
HttpStore.Array.reshape store anode nshape;
228+
let meta = HttpStore.Array.metadata store anode in
229+
assert_equal ~printer:print_int_array nshape (Metadata.Array.shape meta);
175230
assert_raises
176-
(HttpStore.Not_implemented)
177-
(fun () ->
178-
let exp = Ndarray.init Complex32 [|6; 1; 11|] (Fun.const Complex.one) in
179-
HttpStore.Array.write store anode slice exp);
231+
(Zarr.Storage.Invalid_resize_shape)
232+
(fun () -> HttpStore.Array.reshape store anode [|25; 10|]);
233+
assert_raises
234+
(Zarr.Storage.Key_not_found "fakegroup/zarr.json")
235+
(fun () -> HttpStore.Array.metadata store Node.Array.(gnode / "fakegroup"));
236+
assert_raises HttpStore.Not_implemented (fun () -> HttpStore.Array.rename store anode "newname");
237+
assert_raises HttpStore.Not_implemented (fun () -> HttpStore.Group.children store gnode);
238+
assert_raises HttpStore.Not_implemented (fun () -> HttpStore.hierarchy store);
239+
assert_raises HttpStore.Not_implemented (fun () -> HttpStore.Group.delete store gnode);
240+
assert_raises HttpStore.Not_implemented (fun () -> HttpStore.clear store);
180241
Tiny_httpd.stop server)
181242
)
182243
])

0 commit comments

Comments
 (0)