chiark / gitweb /
wip log expiry
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 17 Oct 2020 13:19:24 +0000 (14:19 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 17 Oct 2020 13:19:24 +0000 (14:19 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/gamestate.rs
src/global.rs

index 3d69d2cb9145e4f304261551bfb4f81c9b053faa..77702d6ca3a30ba217289f966cada58b59bcb3b8 100644 (file)
@@ -285,16 +285,18 @@ impl<T> PieceExt for T where T: Piece + ?Sized {
 // ---------- log expiry ==========
 
 impl GameState {
-  pub fn expire_old_logs(&mut self, cutoff: Timestamp) {
-    fn want_trim(gs: &GameState, cutoff: Timestamp) -> bool {
-      (||{
-        let e = gs.log.get(1)?;
-        (e.1.when < cutoff).as_option()
-      })().is_some()
-    };
+  pub fn want_expire_some_logs(&self, cutoff: Timestamp) -> bool {
+    (||{
+      let e = self.log.get(1)?;
+      (e.1.when < cutoff).as_option()
+    })().is_some()
+  }
+
+  pub fn do_expire_old_logs(&mut self, cutoff: Timestamp) {
+    let want_trim = |gs: &GameState| gs.want_expire_some_logs(cutoff);
 
-    if want_trim(self, cutoff) {
-      while want_trim(self, cutoff) {
+    if want_trim(self) {
+      while want_trim(self) {
         self.log.pop_front();
       }
       let front = self.log.front_mut().unwrap();
index fd718f8b2cc77b469fd819aaf7eb560a7b294d10..c138be74ea7e3ba61a79d9dcefac92c49c82ee16 100644 (file)
@@ -247,6 +247,13 @@ impl InstanceRef {
     if !c.live { throw!(InstanceLockError::GameBeingDestroyed) }
     InstanceGuard { c, gref: self.clone() }
   }
+
+  fn lock_even_poisoned(&self) -> MutexGuard<InstanceContainer> {
+    match self.0.lock() {
+      Ok(g) => g,
+      Err(poison) => poison.into_inner(),
+    }
+  }
 }
 
 impl Instance {
@@ -1018,13 +1025,6 @@ pub fn game_flush_task() {
 // ---------- client expiry ----------
 
 fn client_expire_old_clients() {
-  fn lock_even_poisoned(gref: &InstanceRef) -> MutexGuard<InstanceContainer> {
-    match gref.0.lock() {
-      Ok(g) => g,
-      Err(poison) => poison.into_inner(),
-    }
-  }
-
   let mut expire = vec![];
   let max_age = Instant::now() - MAX_CLIENT_INACTIVITY;
 
@@ -1032,7 +1032,7 @@ fn client_expire_old_clients() {
     type Ret;
     fn iter<'g>(&mut self, gref: &'g InstanceRef, max_age: Instant)
             -> (MutexGuard<'g, InstanceContainer>, Option<Self::Ret>) {
-      let c = lock_even_poisoned(gref);
+      let c = gref.lock_even_poisoned();
       let ret = 'ret: loop {
         for (client, cl) in &c.g.clients {
           if cl.lastseen > max_age { continue }
@@ -1086,6 +1086,33 @@ pub fn client_periodic_expiry() {
   }
 }
 
+// ---------- log expiry ----------
+
+fn global_expire_old_logs() {
+  let cutoff = Timestamp(Timestamp::now().0 - MAX_LOG_AGE.as_secs());
+
+  let mut want_expire = vec![];
+
+  let read = GLOBAL.games.read().unwrap();
+  for gref in read.values() {
+    if gref.lock_even_poisoned().g.gs.want_expire_some_logs(cutoff) {
+      want_expire.push(gref.clone())
+    }
+  }
+  drop(read);
+
+  for gref in want_expire.drain(..) {
+    gref.lock_even_poisoned().g.gs.do_expire_old_logs(cutoff);
+  }
+}
+
+pub fn logs_periodic_expiry() {
+  loop {
+    sleep(MAX_LOG_AGE/10);
+    global_expire_old_logs();
+  }
+}
+
 // ========== server config ==========
 
 const DEFAULT_CONFIG_FILENAME : &str = "server.toml";