chiark / gitweb /
wip destroy game
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 28 Jul 2020 18:34:35 +0000 (19:34 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 28 Jul 2020 20:14:22 +0000 (21:14 +0100)
src/cmdlistener.rs
src/global.rs

index 54ed415cefe7ae87ef4344972c944953847ae472..62137214827a83d47ba4aacb414642bddad8a157 100644 (file)
@@ -230,7 +230,11 @@ fn execute(cs: &mut CommandStream, cmd: MgmtCommand) -> MgmtResponse {
 
       execute_for_game(cs, &mut ig, insns, MgmtGameUpdateMode::Bulk)
         .map_err(|e|{
-          Instance::destroy(ig);
+          let name = ig.name.clone();
+          Instance::destroy(ig)
+            .unwrap_or_else(|e|
+ eprintln!("failed to tidy up failecd creation of {:?}: {:?}",
+                                      &name, &e));
           e
         })?;
 
index 435c1307397b76ae4a8f4a6daeeefd4af8ba6295..3fb6290cd90d20768625e971ab92fcd11046e185 100644 (file)
@@ -147,30 +147,29 @@ impl Instance {
     };
 
     let gref = InstanceRef(Arc::new(Mutex::new(cont)));
+    let mut ig = gref.lock()?;
 
-    {
-      // access without save means it's deleted
-      // save without access menas no accesses
-      // we save first since that's more fallible
-      let mut ig = gref.lock()?;
-      ig.save_access_now()?;
-      ig.save_game_now()?;
-    }
+    // We hold the GLOBAL.games lock while we save the new game.
+    // That lock is not on the hot path.
+    let mut games = GLOBAL.games.write().unwrap();
+    let entry = games.entry(name);
 
-    {
-      let mut games = GLOBAL.games.write().unwrap();
-      let entry = games.entry(name);
+    use hash_map::Entry::*;
+    let entry = match entry {
+      Vacant(ve) => ve,
+      Occupied(_) => throw!(MgmtError::AlreadyExists),
+    };
 
-      use hash_map::Entry::*;
-      let entry = match entry {
-        Vacant(ve) => ve,
-        Occupied(_) => throw!(MgmtError::AlreadyExists),
-      };
+    // access without save means it's deleted
+    // save without access menas no accesses
+    ig.save_access_now()?;
+    ig.save_game_now()?;
 
+    (||{
       entry.insert(gref.clone());
-    }
+    })(); // <- No ?, ensures that IEFE is infallible (barring panics)
 
-    gref
+    ig.gref
   }
 
   #[throws(MgmtError)]
@@ -181,9 +180,14 @@ impl Instance {
       .clone()
   }
 
+  #[throws(MgmtError)]
   pub fn destroy(mut g: InstanceGuard) {
     g.c.live = false;
-    // remove the files
+    (||{
+      fs::remove_file(InstanceGuard::savefile(&g.name, "g-", ""))?;
+      fs::remove_file(InstanceGuard::savefile(&g.name, "a-", ""))?;
+      <Result<_,ServerFailure>>::Ok(())
+    })()?;
     GLOBAL.games.write().unwrap().remove(&g.name);
     InstanceGuard::forget_all_tokens(&mut g.tokens_players);
     InstanceGuard::forget_all_tokens(&mut g.tokens_clients);