chiark / gitweb /
wip new account etc., adding acctid etc.
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 28 Oct 2020 23:04:11 +0000 (23:04 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 28 Oct 2020 23:04:11 +0000 (23:04 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/accounts.rs
src/global.rs

index 4ba85afc3631afd3e2650a25b6f3c380ec01ee03..feb6e7e44eb2d5b8533a7f76799e444d9d216797 100644 (file)
@@ -139,12 +139,17 @@ impl FromStr for AccountName {
 
 #[derive(Serialize,Deserialize,Debug)]
 pub struct AccountRecord {
+  pub account: Arc<AccountName>,
   pub nick: String,
   pub timezone: String,
   pub tokens_revealed: HashMap<Html, TokenRevelation>,
-  access: Arc<dyn PlayerAccessSpec>,
+  pub access: AccessRecord,
 }
 
+#[derive(Serialize,Deserialize,Debug)]
+#[serde(transparent)]
+struct AccessRecord (Arc<dyn PlayerAccessSpec>);
+
 #[derive(Copy,Clone,Debug,Ord,PartialOrd,Eq,PartialEq)]
 #[derive(Serialize,Deserialize)]
 pub struct TokenRevelation {
@@ -155,12 +160,17 @@ pub struct TokenRevelation {
 #[derive(Debug,Default)]
 #[derive(Serialize,Deserialize)]
 struct Accounts {
-  names: HashMap<AccountName, AccountId>,
+  names: HashMap<Arc<AccountName>, AccountId>,
   records: DenseSlotMap<AccountId, AccountRecord>,
 }
 
 static ACCOUNTS : RwLock<Option<Accounts>> = const_rwlock(None);
 
+impl Deref for AccessRecord {
+  type Target = Arc<dyn PlayerAccessSpec>;
+  fn deref(&self) -> &Self::Target { return &self.0 }
+}
+
 // xxx load, incl reveleation expiry
 // xxx periodic token reveleation expiry
 
@@ -168,6 +178,22 @@ pub fn save_accounts_now() -> Result<(), InternalError> {
   panic!("xxx")
 }
 
+trait AccountNameOrId : Copy {
+  fn initial_lookup(self, accounts: &Accounts) -> Option<AccountId>;
+}
+
+impl<'n> AccountNameOrId for &'n AccountName {
+  #[throws(as Option)]
+  fn initial_lookup(self, accounts: &Accounts) -> AccountId {
+    *accounts.names.get(self)?
+  }
+}
+
+impl AccountNameOrId for AccountId {
+  #[throws(as Option)]
+  fn initial_lookup(self, _: &Accounts) -> AccountId { self }
+}
+
 #[derive(Default,Debug)]
 struct LookupHelper {
   acctid_r: Option<AccountId>,
@@ -175,8 +201,9 @@ struct LookupHelper {
 
 impl LookupHelper {
   #[throws(as Option)]
-  fn get(&mut self, accounts: &Accounts, account: &AccountName) -> AccountId {
-    let acctid = *accounts.names.get(account)?;
+  fn get<K: AccountNameOrId>(&mut self, accounts: &Accounts, key: &K)
+                             -> AccountId {
+    let acctid = key.initial_lookup(accounts)?;
     self.acctid_r = Some(acctid);
     acctid
   }
@@ -192,14 +219,17 @@ impl LookupHelper {
 }
 
 impl AccountRecord {
-  pub fn bulk_check(names: &[&AccountName]) -> Vec<Option<AccountId>> {
+  pub fn bulk_check<K:AccountNameOrId>(keys: &[K]) -> Vec<Option<AccountId>> {
     let accounts = ACCOUNTS.read();
-    names.iter().map(|&name|{
-      accounts.as_ref()?.names.get(name).map(|&acctid| acctid)
+    keys.iter().map(|&key|{
+      let accounts = accounts.as_ref()?;
+      let acctid = key.initial_lookup(accounts)?;
+      let _record = accounts.records.get(acctid)?;
+      Some(acctid)
     }).collect()
   }
 
-  pub fn lookup(account: &AccountName,  _: Authorisation<AccountName>)
+  pub fn lookup<K: AccountNameOrId>(key: K,  _: Authorisation<AccountName>)
                 -> Option<(MappedRwLockReadGuard<'static, AccountRecord>,
                            AccountId)>
   {
@@ -207,14 +237,14 @@ impl AccountRecord {
     helper.wrap(
       RwLockReadGuard::try_map(ACCOUNTS.read(), |accounts| {
         let accounts = accounts.as_ref()?;
-        let acctid = helper.get(accounts, account)?;
+        let acctid = helper.get(accounts, key)?;
         accounts.records.get(acctid)
       })
     )
   }
 
-  pub fn lookup_mut_caller_must_save
-    ( account: &AccountName, _auth: Authorisation<AccountName>)
+  pub fn lookup_mut_caller_must_save<K: AccountNameOrId>
+    ( key: &K, _auth: Authorisation<AccountName>)
     -> Option<(MappedRwLockWriteGuard<'static, AccountRecord>,
                AccountId)>
   {
@@ -222,22 +252,27 @@ impl AccountRecord {
     helper.wrap(
       RwLockWriteGuard::try_map(ACCOUNTS.write(), |accounts| {
         let accounts = accounts.as_mut()?;
-        let acctid = helper.get(accounts, account)?;
+        let acctid = helper.get(accounts, key)?;
         accounts.records.get_mut(acctid)
       })
     )
   }
 
   #[throws(MgmtError)]
-  pub fn with_entry_mut<T, F>(account: &AccountName,
-                              auth: Authorisation<AccountName>,
-                              set_access: Option<Arc<dyn PlayerAccessSpec>>,
-                              f: F)
-                              -> Result<T, (InternalError, T)>
-  where F: FnOnce(&mut AccountRecord, AccountId) -> T
+  pub fn with_entry_mut
+    <T,
+     K: AccountNameOrId,
+     F: FnOnce(&mut AccountRecord, AccountId) -> T
+     >(
+      key: K,
+      auth: Authorisation<AccountName>,
+      set_access: Option<Arc<dyn PlayerAccessSpec>>,
+      f: F
+    )
+    -> Result<T, (InternalError, T)>
   {
     let (entry, acctid)
-      = AccountRecord::lookup_mut_caller_must_save(account, auth)
+      = AccountRecord::lookup_mut_caller_must_save(key, auth)
       .ok_or(MgmtError::AccountNotFound)?;
 
     if let Some(new_access) = set_access() {
index 8ee30d11b8961047cbf1a3f1a02e686e30f43d67..8e5b1be5aac2e0efa5dfa87dfaad0d558c3b1a83 100644 (file)
@@ -597,7 +597,7 @@ impl InstanceGuard<'_> {
       .pst;
 
     let (access, acctid) = AccountRecord::with_entry_mut(
-      &pst.account, authorised, None,
+      pst.acctid, authorised, None,
       |acct, acctid|
     {
       let access = acct.access;
@@ -887,7 +887,7 @@ impl InstanceGuard<'_> {
   
     let pu_bc = PlayerUpdates::new_begin(&gs);
 
-    let iplayers = {
+    let iplayers : SecondarySlotMap<PlayerId, PlayerRecord> = {
       let a = aplayers;
       a.drain()
     }.map(|(player, pst)| {
@@ -905,15 +905,15 @@ impl InstanceGuard<'_> {
     let name = Arc::new(name);
     let (tokens_players, acctids_players) = {
       let mut tokens = Vec::with_capacity(tokens_players.len());
-      let mut acctnames = Vec::with_capacity(tokens_players.len());
+      let mut acctids = Vec::with_capacity(tokens_players.len());
       for (token, player) in tokens_players { if_chain! {
-        if let Some(name) = gs.players.get(player);
+        if let Some(record) = iplayers.get(player);
         then {
           tokens.push((token, player));
-          acctnames.push(name);
+          acctids.push(record.pst.acctid);
         }
       }}
-      (tokens, AccountRecord::bulk_check(&acctnames))
+      (tokens, AccountRecord::bulk_check(&acctids))
     };
 
     let g = Instance {
@@ -1079,14 +1079,15 @@ pub fn process_all_players_for_account<
     >
   (acctid: AccountId, f: F)
 {
-  let games = GLOBAL.games.write().unlock();
+  let games = GLOBAL.games.write().unwrap();
   for gref in games.values() {
-    let ig = gref.lock();
-    let remove : Vec<_> = ig.iplayers.filter_map(|(player,pr)| {
+    let c = gref.lock_even_poisoned();
+    let remove : Vec<_> = c.g.iplayers.iter().filter_map(|(player,pr)| {
       if pr.pst.acctid == acctid { Some(player) } else { None }
     }).collect();
+    let ig = InstanceGuard { gref: gref.clone(), c };
     for player in remove.drain(..) {
-      f(player)?;
+      f(&mut ig, player)?;
     }
   }
 }