🐝
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

499 lines
16 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. /*
  2. * meli - melib crate.
  3. *
  4. * Copyright 2017-2020 Manos Pitsidianakis
  5. *
  6. * This file is part of meli.
  7. *
  8. * meli is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * meli is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with meli. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. use super::*;
  22. use crate::backends::MailboxHash;
  23. use smallvec::SmallVec;
  24. use std::ops::{Deref, DerefMut};
  25. use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
  26. use std::collections::{BTreeMap, HashMap, HashSet};
  27. pub type EnvelopeRef<'g> = RwRef<'g, EnvelopeHash, Envelope>;
  28. pub type EnvelopeRefMut<'g> = RwRefMut<'g, EnvelopeHash, Envelope>;
  29. #[derive(Debug, Clone)]
  30. pub struct Collection {
  31. pub envelopes: Arc<RwLock<HashMap<EnvelopeHash, Envelope>>>,
  32. pub message_id_index: Arc<RwLock<HashMap<Vec<u8>, EnvelopeHash>>>,
  33. pub threads: Arc<RwLock<HashMap<MailboxHash, Threads>>>,
  34. pub sent_mailbox: Arc<RwLock<Option<MailboxHash>>>,
  35. pub mailboxes: Arc<RwLock<HashMap<MailboxHash, HashSet<EnvelopeHash>>>>,
  36. pub tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
  37. }
  38. impl Default for Collection {
  39. fn default() -> Self {
  40. Self::new()
  41. }
  42. }
  43. /*
  44. impl Drop for Collection {
  45. fn drop(&mut self) {
  46. let cache_dir: xdg::BaseDirectories =
  47. xdg::BaseDirectories::with_profile("meli", "threads".to_string()).unwrap();
  48. if let Ok(cached) = cache_dir.place_cache_file("threads") {
  49. /* place result in cache directory */
  50. let f = match fs::File::create(cached) {
  51. Ok(f) => f,
  52. Err(e) => {
  53. panic!("{}", e);
  54. }
  55. };
  56. let writer = io::BufWriter::new(f);
  57. let _ = bincode::Options::serialize_into(
  58. bincode::config::DefaultOptions::new(),
  59. writer,
  60. &self.thread,
  61. );
  62. }
  63. }
  64. }
  65. */
  66. impl Collection {
  67. pub fn new() -> Collection {
  68. let message_id_index = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
  69. 16,
  70. Default::default(),
  71. )));
  72. let threads = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
  73. 16,
  74. Default::default(),
  75. )));
  76. let mailboxes = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
  77. 16,
  78. Default::default(),
  79. )));
  80. Collection {
  81. envelopes: Arc::new(RwLock::new(Default::default())),
  82. tag_index: Arc::new(RwLock::new(BTreeMap::default())),
  83. message_id_index,
  84. threads,
  85. mailboxes,
  86. sent_mailbox: Arc::new(RwLock::new(None)),
  87. }
  88. }
  89. pub fn len(&self) -> usize {
  90. self.envelopes.read().unwrap().len()
  91. }
  92. pub fn is_empty(&self) -> bool {
  93. self.envelopes.read().unwrap().is_empty()
  94. }
  95. pub fn remove(&self, envelope_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
  96. debug!("DEBUG: Removing {}", envelope_hash);
  97. self.envelopes.write().unwrap().remove(&envelope_hash);
  98. self.mailboxes
  99. .write()
  100. .unwrap()
  101. .entry(mailbox_hash)
  102. .and_modify(|m| {
  103. m.remove(&envelope_hash);
  104. });
  105. let mut threads_lck = self.threads.write().unwrap();
  106. threads_lck
  107. .entry(mailbox_hash)
  108. .or_default()
  109. .remove(envelope_hash);
  110. for (h, t) in threads_lck.iter_mut() {
  111. if *h == mailbox_hash {
  112. continue;
  113. }
  114. t.remove(envelope_hash);
  115. }
  116. }
  117. pub fn rename(
  118. &self,
  119. old_hash: EnvelopeHash,
  120. new_hash: EnvelopeHash,
  121. mailbox_hash: MailboxHash,
  122. ) -> bool {
  123. if !self.envelopes.read().unwrap().contains_key(&old_hash) {
  124. return false;
  125. }
  126. let mut envelope = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
  127. self.mailboxes
  128. .write()
  129. .unwrap()
  130. .entry(mailbox_hash)
  131. .and_modify(|m| {
  132. m.remove(&old_hash);
  133. m.insert(new_hash);
  134. });
  135. envelope.set_hash(new_hash);
  136. self.envelopes.write().unwrap().insert(new_hash, envelope);
  137. let mut threads_lck = self.threads.write().unwrap();
  138. {
  139. if threads_lck
  140. .entry(mailbox_hash)
  141. .or_default()
  142. .update_envelope(&self.envelopes, old_hash, new_hash)
  143. .is_ok()
  144. {
  145. return true;
  146. }
  147. }
  148. /* envelope is not in threads, so insert it */
  149. threads_lck
  150. .entry(mailbox_hash)
  151. .or_default()
  152. .insert(&self.envelopes, new_hash);
  153. for (h, t) in threads_lck.iter_mut() {
  154. if *h == mailbox_hash {
  155. continue;
  156. }
  157. t.update_envelope(&self.envelopes, old_hash, new_hash)
  158. .ok()
  159. .take();
  160. }
  161. true
  162. }
  163. /// Merge new mailbox to collection and update threads.
  164. /// Returns a list of already existing mailboxs whose threads were updated
  165. pub fn merge(
  166. &self,
  167. mut new_envelopes: HashMap<EnvelopeHash, Envelope>,
  168. mailbox_hash: MailboxHash,
  169. sent_mailbox: Option<MailboxHash>,
  170. ) -> Option<SmallVec<[MailboxHash; 8]>> {
  171. *self.sent_mailbox.write().unwrap() = sent_mailbox;
  172. let Collection {
  173. ref threads,
  174. ref envelopes,
  175. ref mailboxes,
  176. ref sent_mailbox,
  177. ..
  178. } = self;
  179. let mut threads_lck = threads.write().unwrap();
  180. let mut mailboxes_lck = mailboxes.write().unwrap();
  181. if !threads_lck.contains_key(&mailbox_hash) {
  182. threads_lck.insert(mailbox_hash, Threads::new(new_envelopes.len()));
  183. mailboxes_lck.insert(mailbox_hash, new_envelopes.keys().cloned().collect());
  184. for (h, e) in new_envelopes {
  185. envelopes.write().unwrap().insert(h, e);
  186. }
  187. } else {
  188. mailboxes_lck.entry(mailbox_hash).and_modify(|m| {
  189. m.extend(new_envelopes.keys().cloned());
  190. });
  191. threads_lck.entry(mailbox_hash).and_modify(|t| {
  192. let mut ordered_hash_set =
  193. new_envelopes.keys().cloned().collect::<Vec<EnvelopeHash>>();
  194. ordered_hash_set.sort_by(|a, b| {
  195. new_envelopes[a]
  196. .date()
  197. .partial_cmp(&new_envelopes[b].date())
  198. .unwrap()
  199. });
  200. for h in ordered_hash_set {
  201. envelopes
  202. .write()
  203. .unwrap()
  204. .insert(h, new_envelopes.remove(&h).unwrap());
  205. t.insert(envelopes, h);
  206. }
  207. });
  208. }
  209. let mut ret = SmallVec::new();
  210. let keys = threads_lck.keys().cloned().collect::<Vec<MailboxHash>>();
  211. for t_fh in keys {
  212. if t_fh == mailbox_hash {
  213. continue;
  214. }
  215. if sent_mailbox
  216. .read()
  217. .unwrap()
  218. .map(|f| f == mailbox_hash)
  219. .unwrap_or(false)
  220. {
  221. let envelopes_lck = envelopes.read().unwrap();
  222. let mut ordered_hash_set = threads_lck[&mailbox_hash]
  223. .hash_set
  224. .iter()
  225. .cloned()
  226. .collect::<Vec<EnvelopeHash>>();
  227. ordered_hash_set.sort_by(|a, b| {
  228. envelopes_lck[a]
  229. .date()
  230. .partial_cmp(&envelopes_lck[b].date())
  231. .unwrap()
  232. });
  233. drop(envelopes_lck);
  234. let mut updated = false;
  235. for h in ordered_hash_set {
  236. updated |= threads_lck
  237. .entry(t_fh)
  238. .or_default()
  239. .insert_reply(envelopes, h);
  240. }
  241. if updated {
  242. ret.push(t_fh);
  243. }
  244. continue;
  245. }
  246. if sent_mailbox
  247. .read()
  248. .unwrap()
  249. .map(|f| f == t_fh)
  250. .unwrap_or(false)
  251. {
  252. let envelopes_lck = envelopes.read().unwrap();
  253. let mut ordered_hash_set = threads_lck[&t_fh]
  254. .hash_set
  255. .iter()
  256. .cloned()
  257. .collect::<Vec<EnvelopeHash>>();
  258. ordered_hash_set.sort_by(|a, b| {
  259. envelopes_lck[a]
  260. .date()
  261. .partial_cmp(&envelopes_lck[b].date())
  262. .unwrap()
  263. });
  264. drop(envelopes_lck);
  265. let mut updated = false;
  266. for h in ordered_hash_set {
  267. updated |= threads_lck
  268. .entry(mailbox_hash)
  269. .or_default()
  270. .insert_reply(envelopes, h);
  271. }
  272. if updated {
  273. ret.push(mailbox_hash);
  274. }
  275. }
  276. }
  277. if ret.is_empty() {
  278. None
  279. } else {
  280. Some(ret)
  281. }
  282. }
  283. pub fn update(
  284. &self,
  285. old_hash: EnvelopeHash,
  286. mut envelope: Envelope,
  287. mailbox_hash: MailboxHash,
  288. ) {
  289. let old_env = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
  290. envelope.set_thread(old_env.thread());
  291. let new_hash = envelope.hash();
  292. self.mailboxes
  293. .write()
  294. .unwrap()
  295. .entry(mailbox_hash)
  296. .and_modify(|m| {
  297. m.remove(&old_hash);
  298. m.insert(new_hash);
  299. });
  300. self.envelopes.write().unwrap().insert(new_hash, envelope);
  301. let mut threads_lck = self.threads.write().unwrap();
  302. if self
  303. .sent_mailbox
  304. .read()
  305. .unwrap()
  306. .map(|f| f == mailbox_hash)
  307. .unwrap_or(false)
  308. {
  309. for (_, t) in threads_lck.iter_mut() {
  310. t.update_envelope(&self.envelopes, old_hash, new_hash)
  311. .unwrap_or(());
  312. }
  313. }
  314. {
  315. if threads_lck
  316. .entry(mailbox_hash)
  317. .or_default()
  318. .update_envelope(&self.envelopes, old_hash, new_hash)
  319. .is_ok()
  320. {
  321. return;
  322. }
  323. }
  324. /* envelope is not in threads, so insert it */
  325. threads_lck
  326. .entry(mailbox_hash)
  327. .or_default()
  328. .insert(&self.envelopes, new_hash);
  329. for (h, t) in threads_lck.iter_mut() {
  330. if *h == mailbox_hash {
  331. continue;
  332. }
  333. t.update_envelope(&self.envelopes, old_hash, new_hash)
  334. .ok()
  335. .take();
  336. }
  337. }
  338. pub fn update_flags(&self, env_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
  339. let mut threads_lck = self.threads.write().unwrap();
  340. if self
  341. .sent_mailbox
  342. .read()
  343. .unwrap()
  344. .map(|f| f == mailbox_hash)
  345. .unwrap_or(false)
  346. {
  347. for (_, t) in threads_lck.iter_mut() {
  348. t.update_envelope(&self.envelopes, env_hash, env_hash)
  349. .unwrap_or(());
  350. }
  351. }
  352. {
  353. if threads_lck
  354. .entry(mailbox_hash)
  355. .or_default()
  356. .update_envelope(&self.envelopes, env_hash, env_hash)
  357. .is_ok()
  358. {
  359. return;
  360. }
  361. }
  362. /* envelope is not in threads, so insert it */
  363. threads_lck
  364. .entry(mailbox_hash)
  365. .or_default()
  366. .insert(&self.envelopes, env_hash);
  367. for (h, t) in threads_lck.iter_mut() {
  368. if *h == mailbox_hash {
  369. continue;
  370. }
  371. t.update_envelope(&self.envelopes, env_hash, env_hash)
  372. .ok()
  373. .take();
  374. }
  375. }
  376. pub fn insert(&self, envelope: Envelope, mailbox_hash: MailboxHash) -> bool {
  377. let hash = envelope.hash();
  378. self.mailboxes
  379. .write()
  380. .unwrap()
  381. .entry(mailbox_hash)
  382. .and_modify(|m| {
  383. m.insert(hash);
  384. });
  385. self.envelopes.write().unwrap().insert(hash, envelope);
  386. self.threads
  387. .write()
  388. .unwrap()
  389. .entry(mailbox_hash)
  390. .or_default()
  391. .insert(&self.envelopes, hash);
  392. if self
  393. .sent_mailbox
  394. .read()
  395. .unwrap()
  396. .map(|f| f == mailbox_hash)
  397. .unwrap_or(false)
  398. {
  399. self.insert_reply(hash);
  400. }
  401. false
  402. }
  403. pub fn insert_reply(&self, env_hash: EnvelopeHash) {
  404. debug_assert!(self.envelopes.read().unwrap().contains_key(&env_hash));
  405. for (_, t) in self.threads.write().unwrap().iter_mut() {
  406. t.insert_reply(&self.envelopes, env_hash);
  407. }
  408. }
  409. pub fn get_env(&'_ self, hash: EnvelopeHash) -> EnvelopeRef<'_> {
  410. let guard: RwLockReadGuard<'_, _> = self.envelopes.read().unwrap();
  411. EnvelopeRef { guard, hash }
  412. }
  413. pub fn get_env_mut(&'_ self, hash: EnvelopeHash) -> EnvelopeRefMut<'_> {
  414. let guard = self.envelopes.write().unwrap();
  415. EnvelopeRefMut { guard, hash }
  416. }
  417. pub fn get_threads(&'_ self, hash: MailboxHash) -> RwRef<'_, MailboxHash, Threads> {
  418. let guard = self.threads.read().unwrap();
  419. RwRef { guard, hash }
  420. }
  421. pub fn get_mailbox(
  422. &'_ self,
  423. hash: MailboxHash,
  424. ) -> RwRef<'_, MailboxHash, HashSet<EnvelopeHash>> {
  425. let guard = self.mailboxes.read().unwrap();
  426. RwRef { guard, hash }
  427. }
  428. pub fn contains_key(&self, env_hash: &EnvelopeHash) -> bool {
  429. self.envelopes.read().unwrap().contains_key(env_hash)
  430. }
  431. pub fn new_mailbox(&self, mailbox_hash: MailboxHash) {
  432. let mut mailboxes_lck = self.mailboxes.write().unwrap();
  433. if !mailboxes_lck.contains_key(&mailbox_hash) {
  434. mailboxes_lck.insert(mailbox_hash, Default::default());
  435. self.threads
  436. .write()
  437. .unwrap()
  438. .insert(mailbox_hash, Threads::default());
  439. }
  440. }
  441. }
  442. pub struct RwRef<'g, K: std::cmp::Eq + std::hash::Hash, V> {
  443. guard: RwLockReadGuard<'g, HashMap<K, V>>,
  444. hash: K,
  445. }
  446. impl<K: std::cmp::Eq + std::hash::Hash, V> Deref for RwRef<'_, K, V> {
  447. type Target = V;
  448. fn deref(&self) -> &V {
  449. self.guard.get(&self.hash).unwrap()
  450. }
  451. }
  452. pub struct RwRefMut<'g, K: std::cmp::Eq + std::hash::Hash, V> {
  453. guard: RwLockWriteGuard<'g, HashMap<K, V>>,
  454. hash: K,
  455. }
  456. impl<K: std::cmp::Eq + std::hash::Hash, V> DerefMut for RwRefMut<'_, K, V> {
  457. fn deref_mut(&mut self) -> &mut V {
  458. self.guard.get_mut(&self.hash).unwrap()
  459. }
  460. }
  461. impl<K: std::cmp::Eq + std::hash::Hash, V> Deref for RwRefMut<'_, K, V> {
  462. type Target = V;
  463. fn deref(&self) -> &V {
  464. self.guard.get(&self.hash).unwrap()
  465. }
  466. }