aneris_examples.ccddb.model.model_update_system

From aneris.aneris_lang Require Import lang resources.
From stdpp Require Import gmap.
From aneris.aneris_lang.lib Require Import util.
From aneris_examples.ccddb.spec Require Import base.
From aneris_examples.ccddb.model Require Import model_lst model_gst
     model_update_lhst model_update_lst model_update_gst.

Section System_update.
  Context `{!anerisG Σ, !DB_params}.

  Lemma DBM_system_write_event_fresh_gmem (e : apply_event) k v i d t s M Ss h :
    (i < length t)
    DBM_Lst_valid i {| Lst_mem := d; Lst_time := t; Lst_hst := s |}
    DBM_GstValid {| Gst_mem := M; Gst_hst := Ss |}
    M !! k = Some h
    Ss !! i = Some s
    e = ApplyEvent k v (incr_time t i) i (S (length (elements s)))
    e s
    erase e h.
  Proof.
    intros Hit Hvlst Hvgst Hmk Hsi He Hes Habs.
    pose proof (DBM_GV_mem_in_hst Hvgst (erase e) h)
      as (si & sii & e' & Ha & Hvs & Hesi & Hers); try naive_solver.
    assert (si = s) as -> by naive_solver.
    assert (e' s).
    { eapply (in_lsec_in_lhst). by erewrite Hvs. }
    assert (we_time (erase e') = we_time (erase e) ae_orig e' = ae_orig e)
      as (Ht & Ho).
    { split; first by rewrite Hers.
      do 2 (rewrite -erase_orig). by rewrite Hers. }
    rewrite !erase_time in Ht.
    assert (e' s).
    { eapply (DBM_system_write_event_fresh_lhst e'); naive_solver. }
    done.
  Qed.

 Lemma DBM_system_write_event_maximum_lhst (e : apply_event) k v i d t s :
    (i < length t)
    DBM_Lst_valid i {| Lst_mem := d; Lst_time := t; Lst_hst := s |}
    e = ApplyEvent k v (incr_time t i) i (S (length (elements s)))
    e s
    (compute_maximum ae_time (s {[e]}) = Some e).
 Proof.
   intros ? Hvl Heeq ?.
   apply compute_maximum_correct.
   - eapply lhst_add_ext; first by eapply (DBM_LSTV_hst_valid Hvl); eauto.
     intros e' He' He'e.
     eapply (vector_clock_lt_irreflexive (ae_time e')).
     rewrite {2}He'e.
     rewrite Heeq /=.
     eapply vector_clock_le_lt_trans; last by apply incr_time_lt.
     eapply (DBM_Lst_valid_time_le _ {|Lst_time := t|}); done.
   - split.
     + apply elem_of_union; right; apply elem_of_singleton; done.
     + intros e' [?| ->%elem_of_singleton_1]%elem_of_union; last done.
       intros.
       eapply vector_clock_le_lt_trans;
         last by rewrite Heeq; apply incr_time_lt.
       eapply (DBM_Lst_valid_time_le _ {|Lst_time := t|}); done.
 Qed.

 Lemma DBM_system_write_event_maximals_gmem
       (e : apply_event) k v i d t s M Ss h :
    (i < length t)
    DBM_Lst_valid i {| Lst_mem := d; Lst_time := t; Lst_hst := s |}
    DBM_Gst_valid {| Gst_mem := M; Gst_hst := Ss |}
    M !! k = Some h
    Ss !! i = Some s
    e = ApplyEvent k v (incr_time t i) i (S (length (elements s)))
    e s
    erase e h
    erase e compute_maximals we_time (h {[erase e]}).
 Proof.
   intros Hit Hvlst Hvgst Hmk Hsi He Hes Heh.
   apply compute_maximals_correct; split; [ set_solver | ].
   intros a [ Ha | ?%elem_of_singleton_1]%elem_of_union Habs; last first.
   - by subst; eapply vector_clock_lt_irreflexive.
   - assert ( p, 0 < p a.(we_time) !! a.(we_orig) = Some p)
       as (aa & H_0_aa & H_aa) by by eapply we_in_valid_gs_time.
     assert ( k, t !! i = Some k) as (ti & H_ti)
         by by apply lookup_lt_is_Some_2.
     pose (ei := S ti).
     assert ((we_time (erase e)) !! i = Some ei) as H_ei.
     { rewrite erase_time; simplify_eq; by eapply incr_time_proj. }
     assert ( k, (we_time a) !! i = Some k ei <= k)
       as (ai & H_ai & H_ei_k).
     { apply vector_clock_lt_le in Habs.
         by eapply (Forall2_lookup_l _ _ (we_time a) i ei) in Habs. }
     assert ( (sa saa : gset apply_event) (e' : apply_event),
                Gst_hst {| Gst_mem := M; Gst_hst := Ss |}
                        !! we_orig a = Some sa
                 DBM_lsec (we_orig a) sa = saa
                 e' sa
                 erase e' = a)
       as (sa & saa & e' & Hsa & Hsaa & He' & He'a).
     { epose proof (DBM_gs_mem_in_gs_hst_aux Hvgst a h k Hmk Ha) as
           (?&?&?&?&Hsec&?&?). destruct Hsec.
       do 3 eexists. repeat split; eauto using in_lsec_in_lhst. }
     destruct (decide (a.(we_orig) = i)) as [<- | Hneq].
     + subst ei a.
       assert (e' s) as He's by set_solver.
       assert (ae_time e' !! we_orig (erase e') = Some ai) as He'ai.
       { by rewrite -H_ai -erase_time. }
       assert (ai <= ti).
       { epose proof DBM_Lst_valid_time_le (we_orig (erase e'))
               _ e' Hvlst He's as Hlet.
         rewrite /vector_clock_le //= in Hlet.
         pose proof (Forall2_lookup_l le
                                       (ae_time e') t
                                       (we_orig (erase e'))
                                       ai Hlet He'ai)
           as
              (?&?&?).
         by simplify_eq. }
       lia.
     + assert ( e'', e'' DBM_lsec i sa (ae_time e'') !! i = Some ei)
         as (e'' & He'' & He''t).
       { eapply (DBM_lsec_causality_lemma _ _ e' ei ai);
           [by eapply DBM_LSTV_at|by eapply DBM_GV_hst_lst_valid|done| |done|];
           last first.
         { rewrite -erase_time He'a; done. }
         rewrite He /= in H_ei.
         erewrite incr_time_proj in H_ei; last done.
         simplify_eq; lia. }
       assert ( a'' h'', M !! e''.(ae_key) = Some h''
                          a'' h'' a''.(we_orig) = i
                          a''.(we_time) !! i = Some ei a'' = erase e'')
         as (a'' & h'' & Hm'' & Ha'' & Ha''orig & Ha''time & Ha''e'').
       { destruct (λ H, DBM_GV_hst_in_mem Hvgst sa H e'')
           as (h' & Hh' & He''h'); simpl in *.
         { eapply elem_of_list_lookup_2; eauto. }
         { eapply in_lsec_in_lhst; eauto. }
         eexists (erase e''), _; split_and!; [done|done| | |done].
         - rewrite erase_orig; eapply orig_in_lsec; eauto.
         - rewrite erase_time; done. }
       assert ( ii, ii DBM_lsec i s (ae_time ii) !! i = Some ei) as
           (ii & Hii & Hiit).
       { destruct (DBM_GV_mem_in_hst Hvgst a'' h'')
           as (s0 & si & ei' & Ha''1 & Ha''2 & Ha''3 & Ha''4); [|done|].
         { by rewrite /= Ha''e'' erase_key. }
         rewrite Ha''orig /= Hsi in Ha''1; simplify_eq Ha''1; intros <-.
         rewrite -Ha''2 Ha''orig in Ha''3.
         exists ei'; split; first done.
         rewrite -erase_time Ha''4; done. }
       subst ei a.
       assert (ii s) as Hiis by set_solver.
       assert (S ti <= ti).
       { epose proof DBM_Lst_valid_time_le i _ ii Hvlst Hiis as Hlet.
         rewrite /vector_clock_le //= in Hlet.
         pose proof (Forall2_lookup_l le (ae_time ii) t i (S ti) Hlet Hiit)
           as (?&?&?).
           by simplify_eq. }
       lia.
 Qed.

End System_update.