chiark / gitweb /
wip server eh
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 Aug 2020 12:04:20 +0000 (13:04 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 Aug 2020 12:04:20 +0000 (13:04 +0100)
src/commands.rs
src/error.rs
src/global.rs

index 374778c4d6e85b4e67135a5de1cb92002d51fb75..d11bcf510fd0126fa50b82acfedb0f204d229ccf 100644 (file)
@@ -60,7 +60,16 @@ pub enum MgmtError {
   GameError(#[from] GameError),
   ServerFailure(String),
 }
-display_as_debug!{MgmtError}
+impl Display for MgmtError {
+  #[throws(fmt::Error)]
+  fn fmt(&self, f: &mut fmt::Formatter) {
+    use MgmtError::*;
+    match self {
+      ServerFailure(s) => write!(f, "ServerFailure: {}", &s)?,
+      _ => <Self as Debug>::fmt(self,f)?,
+    }
+  }
+}
 
 impl From<ServerFailure> for MgmtError {
   fn from(e: ServerFailure) -> MgmtError {
index e0e7351f68efa9e8a99d06876418865dd6dff533..addd35bffb47ae6879908421b677612f574386fd 100644 (file)
@@ -34,14 +34,14 @@ from_instance_lock_error!{OnlineError}
 
 #[derive(Error,Debug)]
 pub enum ServerFailure {
-  #[error("Server IO error {0:?}")]
-  IO(#[from] io::Error),
-  #[error("Server MessagePack encoding error {0:?}")]
+  #[error("Server MessagePack encoding error {0}")]
   MessagePackEncodeFail(#[from] rmp_serde::encode::Error),
-  #[error("Server MessagePack decoding error (game load failed) {0:?}")]
+  #[error("Server MessagePack decoding error (game load failed) {0}")]
   MessagePackDecodeFail(#[from] rmp_serde::decode::Error),
-  #[error("Server internal logic error {0:}")]
+  #[error("Server internal logic error {0}")]
   InternalLogicError(String),
+  #[error("Server error {0:?}")]
+  Anyhow(#[from] anyhow::Error),
 }
 
 #[derive(Error,Debug,Serialize,Copy,Clone)]
index 5d0ee8abd6b47659a69d3255c78226aafb43ec9b..82cd5ae1dc98def8c4adfd4992d768190ab5074e 100644 (file)
@@ -260,7 +260,8 @@ impl Instance {
     let a_savefile = savefilename(&g.name, "a-", "");
 
     let mut gw = GLOBAL.games.write().unwrap();
-    fs::remove_file(savefilename(&g.name, "g-", ""))?;
+    let g_file = savefilename(&g.name, "g-", "");
+    fs::remove_file(&g_file).context("remove").context(g_file)?;
 
     (||{ // Infallible:
       g.c.live = false;
@@ -576,12 +577,19 @@ impl InstanceGuard<'_> {
           -> Result<(),rmp_serde::encode::Error>
   ) {
     let tmp = savefilename(&self.name, prefix,".tmp");
-    let mut f = BufWriter::new(fs::File::create(&tmp)?);
+    let f = fs::File::create(&tmp)
+      .with_context(||format!("save: create {:?}",&tmp))?;
+    let mut f = BufWriter::new(f);
     w(self, &mut f)?;
-    f.flush()?;
-    drop( f.into_inner().map_err(|e| { let e : io::Error = e.into(); e })? );
+    f.flush()
+      .with_context(||format!("save: flush {:?}",&tmp))?;
+    drop(
+      f.into_inner().map_err(|e| { let e : io::Error = e.into(); e })
+        .with_context(||format!("save: close {:?}",&tmp))?
+    );
     let out = savefilename(&self.name, prefix,"");
-    fs::rename(&tmp, &out)?;
+    fs::rename(&tmp, &out).context("install")
+      .with_context(||format!("save: install {:?} as {:?}", &tmp, &out))?;
     eprintln!("saved to {}", &out);
   }
 
@@ -613,7 +621,7 @@ impl InstanceGuard<'_> {
   #[throws(ServerFailure)]
   fn load_something<T:DeserializeOwned>(name: &InstanceName, prefix: &str) -> T {
     let inp = savefilename(name, prefix, "");
-    let mut f = BufReader::new(fs::File::open(&inp)?);
+    let mut f = BufReader::new(fs::File::open(&inp).context(inp)?);
     // xxx handle ENOENT specially, own OE variant
     rmp_serde::decode::from_read(&mut f)?
   }
@@ -626,11 +634,15 @@ impl InstanceGuard<'_> {
     let gs : GameState = Self::load_something(&name, "g-")?;
     let mut al : InstanceSaveAccesses<String>
       = Self::load_something(&name, "a-")
-      .or_else(|e:ServerFailure| match e {
-        ServerFailure::IO(ioe) if ioe.kind() == io::ErrorKind::NotFound => {
-          Ok(Default::default())
-        },
-        e => Err(e),
+      .or_else(|e| {
+        if let ServerFailure::Anyhow(ae) = &e {
+          if let Some(ioe) = ae.downcast_ref::<io::Error>() {
+            if ioe.kind() == io::ErrorKind::NotFound {
+              return Ok(Default::default())
+            }
+          }
+        }
+        Err(e)
       })?;
     let mut updates : SecondarySlotMap<_,_> = Default::default();
     for player in gs.players.keys() {
@@ -787,10 +799,14 @@ pub fn record_token<Id : AccessId> (
 
 const DEFAULT_SAVE_DIRECTORY : &str = "save";
 
+#[derive(Deserialize,Debug,Clone)]
 pub struct ServerConfig {
+  #[serde(default="default_save_directory")]
   pub save_directory: String,
 }
 
+fn default_save_directory() -> String { DEFAULT_SAVE_DIRECTORY.to_owned() }
+
 pub fn config() -> Arc<ServerConfig> {
   GLOBAL.config.read().unwrap().clone()
 }
@@ -810,13 +826,13 @@ const XXX_PLAYERS_TOKENS : &[(&str, &str)] = &[
   ("ccg9kzoTh758QrVE1xMY7BQWB36dNJTx", "bob"),
 ];
 
-#[throws(OE)]
+#[throws(AE)]
 pub fn xxx_global_setup() {
   let gs = xxx_gamestate_init();
   let gref = Instance::new(InstanceName {
     scope: ManagementScope::Server,
     scoped_name: "dummy".to_string()
-  }, gs).expect("xxx create dummy");
+  }, gs)?;
   let mut g = gref.lock()?;
   for (token, nick) in XXX_PLAYERS_TOKENS {
     let player = g.player_new(PlayerState {