triplo malloc su ogni cosa
This commit is contained in:
parent
094d0fc2b0
commit
a111cb1323
@ -5,289 +5,71 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
#include "td/telegram/DialogDb.h"
|
#include "td/telegram/DialogDb.h"
|
||||||
|
|
||||||
#include "td/telegram/Version.h"
|
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "td/actor/SchedulerLocalStorage.h"
|
#include "td/actor/SchedulerLocalStorage.h"
|
||||||
|
|
||||||
#include "td/db/SqliteConnectionSafe.h"
|
#include "td/db/SqliteConnectionSafe.h"
|
||||||
#include "td/db/SqliteDb.h"
|
#include "td/db/SqliteDb.h"
|
||||||
#include "td/db/SqliteKeyValue.h"
|
|
||||||
#include "td/db/SqliteStatement.h"
|
#include "td/db/SqliteStatement.h"
|
||||||
|
|
||||||
#include "td/utils/format.h"
|
|
||||||
#include "td/utils/logging.h"
|
|
||||||
#include "td/utils/ScopeGuard.h"
|
#include "td/utils/ScopeGuard.h"
|
||||||
#include "td/utils/Time.h"
|
#include "td/utils/Time.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
// NB: must happen inside a transaction
|
// NB: must happen inside a transaction
|
||||||
Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) {
|
Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) {
|
||||||
LOG(INFO) << "Init dialog database " << tag("version", version);
|
|
||||||
was_created = false;
|
|
||||||
|
|
||||||
// Check if database exists
|
|
||||||
TRY_RESULT(has_table, db.has_table("dialogs"));
|
|
||||||
if (!has_table) {
|
|
||||||
version = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version < static_cast<int32>(DbVersion::DialogDbCreated) || version > current_db_version()) {
|
|
||||||
TRY_STATUS(drop_dialog_db(db, version));
|
|
||||||
version = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto create_notification_group_table = [&db] {
|
|
||||||
return db.exec(
|
|
||||||
"CREATE TABLE IF NOT EXISTS notification_groups (notification_group_id INT4 PRIMARY KEY, dialog_id "
|
|
||||||
"INT8, last_notification_date INT4)");
|
|
||||||
};
|
|
||||||
|
|
||||||
auto create_last_notification_date_index = [&db] {
|
|
||||||
return db.exec(
|
|
||||||
"CREATE INDEX IF NOT EXISTS notification_group_by_last_notification_date ON notification_groups "
|
|
||||||
"(last_notification_date, dialog_id, notification_group_id) WHERE last_notification_date IS NOT NULL");
|
|
||||||
};
|
|
||||||
|
|
||||||
auto add_dialogs_in_folder_index = [&db] {
|
|
||||||
return db.exec(
|
|
||||||
"CREATE INDEX IF NOT EXISTS dialog_in_folder_by_dialog_order ON dialogs (folder_id, dialog_order, dialog_id) "
|
|
||||||
"WHERE folder_id IS NOT NULL");
|
|
||||||
};
|
|
||||||
|
|
||||||
if (version == 0) {
|
|
||||||
LOG(INFO) << "Create new dialog database";
|
|
||||||
was_created = true;
|
|
||||||
TRY_STATUS(
|
|
||||||
db.exec("CREATE TABLE IF NOT EXISTS dialogs (dialog_id INT8 PRIMARY KEY, dialog_order INT8, data BLOB, "
|
|
||||||
"folder_id INT4)"));
|
|
||||||
TRY_STATUS(create_notification_group_table());
|
|
||||||
TRY_STATUS(create_last_notification_date_index());
|
|
||||||
TRY_STATUS(add_dialogs_in_folder_index());
|
|
||||||
version = current_db_version();
|
|
||||||
}
|
|
||||||
if (version < static_cast<int32>(DbVersion::AddNotificationsSupport)) {
|
|
||||||
TRY_STATUS(create_notification_group_table());
|
|
||||||
TRY_STATUS(create_last_notification_date_index());
|
|
||||||
}
|
|
||||||
if (version < static_cast<int32>(DbVersion::AddFolders)) {
|
|
||||||
TRY_STATUS(db.exec("DROP INDEX IF EXISTS dialog_by_dialog_order"));
|
|
||||||
TRY_STATUS(db.exec("ALTER TABLE dialogs ADD COLUMN folder_id INT4"));
|
|
||||||
TRY_STATUS(add_dialogs_in_folder_index());
|
|
||||||
TRY_STATUS(db.exec("UPDATE dialogs SET folder_id = 0 WHERE dialog_id < -1500000000000 AND dialog_order > 0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: must happen inside a transaction
|
// NB: must happen inside a transaction
|
||||||
Status drop_dialog_db(SqliteDb &db, int version) {
|
Status drop_dialog_db(SqliteDb &db, int version) {
|
||||||
if (version < static_cast<int32>(DbVersion::DialogDbCreated)) {
|
return Status::OK();
|
||||||
LOG(WARNING) << "Drop old pmc dialog_db";
|
|
||||||
SqliteKeyValue kv;
|
|
||||||
kv.init_with_connection(db.clone(), "common").ensure();
|
|
||||||
kv.erase_by_prefix("di");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(WARNING) << "Drop dialog_db " << tag("version", version) << tag("current_db_version", current_db_version());
|
|
||||||
auto status = db.exec("DROP TABLE IF EXISTS dialogs");
|
|
||||||
TRY_STATUS(db.exec("DROP TABLE IF EXISTS notification_groups"));
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DialogDbImpl : public DialogDbSyncInterface {
|
class DialogDbImpl : public DialogDbSyncInterface {
|
||||||
public:
|
public:
|
||||||
explicit DialogDbImpl(SqliteDb db) : db_(std::move(db)) {
|
explicit DialogDbImpl(SqliteDb db) {
|
||||||
init().ensure();
|
init().ensure();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status init() {
|
Status init() {
|
||||||
TRY_RESULT_ASSIGN(add_dialog_stmt_, db_.get_statement("INSERT OR REPLACE INTO dialogs VALUES(?1, ?2, ?3, ?4)"));
|
|
||||||
TRY_RESULT_ASSIGN(add_notification_group_stmt_,
|
|
||||||
db_.get_statement("INSERT OR REPLACE INTO notification_groups VALUES(?1, ?2, ?3)"));
|
|
||||||
TRY_RESULT_ASSIGN(delete_notification_group_stmt_,
|
|
||||||
db_.get_statement("DELETE FROM notification_groups WHERE notification_group_id = ?1"));
|
|
||||||
TRY_RESULT_ASSIGN(get_dialog_stmt_, db_.get_statement("SELECT data FROM dialogs WHERE dialog_id = ?1"));
|
|
||||||
TRY_RESULT_ASSIGN(
|
|
||||||
get_dialogs_stmt_,
|
|
||||||
db_.get_statement("SELECT data, dialog_id, dialog_order FROM dialogs WHERE "
|
|
||||||
"folder_id == ?1 AND (dialog_order < ?2 OR (dialog_order = ?2 AND dialog_id < ?3)) ORDER "
|
|
||||||
"BY dialog_order DESC, dialog_id DESC LIMIT ?4"));
|
|
||||||
TRY_RESULT_ASSIGN(
|
|
||||||
get_notification_groups_by_last_notification_date_stmt_,
|
|
||||||
db_.get_statement("SELECT notification_group_id, dialog_id, last_notification_date FROM notification_groups "
|
|
||||||
"WHERE last_notification_date < ?1 OR (last_notification_date = ?1 "
|
|
||||||
"AND (dialog_id < ?2 OR (dialog_id = ?2 AND notification_group_id < ?3))) ORDER BY "
|
|
||||||
"last_notification_date DESC, dialog_id DESC LIMIT ?4"));
|
|
||||||
// "WHERE (last_notification_date, dialog_id, notification_group_id) < (?1, ?2, ?3) ORDER BY "
|
|
||||||
// "last_notification_date DESC, dialog_id DESC, notification_group_id DESC LIMIT ?4"));
|
|
||||||
TRY_RESULT_ASSIGN(
|
|
||||||
get_notification_group_stmt_,
|
|
||||||
db_.get_statement(
|
|
||||||
"SELECT dialog_id, last_notification_date FROM notification_groups WHERE notification_group_id = ?1"));
|
|
||||||
TRY_RESULT_ASSIGN(
|
|
||||||
get_secret_chat_count_stmt_,
|
|
||||||
db_.get_statement(
|
|
||||||
"SELECT COUNT(*) FROM dialogs WHERE folder_id = ?1 AND dialog_order > 0 AND dialog_id < -1500000000000"));
|
|
||||||
|
|
||||||
// LOG(ERROR) << get_dialog_stmt_.explain().ok();
|
|
||||||
// LOG(ERROR) << get_dialogs_stmt_.explain().ok();
|
|
||||||
// LOG(ERROR) << get_notification_groups_by_last_notification_date_stmt_.explain().ok();
|
|
||||||
// LOG(ERROR) << get_notification_group_stmt_.explain().ok();
|
|
||||||
// LOG(FATAL) << "EXPLAINED";
|
|
||||||
|
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status add_dialog(DialogId dialog_id, FolderId folder_id, int64 order, BufferSlice data,
|
Status add_dialog(DialogId dialog_id, FolderId folder_id, int64 order, BufferSlice data,
|
||||||
vector<NotificationGroupKey> notification_groups) override {
|
vector<NotificationGroupKey> notification_groups) override {
|
||||||
SCOPE_EXIT {
|
|
||||||
add_dialog_stmt_.reset();
|
|
||||||
};
|
|
||||||
add_dialog_stmt_.bind_int64(1, dialog_id.get()).ensure();
|
|
||||||
add_dialog_stmt_.bind_int64(2, order).ensure();
|
|
||||||
add_dialog_stmt_.bind_blob(3, data.as_slice()).ensure();
|
|
||||||
if (order > 0) {
|
|
||||||
add_dialog_stmt_.bind_int32(4, folder_id.get()).ensure();
|
|
||||||
} else {
|
|
||||||
add_dialog_stmt_.bind_null(4).ensure();
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY_STATUS(add_dialog_stmt_.step());
|
|
||||||
|
|
||||||
for (auto &to_add : notification_groups) {
|
|
||||||
if (to_add.dialog_id.is_valid()) {
|
|
||||||
SCOPE_EXIT {
|
|
||||||
add_notification_group_stmt_.reset();
|
|
||||||
};
|
|
||||||
add_notification_group_stmt_.bind_int32(1, to_add.group_id.get()).ensure();
|
|
||||||
add_notification_group_stmt_.bind_int64(2, to_add.dialog_id.get()).ensure();
|
|
||||||
if (to_add.last_notification_date != 0) {
|
|
||||||
add_notification_group_stmt_.bind_int32(3, to_add.last_notification_date).ensure();
|
|
||||||
} else {
|
|
||||||
add_notification_group_stmt_.bind_null(3).ensure();
|
|
||||||
}
|
|
||||||
TRY_STATUS(add_notification_group_stmt_.step());
|
|
||||||
} else {
|
|
||||||
SCOPE_EXIT {
|
|
||||||
delete_notification_group_stmt_.reset();
|
|
||||||
};
|
|
||||||
delete_notification_group_stmt_.bind_int32(1, to_add.group_id.get()).ensure();
|
|
||||||
TRY_STATUS(delete_notification_group_stmt_.step());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<BufferSlice> get_dialog(DialogId dialog_id) override {
|
Result<BufferSlice> get_dialog(DialogId dialog_id) override {
|
||||||
SCOPE_EXIT {
|
return Status::Error("Not found");
|
||||||
get_dialog_stmt_.reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
get_dialog_stmt_.bind_int64(1, dialog_id.get()).ensure();
|
|
||||||
TRY_STATUS(get_dialog_stmt_.step());
|
|
||||||
if (!get_dialog_stmt_.has_row()) {
|
|
||||||
return Status::Error("Not found");
|
|
||||||
}
|
|
||||||
return BufferSlice(get_dialog_stmt_.view_blob(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<NotificationGroupKey> get_notification_group(NotificationGroupId notification_group_id) override {
|
Result<NotificationGroupKey> get_notification_group(NotificationGroupId notification_group_id) override {
|
||||||
SCOPE_EXIT {
|
return Status::Error("Not found");
|
||||||
get_notification_group_stmt_.reset();
|
|
||||||
};
|
|
||||||
get_notification_group_stmt_.bind_int32(1, notification_group_id.get()).ensure();
|
|
||||||
TRY_STATUS(get_notification_group_stmt_.step());
|
|
||||||
if (!get_notification_group_stmt_.has_row()) {
|
|
||||||
return Status::Error("Not found");
|
|
||||||
}
|
|
||||||
return NotificationGroupKey(notification_group_id, DialogId(get_notification_group_stmt_.view_int64(0)),
|
|
||||||
get_last_notification_date(get_notification_group_stmt_, 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<int32> get_secret_chat_count(FolderId folder_id) override {
|
Result<int32> get_secret_chat_count(FolderId folder_id) override {
|
||||||
SCOPE_EXIT {
|
return 0;
|
||||||
get_secret_chat_count_stmt_.reset();
|
|
||||||
};
|
|
||||||
get_secret_chat_count_stmt_.bind_int32(1, folder_id.get()).ensure();
|
|
||||||
TRY_STATUS(get_secret_chat_count_stmt_.step());
|
|
||||||
CHECK(get_secret_chat_count_stmt_.has_row());
|
|
||||||
return get_secret_chat_count_stmt_.view_int32(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<DialogDbGetDialogsResult> get_dialogs(FolderId folder_id, int64 order, DialogId dialog_id,
|
Result<DialogDbGetDialogsResult> get_dialogs(FolderId folder_id, int64 order, DialogId dialog_id,
|
||||||
int32 limit) override {
|
int32 limit) override {
|
||||||
SCOPE_EXIT {
|
|
||||||
get_dialogs_stmt_.reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
get_dialogs_stmt_.bind_int32(1, folder_id.get()).ensure();
|
|
||||||
get_dialogs_stmt_.bind_int64(2, order).ensure();
|
|
||||||
get_dialogs_stmt_.bind_int64(3, dialog_id.get()).ensure();
|
|
||||||
get_dialogs_stmt_.bind_int32(4, limit).ensure();
|
|
||||||
|
|
||||||
DialogDbGetDialogsResult result;
|
DialogDbGetDialogsResult result;
|
||||||
TRY_STATUS(get_dialogs_stmt_.step());
|
|
||||||
while (get_dialogs_stmt_.has_row()) {
|
|
||||||
BufferSlice data(get_dialogs_stmt_.view_blob(0));
|
|
||||||
result.next_dialog_id = DialogId(get_dialogs_stmt_.view_int64(1));
|
|
||||||
result.next_order = get_dialogs_stmt_.view_int64(2);
|
|
||||||
LOG(INFO) << "Load " << result.next_dialog_id << " with order " << result.next_order;
|
|
||||||
result.dialogs.emplace_back(std::move(data));
|
|
||||||
TRY_STATUS(get_dialogs_stmt_.step());
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<vector<NotificationGroupKey>> get_notification_groups_by_last_notification_date(
|
Result<vector<NotificationGroupKey>> get_notification_groups_by_last_notification_date(
|
||||||
NotificationGroupKey notification_group_key, int32 limit) override {
|
NotificationGroupKey notification_group_key, int32 limit) override {
|
||||||
auto &stmt = get_notification_groups_by_last_notification_date_stmt_;
|
|
||||||
SCOPE_EXIT {
|
|
||||||
stmt.reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
stmt.bind_int32(1, notification_group_key.last_notification_date).ensure();
|
|
||||||
stmt.bind_int64(2, notification_group_key.dialog_id.get()).ensure();
|
|
||||||
stmt.bind_int32(3, notification_group_key.group_id.get()).ensure();
|
|
||||||
stmt.bind_int32(4, limit).ensure();
|
|
||||||
|
|
||||||
vector<NotificationGroupKey> notification_groups;
|
vector<NotificationGroupKey> notification_groups;
|
||||||
TRY_STATUS(stmt.step());
|
|
||||||
while (stmt.has_row()) {
|
|
||||||
notification_groups.emplace_back(NotificationGroupId(stmt.view_int32(0)), DialogId(stmt.view_int64(1)),
|
|
||||||
get_last_notification_date(stmt, 2));
|
|
||||||
TRY_STATUS(stmt.step());
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::move(notification_groups);
|
return std::move(notification_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status begin_transaction() override {
|
Status begin_transaction() override {
|
||||||
return db_.begin_transaction();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
Status commit_transaction() override {
|
Status commit_transaction() override {
|
||||||
return db_.commit_transaction();
|
return Status::OK();
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SqliteDb db_;
|
|
||||||
|
|
||||||
SqliteStatement add_dialog_stmt_;
|
|
||||||
SqliteStatement add_notification_group_stmt_;
|
|
||||||
SqliteStatement delete_notification_group_stmt_;
|
|
||||||
SqliteStatement get_dialog_stmt_;
|
|
||||||
SqliteStatement get_dialogs_stmt_;
|
|
||||||
SqliteStatement get_notification_groups_by_last_notification_date_stmt_;
|
|
||||||
SqliteStatement get_notification_group_stmt_;
|
|
||||||
SqliteStatement get_secret_chat_count_stmt_;
|
|
||||||
|
|
||||||
static int32 get_last_notification_date(SqliteStatement &stmt, int id) {
|
|
||||||
if (stmt.view_datatype(id) == SqliteStatement::Datatype::Null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return stmt.view_int32(id);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -431,28 +213,12 @@ class DialogDbAsync : public DialogDbAsyncInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_read_query() {
|
void add_read_query() {
|
||||||
do_flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_flush() {
|
void do_flush() {
|
||||||
if (pending_writes_.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sync_db_->begin_transaction().ensure();
|
|
||||||
for (auto &query : pending_writes_) {
|
|
||||||
query.set_value(Unit());
|
|
||||||
}
|
|
||||||
sync_db_->commit_transaction().ensure();
|
|
||||||
pending_writes_.clear();
|
|
||||||
for (auto &p : pending_write_results_) {
|
|
||||||
p.first.set_result(std::move(p.second));
|
|
||||||
}
|
|
||||||
pending_write_results_.clear();
|
|
||||||
cancel_timeout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_expired() override {
|
void timeout_expired() override {
|
||||||
do_flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_up() override {
|
void start_up() override {
|
||||||
|
@ -642,6 +642,10 @@ bool DocumentsManager::merge_documents(FileId new_id, FileId old_id, bool can_de
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DocumentsManager::memory_cleanup() {
|
||||||
|
documents_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
string DocumentsManager::get_document_search_text(FileId file_id) const {
|
string DocumentsManager::get_document_search_text(FileId file_id) const {
|
||||||
auto document = get_document(file_id);
|
auto document = get_document(file_id);
|
||||||
CHECK(document);
|
CHECK(document);
|
||||||
|
@ -76,6 +76,8 @@ class DocumentsManager {
|
|||||||
|
|
||||||
tl_object_ptr<td_api::document> get_document_object(FileId file_id);
|
tl_object_ptr<td_api::document> get_document_object(FileId file_id);
|
||||||
|
|
||||||
|
void memory_cleanup();
|
||||||
|
|
||||||
Document on_get_document(RemoteDocument remote_document, DialogId owner_dialog_id,
|
Document on_get_document(RemoteDocument remote_document, DialogId owner_dialog_id,
|
||||||
MultiPromiseActor *load_data_multipromise_ptr = nullptr,
|
MultiPromiseActor *load_data_multipromise_ptr = nullptr,
|
||||||
Document::Type default_document_type = Document::Type::General, bool is_background = false,
|
Document::Type default_document_type = Document::Type::General, bool is_background = false,
|
||||||
|
@ -23,7 +23,9 @@ template <class StorerT>
|
|||||||
void DocumentsManager::store_document(FileId file_id, StorerT &storer) const {
|
void DocumentsManager::store_document(FileId file_id, StorerT &storer) const {
|
||||||
LOG(DEBUG) << "Store document " << file_id;
|
LOG(DEBUG) << "Store document " << file_id;
|
||||||
auto it = documents_.find(file_id);
|
auto it = documents_.find(file_id);
|
||||||
CHECK(it != documents_.end());
|
if (it == documents_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const GeneralDocument *document = it->second.get();
|
const GeneralDocument *document = it->second.get();
|
||||||
store(document->file_name, storer);
|
store(document->file_name, storer);
|
||||||
store(document->mime_type, storer);
|
store(document->mime_type, storer);
|
||||||
|
@ -1327,9 +1327,17 @@ tl_object_ptr<td_api::sticker> StickersManager::get_sticker_object(FileId file_i
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto it = stickers_.find(file_id);
|
auto it = stickers_.find(file_id);
|
||||||
CHECK(it != stickers_.end());
|
|
||||||
|
if (it == stickers_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto sticker = it->second.get();
|
auto sticker = it->second.get();
|
||||||
CHECK(sticker != nullptr);
|
|
||||||
|
if (sticker == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
sticker->is_changed = false;
|
sticker->is_changed = false;
|
||||||
|
|
||||||
auto mask_position = sticker->point >= 0
|
auto mask_position = sticker->point >= 0
|
||||||
@ -1715,7 +1723,11 @@ void StickersManager::delete_sticker_thumbnail(FileId file_id) {
|
|||||||
vector<FileId> StickersManager::get_sticker_file_ids(FileId file_id) const {
|
vector<FileId> StickersManager::get_sticker_file_ids(FileId file_id) const {
|
||||||
vector<FileId> result;
|
vector<FileId> result;
|
||||||
auto sticker = get_sticker(file_id);
|
auto sticker = get_sticker(file_id);
|
||||||
CHECK(sticker != nullptr);
|
|
||||||
|
if (sticker == nullptr) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result.push_back(file_id);
|
result.push_back(file_id);
|
||||||
if (sticker->s_thumbnail.file_id.is_valid()) {
|
if (sticker->s_thumbnail.file_id.is_valid()) {
|
||||||
result.push_back(sticker->s_thumbnail.file_id);
|
result.push_back(sticker->s_thumbnail.file_id);
|
||||||
@ -1933,7 +1945,11 @@ void StickersManager::create_sticker(FileId file_id, PhotoSize thumbnail, Dimens
|
|||||||
|
|
||||||
bool StickersManager::has_input_media(FileId sticker_file_id, bool is_secret) const {
|
bool StickersManager::has_input_media(FileId sticker_file_id, bool is_secret) const {
|
||||||
const Sticker *sticker = get_sticker(sticker_file_id);
|
const Sticker *sticker = get_sticker(sticker_file_id);
|
||||||
CHECK(sticker != nullptr);
|
|
||||||
|
if (sticker == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
||||||
if (is_secret) {
|
if (is_secret) {
|
||||||
if (file_view.is_encrypted_secret()) {
|
if (file_view.is_encrypted_secret()) {
|
||||||
@ -1962,7 +1978,11 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
|||||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
|
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
|
||||||
BufferSlice thumbnail) const {
|
BufferSlice thumbnail) const {
|
||||||
const Sticker *sticker = get_sticker(sticker_file_id);
|
const Sticker *sticker = get_sticker(sticker_file_id);
|
||||||
CHECK(sticker != nullptr);
|
|
||||||
|
if (sticker == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
||||||
if (file_view.is_encrypted_secret()) {
|
if (file_view.is_encrypted_secret()) {
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
@ -5005,7 +5025,9 @@ int32 StickersManager::get_recent_stickers_hash(const vector<FileId> &sticker_id
|
|||||||
numbers.reserve(sticker_ids.size() * 2);
|
numbers.reserve(sticker_ids.size() * 2);
|
||||||
for (auto sticker_id : sticker_ids) {
|
for (auto sticker_id : sticker_ids) {
|
||||||
auto sticker = get_sticker(sticker_id);
|
auto sticker = get_sticker(sticker_id);
|
||||||
CHECK(sticker != nullptr);
|
if (sticker == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
||||||
CHECK(file_view.has_remote_location());
|
CHECK(file_view.has_remote_location());
|
||||||
if (!file_view.remote_location().is_document()) {
|
if (!file_view.remote_location().is_document()) {
|
||||||
@ -6179,19 +6201,19 @@ void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StickersManager::memory_cleanup() {
|
void StickersManager::memory_cleanup() {
|
||||||
// stickers_.clear();
|
stickers_.clear();
|
||||||
// sticker_sets_.clear();
|
sticker_sets_.clear();
|
||||||
// short_name_to_sticker_set_id_.clear();
|
short_name_to_sticker_set_id_.clear();
|
||||||
// attached_sticker_sets_.clear();
|
attached_sticker_sets_.clear();
|
||||||
// found_stickers_.clear();
|
found_stickers_.clear();
|
||||||
// found_sticker_sets_.clear();
|
found_sticker_sets_.clear();
|
||||||
// special_sticker_sets_.clear();
|
special_sticker_sets_.clear();
|
||||||
// sticker_set_load_requests_.clear();
|
sticker_set_load_requests_.clear();
|
||||||
// emoji_language_codes_.clear();
|
emoji_language_codes_.clear();
|
||||||
// emoji_language_code_versions_.clear();
|
emoji_language_code_versions_.clear();
|
||||||
// emoji_language_code_last_difference_times_.clear();
|
emoji_language_code_last_difference_times_.clear();
|
||||||
// emoji_suggestions_urls_.clear();
|
emoji_suggestions_urls_.clear();
|
||||||
// dice_messages_.clear();
|
dice_messages_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -23,7 +23,9 @@ namespace td {
|
|||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void StickersManager::store_sticker(FileId file_id, bool in_sticker_set, StorerT &storer) const {
|
void StickersManager::store_sticker(FileId file_id, bool in_sticker_set, StorerT &storer) const {
|
||||||
auto it = stickers_.find(file_id);
|
auto it = stickers_.find(file_id);
|
||||||
CHECK(it != stickers_.end());
|
if (it == stickers_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const Sticker *sticker = it->second.get();
|
const Sticker *sticker = it->second.get();
|
||||||
bool has_sticker_set_access_hash = sticker->set_id.is_valid() && !in_sticker_set;
|
bool has_sticker_set_access_hash = sticker->set_id.is_valid() && !in_sticker_set;
|
||||||
BEGIN_STORE_FLAGS();
|
BEGIN_STORE_FLAGS();
|
||||||
|
@ -5025,6 +5025,7 @@ void Td::on_request(uint64 id, td_api::optimizeStorage &request) {
|
|||||||
contacts_manager_->memory_cleanup();
|
contacts_manager_->memory_cleanup();
|
||||||
web_pages_manager_->memory_cleanup();
|
web_pages_manager_->memory_cleanup();
|
||||||
stickers_manager_->memory_cleanup();
|
stickers_manager_->memory_cleanup();
|
||||||
|
documents_manager_->memory_cleanup();
|
||||||
|
|
||||||
std::vector<FileType> file_types;
|
std::vector<FileType> file_types;
|
||||||
for (auto &file_type : request.file_types_) {
|
for (auto &file_type : request.file_types_) {
|
||||||
|
@ -11,115 +11,33 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
Result<bool> SqliteKeyValue::init(string path) {
|
Result<bool> SqliteKeyValue::init(string path) {
|
||||||
path_ = std::move(path);
|
return true;
|
||||||
bool is_created = false;
|
|
||||||
SqliteDb db;
|
|
||||||
TRY_STATUS(db.init(path, &is_created));
|
|
||||||
TRY_STATUS(db.exec("PRAGMA encoding=\"UTF-8\""));
|
|
||||||
TRY_STATUS(db.exec("PRAGMA synchronous=NORMAL"));
|
|
||||||
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
|
|
||||||
TRY_STATUS(db.exec("PRAGMA temp_store=MEMORY"));
|
|
||||||
TRY_STATUS(init_with_connection(std::move(db), "KV"));
|
|
||||||
return is_created;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status SqliteKeyValue::init_with_connection(SqliteDb connection, string table_name) {
|
Status SqliteKeyValue::init_with_connection(SqliteDb connection, string table_name) {
|
||||||
auto init_guard = ScopeExit() + [&] {
|
|
||||||
close();
|
|
||||||
};
|
|
||||||
db_ = std::move(connection);
|
|
||||||
table_name_ = std::move(table_name);
|
|
||||||
TRY_STATUS(init(db_, table_name_));
|
|
||||||
|
|
||||||
TRY_RESULT_ASSIGN(set_stmt_,
|
|
||||||
db_.get_statement(PSLICE() << "REPLACE INTO " << table_name_ << " (k, v) VALUES (?1, ?2)"));
|
|
||||||
TRY_RESULT_ASSIGN(get_stmt_, db_.get_statement(PSLICE() << "SELECT v FROM " << table_name_ << " WHERE k = ?1"));
|
|
||||||
TRY_RESULT_ASSIGN(erase_stmt_, db_.get_statement(PSLICE() << "DELETE FROM " << table_name_ << " WHERE k = ?1"));
|
|
||||||
TRY_RESULT_ASSIGN(get_all_stmt_, db_.get_statement(PSLICE() << "SELECT k, v FROM " << table_name_));
|
|
||||||
|
|
||||||
TRY_RESULT_ASSIGN(erase_by_prefix_stmt_,
|
|
||||||
db_.get_statement(PSLICE() << "DELETE FROM " << table_name_ << " WHERE ?1 <= k AND k < ?2"));
|
|
||||||
TRY_RESULT_ASSIGN(erase_by_prefix_rare_stmt_,
|
|
||||||
db_.get_statement(PSLICE() << "DELETE FROM " << table_name_ << " WHERE ?1 <= k"));
|
|
||||||
|
|
||||||
TRY_RESULT_ASSIGN(get_by_prefix_stmt_,
|
|
||||||
db_.get_statement(PSLICE() << "SELECT k, v FROM " << table_name_ << " WHERE ?1 <= k AND k < ?2"));
|
|
||||||
TRY_RESULT_ASSIGN(get_by_prefix_rare_stmt_,
|
|
||||||
db_.get_statement(PSLICE() << "SELECT k, v FROM " << table_name_ << " WHERE ?1 <= k"));
|
|
||||||
|
|
||||||
init_guard.dismiss();
|
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status SqliteKeyValue::drop() {
|
Status SqliteKeyValue::drop() {
|
||||||
if (empty()) {
|
return Status::OK();
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = drop(db_, table_name_);
|
|
||||||
close();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SqliteKeyValue::SeqNo SqliteKeyValue::set(Slice key, Slice value) {
|
SqliteKeyValue::SeqNo SqliteKeyValue::set(Slice key, Slice value) {
|
||||||
set_stmt_.bind_blob(1, key).ensure();
|
|
||||||
set_stmt_.bind_blob(2, value).ensure();
|
|
||||||
set_stmt_.step().ensure();
|
|
||||||
set_stmt_.reset();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string SqliteKeyValue::get(Slice key) {
|
string SqliteKeyValue::get(Slice key) {
|
||||||
SCOPE_EXIT {
|
return "";
|
||||||
get_stmt_.reset();
|
|
||||||
};
|
|
||||||
get_stmt_.bind_blob(1, key).ensure();
|
|
||||||
get_stmt_.step().ensure();
|
|
||||||
if (!get_stmt_.has_row()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
auto data = get_stmt_.view_blob(0).str();
|
|
||||||
get_stmt_.step().ignore();
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SqliteKeyValue::SeqNo SqliteKeyValue::erase(Slice key) {
|
SqliteKeyValue::SeqNo SqliteKeyValue::erase(Slice key) {
|
||||||
erase_stmt_.bind_blob(1, key).ensure();
|
|
||||||
erase_stmt_.step().ensure();
|
|
||||||
erase_stmt_.reset();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SqliteKeyValue::erase_by_prefix(Slice prefix) {
|
void SqliteKeyValue::erase_by_prefix(Slice prefix) {
|
||||||
auto next = next_prefix(prefix);
|
|
||||||
if (next.empty()) {
|
|
||||||
SCOPE_EXIT {
|
|
||||||
erase_by_prefix_rare_stmt_.reset();
|
|
||||||
};
|
|
||||||
erase_by_prefix_rare_stmt_.bind_blob(1, prefix).ensure();
|
|
||||||
erase_by_prefix_rare_stmt_.step().ensure();
|
|
||||||
} else {
|
|
||||||
SCOPE_EXIT {
|
|
||||||
erase_by_prefix_stmt_.reset();
|
|
||||||
};
|
|
||||||
erase_by_prefix_stmt_.bind_blob(1, prefix).ensure();
|
|
||||||
erase_by_prefix_stmt_.bind_blob(2, next).ensure();
|
|
||||||
erase_by_prefix_stmt_.step().ensure();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string SqliteKeyValue::next_prefix(Slice prefix) {
|
string SqliteKeyValue::next_prefix(Slice prefix) {
|
||||||
string next = prefix.str();
|
|
||||||
size_t pos = next.size();
|
|
||||||
while (pos) {
|
|
||||||
pos--;
|
|
||||||
auto value = static_cast<uint8>(next[pos]);
|
|
||||||
value++;
|
|
||||||
next[pos] = static_cast<char>(value);
|
|
||||||
if (value != 0) {
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string{};
|
return string{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,17 +20,17 @@ namespace td {
|
|||||||
class SqliteKeyValue {
|
class SqliteKeyValue {
|
||||||
public:
|
public:
|
||||||
static Status drop(SqliteDb &connection, Slice table_name) TD_WARN_UNUSED_RESULT {
|
static Status drop(SqliteDb &connection, Slice table_name) TD_WARN_UNUSED_RESULT {
|
||||||
return connection.exec(PSLICE() << "DROP TABLE IF EXISTS " << table_name);
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Status init(SqliteDb &connection, Slice table_name) TD_WARN_UNUSED_RESULT {
|
static Status init(SqliteDb &connection, Slice table_name) TD_WARN_UNUSED_RESULT {
|
||||||
return connection.exec(PSLICE() << "CREATE TABLE IF NOT EXISTS " << table_name << " (k BLOB PRIMARY KEY, v BLOB)");
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
using SeqNo = uint64;
|
using SeqNo = uint64;
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return db_.empty();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<bool> init(string path) TD_WARN_UNUSED_RESULT;
|
Result<bool> init(string path) TD_WARN_UNUSED_RESULT;
|
||||||
@ -54,10 +54,10 @@ class SqliteKeyValue {
|
|||||||
SeqNo erase(Slice key);
|
SeqNo erase(Slice key);
|
||||||
|
|
||||||
Status begin_transaction() TD_WARN_UNUSED_RESULT {
|
Status begin_transaction() TD_WARN_UNUSED_RESULT {
|
||||||
return db_.begin_transaction();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
Status commit_transaction() TD_WARN_UNUSED_RESULT {
|
Status commit_transaction() TD_WARN_UNUSED_RESULT {
|
||||||
return db_.commit_transaction();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase_by_prefix(Slice prefix);
|
void erase_by_prefix(Slice prefix);
|
||||||
@ -107,14 +107,7 @@ class SqliteKeyValue {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string path_;
|
string path_;
|
||||||
string table_name_;
|
|
||||||
SqliteDb db_;
|
|
||||||
SqliteStatement get_stmt_;
|
|
||||||
SqliteStatement set_stmt_;
|
|
||||||
SqliteStatement erase_stmt_;
|
|
||||||
SqliteStatement get_all_stmt_;
|
SqliteStatement get_all_stmt_;
|
||||||
SqliteStatement erase_by_prefix_stmt_;
|
|
||||||
SqliteStatement erase_by_prefix_rare_stmt_;
|
|
||||||
SqliteStatement get_by_prefix_stmt_;
|
SqliteStatement get_by_prefix_stmt_;
|
||||||
SqliteStatement get_by_prefix_rare_stmt_;
|
SqliteStatement get_by_prefix_rare_stmt_;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user