From 88bbec4cf74f405ab326f168b0a3ae3c313f5a8c Mon Sep 17 00:00:00 2001 From: Alexander Diemand Date: Mon, 29 Jan 2024 22:58:32 +0100 Subject: [PATCH 1/2] +store for keys, fblocks --- _CoqProject | 1 + bin/lxr_assembly.ml | 2 +- bin/lxr_backup.ml | 4 +- elykseer-utils/actrl.ml | 4 +- lxr.ml | 130 +++++++++++++++++++++++++++++++++------- lxr.mli | 72 ++++++++++++++++++++-- theories/Environment.v | 31 ++++------ theories/MakeML.v | 3 +- theories/Store.v | 129 +++++++++++++++++++++++++++++++++++++++ theories/Version.v | 2 +- 10 files changed, 325 insertions(+), 53 deletions(-) create mode 100644 theories/Store.v diff --git a/_CoqProject b/_CoqProject index 7a06a88..3c4937c 100644 --- a/_CoqProject +++ b/_CoqProject @@ -10,5 +10,6 @@ theories/Conversion.v theories/Utilities.v theories/BackupPlanner.v theories/AssemblyCache.v +theories/Store.v theories/MakeML.v theories/Version.v diff --git a/bin/lxr_assembly.ml b/bin/lxr_assembly.ml index 06fc6d7..5921342 100644 --- a/bin/lxr_assembly.ml +++ b/bin/lxr_assembly.ml @@ -62,7 +62,7 @@ let main () = Arg.parse argspec anon_args_fun "lxr_assembly: vaf"; let e1 = Environment.EnvironmentWritable.env_add_file_block "test1M" e0 bi in let e2 = Environment.EnvironmentWritable.env_add_aid_key (aid a') e1 {pkey="abc97391af";ivec="323453";localnchunks=Nchunks.to_positive c.config_nchunks;localid=c.my_id} in let relkeys = Environment.keys e2 in - let relkey = List.assoc (aid a') relkeys in + let relkey = List.assoc (aid a') relkeys.entries in let (a'', b') = Elykseer__Lxr.Assembly.finish a' b in match Elykseer__Lxr.Assembly.encrypt a'' b' relkey with | None -> Lwt_io.printl "failed to encrypt" diff --git a/bin/lxr_backup.ml b/bin/lxr_backup.ml index edadabd..2bb40d7 100644 --- a/bin/lxr_backup.ml +++ b/bin/lxr_backup.ml @@ -135,7 +135,7 @@ let validate_fileblocks fname fhash bis = else Lwt.return () let output_rel_files e (bp : backup_plan) = - let fbis = Env.consolidate_files e.fblocks in + let fbis = Env.consolidate_files e.fblocks.entries in if !arg_dryrun then Lwt_list.iter_s (fun (fname, bis) -> let fhash = sha256 fname in let%lwt () = validate_fileblocks fname fhash bis in @@ -159,7 +159,7 @@ let output_rel_files e (bp : backup_plan) = let output_rel_keys e = let%lwt rel = Relkeys.new_map e.config in let%lwt () = Lwt_list.iter_s (fun (aid, ki) -> - let%lwt _ = Relkeys.add aid ki rel in Lwt.return ()) e.keys in + let%lwt _ = Relkeys.add aid ki rel in Lwt.return ()) e.keys.entries in Relkeys.close_map rel let output_relations e (bp : backup_plan) = diff --git a/elykseer-utils/actrl.ml b/elykseer-utils/actrl.ml index ffb6820..0e486eb 100644 --- a/elykseer-utils/actrl.ml +++ b/elykseer-utils/actrl.ml @@ -14,7 +14,7 @@ let stop actrl = let env = Environment.EnvironmentWritable.finalise_assembly actrl.env in let%lwt relk = Relkeys.new_map env.config in let%lwt () = Lwt_list.iter_s (fun (aid, ki) -> - let%lwt _ = Relkeys.add aid ki relk in Lwt.return ()) env.keys in + let%lwt _ = Relkeys.add aid ki relk in Lwt.return ()) env.keys.entries in let%lwt () = Relkeys.close_map relk in Lwt_io.printlf "stopping assembly controller %s" actrl.myid @@ -23,5 +23,5 @@ let addblock actrl fn (fb : Assembly.blockinformation) buf = (Cstdio.File.Buffer.size buf) in *) let bplain = Buffer.BufferPlain.from_buffer buf in let env' = Environment.EnvironmentWritable.backup actrl.env fn fb.filepos bplain in - let (_fname, fb') = List.hd @@ Environment.fblocks env' in + let (_fname, fb') = List.hd @@ env'.fblocks.entries in Lwt.return ({actrl with env = env'}, {fb' with blockid = fb.blockid}) diff --git a/lxr.ml b/lxr.ml index a16d15f..dcd1f54 100644 --- a/lxr.ml +++ b/lxr.ml @@ -1207,14 +1207,103 @@ module Assembly = (Utilities.make_list a.nchunks) N0 end +module Store = + struct + type 'kVs store = { config : Configuration.configuration; entries : 'kVs } + + (** val config : 'a1 store -> Configuration.configuration **) + + let config s = + s.config + + (** val entries : 'a1 store -> 'a1 **) + + let entries s = + s.entries + + (** val rec_find : string -> (string * 'a1) list -> 'a1 option **) + + let rec rec_find k = function + | [] -> None + | p :: r -> let (k', v') = p in if (=) k' k then Some v' else rec_find k r + + module type STORE = + sig + type coq_K + + type coq_V + + type coq_KVs + + type coq_R + + val init : Configuration.configuration -> coq_R + + val add : coq_K -> coq_V -> coq_R -> coq_R + + val find : coq_K -> coq_R -> coq_V option + end + + module KeyListStore = + struct + type coq_K = string + + type coq_V = Assembly.keyinformation + + type coq_KVs = (coq_K * coq_V) list + + type coq_R = coq_KVs store + + (** val init : Configuration.configuration -> coq_R **) + + let init c = + { config = c; entries = [] } + + (** val add : coq_K -> coq_V -> coq_R -> coq_R **) + + let add k v r = + { config = r.config; entries = ((k, v) :: r.entries) } + + (** val find : coq_K -> coq_R -> coq_V option **) + + let find k r = + rec_find k r.entries + end + + module FBlockListStore = + struct + type coq_K = Assembly.aid_t + + type coq_V = Assembly.blockinformation + + type coq_KVs = (coq_K * coq_V) list + + type coq_R = coq_KVs store + + (** val init : Configuration.configuration -> coq_R **) + + let init c = + { config = c; entries = [] } + + (** val add : coq_K -> coq_V -> coq_R -> coq_R **) + + let add k v r = + { config = r.config; entries = ((k, v) :: r.entries) } + + (** val find : coq_K -> coq_R -> coq_V option **) + + let find k r = + rec_find k r.entries + end + end + module Environment = struct type 'aB environment = { cur_assembly : Assembly.assemblyinformation; cur_buffer : 'aB; config : Configuration.configuration; - fblocks : (string * Assembly.blockinformation) list; - keys : (Assembly.aid_t * Assembly.keyinformation) - list } + fblocks : Store.FBlockListStore.coq_R; + keys : Store.KeyListStore.coq_R } (** val cur_assembly : 'a1 environment -> Assembly.assemblyinformation **) @@ -1231,14 +1320,12 @@ module Environment = let config e = e.config - (** val fblocks : - 'a1 environment -> (string * Assembly.blockinformation) list **) + (** val fblocks : 'a1 environment -> Store.FBlockListStore.coq_R **) let fblocks e = e.fblocks - (** val keys : - 'a1 environment -> (Assembly.aid_t * Assembly.keyinformation) list **) + (** val keys : 'a1 environment -> Store.KeyListStore.coq_R **) let keys e = e.keys @@ -1270,8 +1357,8 @@ module Environment = let initial_environment c = let (a, b) = Assembly.AssemblyPlainWritable.create c in - { cur_assembly = a; cur_buffer = b; config = c; fblocks = []; keys = - [] } + { cur_assembly = a; cur_buffer = b; config = c; fblocks = + (Store.FBlockListStore.init c); keys = (Store.KeyListStore.init c) } (** val recreate_assembly : coq_AB environment -> coq_AB environment **) @@ -1286,7 +1373,8 @@ module Environment = let env_add_file_block fname0 e bi = { cur_assembly = e.cur_assembly; cur_buffer = e.cur_buffer; config = - e.config; fblocks = ((fname0, bi) :: e.fblocks); keys = e.keys } + e.config; fblocks = (Store.FBlockListStore.add fname0 bi e.fblocks); + keys = e.keys } (** val env_add_aid_key : Assembly.aid_t -> coq_AB environment -> Assembly.keyinformation -> @@ -1294,15 +1382,14 @@ module Environment = let env_add_aid_key aid0 e ki = { cur_assembly = e.cur_assembly; cur_buffer = e.cur_buffer; config = - e.config; fblocks = e.fblocks; keys = ((aid0, ki) :: e.keys) } + e.config; fblocks = e.fblocks; keys = + (Store.KeyListStore.add aid0 ki e.keys) } (** val key_for_aid : coq_AB environment -> Assembly.aid_t -> Assembly.keyinformation option **) let key_for_aid e aid0 = - match filter (fun e0 -> (=) (fst e0) aid0) e.keys with - | [] -> None - | p :: _ -> let (_, ki) = p in Some ki + Store.KeyListStore.find aid0 e.keys (** val finalise_assembly : coq_AB environment -> coq_AB environment **) @@ -1352,7 +1439,7 @@ module Environment = Assembly.backup e1.cur_assembly e1.cur_buffer fpos content in { cur_assembly = a'; cur_buffer = e1.cur_buffer; config = e1.config; - fblocks = ((fp, bi) :: e1.fblocks); keys = e1.keys } + fblocks = (Store.FBlockListStore.add fp bi e1.fblocks); keys = e1.keys } end module EnvironmentReadable = @@ -1365,8 +1452,8 @@ module Environment = let initial_environment c = let (a, b) = Assembly.AssemblyPlainFull.create c in - { cur_assembly = a; cur_buffer = b; config = c; fblocks = []; keys = - [] } + { cur_assembly = a; cur_buffer = b; config = c; fblocks = + (Store.FBlockListStore.init c); keys = (Store.KeyListStore.init c) } (** val env_add_aid_key : Assembly.aid_t -> coq_AB environment -> Assembly.keyinformation -> @@ -1374,15 +1461,14 @@ module Environment = let env_add_aid_key aid0 e ki = { cur_assembly = e.cur_assembly; cur_buffer = e.cur_buffer; config = - e.config; fblocks = e.fblocks; keys = ((aid0, ki) :: e.keys) } + e.config; fblocks = e.fblocks; keys = + (Store.KeyListStore.add aid0 ki e.keys) } (** val key_for_aid : coq_AB environment -> Assembly.aid_t -> Assembly.keyinformation option **) let key_for_aid e aid0 = - match filter (fun e0 -> (=) (fst e0) aid0) e.keys with - | [] -> None - | p :: _ -> let (_, ki) = p in Some ki + Store.KeyListStore.find aid0 e.keys (** val restore_assembly : coq_AB environment -> Assembly.aid_t -> coq_AB environment option **) @@ -1894,7 +1980,7 @@ module Version = (** val build : string **) let build = - "6" + "7" (** val version : string **) diff --git a/lxr.mli b/lxr.mli index a54e57a..961bb08 100644 --- a/lxr.mli +++ b/lxr.mli @@ -409,14 +409,75 @@ module Assembly : AssemblyEncrypted.coq_B -> n end +module Store : + sig + type 'kVs store = { config : Configuration.configuration; entries : 'kVs } + + val config : 'a1 store -> Configuration.configuration + + val entries : 'a1 store -> 'a1 + + val rec_find : string -> (string * 'a1) list -> 'a1 option + + module type STORE = + sig + type coq_K + + type coq_V + + type coq_KVs + + type coq_R + + val init : Configuration.configuration -> coq_R + + val add : coq_K -> coq_V -> coq_R -> coq_R + + val find : coq_K -> coq_R -> coq_V option + end + + module KeyListStore : + sig + type coq_K = string + + type coq_V = Assembly.keyinformation + + type coq_KVs = (coq_K * coq_V) list + + type coq_R = coq_KVs store + + val init : Configuration.configuration -> coq_R + + val add : coq_K -> coq_V -> coq_R -> coq_R + + val find : coq_K -> coq_R -> coq_V option + end + + module FBlockListStore : + sig + type coq_K = Assembly.aid_t + + type coq_V = Assembly.blockinformation + + type coq_KVs = (coq_K * coq_V) list + + type coq_R = coq_KVs store + + val init : Configuration.configuration -> coq_R + + val add : coq_K -> coq_V -> coq_R -> coq_R + + val find : coq_K -> coq_R -> coq_V option + end + end + module Environment : sig type 'aB environment = { cur_assembly : Assembly.assemblyinformation; cur_buffer : 'aB; config : Configuration.configuration; - fblocks : (string * Assembly.blockinformation) list; - keys : (Assembly.aid_t * Assembly.keyinformation) - list } + fblocks : Store.FBlockListStore.coq_R; + keys : Store.KeyListStore.coq_R } val cur_assembly : 'a1 environment -> Assembly.assemblyinformation @@ -424,10 +485,9 @@ module Environment : val config : 'a1 environment -> Configuration.configuration - val fblocks : 'a1 environment -> (string * Assembly.blockinformation) list + val fblocks : 'a1 environment -> Store.FBlockListStore.coq_R - val keys : - 'a1 environment -> (Assembly.aid_t * Assembly.keyinformation) list + val keys : 'a1 environment -> Store.KeyListStore.coq_R val cpp_mk_key256 : unit -> string diff --git a/theories/Environment.v b/theories/Environment.v index 2ddcb41..6c4333c 100644 --- a/theories/Environment.v +++ b/theories/Environment.v @@ -10,6 +10,7 @@ From RecordUpdate Require Import RecordUpdate. From LXR Require Import Assembly. From LXR Require Import Buffer. From LXR Require Import Configuration. +From LXR Require Import Store. From LXR Require Import Nchunks. Module Export Environment. @@ -23,8 +24,8 @@ Record environment (AB : Type) : RecordEnvironment := { cur_assembly : assemblyinformation ; cur_buffer : AB ; config : configuration - ; fblocks : list (string * Assembly.blockinformation) - ; keys : list (aid_t * Assembly.keyinformation) + ; fblocks : FBlockListStore.R + ; keys : KeyListStore.R }. (* #[export] Instance etaX : Settable _ := settable! mkenvironment (AB) . *) (* Print environment. @@ -51,8 +52,8 @@ Module EnvironmentWritable <: ENV. {| cur_assembly := a ; cur_buffer := b ; config := c - ; fblocks := nil - ; keys := nil + ; fblocks := FBlockListStore.init c + ; keys := KeyListStore.init c |}. Definition recreate_assembly (e : environment AB) : environment AB := let (a,b) := AssemblyPlainWritable.create (e.(config AB)) in @@ -65,7 +66,7 @@ Module EnvironmentWritable <: ENV. {| cur_assembly := e.(cur_assembly AB) ; cur_buffer := e.(cur_buffer AB) ; config := e.(config AB) - ; fblocks := (fname,bi) :: e.(fblocks AB) + ; fblocks := FBlockListStore.add fname bi e.(fblocks AB) ; keys := e.(keys AB) |}. Definition env_add_aid_key (aid : aid_t) (e : environment AB) (ki : keyinformation) : environment AB := @@ -73,13 +74,10 @@ Module EnvironmentWritable <: ENV. ; cur_buffer := e.(cur_buffer AB) ; config := e.(config AB) ; fblocks := e.(fblocks AB) - ; keys := (aid,ki) :: e.(keys AB) + ; keys := KeyListStore.add aid ki e.(keys AB) |}. Definition key_for_aid (e : environment AB) (aid : Assembly.aid_t) : option keyinformation := - match List.filter (fun e => String.eqb (fst e) aid) e.(keys AB) with - | nil => None - | (_,ki) :: _ => Some ki - end. + KeyListStore.find aid e.(keys AB). Definition finalise_assembly (e0 : environment AB) : environment AB := let a0 := e0.(cur_assembly AB) in let apos := Assembly.apos a0 in @@ -114,7 +112,7 @@ Module EnvironmentWritable <: ENV. {| cur_assembly := a' ; cur_buffer := e1.(cur_buffer AB) ; config := e1.(config AB) - ; fblocks := (fp,bi) :: e1.(fblocks AB) + ; fblocks := FBlockListStore.add fp bi e1.(fblocks AB) ; keys := e1.(keys AB) |}. @@ -129,21 +127,18 @@ Module EnvironmentReadable <: ENV. {| cur_assembly := a ; cur_buffer := b ; config := c - ; fblocks := nil - ; keys := nil + ; fblocks := FBlockListStore.init c + ; keys := KeyListStore.init c |}. Definition env_add_aid_key (aid : aid_t) (e : environment AB) (ki : keyinformation) : environment AB := {| cur_assembly := e.(cur_assembly AB) ; cur_buffer := e.(cur_buffer AB) ; config := e.(config AB) ; fblocks := e.(fblocks AB) - ; keys := (aid,ki) :: e.(keys AB) + ; keys := KeyListStore.add aid ki e.(keys AB) |}. Definition key_for_aid (e : environment AB) (aid : Assembly.aid_t) : option keyinformation := - match List.filter (fun e => String.eqb (fst e) aid) e.(keys AB) with - | nil => None - | (_,ki) :: _ => Some ki - end. + KeyListStore.find aid e.(keys AB). Definition restore_assembly (e0 : environment AB) (aid : aid_t) : option (environment AB) := match key_for_aid e0 aid with | None => None diff --git a/theories/MakeML.v b/theories/MakeML.v index 76df1c4..54c49fc 100644 --- a/theories/MakeML.v +++ b/theories/MakeML.v @@ -7,6 +7,7 @@ Open Scope positive_scope. From LXR Require Import Assembly. From LXR Require Import AssemblyCache. +From LXR Require Import Store. From LXR Require Import BackupPlanner. From LXR Require Import Buffer. From LXR Require Import Configuration. @@ -197,4 +198,4 @@ Extract Constant get_file_information => (* extract into "lxr.ml" all named modules and definitions, and their dependencies *) Extraction "lxr.ml" Version Conversion Utilities Filesupport Nchunks Assembly - Configuration Environment Buffer BackupPlanner AssemblyCache. + Configuration Environment Buffer BackupPlanner AssemblyCache Store. diff --git a/theories/Store.v b/theories/Store.v new file mode 100644 index 0000000..8eb1807 --- /dev/null +++ b/theories/Store.v @@ -0,0 +1,129 @@ +(** + e L y K s e e R +*) + +Require Import NArith PArith. +From Coq Require Import NArith.BinNat Lists.List Strings.String Program.Basics. + +From RecordUpdate Require Import RecordUpdate. + +From LXR Require Import Assembly. +From LXR Require Import Configuration. + +Open Scope list_scope. + +Import ListNotations. + +Module Export Store. + +Definition RecordStore := Type. +Record store (KVs : Type): RecordStore := + mkstore + { config : configuration + ; entries : KVs + }. +Print RecordStore. +Print store. + +Print option. + +Fixpoint rec_find {V : Type} (k : string) (es : list (string * V)) : option V := + match es with + | [] => None + | (k', v')::r => if k' =? k then Some v' + else rec_find k r + end. + +Module Type STORE. + Parameter K : Type. + Parameter V : Type. + Parameter KVs : Type. + Parameter R : Type. + Parameter init : configuration -> R. + Parameter add : K -> V -> R -> R. + Parameter find : K -> R -> option V. +End STORE. +Print STORE. + +Module KeyListStore <: STORE. + Definition K := String.string. + Definition V := Assembly.keyinformation. + Definition KVs := list (K * V). + Definition R : RecordStore := store KVs. + Definition init (c : configuration) : R := {| config := c; entries := [] |}. + Definition add (k : K) (v : V) (r : R) : R := + {| config := r.(config KVs); entries := (k, v) :: r.(entries KVs) |}. + Definition find (k : K) (r : R) : option V := + rec_find k r.(entries KVs). +End KeyListStore. +Print KeyListStore. + +Module FBlockListStore <: STORE. + Definition K := Assembly.aid_t. + Definition V := Assembly.blockinformation. + Definition KVs := list (K * V). + Definition R : RecordStore := store KVs. + Definition init (c : configuration) : R := {| config := c; entries := [] |}. + Definition add (k : K) (v : V) (r : R) : R := + {| config := r.(config KVs); entries := (k, v) :: r.(entries KVs) |}. + Definition find (k : K) (r : R) : option V := + rec_find k r.(entries KVs). + +End FBlockListStore. +Print FBlockListStore. + + +Example find_entry_in_empty : forall c, + let es := FBlockListStore.init c in + let k : Assembly.aid_t := "t1" in + FBlockListStore.find k es = None. + +Proof. + intros. + unfold FBlockListStore.find. + unfold rec_find. simpl. reflexivity. +Qed. + +Example add_then_find_entry : forall c, + let es := FBlockListStore.init c in + let v := {| blockid := 1; bchecksum := "chksum"; blocksize := 1024; filepos := 0; blockaid := "aid001"; blockapos := 42 |} in + let k : Assembly.aid_t := "t1" in + FBlockListStore.find k (FBlockListStore.add k v es) = Some v. + +Proof. + intros. + unfold FBlockListStore.add. + unfold FBlockListStore.find. + unfold rec_find. simpl. reflexivity. +Qed. + +Example add_add_then_find_entry : forall c, + let es := FBlockListStore.init c in + let v1 := {| blockid := 1; bchecksum := "chksum"; blocksize := 1024; filepos := 0; blockaid := "aid001"; blockapos := 42 |} in + let v2 := {| blockid := 2; bchecksum := "chksum"; blocksize := 1024; filepos := 42; blockaid := "aid001"; blockapos := 1066 |} in + let k1 : Assembly.aid_t := "t1" in + let k2 : Assembly.aid_t := "t2" in + FBlockListStore.find k1 (FBlockListStore.add k2 v2 (FBlockListStore.add k1 v1 es)) = Some v1. + +Proof. + intros. + unfold FBlockListStore.add. simpl. + unfold FBlockListStore.find. + unfold rec_find. simpl. reflexivity. +Qed. + +Example add_then_find_another_entry : forall c, + let es := FBlockListStore.init c in + let v := {| blockid := 1; bchecksum := "chksum"; blocksize := 1024; filepos := 0; blockaid := "aid001"; blockapos := 42 |} in + let k1 : Assembly.aid_t := "t1" in + let k2 : Assembly.aid_t := "t2" in + FBlockListStore.find k2 (FBlockListStore.add k1 v es) = None. + +Proof. + intros. + unfold FBlockListStore.add. + unfold FBlockListStore.find. + unfold rec_find. simpl. reflexivity. +Qed. + +End Store. \ No newline at end of file diff --git a/theories/Version.v b/theories/Version.v index 3a9cfcc..9d230c0 100644 --- a/theories/Version.v +++ b/theories/Version.v @@ -10,7 +10,7 @@ Open Scope string_scope. Definition major : string := "0". Definition minor : string := "9". -Definition build : string := "6". +Definition build : string := "7". Definition version : string := major ++ "." ++ minor ++ "." ++ build. End Version. From 971068861a0d2aa5c4cfde56d87d0825d54f07a9 Mon Sep 17 00:00:00 2001 From: Alexander Diemand Date: Sat, 3 Feb 2024 23:10:37 +0100 Subject: [PATCH 2/2] + Store.v Signed-off-by: Alexander Diemand --- doc/00_Content.md | 12 ++++++++++++ doc/01_Content.md | 10 ---------- ...{02_Functionality.md => 01_Functionality.md} | 0 doc/{03_Relations.md => 02_Relations.md} | 0 doc/{04_Storage.md => 03_Storage.md} | 0 doc/{05_Modules.md => 04_Modules.md} | 4 ++++ doc/05_AssemblyCache.md | 13 +++++++++++++ doc/img/img4.png | Bin 0 -> 75833 bytes lxr.ml | 4 ++++ lxr.mli | 2 ++ theories/Filesupport.v | 6 +++--- theories/MakeML.v | 3 +++ theories/Utilities.v | 4 ++++ 13 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 doc/00_Content.md delete mode 100644 doc/01_Content.md rename doc/{02_Functionality.md => 01_Functionality.md} (100%) rename doc/{03_Relations.md => 02_Relations.md} (100%) rename doc/{04_Storage.md => 03_Storage.md} (100%) rename doc/{05_Modules.md => 04_Modules.md} (87%) create mode 100644 doc/05_AssemblyCache.md create mode 100644 doc/img/img4.png diff --git a/doc/00_Content.md b/doc/00_Content.md new file mode 100644 index 0000000..8daa1de --- /dev/null +++ b/doc/00_Content.md @@ -0,0 +1,12 @@ + +# Content + +## 01 [Functionality](01_Functionality.md) + +## 02 Information [Relations](02_Relations.md) + +## 03 Data [Storage](03_Storage.md) + +## 04 Code organisation in [Modules](04_Modules.md) + +## 05 [Caching](05_AssemblyCache.md) data \ No newline at end of file diff --git a/doc/01_Content.md b/doc/01_Content.md deleted file mode 100644 index d8163e9..0000000 --- a/doc/01_Content.md +++ /dev/null @@ -1,10 +0,0 @@ - -# Content - -## [Functionality](02_Functionality.md) - -## Information [Relations](03_Relations.md) - -## Data [Storage](04_Storage.md) - -## Code organisation in [Modules](05_Modules.md) diff --git a/doc/02_Functionality.md b/doc/01_Functionality.md similarity index 100% rename from doc/02_Functionality.md rename to doc/01_Functionality.md diff --git a/doc/03_Relations.md b/doc/02_Relations.md similarity index 100% rename from doc/03_Relations.md rename to doc/02_Relations.md diff --git a/doc/04_Storage.md b/doc/03_Storage.md similarity index 100% rename from doc/04_Storage.md rename to doc/03_Storage.md diff --git a/doc/05_Modules.md b/doc/04_Modules.md similarity index 87% rename from doc/05_Modules.md rename to doc/04_Modules.md index 206ce69..bb1b342 100644 --- a/doc/05_Modules.md +++ b/doc/04_Modules.md @@ -45,6 +45,10 @@ Computes a plan to backup a file. Provides a cache of assemblies and recreates them on demand. +### Store +[Store](../theories/Store.v) + +Meta information about file blocks and encryption keys need to be stored in an accessible way. This module provides basic implementations using lists. ## Other modules diff --git a/doc/05_AssemblyCache.md b/doc/05_AssemblyCache.md new file mode 100644 index 0000000..3c2c733 --- /dev/null +++ b/doc/05_AssemblyCache.md @@ -0,0 +1,13 @@ +[Content](01_Content.md) + +# Data caching + +The module [AssemblyCache](../theories/AssemblyCache.v) maintains a fixed size cache of assemblies. + +* one assembly is writeable. As soon as it is full it will get encrypted and extracted to chunks. + +* a fixed number of assemblies are decrypted. Only the one in the first place is readable. If another one is requested and not yet decrypted, then it will be reconstructed from chunks, decrypted and put in front of the others. The last one is dropped. + +![Caching of data with AssemblyCache](./img/img4.png) + +* client processes interact with the cache to add data to it or retrieve data. diff --git a/doc/img/img4.png b/doc/img/img4.png new file mode 100644 index 0000000000000000000000000000000000000000..0336bacdd77807e37a51422f8f05f939f2d534cc GIT binary patch literal 75833 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%0A1M}qC6Lp*}N~{YKs_<=QsXl`95i&F;(6iNGSSY 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 String.cat (Unix.gettimeofday () |> string_of_float) |> Elykseer_crypto.Sha256.string + + (** val sha256 : string -> string **) + + let sha256 = Elykseer_crypto.Sha256.string end module Assembly = diff --git a/lxr.mli b/lxr.mli index 961bb08..6a7ebf0 100644 --- a/lxr.mli +++ b/lxr.mli @@ -267,6 +267,8 @@ module Utilities : val rnd : n -> n val rnd256 : string -> string + + val sha256 : string -> string end module Assembly : diff --git a/theories/Filesupport.v b/theories/Filesupport.v index 2415772..63bc674 100644 --- a/theories/Filesupport.v +++ b/theories/Filesupport.v @@ -7,10 +7,10 @@ Description: provides abstract definitions of file functions. *) - From Coq Require Import Strings.String. - Require Import NArith. +From Coq Require Import Strings.String. +Require Import NArith. - Module Export Filesupport. +Module Export Filesupport. Definition filename := string. diff --git a/theories/MakeML.v b/theories/MakeML.v index 54c49fc..022da6e 100644 --- a/theories/MakeML.v +++ b/theories/MakeML.v @@ -196,6 +196,9 @@ Extract Constant get_file_information => fchecksum = Elykseer_base.Fsutils.fchksum fn } ". +Extract Constant sha256 => "Elykseer_crypto.Sha256.string". + + (* extract into "lxr.ml" all named modules and definitions, and their dependencies *) Extraction "lxr.ml" Version Conversion Utilities Filesupport Nchunks Assembly Configuration Environment Buffer BackupPlanner AssemblyCache Store. diff --git a/theories/Utilities.v b/theories/Utilities.v index 0391482..2db9c8d 100644 --- a/theories/Utilities.v +++ b/theories/Utilities.v @@ -32,6 +32,10 @@ Axiom rnd : N -> N. *) Axiom rnd256 : string -> string. +(* returns hash of a string +*) +Axiom sha256 : string -> string. + End axioms. End Utilities.