data_sparse_ids.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. #pragma once
  8. #include "data/data_abstract_sparse_ids.h"
  9. #include "data/data_messages.h"
  10. namespace Storage {
  11. struct SparseIdsListResult;
  12. struct SparseIdsSliceUpdate;
  13. } // namespace Storage
  14. class SparseIdsSlice final : public AbstractSparseIds<base::flat_set<MsgId>> {
  15. public:
  16. using Key = MsgId;
  17. using AbstractSparseIds<base::flat_set<MsgId>>::AbstractSparseIds;
  18. };
  19. using SparseUnsortedIdsSlice = AbstractSparseIds<std::vector<MsgId>>;
  20. class SparseIdsMergedSlice {
  21. public:
  22. using UniversalMsgId = MsgId;
  23. static constexpr MsgId kScheduledTopicId = ScheduledMaxMsgId;
  24. struct Key {
  25. Key(
  26. PeerId peerId,
  27. MsgId topicRootId,
  28. PeerId migratedPeerId,
  29. UniversalMsgId universalId)
  30. : peerId(peerId)
  31. , topicRootId(topicRootId)
  32. , migratedPeerId(topicRootId ? 0 : migratedPeerId)
  33. , universalId(universalId) {
  34. }
  35. friend inline constexpr bool operator==(
  36. const Key &,
  37. const Key &) = default;
  38. PeerId peerId = 0;
  39. MsgId topicRootId = 0;
  40. PeerId migratedPeerId = 0;
  41. UniversalMsgId universalId = 0;
  42. };
  43. SparseIdsMergedSlice(Key key);
  44. SparseIdsMergedSlice(
  45. Key key,
  46. SparseIdsSlice part,
  47. std::optional<SparseIdsSlice> migrated);
  48. SparseIdsMergedSlice(
  49. Key key,
  50. SparseUnsortedIdsSlice unsorted);
  51. std::optional<int> fullCount() const;
  52. std::optional<int> skippedBefore() const;
  53. std::optional<int> skippedAfter() const;
  54. std::optional<int> indexOf(FullMsgId fullId) const;
  55. int size() const;
  56. FullMsgId operator[](int index) const;
  57. std::optional<int> distance(const Key &a, const Key &b) const;
  58. std::optional<FullMsgId> nearest(UniversalMsgId id) const;
  59. using SimpleViewerFunction = rpl::producer<SparseIdsSlice>(
  60. PeerId peerId,
  61. MsgId topicRootId,
  62. SparseIdsSlice::Key simpleKey,
  63. int limitBefore,
  64. int limitAfter);
  65. static rpl::producer<SparseIdsMergedSlice> CreateViewer(
  66. SparseIdsMergedSlice::Key key,
  67. int limitBefore,
  68. int limitAfter,
  69. Fn<SimpleViewerFunction> simpleViewer);
  70. private:
  71. static SparseIdsSlice::Key PartKey(const Key &key) {
  72. return (key.universalId < 0) ? 1 : key.universalId;
  73. }
  74. static SparseIdsSlice::Key MigratedKey(const Key &key) {
  75. return (key.universalId < 0)
  76. ? (ServerMaxMsgId + key.universalId)
  77. : (key.universalId > 0) ? (ServerMaxMsgId - 1) : 0;
  78. }
  79. static std::optional<SparseIdsSlice> MigratedSlice(const Key &key) {
  80. return key.migratedPeerId
  81. ? base::make_optional(SparseIdsSlice())
  82. : std::nullopt;
  83. }
  84. static bool IsFromSlice(PeerId peerId, FullMsgId fullId) {
  85. return (peerId == fullId.peer);
  86. }
  87. static FullMsgId ComputeId(PeerId peerId, MsgId msgId) {
  88. return FullMsgId(peerId, msgId);
  89. }
  90. static FullMsgId ComputeId(const Key &key) {
  91. return (key.universalId >= 0)
  92. ? ComputeId(key.peerId, key.universalId)
  93. : ComputeId(key.migratedPeerId, ServerMaxMsgId + key.universalId);
  94. }
  95. static std::optional<int> Add(
  96. const std::optional<int> &a,
  97. const std::optional<int> &b) {
  98. return (a && b) ? base::make_optional(*a + *b) : std::nullopt;
  99. }
  100. bool isFromPart(FullMsgId fullId) const {
  101. return IsFromSlice(_key.peerId, fullId);
  102. }
  103. bool isFromMigrated(FullMsgId fullId) const {
  104. return _migrated
  105. ? IsFromSlice(_key.migratedPeerId, fullId)
  106. : false;
  107. }
  108. int migratedSize() const {
  109. return isolatedInPart() ? 0 : _migrated->size();
  110. }
  111. bool isolatedInPart() const {
  112. return IsServerMsgId(_key.universalId)
  113. && (!_migrated || _part.skippedBefore() != 0);
  114. }
  115. bool isolatedInMigrated() const {
  116. return IsServerMsgId(ServerMaxMsgId + _key.universalId)
  117. && (_migrated->skippedAfter() != 0);
  118. }
  119. Key _key;
  120. SparseIdsSlice _part;
  121. std::optional<SparseIdsSlice> _migrated;
  122. std::optional<SparseUnsortedIdsSlice> _unsorted;
  123. };
  124. class SparseIdsSliceBuilder {
  125. public:
  126. using Key = SparseIdsSlice::Key;
  127. SparseIdsSliceBuilder(Key key, int limitBefore, int limitAfter);
  128. bool applyInitial(const Storage::SparseIdsListResult &result);
  129. bool applyUpdate(const Storage::SparseIdsSliceUpdate &update);
  130. bool removeOne(MsgId messageId);
  131. bool removeAll();
  132. bool invalidateBottom();
  133. void checkInsufficient();
  134. struct AroundData {
  135. MsgId aroundId = 0;
  136. Data::LoadDirection direction = Data::LoadDirection::Around;
  137. inline bool operator<(const AroundData &other) const {
  138. return (aroundId < other.aroundId)
  139. || ((aroundId == other.aroundId)
  140. && (direction < other.direction));
  141. }
  142. };
  143. auto insufficientAround() const {
  144. return _insufficientAround.events();
  145. }
  146. SparseIdsSlice snapshot() const;
  147. private:
  148. enum class RequestDirection {
  149. Before,
  150. After,
  151. };
  152. void requestMessages(RequestDirection direction);
  153. void requestMessagesCount();
  154. void fillSkippedAndSliceToLimits();
  155. void sliceToLimits();
  156. void mergeSliceData(
  157. std::optional<int> count,
  158. const base::flat_set<MsgId> &messageIds,
  159. std::optional<int> skippedBefore = std::nullopt,
  160. std::optional<int> skippedAfter = std::nullopt);
  161. Key _key;
  162. base::flat_set<MsgId> _ids;
  163. std::optional<int> _fullCount;
  164. std::optional<int> _skippedBefore;
  165. std::optional<int> _skippedAfter;
  166. int _limitBefore = 0;
  167. int _limitAfter = 0;
  168. rpl::event_stream<AroundData> _insufficientAround;
  169. };