···
(* Remove any existing file for this key *)
(match find_file t.base_dir key with
| Some (old_path, _, _) ->
196
-
(try Path.unlink old_path
197
+
Path.unlink old_path;
198
+
(* Also remove the sidecar .key file if it exists *)
199
+
(* Get the parent directory and filename from the path *)
200
+
let dirs = key_to_dirs key in
201
+
let dir_path = List.fold_left (fun acc d -> Path.(acc / d)) t.base_dir dirs in
202
+
(* We need to find the actual filename to append .key to it *)
203
+
(match find_file t.base_dir key with
204
+
| Some (_, _, _) ->
205
+
(* The file was found, so let's find its name and remove the .key file *)
207
+
let entries = Path.read_dir dir_path in
208
+
let hash = hash_key key in
209
+
let hash_rest = String.sub hash 4 (String.length hash - 4) in
210
+
List.iter (fun entry ->
211
+
if String.starts_with ~prefix:(hash_rest ^ ":2") entry then
212
+
let key_file_path = Path.(dir_path / (entry ^ ".key")) in
213
+
(try Path.unlink key_file_path with _ -> ())
with Eio.Io (Eio.Fs.E (Not_found _), _) -> ()
···
(* Create final filename and move *)
let final_name = key_to_filename ?ttl:ttl_abs ~flags key in
let final_path = Path.(dir / final_name) in
221
-
Path.rename temp_path final_path
241
+
Path.rename temp_path final_path;
243
+
(* Write the sidecar .key file containing the original key *)
244
+
let key_file_path = Path.(dir / (final_name ^ ".key")) in
245
+
Switch.run @@ fun sw ->
246
+
let key_sink = Path.open_out ~sw ~create:(`Or_truncate 0o644) key_file_path in
247
+
Flow.copy (Flow.string_source key) key_sink;
248
+
Flow.close key_sink
(** {1 Basic Operations} *)
···
Mutex.use_rw ~protect:false t.mutex @@ fun () ->
match find_file t.base_dir key with
235
-
(try Path.unlink path
264
+
(* Also remove the sidecar .key file if it exists *)
265
+
(* Since we have the full path, we need to extract the directory and filename *)
266
+
let dirs = key_to_dirs key in
267
+
let dir_path = List.fold_left (fun acc d -> Path.(acc / d)) t.base_dir dirs in
269
+
let entries = Path.read_dir dir_path in
270
+
let hash = hash_key key in
271
+
let hash_rest = String.sub hash 4 (String.length hash - 4) in
272
+
List.iter (fun entry ->
273
+
if String.starts_with ~prefix:(hash_rest ^ ":2") entry then
274
+
let key_file_path = Path.(dir_path / (entry ^ ".key")) in
275
+
(try Path.unlink key_file_path with _ -> ())
with Eio.Io (Eio.Fs.E (Not_found _), _) -> ()
···
let dir2_path = Path.(dir1_path / dir2) in
List.fold_left (fun acc filename ->
310
-
match parse_filename filename with
312
-
| Some (hash_rest, ttl, flags) ->
313
-
let path = Path.(dir2_path / filename) in
315
-
let stat = Path.stat ~follow:false path in
316
-
(* Reconstruct the original key from the hash *)
317
-
(* This is a limitation - we lose the original key *)
318
-
(* For now, use the hash as the key *)
319
-
let hash = dir1 ^ dir2 ^ hash_rest in
320
-
let entry = Entry.create
322
-
~size:(Optint.Int63.to_int64 stat.size)
352
+
(* Skip .key files themselves *)
353
+
if String.ends_with ~suffix:".key" filename then
356
+
match parse_filename filename with
358
+
| Some (hash_rest, ttl, flags) ->
359
+
let path = Path.(dir2_path / filename) in
361
+
let stat = Path.stat ~follow:false path in
362
+
(* Try to read the original key from the sidecar file *)
364
+
let key_path = Path.(dir2_path / (filename ^ ".key")) in
366
+
Switch.run @@ fun sw ->
367
+
let source = Path.open_in ~sw key_path in
368
+
let buf_read = Eio.Buf_read.of_flow ~max_size:4096 source in
369
+
let content = Eio.Buf_read.take_all buf_read in
370
+
Eio.Flow.close source;
373
+
(* Fall back to using the hash if sidecar file doesn't exist *)
374
+
dir1 ^ dir2 ^ hash_rest
376
+
let entry = Entry.create
378
+
~size:(Optint.Int63.to_int64 stat.size)
) acc (Path.read_dir dir2_path)
) acc (Path.read_dir dir1_path)
···
(* Move to final location *)
let final_path = Path.(dir / filename) in
416
-
Path.rename temp_path final_path
472
+
Path.rename temp_path final_path;
474
+
(* Write the sidecar .key file for chunks too *)
475
+
let key_file_path = Path.(dir / (filename ^ ".key")) in
476
+
Switch.run @@ fun sw ->
477
+
let key_sink = Path.open_out ~sw ~create:(`Or_truncate 0o644) key_file_path in
478
+
Flow.copy (Flow.string_source key) key_sink;
479
+
Flow.close key_sink
let get_range t ~key ~range ~sw =
(* First check for complete file *)
···
let cleanup_chunks t ~key =
let chunks = list_chunks t ~key in
541
-
try Path.unlink (Chunk.path chunk)
605
+
let path = Chunk.path chunk in
607
+
(* Also remove the sidecar .key file if it exists *)
608
+
(* We need to derive the key file path from the chunk path *)
609
+
(* Since chunk.path is the full path to the chunk file, we can't decompose it easily *)
610
+
(* Instead, let's find and remove any matching .key files in the directory *)
611
+
let dirs = key_to_dirs (Chunk.key chunk) in
612
+
let dir_path = List.fold_left (fun acc d -> Path.(acc / d)) t.base_dir dirs in
614
+
let entries = Path.read_dir dir_path in
615
+
List.iter (fun entry ->
616
+
if String.ends_with ~suffix:".key" entry && String.starts_with ~prefix:(Chunk.hash chunk |> fun h -> String.sub h 4 (String.length h - 4)) entry then
617
+
(try Path.unlink Path.(dir_path / entry) with _ -> ())