LimitExceeded,
SVGProcessingFailed(#[from] SVGProcessingError),
GameError(#[from] GameError),
+ ServerFailure(String),
}
display_as_debug!{MgmtError}
+impl From<ServerFailure> for MgmtError {
+ fn from(e: ServerFailure) -> MgmtError {
+ MgmtError::ServerFailure(format!("ServerFailure {}\n", &e))
+ }
+}
JSONSerializeFailed(#[from] serde_json::error::Error),
#[error("SVG processing/generation error {0:?}")]
SVGProcessingFailed(#[from] SVGProcessingError),
+ #[error("Server operational problems: {0:?}")]
+ ServerFailure(#[from] ServerFailure),
+}
+from_instance_lock_error!{OnlineError}
+
+#[derive(Error,Debug)]
+pub enum ServerFailure {
#[error("Server IO error {0:?}")]
- ServerIOError(#[from] io::Error),
+ IO(#[from] io::Error),
#[error("Server MessagePack encoding error {0:?}")]
- ServerMessagePackEncodeFail(#[from] rmp_serde::encode::Error),
+ MessagePackEncodeFail(#[from] rmp_serde::encode::Error),
#[error("Server MessagePack decoding error (game load failed) {0:?}")]
- ServerMessagePackDecodeFail(#[from] rmp_serde::decode::Error),
+ MessagePackDecodeFail(#[from] rmp_serde::decode::Error),
}
-from_instance_lock_error!{OnlineError}
pub type StartupError = anyhow::Error;
let gref = InstanceRef(Arc::new(Mutex::new(cont)));
- let mut games = GLOBAL.games.write().unwrap();
- let entry = games.entry(name);
+ {
+ // 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()?;
+ }
- use hash_map::Entry::*;
- let entry = match entry {
- Vacant(ve) => ve,
- Occupied(_) => throw!(MgmtError::AlreadyExists),
- };
+ {
+ let mut games = GLOBAL.games.write().unwrap();
+ let entry = games.entry(name);
- entry.insert(gref.clone());
+ use hash_map::Entry::*;
+ let entry = match entry {
+ Vacant(ve) => ve,
+ Occupied(_) => throw!(MgmtError::AlreadyExists),
+ };
- // xxx save, but first release the GLOBAL.games lock
+ entry.insert(gref.clone());
+ }
gref
}
.chain( iter::once(suffix) )
.collect()
}
- #[throws(OE)]
+ #[throws(ServerFailure)]
fn save_something(
&self, prefix: &str,
w: fn(s: &Self, w: &mut BufWriter<fs::File>)
eprintln!("saved to {}", &out);
}
- #[throws(OE)]
+ #[throws(ServerFailure)]
pub fn save_game_now(&mut self) {
self.save_something("g-", |s,w| {
rmp_serde::encode::write_named(w, &s.c.g.gs)
})?;
}
- #[throws(OE)]
+ #[throws(ServerFailure)]
fn save_access_now(&mut self) {
self.save_something("a-", |s,w| {
let global_players = GLOBAL.players.read().unwrap();
})?;
}
- #[throws(OE)]
+ #[throws(ServerFailure)]
fn load_something<T:DeserializeOwned>(name: &InstanceName, prefix: &str) -> T {
let inp = Self::savefile(name, prefix, "");
let mut f = BufReader::new(fs::File::open(&inp)?);
use OnlineError::*;
let status = match self {
GameCorrupted | JSONSerializeFailed(_) | SVGProcessingFailed(_)
- | ServerIOError(_)
- | ServerMessagePackEncodeFail(_)
- | ServerMessagePackDecodeFail(_)
+ | ServerFailure(_)
=> Status::InternalServerError,
NoClient | NoPlayer | GameBeingDestroyed => Status::NotFound,
InvalidZCoord => Status::BadRequest,