data_messages.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "data/data_messages.h"
  8. namespace Data {
  9. MessagesList::Slice::Slice(
  10. base::flat_set<MessagePosition> &&messages,
  11. MessagesRange range)
  12. : messages(std::move(messages))
  13. , range(range) {
  14. }
  15. template <typename Range>
  16. void MessagesList::Slice::merge(
  17. const Range &moreMessages,
  18. MessagesRange moreNoSkipRange) {
  19. Expects(moreNoSkipRange.from <= range.till);
  20. Expects(range.from <= moreNoSkipRange.till);
  21. messages.merge(std::begin(moreMessages), std::end(moreMessages));
  22. range = {
  23. qMin(range.from, moreNoSkipRange.from),
  24. qMax(range.till, moreNoSkipRange.till)
  25. };
  26. }
  27. template <typename Range>
  28. int MessagesList::uniteAndAdd(
  29. MessagesSliceUpdate &update,
  30. base::flat_set<Slice>::iterator uniteFrom,
  31. base::flat_set<Slice>::iterator uniteTill,
  32. const Range &messages,
  33. MessagesRange noSkipRange) {
  34. auto uniteFromIndex = uniteFrom - _slices.begin();
  35. auto was = uniteFrom->messages.size();
  36. _slices.modify(uniteFrom, [&](Slice &slice) {
  37. slice.merge(messages, noSkipRange);
  38. });
  39. auto firstToErase = uniteFrom + 1;
  40. if (firstToErase != uniteTill) {
  41. for (auto it = firstToErase; it != uniteTill; ++it) {
  42. _slices.modify(uniteFrom, [&](Slice &slice) {
  43. slice.merge(it->messages, it->range);
  44. });
  45. }
  46. _slices.erase(firstToErase, uniteTill);
  47. uniteFrom = _slices.begin() + uniteFromIndex;
  48. }
  49. update.messages = &uniteFrom->messages;
  50. update.range = uniteFrom->range;
  51. return uniteFrom->messages.size() - was;
  52. }
  53. template <typename Range>
  54. int MessagesList::addRangeItemsAndCountNew(
  55. MessagesSliceUpdate &update,
  56. const Range &messages,
  57. MessagesRange noSkipRange) {
  58. Expects(noSkipRange.from <= noSkipRange.till);
  59. auto uniteFrom = ranges::lower_bound(
  60. _slices,
  61. noSkipRange.from,
  62. std::less<>(),
  63. [](const Slice &slice) { return slice.range.till; });
  64. auto uniteTill = ranges::upper_bound(
  65. _slices,
  66. noSkipRange.till,
  67. std::less<>(),
  68. [](const Slice &slice) { return slice.range.from; });
  69. if (uniteFrom < uniteTill) {
  70. return uniteAndAdd(update, uniteFrom, uniteTill, messages, noSkipRange);
  71. }
  72. auto sliceMessages = base::flat_set<MessagePosition> {
  73. std::begin(messages),
  74. std::end(messages) };
  75. auto slice = _slices.emplace(
  76. std::move(sliceMessages),
  77. noSkipRange
  78. ).first;
  79. update.messages = &slice->messages;
  80. update.range = slice->range;
  81. return slice->messages.size();
  82. }
  83. template <typename Range>
  84. void MessagesList::addRange(
  85. const Range &messages,
  86. MessagesRange noSkipRange,
  87. std::optional<int> count,
  88. bool incrementCount) {
  89. Expects(!count || !incrementCount);
  90. auto update = MessagesSliceUpdate();
  91. auto result = addRangeItemsAndCountNew(
  92. update,
  93. messages,
  94. noSkipRange);
  95. if (count) {
  96. _count = count;
  97. } else if (incrementCount && _count && result > 0) {
  98. *_count += result;
  99. }
  100. if (_slices.size() == 1) {
  101. if (_slices.front().range == FullMessagesRange) {
  102. _count = _slices.front().messages.size();
  103. }
  104. }
  105. update.count = _count;
  106. _sliceUpdated.fire(std::move(update));
  107. }
  108. void MessagesList::addOne(MessagePosition messageId) {
  109. auto range = { messageId };
  110. addRange(range, { messageId, messageId }, std::nullopt, true);
  111. }
  112. void MessagesList::addNew(MessagePosition messageId) {
  113. auto range = { messageId };
  114. addRange(range, { messageId, MaxMessagePosition }, std::nullopt, true);
  115. }
  116. void MessagesList::addSlice(
  117. std::vector<MessagePosition> &&messageIds,
  118. MessagesRange noSkipRange,
  119. std::optional<int> count) {
  120. addRange(messageIds, noSkipRange, count);
  121. }
  122. void MessagesList::removeOne(MessagePosition messageId) {
  123. auto update = MessagesSliceUpdate();
  124. auto slice = ranges::lower_bound(
  125. _slices,
  126. messageId,
  127. std::less<>(),
  128. [](const Slice &slice) { return slice.range.till; });
  129. if (slice != _slices.end() && slice->range.from <= messageId) {
  130. _slices.modify(slice, [&](Slice &slice) {
  131. return slice.messages.remove(messageId);
  132. });
  133. update.messages = &slice->messages;
  134. update.range = slice->range;
  135. }
  136. if (_count) {
  137. --*_count;
  138. }
  139. update.count = _count;
  140. if (update.messages) {
  141. _sliceUpdated.fire(std::move(update));
  142. }
  143. }
  144. void MessagesList::removeLessThan(MessagePosition messageId) {
  145. auto removed = 0;
  146. for (auto i = begin(_slices); i != end(_slices);) {
  147. if (i->range.till <= messageId) {
  148. removed += i->messages.size();
  149. i = _slices.erase(i);
  150. continue;
  151. } else if (i->range.from <= messageId) {
  152. _slices.modify(i, [&](Slice &slice) {
  153. slice.range.from = MinMessagePosition;
  154. auto from = begin(slice.messages);
  155. auto till = ranges::lower_bound(slice.messages, messageId);
  156. if (from != till) {
  157. removed += till - from;
  158. slice.messages.erase(from, till);
  159. }
  160. });
  161. break;
  162. } else {
  163. break;
  164. }
  165. }
  166. if (removed && _count) {
  167. *_count -= removed;
  168. }
  169. }
  170. void MessagesList::invalidate() {
  171. _slices.clear();
  172. _count = std::nullopt;
  173. }
  174. void MessagesList::invalidateBottom() {
  175. if (!_slices.empty()) {
  176. const auto &last = _slices.back();
  177. if (last.range.till == MaxMessagePosition) {
  178. _slices.modify(_slices.end() - 1, [](Slice &slice) {
  179. slice.range.till = slice.messages.empty()
  180. ? slice.range.from
  181. : slice.messages.back();
  182. });
  183. }
  184. }
  185. _count = std::nullopt;
  186. }
  187. MessagesResult MessagesList::queryCurrent(const MessagesQuery &query) const {
  188. if (!query.aroundId) {
  189. return MessagesResult();
  190. }
  191. const auto slice = ranges::lower_bound(
  192. _slices,
  193. query.aroundId,
  194. std::less<>(),
  195. [](const Slice &slice) { return slice.range.till; });
  196. return (slice != _slices.end() && slice->range.from <= query.aroundId)
  197. ? queryFromSlice(query, *slice)
  198. : MessagesResult();
  199. }
  200. rpl::producer<MessagesResult> MessagesList::query(
  201. MessagesQuery &&query) const {
  202. return [this, query = std::move(query)](auto consumer) {
  203. auto current = queryCurrent(query);
  204. if (current.count.has_value() || !current.messageIds.empty()) {
  205. consumer.put_next(std::move(current));
  206. }
  207. consumer.put_done();
  208. return rpl::lifetime();
  209. };
  210. }
  211. rpl::producer<MessagesSliceUpdate> MessagesList::sliceUpdated() const {
  212. return _sliceUpdated.events();
  213. }
  214. MessagesResult MessagesList::snapshot(MessagesQuery &&query) const {
  215. return queryCurrent(query);
  216. }
  217. bool MessagesList::empty() const {
  218. for (const auto &slice : _slices) {
  219. if (!slice.messages.empty()) {
  220. return false;
  221. }
  222. }
  223. return true;
  224. }
  225. rpl::producer<MessagesResult> MessagesList::viewer(
  226. MessagesQuery &&query) const {
  227. return rpl::single(
  228. queryCurrent(query)
  229. ) | rpl::then(sliceUpdated() | rpl::map([=] {
  230. return queryCurrent(query);
  231. })) | rpl::filter([=](const MessagesResult &value) {
  232. return value.count.has_value() || !value.messageIds.empty();
  233. });
  234. }
  235. MessagesResult MessagesList::queryFromSlice(
  236. const MessagesQuery &query,
  237. const Slice &slice) const {
  238. auto result = MessagesResult {};
  239. auto position = ranges::lower_bound(slice.messages, query.aroundId);
  240. auto haveBefore = int(position - begin(slice.messages));
  241. auto haveEqualOrAfter = int(end(slice.messages) - position);
  242. auto before = qMin(haveBefore, query.limitBefore);
  243. auto equalOrAfter = qMin(haveEqualOrAfter, query.limitAfter + 1);
  244. auto ids = std::vector<MessagePosition>(position - before, position + equalOrAfter);
  245. result.messageIds.merge(ids.begin(), ids.end());
  246. if (slice.range.from == MinMessagePosition) {
  247. result.skippedBefore = haveBefore - before;
  248. }
  249. if (slice.range.till == MaxMessagePosition) {
  250. result.skippedAfter = haveEqualOrAfter - equalOrAfter;
  251. }
  252. if (_count) {
  253. result.count = _count;
  254. if (!result.skippedBefore && result.skippedAfter) {
  255. result.skippedBefore = *result.count
  256. - *result.skippedAfter
  257. - int(result.messageIds.size());
  258. } else if (!result.skippedAfter && result.skippedBefore) {
  259. result.skippedAfter = *result.count
  260. - *result.skippedBefore
  261. - int(result.messageIds.size());
  262. }
  263. }
  264. return result;
  265. }
  266. MessagesSliceBuilder::MessagesSliceBuilder(
  267. Key key,
  268. int limitBefore,
  269. int limitAfter)
  270. : _key(key)
  271. , _limitBefore(limitBefore)
  272. , _limitAfter(limitAfter) {
  273. }
  274. bool MessagesSliceBuilder::applyInitial(const MessagesResult &result) {
  275. mergeSliceData(
  276. result.count,
  277. result.messageIds,
  278. result.skippedBefore,
  279. result.skippedAfter);
  280. return true;
  281. }
  282. bool MessagesSliceBuilder::applyUpdate(const MessagesSliceUpdate &update) {
  283. auto intersects = [](MessagesRange range1, MessagesRange range2) {
  284. return (range1.from <= range2.till)
  285. && (range2.from <= range1.till);
  286. };
  287. auto needMergeMessages = (update.messages != nullptr)
  288. && intersects(update.range, {
  289. _ids.empty() ? _key : _ids.front(),
  290. _ids.empty() ? _key : _ids.back()
  291. });
  292. if (!needMergeMessages && !update.count) {
  293. return false;
  294. }
  295. auto skippedBefore = (update.range.from == MinMessagePosition)
  296. ? 0
  297. : std::optional<int> {};
  298. auto skippedAfter = (update.range.till == MaxMessagePosition)
  299. ? 0
  300. : std::optional<int> {};
  301. mergeSliceData(
  302. update.count,
  303. needMergeMessages
  304. ? *update.messages
  305. : base::flat_set<MessagePosition> {},
  306. skippedBefore,
  307. skippedAfter);
  308. return true;
  309. }
  310. bool MessagesSliceBuilder::removeOne(MessagePosition messageId) {
  311. auto changed = false;
  312. if (_fullCount && *_fullCount > 0) {
  313. --*_fullCount;
  314. changed = true;
  315. }
  316. if (_ids.contains(messageId)) {
  317. _ids.remove(messageId);
  318. changed = true;
  319. } else if (!_ids.empty()) {
  320. if (_ids.front() > messageId
  321. && _skippedBefore
  322. && *_skippedBefore > 0) {
  323. --*_skippedBefore;
  324. changed = true;
  325. } else if (_ids.back() < messageId
  326. && _skippedAfter
  327. && *_skippedAfter > 0) {
  328. --*_skippedAfter;
  329. changed = true;
  330. }
  331. }
  332. return changed;
  333. }
  334. bool MessagesSliceBuilder::removeAll() {
  335. _ids = {};
  336. _range = FullMessagesRange;
  337. _fullCount = 0;
  338. _skippedBefore = 0;
  339. _skippedAfter = 0;
  340. return true;
  341. }
  342. bool MessagesSliceBuilder::invalidated() {
  343. _fullCount = _skippedBefore = _skippedAfter = std::nullopt;
  344. _ids.clear();
  345. checkInsufficient();
  346. return false;
  347. }
  348. bool MessagesSliceBuilder::bottomInvalidated() {
  349. _fullCount = _skippedAfter = std::nullopt;
  350. checkInsufficient();
  351. return true;
  352. }
  353. void MessagesSliceBuilder::checkInsufficient() {
  354. sliceToLimits();
  355. }
  356. void MessagesSliceBuilder::mergeSliceData(
  357. std::optional<int> count,
  358. const base::flat_set<MessagePosition> &messageIds,
  359. std::optional<int> skippedBefore,
  360. std::optional<int> skippedAfter) {
  361. if (messageIds.empty()) {
  362. if (count && _fullCount != count) {
  363. _fullCount = count;
  364. if (*_fullCount <= _ids.size()) {
  365. _fullCount = _ids.size();
  366. _skippedBefore = _skippedAfter = 0;
  367. }
  368. }
  369. fillSkippedAndSliceToLimits();
  370. return;
  371. }
  372. if (count) {
  373. _fullCount = count;
  374. }
  375. const auto impossible = MessagePosition{ .fullId = {}, .date = -1 };
  376. auto wasMinId = _ids.empty() ? impossible : _ids.front();
  377. auto wasMaxId = _ids.empty() ? impossible : _ids.back();
  378. _ids.merge(messageIds.begin(), messageIds.end());
  379. auto adjustSkippedBefore = [&](MessagePosition oldId, int oldSkippedBefore) {
  380. auto it = _ids.find(oldId);
  381. Assert(it != _ids.end());
  382. _skippedBefore = oldSkippedBefore - (it - _ids.begin());
  383. accumulate_max(*_skippedBefore, 0);
  384. };
  385. if (skippedBefore) {
  386. adjustSkippedBefore(messageIds.front(), *skippedBefore);
  387. } else if (wasMinId != impossible && _skippedBefore) {
  388. adjustSkippedBefore(wasMinId, *_skippedBefore);
  389. } else {
  390. _skippedBefore = std::nullopt;
  391. }
  392. auto adjustSkippedAfter = [&](MessagePosition oldId, int oldSkippedAfter) {
  393. auto it = _ids.find(oldId);
  394. Assert(it != _ids.end());
  395. _skippedAfter = oldSkippedAfter - (_ids.end() - it - 1);
  396. accumulate_max(*_skippedAfter, 0);
  397. };
  398. if (skippedAfter) {
  399. adjustSkippedAfter(messageIds.back(), *skippedAfter);
  400. } else if (wasMaxId != impossible && _skippedAfter) {
  401. adjustSkippedAfter(wasMaxId, *_skippedAfter);
  402. } else {
  403. _skippedAfter = std::nullopt;
  404. }
  405. fillSkippedAndSliceToLimits();
  406. }
  407. void MessagesSliceBuilder::fillSkippedAndSliceToLimits() {
  408. if (_fullCount) {
  409. if (_skippedBefore && !_skippedAfter) {
  410. _skippedAfter = *_fullCount
  411. - *_skippedBefore
  412. - int(_ids.size());
  413. } else if (_skippedAfter && !_skippedBefore) {
  414. _skippedBefore = *_fullCount
  415. - *_skippedAfter
  416. - int(_ids.size());
  417. }
  418. }
  419. sliceToLimits();
  420. }
  421. void MessagesSliceBuilder::sliceToLimits() {
  422. if (!_key) {
  423. if (!_fullCount) {
  424. requestMessagesCount();
  425. }
  426. return;
  427. }
  428. auto requestedSomething = false;
  429. auto aroundIt = ranges::lower_bound(_ids, _key);
  430. auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
  431. auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
  432. if (removeFromBegin > 0) {
  433. _ids.erase(_ids.begin(), _ids.begin() + removeFromBegin);
  434. if (_skippedBefore) {
  435. *_skippedBefore += removeFromBegin;
  436. }
  437. } else if (removeFromBegin < 0
  438. && (!_skippedBefore || *_skippedBefore > 0)) {
  439. requestedSomething = true;
  440. requestMessages(RequestDirection::Before);
  441. }
  442. if (removeFromEnd > 0) {
  443. _ids.erase(_ids.end() - removeFromEnd, _ids.end());
  444. if (_skippedAfter) {
  445. *_skippedAfter += removeFromEnd;
  446. }
  447. } else if (removeFromEnd < 0
  448. && (!_skippedAfter || *_skippedAfter > 0)) {
  449. requestedSomething = true;
  450. requestMessages(RequestDirection::After);
  451. }
  452. if (!_fullCount && !requestedSomething) {
  453. requestMessagesCount();
  454. }
  455. }
  456. void MessagesSliceBuilder::requestMessages(RequestDirection direction) {
  457. auto requestAroundData = [&]() -> AroundData {
  458. if (_ids.empty()) {
  459. return { _key, Data::LoadDirection::Around };
  460. } else if (direction == RequestDirection::Before) {
  461. return { _ids.front(), Data::LoadDirection::Before };
  462. }
  463. return { _ids.back(), Data::LoadDirection::After };
  464. };
  465. _insufficientAround.fire(requestAroundData());
  466. }
  467. void MessagesSliceBuilder::requestMessagesCount() {
  468. _insufficientAround.fire({
  469. MessagePosition(),
  470. Data::LoadDirection::Around });
  471. }
  472. MessagesSlice MessagesSliceBuilder::snapshot() const {
  473. auto result = MessagesSlice();
  474. result.ids.reserve(_ids.size());
  475. auto nearestToAround = std::optional<FullMsgId>();
  476. for (const auto &position : _ids) {
  477. result.ids.push_back(position.fullId);
  478. if (!nearestToAround && position >= _key) {
  479. nearestToAround = position.fullId;
  480. }
  481. }
  482. result.nearestToAround = nearestToAround.value_or(
  483. _ids.empty() ? FullMsgId() : _ids.back().fullId);
  484. result.skippedBefore = _skippedBefore;
  485. result.skippedAfter = _skippedAfter;
  486. result.fullCount = _fullCount;
  487. return result;
  488. }
  489. } // namespace Data