chiark / gitweb /
cmd updates: Restart updates when insert follows delete (properly)
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 31 Mar 2021 18:46:20 +0000 (19:46 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 1 Apr 2021 10:37:58 +0000 (11:37 +0100)
We do this prospectively, when we see AddPieces but before it has been
processed.  This means execute_for_game has special knowledge of
particular commands - oh well.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs

index 48b45944fb9a34f8f01a349085aa62aae51fd7af..54d9300a9f0b5ac15ede8b520c8150cadce6777f 100644 (file)
@@ -849,8 +849,9 @@ fn execute_for_game<'cs, 'igr, 'ig: 'igr>(
   struct St {
     uh: UpdateHandler,
     auth: Authorisation<InstanceName>,
+    have_deleted: bool,
   }
-  let mut uh_auth = None;
+  let mut uh_auth: Option<St> = None;
   let mk_uh = || UpdateHandler::from_how(how);
   let who = if_chain! {
     let account = &cs.current_account()?.notional_account;
@@ -869,14 +870,29 @@ fn execute_for_game<'cs, 'igr, 'ig: 'igr>(
   let res = (||{
     for insn in insns.drain(0..) {
       trace_dbg!("exeucting game insns", insn);
+
+      if let (MGI::AddPieces{..},
+              &mut Some(St { ref mut uh, auth, have_deleted: true }))
+        = (&insn, &mut uh_auth)
+      {
+        // This makes sure that all the updates we have queued up
+        // talking about the old PieceId, will be Prepared (ie, the
+        // vpid lookup done) before we reuse the slot and render the
+        // vpid lookup impossible.
+        let ig = igu.by_mut(auth);
+        mem::replace(uh, mk_uh()).complete(ig, &who)?;
+      };
+      let was_delete = matches!(&insn, MGI::DeletePiece(..));
+
       let (updates, resp, unprepared, ig) =
         execute_game_insn(cs, ag, igu, insn, &who,
                           &mut to_permute)?;
       let st = uh_auth.get_or_insert_with(||{
         let auth = Authorisation::authorised(&*ig.name);
         let uh = mk_uh();
-        St { uh, auth }
+        St { uh, auth, have_deleted: false }
       });
+      st.have_deleted |= was_delete;
       st.uh.accumulate(ig, updates)?;
       responses.push(resp);
       if let Some(unprepared) = unprepared {