ClientMetadataManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. namespace WatsonTcp
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Threading;
  6. internal class ClientMetadataManager : IDisposable
  7. {
  8. #region Internal-Members
  9. #endregion
  10. #region Private-Members
  11. private readonly ReaderWriterLockSlim _UnauthenticatedClientsLock = new ReaderWriterLockSlim();
  12. private Dictionary<Guid, DateTime> _UnauthenticatedClients = new Dictionary<Guid, DateTime>();
  13. private readonly ReaderWriterLockSlim _ClientsLock = new ReaderWriterLockSlim();
  14. private Dictionary<Guid, ClientMetadata> _Clients = new Dictionary<Guid, ClientMetadata>();
  15. private readonly ReaderWriterLockSlim _ClientsLastSeenLock = new ReaderWriterLockSlim();
  16. private Dictionary<Guid, DateTime> _ClientsLastSeen = new Dictionary<Guid, DateTime>();
  17. private readonly ReaderWriterLockSlim _ClientsKickedLock = new ReaderWriterLockSlim();
  18. private Dictionary<Guid, DateTime> _ClientsKicked = new Dictionary<Guid, DateTime>();
  19. private readonly ReaderWriterLockSlim _ClientsTimedoutLock = new ReaderWriterLockSlim();
  20. private Dictionary<Guid, DateTime> _ClientsTimedout = new Dictionary<Guid, DateTime>();
  21. #endregion
  22. #region Constructors-and-Factories
  23. internal ClientMetadataManager()
  24. {
  25. }
  26. #endregion
  27. #region Public-Methods
  28. /// <summary>
  29. /// Dispose.
  30. /// </summary>
  31. public void Dispose()
  32. {
  33. Dispose(true);
  34. GC.SuppressFinalize(this);
  35. }
  36. /// <summary>
  37. /// Dispose.
  38. /// </summary>
  39. /// <param name="disposing">Indicate if resources should be disposed.</param>
  40. protected virtual void Dispose(bool disposing)
  41. {
  42. if (disposing)
  43. {
  44. _UnauthenticatedClients = null;
  45. _Clients = null;
  46. _ClientsLastSeen = null;
  47. _ClientsKicked = null;
  48. _ClientsTimedout = null;
  49. }
  50. }
  51. #endregion
  52. #region Internal-Methods
  53. internal void Reset()
  54. {
  55. }
  56. internal void ReplaceGuid(Guid original, Guid replace)
  57. {
  58. ReplaceUnauthenticatedClient(original, replace);
  59. ReplaceClient(original, replace);
  60. ReplaceClientLastSeen(original, replace);
  61. ReplaceClientKicked(original, replace);
  62. ReplaceClientTimedout(original, replace);
  63. }
  64. internal void Remove(Guid guid)
  65. {
  66. RemoveUnauthenticatedClient(guid);
  67. RemoveClient(guid);
  68. RemoveClientLastSeen(guid);
  69. RemoveClientKicked(guid);
  70. RemoveClientTimedout(guid);
  71. }
  72. /*
  73. private ConcurrentDictionary<Guid, DateTime> _UnauthenticatedClients = new ConcurrentDictionary<Guid, DateTime>();
  74. private ConcurrentDictionary<Guid, ClientMetadata> _Clients = new ConcurrentDictionary<Guid, ClientMetadata>();
  75. private ConcurrentDictionary<Guid, DateTime> _ClientsLastSeen = new ConcurrentDictionary<Guid, DateTime>();
  76. private ConcurrentDictionary<Guid, DateTime> _ClientsKicked = new ConcurrentDictionary<Guid, DateTime>();
  77. private ConcurrentDictionary<Guid, DateTime> _ClientsTimedout = new ConcurrentDictionary<Guid, DateTime>();
  78. */
  79. #region Unauthenticated-Clients
  80. #region Helpers
  81. private void _addUnauthenticatedClient(Guid guid, DateTime? dt = null)
  82. {
  83. _UnauthenticatedClientsLock.EnterWriteLock();
  84. try
  85. {
  86. if (dt == null)
  87. {
  88. _UnauthenticatedClients.Add(guid, DateTime.UtcNow);
  89. }
  90. else
  91. {
  92. _UnauthenticatedClients.Add(guid, dt.Value);
  93. }
  94. }
  95. finally
  96. {
  97. _UnauthenticatedClientsLock.ExitWriteLock();
  98. }
  99. }
  100. private void _removeUnauthenticatedClient(Guid guid)
  101. {
  102. if (_existsUnauthenticatedClient(guid))
  103. {
  104. _UnauthenticatedClientsLock.EnterWriteLock();
  105. try
  106. {
  107. _UnauthenticatedClients.Remove(guid);
  108. }
  109. finally
  110. {
  111. _UnauthenticatedClientsLock.ExitWriteLock();
  112. }
  113. }
  114. }
  115. private bool _existsUnauthenticatedClient(Guid guid)
  116. {
  117. _UnauthenticatedClientsLock.EnterReadLock();
  118. try
  119. {
  120. return _UnauthenticatedClients.ContainsKey(guid);
  121. }
  122. finally
  123. {
  124. _UnauthenticatedClientsLock.ExitReadLock();
  125. }
  126. }
  127. private DateTime _unauthenticatedClientsGetDateTime(Guid guid)
  128. {
  129. _UnauthenticatedClientsLock.EnterReadLock();
  130. try
  131. {
  132. return _UnauthenticatedClients[guid];
  133. }
  134. finally
  135. {
  136. _UnauthenticatedClientsLock.ExitReadLock();
  137. }
  138. }
  139. #endregion
  140. internal void AddUnauthenticatedClient(Guid guid) => _addUnauthenticatedClient(guid);
  141. internal void RemoveUnauthenticatedClient(Guid guid) => _removeUnauthenticatedClient(guid);
  142. internal bool ExistsUnauthenticatedClient(Guid guid) => _existsUnauthenticatedClient(guid);
  143. internal void ReplaceUnauthenticatedClient(Guid original, Guid update)
  144. {
  145. if (_existsUnauthenticatedClient(original))
  146. {
  147. DateTime dt = _unauthenticatedClientsGetDateTime(original);
  148. _removeUnauthenticatedClient(original);
  149. _addUnauthenticatedClient(update, dt);
  150. }
  151. }
  152. internal Dictionary<Guid, DateTime> AllUnauthenticatedClients()
  153. {
  154. _UnauthenticatedClientsLock.EnterReadLock();
  155. try
  156. {
  157. return new Dictionary<Guid, DateTime>(_UnauthenticatedClients);
  158. }
  159. finally
  160. {
  161. _UnauthenticatedClientsLock.ExitReadLock();
  162. }
  163. }
  164. #endregion
  165. #region Clients
  166. #region Helpers
  167. private void _addClient(Guid guid, ClientMetadata client)
  168. {
  169. _ClientsLock.EnterWriteLock();
  170. try
  171. {
  172. _Clients.Add(guid, client);
  173. }
  174. finally
  175. {
  176. _ClientsLock.ExitWriteLock();
  177. }
  178. }
  179. private void _removeClient(Guid guid)
  180. {
  181. if (_existsClient(guid))
  182. {
  183. _ClientsLock.EnterWriteLock();
  184. try
  185. {
  186. _Clients.Remove(guid);
  187. }
  188. finally
  189. {
  190. _ClientsLock.ExitWriteLock();
  191. }
  192. }
  193. }
  194. private bool _existsClient(Guid guid)
  195. {
  196. _ClientsLock.EnterReadLock();
  197. try
  198. {
  199. return _Clients.ContainsKey(guid);
  200. }
  201. finally
  202. {
  203. _ClientsLock.ExitReadLock();
  204. }
  205. }
  206. private ClientMetadata _getClientMetadata(Guid guid)
  207. {
  208. _ClientsLock.EnterReadLock();
  209. try
  210. {
  211. return _Clients[guid];
  212. }
  213. finally
  214. {
  215. _ClientsLock.ExitReadLock();
  216. }
  217. }
  218. #endregion
  219. internal void AddClient(Guid guid, ClientMetadata client) => _addClient(guid, client);
  220. internal ClientMetadata GetClient(Guid guid) => _existsClient(guid) ? _Clients[guid] : null;
  221. internal void RemoveClient(Guid guid) => _removeClient(guid);
  222. internal bool ExistsClient(Guid guid) => _existsClient(guid);
  223. internal void ReplaceClient(Guid original, Guid update)
  224. {
  225. if (_existsClient(original))
  226. {
  227. ClientMetadata md = _getClientMetadata(original);
  228. _removeClient(original);
  229. _addClient(update, md);
  230. }
  231. }
  232. internal Dictionary<Guid, ClientMetadata> AllClients()
  233. {
  234. _ClientsLock.EnterReadLock();
  235. try
  236. {
  237. return new Dictionary<Guid, ClientMetadata>(_Clients);
  238. }
  239. finally
  240. {
  241. _ClientsLock.ExitReadLock();
  242. }
  243. }
  244. #endregion
  245. #region Clients-Last-Seen
  246. #region Helpers
  247. private void _addClientLastSeen(Guid guid, DateTime? dt = null)
  248. {
  249. if (_existsClientLastSeen(guid)) return;
  250. _ClientsLastSeenLock.EnterWriteLock();
  251. try
  252. {
  253. if (dt == null)
  254. {
  255. _ClientsLastSeen.Add(guid, DateTime.UtcNow);
  256. }
  257. else
  258. {
  259. _ClientsLastSeen.Add(guid, dt.Value);
  260. }
  261. }
  262. finally
  263. {
  264. _ClientsLastSeenLock.ExitWriteLock();
  265. }
  266. }
  267. private void _removeClientLastSeen(Guid guid)
  268. {
  269. if (!_existsClientLastSeen(guid)) return;
  270. _ClientsLastSeenLock.EnterWriteLock();
  271. try
  272. {
  273. _ClientsLastSeen.Remove(guid);
  274. }
  275. finally
  276. {
  277. _ClientsLastSeenLock.ExitWriteLock();
  278. }
  279. }
  280. private bool _existsClientLastSeen(Guid guid)
  281. {
  282. _ClientsLastSeenLock.EnterReadLock();
  283. try
  284. {
  285. return _ClientsLastSeen.ContainsKey(guid);
  286. }
  287. finally
  288. {
  289. _ClientsLastSeenLock.ExitReadLock();
  290. }
  291. }
  292. private DateTime _clientLastSeenGetDateTime(Guid guid)
  293. {
  294. _ClientsLastSeenLock.EnterReadLock();
  295. try
  296. {
  297. return _ClientsLastSeen[guid];
  298. }
  299. finally
  300. {
  301. _ClientsLastSeenLock.ExitReadLock();
  302. }
  303. }
  304. #endregion
  305. internal void AddClientLastSeen(Guid guid) => _addClientLastSeen(guid);
  306. internal void RemoveClientLastSeen(Guid guid) => _removeClientLastSeen(guid);
  307. internal bool ExistsClientLastSeen(Guid guid) => _existsClientLastSeen(guid);
  308. internal void ReplaceClientLastSeen(Guid original, Guid update)
  309. {
  310. if (_existsClientLastSeen(original))
  311. {
  312. DateTime dt = _clientLastSeenGetDateTime(original);
  313. _removeClientLastSeen(original);
  314. _addClientLastSeen(update, dt);
  315. }
  316. }
  317. internal void UpdateClientLastSeen(Guid guid, DateTime dt)
  318. {
  319. if (_existsClientLastSeen(guid))
  320. {
  321. _removeClientLastSeen(guid);
  322. _addClientLastSeen(guid, dt.ToUniversalTime());
  323. }
  324. }
  325. internal Dictionary<Guid, DateTime> AllClientsLastSeen()
  326. {
  327. _ClientsLastSeenLock.EnterReadLock();
  328. try
  329. {
  330. return new Dictionary<Guid, DateTime>(_ClientsLastSeen);
  331. }
  332. finally
  333. {
  334. _ClientsLastSeenLock.ExitReadLock();
  335. }
  336. }
  337. #endregion
  338. #region Clients-Kicked
  339. #region Helpers
  340. private void _addClientKicked(Guid guid, DateTime? dt = null)
  341. {
  342. if (_existsClientKicked(guid)) return;
  343. _ClientsKickedLock.EnterWriteLock();
  344. try
  345. {
  346. if (dt == null)
  347. {
  348. _ClientsKicked.Add(guid, DateTime.UtcNow);
  349. }
  350. else
  351. {
  352. _ClientsKicked.Add(guid, dt.Value);
  353. }
  354. }
  355. finally
  356. {
  357. _ClientsKickedLock.ExitWriteLock();
  358. }
  359. }
  360. private void _removeClientKicked(Guid guid)
  361. {
  362. if (!_existsClientKicked(guid)) return;
  363. _ClientsKickedLock.EnterWriteLock();
  364. try
  365. {
  366. _ClientsKicked.Remove(guid);
  367. }
  368. finally
  369. {
  370. _ClientsKickedLock.ExitWriteLock();
  371. }
  372. }
  373. private bool _existsClientKicked(Guid guid)
  374. {
  375. _ClientsKickedLock.EnterReadLock();
  376. try
  377. {
  378. return _ClientsKicked.ContainsKey(guid);
  379. }
  380. finally
  381. {
  382. _ClientsKickedLock.ExitReadLock();
  383. }
  384. }
  385. private DateTime _clientKickedGetDateTime(Guid guid)
  386. {
  387. _ClientsKickedLock.EnterReadLock();
  388. try
  389. {
  390. return _ClientsKicked[guid];
  391. }
  392. finally
  393. {
  394. _ClientsKickedLock.ExitReadLock();
  395. }
  396. }
  397. #endregion
  398. internal void AddClientKicked(Guid guid) => _addClientKicked(guid);
  399. internal void RemoveClientKicked(Guid guid) => _removeClientKicked(guid);
  400. internal bool ExistsClientKicked(Guid guid) => _existsClientKicked(guid);
  401. internal void ReplaceClientKicked(Guid original, Guid update)
  402. {
  403. if (_existsClientKicked(original))
  404. {
  405. DateTime dt = _clientKickedGetDateTime(original);
  406. _removeClientKicked(original);
  407. _addClientKicked(update, dt);
  408. }
  409. }
  410. internal void UpdateClientKicked(Guid guid, DateTime dt)
  411. {
  412. if (_existsClientKicked(guid))
  413. {
  414. _removeClientKicked(guid);
  415. _addClientKicked(guid, dt.ToUniversalTime());
  416. }
  417. }
  418. internal Dictionary<Guid, DateTime> AllClientsKicked()
  419. {
  420. _ClientsKickedLock.EnterReadLock();
  421. try
  422. {
  423. return new Dictionary<Guid, DateTime>(_ClientsKicked);
  424. }
  425. finally
  426. {
  427. _ClientsKickedLock.ExitReadLock();
  428. }
  429. }
  430. #endregion
  431. #region Clients-Timedout
  432. #region Helpers
  433. private void _addClientTimedout(Guid guid, DateTime? dt = null)
  434. {
  435. if (_existsClientTimedout(guid)) return;
  436. _ClientsTimedoutLock.EnterWriteLock();
  437. try
  438. {
  439. if (dt == null)
  440. {
  441. _ClientsTimedout.Add(guid, DateTime.UtcNow);
  442. }
  443. else
  444. {
  445. _ClientsTimedout.Add(guid, dt.Value);
  446. }
  447. }
  448. finally
  449. {
  450. _ClientsTimedoutLock.ExitWriteLock();
  451. }
  452. }
  453. private void _removeClientTimedout(Guid guid)
  454. {
  455. if (!_existsClientTimedout(guid)) return;
  456. _ClientsTimedoutLock.EnterWriteLock();
  457. try
  458. {
  459. _ClientsTimedout.Remove(guid);
  460. }
  461. finally
  462. {
  463. _ClientsTimedoutLock.ExitWriteLock();
  464. }
  465. }
  466. private bool _existsClientTimedout(Guid guid)
  467. {
  468. _ClientsTimedoutLock.EnterReadLock();
  469. try
  470. {
  471. return _ClientsTimedout.ContainsKey(guid);
  472. }
  473. finally
  474. {
  475. _ClientsTimedoutLock.ExitReadLock();
  476. }
  477. }
  478. private DateTime _clientTimeoutGetDateTime(Guid guid)
  479. {
  480. _ClientsTimedoutLock.EnterReadLock();
  481. try
  482. {
  483. return _ClientsTimedout[guid];
  484. }
  485. finally
  486. {
  487. _ClientsTimedoutLock.ExitReadLock();
  488. }
  489. }
  490. #endregion
  491. internal void AddClientTimedout(Guid guid) => _addClientTimedout(guid);
  492. internal void RemoveClientTimedout(Guid guid) => _removeClientTimedout(guid);
  493. internal bool ExistsClientTimedout(Guid guid) => _existsClientTimedout(guid);
  494. internal void ReplaceClientTimedout(Guid original, Guid update)
  495. {
  496. if (_existsClientTimedout(original))
  497. {
  498. DateTime dt = _clientTimeoutGetDateTime(original);
  499. _removeClientTimedout(original);
  500. _addClientTimedout(update, dt);
  501. }
  502. }
  503. internal void UpdateClientTimeout(Guid guid, DateTime dt)
  504. {
  505. if (_existsClientTimedout(guid))
  506. {
  507. _removeClientTimedout(guid);
  508. _addClientTimedout(guid, dt.ToUniversalTime());
  509. }
  510. }
  511. internal Dictionary<Guid, DateTime> AllClientsTimedout()
  512. {
  513. _ClientsTimedoutLock.EnterReadLock();
  514. try
  515. {
  516. return new Dictionary<Guid, DateTime>(_ClientsTimedout);
  517. }
  518. finally
  519. {
  520. _ClientsTimedoutLock.ExitReadLock();
  521. }
  522. }
  523. #endregion
  524. #endregion
  525. #region Private-Methods
  526. #endregion
  527. }
  528. }