blob: bbe5ecaeb2f8f94d725bc534620680ab2d230d34 [file]
(*
* Copyright 2016, NICTA
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(NICTA_GPL)
*)
theory OstoreS
imports
"../impl/BilbyFs_Shallow_Desugar_Tuples"
"../impl/BilbyFs_ShallowConsts_Desugar_Tuples"
"../adt/ArrayT"
begin
type_synonym ostore_map = "ObjId \<Rightarrow> Obj\<^sub>T option"
definition "obj_id_xinfo oid \<equiv> bilbyFsXinfoMask AND oid"
definition "obj_is_inode obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeInode"
definition "obj_is_dentarr obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeDentarr"
definition "obj_is_data obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeData"
definition "obj_is_pad obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypePad"
definition "obj_is_super obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeSuper"
definition "obj_is_del obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeDel"
definition "obj_is_summary obj \<equiv> otype\<^sub>f obj = bilbyFsObjTypeSum"
definition
oid_is_deleted_by :: "ObjId \<Rightarrow> ObjId \<Rightarrow> bool"
where
"oid_is_deleted_by oid delid \<equiv>
(if obj_id_is_inode delid then
inum_from_obj_id delid = inum_from_obj_id oid
else if obj_id_is_dentarr delid then
delid = oid
else if obj_id_is_data delid then
inum_from_obj_id delid = inum_from_obj_id oid \<and>
obj_id_xinfo oid \<ge> obj_id_xinfo delid
else
False)"
definition
obj_is_deleted_by :: "Obj\<^sub>T \<Rightarrow> Obj\<^sub>T \<Rightarrow> bool"
where
"obj_is_deleted_by obj delobj \<equiv>
Obj.sqnum\<^sub>f obj < Obj.sqnum\<^sub>f delobj \<and>
oid_is_deleted_by (get_obj_oid obj) (get_obj_oid delobj)"
definition
max_opt_obj :: "Obj\<^sub>T option \<Rightarrow> Obj\<^sub>T option \<Rightarrow> Obj\<^sub>T option"
where
"max_opt_obj o1 o2 \<equiv>
case (o1, o2) of
(option.None, v) \<Rightarrow> v
| (v, option.None) \<Rightarrow> v
| (option.Some o1, option.Some o2) \<Rightarrow>
option.Some (if Obj.sqnum\<^sub>f o1 > Obj.sqnum\<^sub>f o2 then o1 else o2)"
text {* ostore_list_upd: is a helper function for ostore_update.
It captures the changes inflicted to the object store by the
list of object passed as argument. The list of object represent
an object store update, deletion object remove elements and
other objects get inserted or replace existing ones.
ostore_list_upd returns Some None if the list of objects indicates that
the oid passed as argument is deleted by the update and returns the object
if the update contains it.
We have to use a type option of option to differentiate the
case where the object was not found and the case where it is
deleted by the update.
Object was deleted : Some None
Object was added/overwrite: Some Some
Object didn't exist: None
*}
primrec
ostore_list_upd :: "Obj\<^sub>T list \<Rightarrow> ObjId \<Rightarrow> Obj\<^sub>T option option"
where
"ostore_list_upd [] oid = option.None" |
"ostore_list_upd (x#xs) oid =
(if obj_is_del x \<and> oid_is_deleted_by oid (get_obj_oid x) then
option.Some option.None
else
(if get_obj_oid x = oid then
option.Some (option.Some x)
else ostore_list_upd xs oid))"
text {* Need to update ostore_list_upd to make delete
a second phase as it is required by mount. *}
definition
ostore_delete :: "Obj\<^sub>T list \<Rightarrow> (ostore_map \<Rightarrow> ostore_map)"
where
"ostore_delete objs gos =
(\<lambda>oid. case ostore_list_upd objs oid of
option.None \<Rightarrow> gos oid
| option.Some (option.None) \<Rightarrow> option.None
| option.Some (option.Some v) \<Rightarrow> gos oid)"
definition
ostore_update :: "Obj\<^sub>T list \<Rightarrow> (ostore_map \<Rightarrow> ostore_map)"
where
"ostore_update objs gos =
(\<lambda>oid. case ostore_list_upd objs oid of
option.Some x \<Rightarrow> max_opt_obj x (gos oid) |
option.None \<Rightarrow> gos oid)"
lemmas obj_id_is_defs_simps = obj_id_is_inode_def obj_id_is_dentarr_def obj_id_is_data_def
definition is_valid_dentarr_entries
where
"is_valid_dentarr_entries entries = (\<forall>entry\<in>set entries. wordarray_length (name\<^sub>f entry) \<le> bilbyFsMaxNameLen)"
definition obj_odentarr :: "Obj\<^sub>T \<Rightarrow> ObjDentarr\<^sub>T"
where
"obj_odentarr obj \<equiv> (case ounion\<^sub>f obj of TObjDentarr dentarr \<Rightarrow> dentarr)"
definition obj_oinode :: "Obj\<^sub>T \<Rightarrow> ObjInode\<^sub>T"
where
"obj_oinode obj \<equiv> (case ounion\<^sub>f obj of TObjInode i \<Rightarrow> i)"
definition obj_odata :: "Obj\<^sub>T \<Rightarrow> ObjData\<^sub>T"
where
"obj_odata obj \<equiv> (case ounion\<^sub>f obj of TObjData d \<Rightarrow> d)"
definition obj_osummary :: "Obj\<^sub>T \<Rightarrow> ObjSummary\<^sub>T"
where
"obj_osummary obj \<equiv> (case ounion\<^sub>f obj of _ \<Rightarrow> undefined)"
primrec stripNone :: "'a Option\<^sub>T list \<Rightarrow> 'a list"
where
"stripNone [] = []" |
"stripNone (x#xs) = (case x of Option.None () \<Rightarrow> stripNone xs | Option.Some v \<Rightarrow> v#stripNone xs)"
definition obj_is_valid :: "Obj\<^sub>T \<Rightarrow> bool"
where
"obj_is_valid obj \<equiv>
(obj_is_dentarr obj \<longrightarrow>
(let entries = stripNone (\<alpha>a $ ObjDentarr.entries\<^sub>f $ obj_odentarr obj) in
(distinct (map name\<^sub>f entries) \<and>
length entries \<le> unat bilbyFsMaxNbDentarrEntries \<and>
is_valid_dentarr_entries entries)))"
lemma obj_is_valid_valid_entries:
"\<lbrakk> obj_is_valid x ; obj_is_dentarr x\<rbrakk> \<Longrightarrow>
is_valid_dentarr_entries (stripNone $ \<alpha>a $ ObjDentarr.entries\<^sub>f $ obj_odentarr x)"
by (simp add: Let_def obj_is_valid_def)
definition obj_inv_oid :: "Obj\<^sub>T \<Rightarrow> bool"
where
"obj_inv_oid obj \<equiv> (obj_is_inode obj \<or> obj_is_dentarr obj \<or> obj_is_data obj) \<longrightarrow>
obj_id_type (get_obj_oid obj) = ucast (otype\<^sub>f obj)"
definition
inv_read_obj :: "Obj\<^sub>T \<Rightarrow> bool"
where
"inv_read_obj obj \<equiv>
obj_is_valid obj \<and> obj_inv_oid obj \<and> (obj_is_dentarr obj \<longrightarrow>
(length $ stripNone $ \<alpha>a $ ObjDentarr.entries\<^sub>f $ obj_odentarr obj) > 0)
(* FIXME: add something like @{otype\<^sub>f obj = otype_from_ounion obj} *)
"
text {* inv_\<alpha>_ostore: invariant on the object store \<alpha> projection (user point-of-view invariant *) *}
definition
inv_\<alpha>_ostore :: "ostore_map \<Rightarrow> bool"
where
"inv_\<alpha>_ostore os \<equiv>
(\<forall>oid obj. os oid = option.Some obj \<longrightarrow> (get_obj_oid obj = oid \<and> inv_read_obj obj))"
definition
no_deleted_objs_list :: "Obj\<^sub>T list \<Rightarrow> bool"
where
"no_deleted_objs_list xs \<equiv> (\<forall>entry\<in>set xs. \<not> obj_is_del entry)"
lemma ostore_list_upd_no_deleted[rule_format]:
"\<And>objs. no_deleted_objs_list objs \<longrightarrow>
ostore_list_upd objs oid \<noteq> option.Some option.None"
unfolding no_deleted_objs_list_def
by (induct_tac objs, simp+)
fun
apply_n_updates :: "nat \<Rightarrow> ostore_map \<Rightarrow> (ostore_map \<Rightarrow> ostore_map) list \<Rightarrow> ostore_map"
where
"apply_n_updates n os_map os_updates = fold id (take n os_updates) os_map"
end