tdesktop/Telegram/SourceFiles/storage/cache/storage_cache_types.h

240 lines
5.1 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/basic_types.h"
#include "base/flat_map.h"
#include "base/optional.h"
#include <crl/crl_time.h>
#include <QtCore/QString>
#include <QtCore/QByteArray>
namespace Storage {
namespace Cache {
struct Key {
uint64 high = 0;
uint64 low = 0;
};
inline bool operator==(const Key &a, const Key &b) {
return (a.high == b.high) && (a.low == b.low);
}
inline bool operator!=(const Key &a, const Key &b) {
return !(a == b);
}
inline bool operator<(const Key &a, const Key &b) {
return std::tie(a.high, a.low) < std::tie(b.high, b.low);
}
struct Error {
enum class Type {
None,
IO,
WrongKey,
LockFailed,
};
Type type = Type::None;
QString path;
static Error NoError();
};
inline Error Error::NoError() {
return Error();
}
namespace details {
using RecordType = uint8;
using PlaceId = std::array<uint8, 7>;
using EntrySize = std::array<uint8, 3>;
using RecordsCount = std::array<uint8, 3>;
constexpr auto kRecordSizeUnknown = size_type(-1);
constexpr auto kRecordSizeInvalid = size_type(-2);
constexpr auto kBundledRecordsLimit
= size_type(1 << (RecordsCount().size() * 8));
constexpr auto kDataSizeLimit = size_type(1 << (EntrySize().size() * 8));
struct Settings {
size_type maxBundledRecords = 16 * 1024;
size_type readBlockSize = 8 * 1024 * 1024;
size_type maxDataSize = (kDataSizeLimit - 1);
crl::time writeBundleDelay = 15 * 60 * crl::time(1000);
size_type staleRemoveChunk = 256;
int64 compactAfterExcess = 8 * 1024 * 1024;
int64 compactAfterFullSize = 0;
size_type compactChunkSize = 16 * 1024;
bool trackEstimatedTime = true;
int64 totalSizeLimit = 1024 * 1024 * 1024;
size_type totalTimeLimit = 31 * 24 * 60 * 60; // One month in seconds.
crl::time pruneTimeout = 5 * crl::time(1000);
crl::time maxPruneCheckTimeout = 3600 * crl::time(1000);
bool clearOnWrongKey = false;
};
struct SettingsUpdate {
int64 totalSizeLimit = Settings().totalSizeLimit;
size_type totalTimeLimit = Settings().totalTimeLimit;
};
struct TaggedValue {
TaggedValue() = default;
TaggedValue(QByteArray &&bytes, uint8 tag);
QByteArray bytes;
uint8 tag = 0;
};
struct TaggedSummary {
size_type count = 0;
int64 totalSize = 0;
};
struct Stats {
TaggedSummary full;
base::flat_map<uint8, TaggedSummary> tagged;
bool clearing = false;
};
using Version = int32;
QString ComputeBasePath(const QString &original);
QString VersionFilePath(const QString &base);
std::optional<Version> ReadVersionValue(const QString &base);
bool WriteVersionValue(const QString &base, Version value);
template <typename Record>
constexpr auto GoodForEncryption = ((sizeof(Record) & 0x0F) == 0);
enum class Format : uint32 {
Format_0,
};
struct BasicHeader {
BasicHeader();
static constexpr auto kTrackEstimatedTime = 0x01U;
Format getFormat() const {
return static_cast<Format>(format);
}
void setFormat(Format format) {
this->format = static_cast<uint32>(format);
}
uint32 format : 8;
uint32 flags : 24;
uint32 systemTime = 0;
uint32 reserved1 = 0;
uint32 reserved2 = 0;
};
struct EstimatedTimePoint {
uint32 relative1 = 0;
uint32 relative2 = 0;
uint32 system = 0;
void setRelative(uint64 value) {
relative1 = uint32(value & 0xFFFFFFFFU);
relative2 = uint32((value >> 32) & 0xFFFFFFFFU);
}
uint64 getRelative() const {
return uint64(relative1) | (uint64(relative2) << 32);
}
};
struct Store {
static constexpr auto kType = RecordType(0x01);
void setSize(size_type size);
size_type getSize() const;
RecordType type = kType;
uint8 tag = 0;
EntrySize size = { { 0 } };
PlaceId place = { { 0 } };
uint32 checksum = 0;
Key key;
};
struct StoreWithTime : Store {
EstimatedTimePoint time;
uint32 reserved = 0;
};
struct MultiStore {
static constexpr auto kType = RecordType(0x02);
explicit MultiStore(size_type count = 0);
RecordType type = kType;
RecordsCount count = { { 0 } };
uint32 reserved1 = 0;
uint32 reserved2 = 0;
uint32 reserved3 = 0;
using Part = Store;
size_type validateCount() const;
};
struct MultiStoreWithTime : MultiStore {
using MultiStore::MultiStore;
using Part = StoreWithTime;
};
struct MultiRemove {
static constexpr auto kType = RecordType(0x03);
explicit MultiRemove(size_type count = 0);
RecordType type = kType;
RecordsCount count = { { 0 } };
uint32 reserved1 = 0;
uint32 reserved2 = 0;
uint32 reserved3 = 0;
using Part = Key;
size_type validateCount() const;
};
struct MultiAccess {
static constexpr auto kType = RecordType(0x04);
explicit MultiAccess(
EstimatedTimePoint time,
size_type count = 0);
RecordType type = kType;
RecordsCount count = { { 0 } };
EstimatedTimePoint time;
using Part = Key;
size_type validateCount() const;
};
} // namespace details
} // namespace Cache
} // namespace Storage
namespace std {
template <>
struct hash<Storage::Cache::Key> {
size_t operator()(const Storage::Cache::Key &key) const {
return (hash<uint64>()(key.high) ^ hash<uint64>()(key.low));
}
};
} // namespace std