storage_shared_media.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "storage/storage_shared_media.h"
  8. #include <rpl/map.h>
  9. namespace Storage {
  10. auto SharedMedia::enforceLists(Key key)
  11. -> std::map<Key, SharedMedia::Lists>::iterator {
  12. auto result = _lists.find(key);
  13. if (result != _lists.end()) {
  14. return result;
  15. }
  16. result = _lists.emplace(key, Lists {}).first;
  17. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  18. auto &list = result->second[index];
  19. auto type = static_cast<SharedMediaType>(index);
  20. list.sliceUpdated(
  21. ) | rpl::map([=](const SparseIdsSliceUpdate &update) {
  22. return SharedMediaSliceUpdate(
  23. key.peerId,
  24. key.topicRootId,
  25. type,
  26. update);
  27. }) | rpl::start_to_stream(_sliceUpdated, _lifetime);
  28. }
  29. return result;
  30. }
  31. void SharedMedia::add(SharedMediaAddNew &&query) {
  32. const auto addByIt = [&](const auto i) {
  33. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  34. auto type = static_cast<SharedMediaType>(index);
  35. if (query.types.test(type)) {
  36. i->second[index].addNew(query.messageId);
  37. }
  38. }
  39. };
  40. addByIt(enforceLists({ query.peerId, MsgId(0) }));
  41. const auto topicIt = query.topicRootId
  42. ? _lists.find({ query.peerId, query.topicRootId })
  43. : end(_lists);
  44. if (topicIt != end(_lists)) {
  45. addByIt(topicIt);
  46. }
  47. }
  48. void SharedMedia::add(SharedMediaAddExisting &&query) {
  49. auto peerIt = enforceLists({ query.peerId, query.topicRootId });
  50. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  51. auto type = static_cast<SharedMediaType>(index);
  52. if (query.types.test(type)) {
  53. peerIt->second[index].addExisting(
  54. query.messageId,
  55. query.noSkipRange);
  56. }
  57. }
  58. }
  59. void SharedMedia::add(SharedMediaAddSlice &&query) {
  60. Expects(IsValidSharedMediaType(query.type));
  61. auto peerIt = enforceLists({ query.peerId, query.topicRootId });
  62. auto index = static_cast<int>(query.type);
  63. peerIt->second[index].addSlice(
  64. std::move(query.messageIds),
  65. query.noSkipRange,
  66. query.count);
  67. }
  68. void SharedMedia::remove(SharedMediaRemoveOne &&query) {
  69. auto peerIt = _lists.lower_bound({ query.peerId, MsgId(0) });
  70. while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
  71. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  72. auto type = static_cast<SharedMediaType>(index);
  73. if (query.types.test(type)) {
  74. peerIt->second[index].removeOne(query.messageId);
  75. }
  76. }
  77. ++peerIt;
  78. }
  79. _oneRemoved.fire(std::move(query));
  80. }
  81. void SharedMedia::remove(SharedMediaRemoveAll &&query) {
  82. auto peerIt = _lists.lower_bound({ query.peerId, query.topicRootId });
  83. while (peerIt != end(_lists)
  84. && peerIt->first.peerId == query.peerId
  85. && (!query.topicRootId
  86. || peerIt->first.topicRootId == query.topicRootId)) {
  87. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  88. auto type = static_cast<SharedMediaType>(index);
  89. if (query.types.test(type)) {
  90. peerIt->second[index].removeAll();
  91. }
  92. }
  93. ++peerIt;
  94. }
  95. _allRemoved.fire(std::move(query));
  96. }
  97. void SharedMedia::invalidate(SharedMediaInvalidateBottom &&query) {
  98. auto peerIt = _lists.lower_bound({ query.peerId, MsgId(0) });
  99. while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
  100. for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
  101. peerIt->second[index].invalidateBottom();
  102. }
  103. ++peerIt;
  104. }
  105. _bottomInvalidated.fire(std::move(query));
  106. }
  107. void SharedMedia::unload(SharedMediaUnloadThread &&query) {
  108. _lists.erase({ query.peerId, query.topicRootId });
  109. }
  110. rpl::producer<SharedMediaResult> SharedMedia::query(SharedMediaQuery &&query) const {
  111. Expects(IsValidSharedMediaType(query.key.type));
  112. auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId });
  113. if (peerIt != _lists.end()) {
  114. auto index = static_cast<int>(query.key.type);
  115. return peerIt->second[index].query(SparseIdsListQuery(
  116. query.key.messageId,
  117. query.limitBefore,
  118. query.limitAfter));
  119. }
  120. return [](auto consumer) {
  121. consumer.put_done();
  122. return rpl::lifetime();
  123. };
  124. }
  125. SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const {
  126. Expects(IsValidSharedMediaType(query.key.type));
  127. auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId });
  128. if (peerIt != _lists.end()) {
  129. auto index = static_cast<int>(query.key.type);
  130. return peerIt->second[index].snapshot(SparseIdsListQuery(
  131. query.key.messageId,
  132. query.limitBefore,
  133. query.limitAfter));
  134. }
  135. return {};
  136. }
  137. bool SharedMedia::empty(const SharedMediaKey &key) const {
  138. Expects(IsValidSharedMediaType(key.type));
  139. auto peerIt = _lists.find({ key.peerId, key.topicRootId });
  140. if (peerIt != _lists.end()) {
  141. auto index = static_cast<int>(key.type);
  142. return peerIt->second[index].empty();
  143. }
  144. return true;
  145. }
  146. rpl::producer<SharedMediaSliceUpdate> SharedMedia::sliceUpdated() const {
  147. return _sliceUpdated.events();
  148. }
  149. rpl::producer<SharedMediaRemoveOne> SharedMedia::oneRemoved() const {
  150. return _oneRemoved.events();
  151. }
  152. rpl::producer<SharedMediaRemoveAll> SharedMedia::allRemoved() const {
  153. return _allRemoved.events();
  154. }
  155. rpl::producer<SharedMediaInvalidateBottom> SharedMedia::bottomInvalidated() const {
  156. return _bottomInvalidated.events();
  157. }
  158. } // namespace Storage