2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Cache topPeers locally.

This commit is contained in:
John Preston
2024-04-11 17:46:19 +04:00
parent c11f4efc5c
commit 4cdd939028
9 changed files with 280 additions and 14 deletions

View File

@@ -9,6 +9,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Serialize {
ByteArrayWriter::ByteArrayWriter(int expectedSize)
: _stream(&_result, QIODevice::WriteOnly) {
if (expectedSize) {
_result.reserve(expectedSize);
}
_stream.setVersion(QDataStream::Qt_5_1);
}
QByteArray ByteArrayWriter::result() && {
_stream.device()->close();
return std::move(_result);
}
ByteArrayReader::ByteArrayReader(QByteArray data)
: _data(std::move(data))
, _stream(&_data, QIODevice::ReadOnly) {
_stream.setVersion(QDataStream::Qt_5_1);
}
void writeColor(QDataStream &stream, const QColor &color) {
stream << (quint32(uchar(color.red()))
| (quint32(uchar(color.green())) << 8)

View File

@@ -14,6 +14,70 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Serialize {
class ByteArrayWriter final {
public:
explicit ByteArrayWriter(int expectedSize = 0);
[[nodiscard]] QDataStream &underlying() {
return _stream;
}
[[nodiscard]] operator QDataStream &() {
return _stream;
}
[[nodiscard]] QByteArray result() &&;
private:
QByteArray _result;
QDataStream _stream;
};
template <typename T>
inline ByteArrayWriter &operator<<(ByteArrayWriter &stream, const T &data) {
stream.underlying() << data;
return stream;
}
class ByteArrayReader final {
public:
explicit ByteArrayReader(QByteArray data);
[[nodiscard]] QDataStream &underlying() {
return _stream;
}
[[nodiscard]] operator QDataStream &() {
return _stream;
}
[[nodiscard]] bool atEnd() const {
return _stream.atEnd();
}
[[nodiscard]] bool status() const {
return _stream.status();
}
[[nodiscard]] bool ok() const {
return _stream.status() == QDataStream::Ok;
}
private:
QByteArray _data;
QDataStream _stream;
};
template <typename T>
inline ByteArrayReader &operator>>(ByteArrayReader &stream, T &data) {
if (!stream.ok()) {
data = T();
} else {
stream.underlying() >> data;
if (!stream.ok()) {
data = T();
}
}
return stream;
}
inline int stringSize(const QString &str) {
return sizeof(quint32) + str.size() * sizeof(ushort);
}

View File

@@ -118,12 +118,16 @@ uint32 peerSize(not_null<PeerData*> peer) {
+ imageLocationSize(peer->userpicLocation())
+ sizeof(qint32); // userpic has video
if (const auto user = peer->asUser()) {
const auto botInlinePlaceholder = user->isBot()
? user->botInfo->inlinePlaceholder
: QString();
result += stringSize(user->firstName)
+ stringSize(user->lastName)
+ stringSize(user->phone())
+ stringSize(user->username())
+ sizeof(quint64) // access
+ sizeof(qint32) // flags
+ stringSize(botInlinePlaceholder)
+ sizeof(quint32) // lastseen
+ sizeof(qint32) // contact
+ sizeof(qint32); // botInfoVersion

View File

@@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "core/file_location.h"
#include "data/components/top_peers.h"
#include "data/stickers/data_stickers.h"
#include "data/data_session.h"
#include "data/data_document.h"
@@ -42,6 +43,7 @@ using namespace details;
using Database = Cache::Database;
constexpr auto kDelayedWriteTimeout = crl::time(1000);
constexpr auto kWriteSearchSuggestionsDelay = 5 * crl::time(1000);
constexpr auto kStickersVersionTag = quint32(-1);
constexpr auto kStickersSerializeVersion = 4;
@@ -87,6 +89,7 @@ enum { // Local Storage Keys
lskSelfSerialized = 0x15, // serialized self
lskMasksKeys = 0x16, // no data
lskCustomEmojiKeys = 0x17, // no data
lskSearchSuggestions = 0x18, // no data
};
auto EmptyMessageDraftSources()
@@ -137,10 +140,13 @@ Account::Account(not_null<Main::Account*> owner, const QString &dataName)
, _cacheTotalTimeLimit(Database::Settings().totalTimeLimit)
, _cacheBigFileTotalTimeLimit(Database::Settings().totalTimeLimit)
, _writeMapTimer([=] { writeMap(); })
, _writeLocationsTimer([=] { writeLocations(); }) {
, _writeLocationsTimer([=] { writeLocations(); })
, _writeSearchSuggestionsTimer([=] { writeSearchSuggestions(); }) {
}
Account::~Account() {
Expects(!_writeSearchSuggestionsTimer.isActive());
if (_localKey && _mapChanged) {
writeMap();
}
@@ -209,6 +215,7 @@ base::flat_set<QString> Account::collectGoodNames() const {
_installedCustomEmojiKey,
_featuredCustomEmojiKey,
_archivedCustomEmojiKey,
_searchSuggestionsKey,
};
auto result = base::flat_set<QString>{
"map0",
@@ -294,6 +301,7 @@ Account::ReadMapResult Account::readMapWith(
quint64 savedGifsKey = 0;
quint64 legacyBackgroundKeyDay = 0, legacyBackgroundKeyNight = 0;
quint64 userSettingsKey = 0, recentHashtagsAndBotsKey = 0, exportSettingsKey = 0;
quint64 searchSuggestionsKey = 0;
while (!map.stream.atEnd()) {
quint32 keyType;
map.stream >> keyType;
@@ -399,6 +407,9 @@ Account::ReadMapResult Account::readMapWith(
>> featuredCustomEmojiKey
>> archivedCustomEmojiKey;
} break;
case lskSearchSuggestions: {
map.stream >> searchSuggestionsKey;
} break;
default:
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
return ReadMapResult::Failed;
@@ -434,6 +445,7 @@ Account::ReadMapResult Account::readMapWith(
_settingsKey = userSettingsKey;
_recentHashtagsAndBotsKey = recentHashtagsAndBotsKey;
_exportSettingsKey = exportSettingsKey;
_searchSuggestionsKey = searchSuggestionsKey;
_oldMapVersion = mapData.version;
if (_oldMapVersion < AppVersion) {
@@ -539,6 +551,7 @@ void Account::writeMap() {
if (_installedCustomEmojiKey || _featuredCustomEmojiKey || _archivedCustomEmojiKey) {
mapSize += sizeof(quint32) + 3 * sizeof(quint64);
}
if (_searchSuggestionsKey) mapSize += sizeof(quint32) + sizeof(quint64);
EncryptedDescriptor mapData(mapSize);
if (!self.isEmpty()) {
@@ -598,12 +611,18 @@ void Account::writeMap() {
<< quint64(_featuredCustomEmojiKey)
<< quint64(_archivedCustomEmojiKey);
}
if (_searchSuggestionsKey) {
mapData.stream << quint32(lskSearchSuggestions);
mapData.stream << quint64(_searchSuggestionsKey);
}
map.writeEncrypted(mapData, _localKey);
_mapChanged = false;
}
void Account::reset() {
_writeSearchSuggestionsTimer.cancel();
auto names = collectGoodNames();
_draftsMap.clear();
_draftCursorsMap.clear();
@@ -624,6 +643,7 @@ void Account::reset() {
_archivedCustomEmojiKey = 0;
_legacyBackgroundKeyDay = _legacyBackgroundKeyNight = 0;
_settingsKey = _recentHashtagsAndBotsKey = _exportSettingsKey = 0;
_searchSuggestionsKey = 0;
_oldMapVersion = 0;
_fileLocations.clear();
_fileLocationPairs.clear();
@@ -2842,6 +2862,73 @@ Export::Settings Account::readExportSettings() {
: Export::Settings();
}
void Account::writeSearchSuggestionsDelayed() {
Expects(_owner->sessionExists());
if (!_writeSearchSuggestionsTimer.isActive()) {
_writeSearchSuggestionsTimer.callOnce(kWriteSearchSuggestionsDelay);
}
}
void Account::writeSearchSuggestionsIfNeeded() {
if (_writeSearchSuggestionsTimer.isActive()) {
_writeSearchSuggestionsTimer.cancel();
writeSearchSuggestions();
}
}
void Account::writeSearchSuggestions() {
Expects(_owner->sessionExists());
const auto top = _owner->session().topPeers().serialize();
const auto recent = QByteArray();// _owner->session().recentPeers().serialize();
if (top.isEmpty() && recent.isEmpty()) {
if (_searchSuggestionsKey) {
ClearKey(_searchSuggestionsKey, _basePath);
_searchSuggestionsKey = 0;
writeMapDelayed();
}
return;
}
if (!_searchSuggestionsKey) {
_searchSuggestionsKey = GenerateKey(_basePath);
writeMapQueued();
}
quint32 size = Serialize::bytearraySize(top)
+ Serialize::bytearraySize(recent);
EncryptedDescriptor data(size);
data.stream << top << recent;
FileWriteDescriptor file(_searchSuggestionsKey, _basePath);
file.writeEncrypted(data, _localKey);
}
void Account::readSearchSuggestions() {
if (_searchSuggestionsRead) {
return;
}
_searchSuggestionsRead = true;
if (!_searchSuggestionsKey) {
return;
}
FileReadDescriptor suggestions;
if (!ReadEncryptedFile(suggestions, _searchSuggestionsKey, _basePath, _localKey)) {
ClearKey(_searchSuggestionsKey, _basePath);
_searchSuggestionsKey = 0;
writeMapDelayed();
return;
}
auto top = QByteArray();
auto recent = QByteArray();
suggestions.stream >> top >> recent;
if (CheckStreamStatus(suggestions.stream)) {
_owner->session().topPeers().applyLocal(top);
//_owner->session().recentPeers().applyLocal(recent);
}
}
void Account::writeSelf() {
writeMapDelayed();
}

View File

@@ -148,6 +148,11 @@ public:
void writeExportSettings(const Export::Settings &settings);
[[nodiscard]] Export::Settings readExportSettings();
void writeSearchSuggestionsDelayed();
void writeSearchSuggestionsIfNeeded();
void writeSearchSuggestions();
void readSearchSuggestions();
void writeSelf();
// Read self is special, it can't get session from account, because
@@ -291,6 +296,7 @@ private:
FileKey _installedCustomEmojiKey = 0;
FileKey _featuredCustomEmojiKey = 0;
FileKey _archivedCustomEmojiKey = 0;
FileKey _searchSuggestionsKey = 0;
qint64 _cacheTotalSizeLimit = 0;
qint64 _cacheBigFileTotalSizeLimit = 0;
@@ -301,11 +307,13 @@ private:
bool _trustedBotsRead = false;
bool _readingUserSettings = false;
bool _recentHashtagsAndBotsWereRead = false;
bool _searchSuggestionsRead = false;
int _oldMapVersion = 0;
base::Timer _writeMapTimer;
base::Timer _writeLocationsTimer;
base::Timer _writeSearchSuggestionsTimer;
bool _mapChanged = false;
bool _locationsChanged = false;