Cache backgorund by their names.

GitOrigin-RevId: 2e5c5ed30185f53240ab806f866bd4c83ee5da51
This commit is contained in:
levlam 2019-07-19 05:34:49 +03:00
parent c6d7daa460
commit 6dd2a822ad
3 changed files with 94 additions and 15 deletions

View File

@ -25,6 +25,8 @@
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/TdDb.h" #include "td/telegram/TdDb.h"
#include "td/db/SqliteKeyValueAsync.h"
#include "td/utils/buffer.h" #include "td/utils/buffer.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
@ -38,14 +40,17 @@ namespace td {
class GetBackgroundQuery : public Td::ResultHandler { class GetBackgroundQuery : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
BackgroundId background_id_; BackgroundId background_id_;
string background_name_;
public: public:
explicit GetBackgroundQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) { explicit GetBackgroundQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
} }
void send(BackgroundId background_id, telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper) { void send(BackgroundId background_id, const string &background_name,
telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper) {
background_id_ = background_id; background_id_ = background_id;
LOG(INFO) << "Load " << background_id << " from server: " << to_string(input_wallpaper); background_name_ = background_name;
LOG(INFO) << "Load " << background_id_ << "/" << background_name_ << " from server: " << to_string(input_wallpaper);
send_query( send_query(
G()->net_query_creator().create(create_storer(telegram_api::account_getWallPaper(std::move(input_wallpaper))))); G()->net_query_creator().create(create_storer(telegram_api::account_getWallPaper(std::move(input_wallpaper)))));
} }
@ -56,13 +61,13 @@ class GetBackgroundQuery : public Td::ResultHandler {
return on_error(id, result_ptr.move_as_error()); return on_error(id, result_ptr.move_as_error());
} }
td->background_manager_->on_get_background(background_id_, result_ptr.move_as_ok()); td->background_manager_->on_get_background(background_id_, background_name_, result_ptr.move_as_ok());
promise_.set_value(Unit()); promise_.set_value(Unit());
} }
void on_error(uint64 id, Status status) override { void on_error(uint64 id, Status status) override {
LOG(INFO) << "Receive error for getBackground: " << status; LOG(INFO) << "Receive error for getBackground " << background_id_ << "/" << background_name_ << ": " << status;
promise_.set_error(std::move(status)); promise_.set_error(std::move(status));
} }
}; };
@ -395,18 +400,19 @@ Result<string> BackgroundManager::get_background_url(const string &name,
} }
void BackgroundManager::reload_background_from_server( void BackgroundManager::reload_background_from_server(
BackgroundId background_id, telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, BackgroundId background_id, const string &background_name,
Promise<Unit> &&promise) const { telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, Promise<Unit> &&promise) const {
if (G()->close_flag()) { if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Status::Error(500, "Request aborted"));
} }
td_->create_handler<GetBackgroundQuery>(std::move(promise))->send(background_id, std::move(input_wallpaper)); td_->create_handler<GetBackgroundQuery>(std::move(promise))
->send(background_id, background_name, std::move(input_wallpaper));
} }
void BackgroundManager::reload_background(BackgroundId background_id, int64 access_hash, Promise<Unit> &&promise) { void BackgroundManager::reload_background(BackgroundId background_id, int64 access_hash, Promise<Unit> &&promise) {
reload_background_from_server( reload_background_from_server(
background_id, telegram_api::make_object<telegram_api::inputWallPaper>(background_id.get(), access_hash), background_id, string(),
std::move(promise)); telegram_api::make_object<telegram_api::inputWallPaper>(background_id.get(), access_hash), std::move(promise));
} }
BackgroundId BackgroundManager::search_background(const string &name, Promise<Unit> &&promise) { BackgroundId BackgroundManager::search_background(const string &name, Promise<Unit> &&promise) {
@ -434,11 +440,56 @@ BackgroundId BackgroundManager::search_background(const string &name, Promise<Un
return background_id; return background_id;
} }
reload_background_from_server(BackgroundId(), telegram_api::make_object<telegram_api::inputWallPaperSlug>(name), if (G()->parameters().use_file_db && loaded_from_database_backgrounds_.count(name) == 0) {
auto &queries = being_loaded_from_database_backgrounds_[name];
queries.push_back(std::move(promise));
if (queries.size() == 1) {
LOG(INFO) << "Trying to load background " << name << " from database";
G()->td_db()->get_sqlite_pmc()->get(
get_background_name_database_key(name), PromiseCreator::lambda([name](string value) {
send_closure(G()->background_manager(), &BackgroundManager::on_load_background_from_database,
std::move(name), std::move(value));
}));
}
return BackgroundId();
}
reload_background_from_server(BackgroundId(), name, telegram_api::make_object<telegram_api::inputWallPaperSlug>(name),
std::move(promise)); std::move(promise));
return BackgroundId(); return BackgroundId();
} }
void BackgroundManager::on_load_background_from_database(string name, string value) {
auto promises_it = being_loaded_from_database_backgrounds_.find(name);
CHECK(promises_it != being_loaded_from_database_backgrounds_.end());
auto promises = std::move(promises_it->second);
CHECK(!promises.empty());
being_loaded_from_database_backgrounds_.erase(promises_it);
loaded_from_database_backgrounds_.insert(name);
CHECK(name.size() > 6);
if (name_to_background_id_.count(name) == 0 && !value.empty()) {
LOG(INFO) << "Successfully loaded background " << name << " of size " << value.size() << " from database";
Background background;
auto status = log_event_parse(background, value);
if (status.is_error() || background.type.type == BackgroundType::Type::Solid || !background.file_id.is_valid() ||
!background.id.is_valid()) {
LOG(ERROR) << "Can't load bacground " << name << ": " << status << ' ' << format::as_hex_dump<4>(Slice(value));
} else {
if (background.name != name) {
LOG(ERROR) << "Expected background " << name << ", but received " << background.name;
name_to_background_id_.emplace(name, background.id);
}
add_background(background);
}
}
for (auto &promise : promises) {
promise.set_value(Unit());
}
}
td_api::object_ptr<td_api::updateSelectedBackground> BackgroundManager::get_update_selected_background_object( td_api::object_ptr<td_api::updateSelectedBackground> BackgroundManager::get_update_selected_background_object(
bool for_dark_theme) const { bool for_dark_theme) const {
return td_api::make_object<td_api::updateSelectedBackground>( return td_api::make_object<td_api::updateSelectedBackground>(
@ -678,7 +729,7 @@ void BackgroundManager::on_uploaded_background_file(FileId file_id, const Backgr
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
CHECK(wallpaper != nullptr); CHECK(wallpaper != nullptr);
BackgroundId background_id = on_get_background(BackgroundId(), std::move(wallpaper)); BackgroundId background_id = on_get_background(BackgroundId(), string(), std::move(wallpaper));
if (!background_id.is_valid()) { if (!background_id.is_valid()) {
td_->file_manager_->cancel_upload(file_id); td_->file_manager_->cancel_upload(file_id);
return promise.set_error(Status::Error(500, "Receive wrong uploaded background")); return promise.set_error(Status::Error(500, "Receive wrong uploaded background"));
@ -774,13 +825,16 @@ void BackgroundManager::add_background(const Background &background) {
if (result->name != background.name) { if (result->name != background.name) {
if (!result->name.empty()) { if (!result->name.empty()) {
LOG(ERROR) << "Background name has changed from " << result->name << " to " << background.name; LOG(ERROR) << "Background name has changed from " << result->name << " to " << background.name;
name_to_background_id_.erase(result->name); // keep correspondence from previous name to background ID
// it will not harm, because background names can't be reassigned
// name_to_background_id_.erase(result->name);
} }
result->name = background.name; result->name = background.name;
if (result->name.size() > 6) { if (result->name.size() > 6) {
name_to_background_id_.emplace(result->name, result->id); name_to_background_id_.emplace(result->name, result->id);
loaded_from_database_backgrounds_.erase(result->name); // don't needed anymore
} }
} }
@ -836,7 +890,12 @@ const BackgroundManager::Background *BackgroundManager::get_background(Backgroun
} }
} }
string BackgroundManager::get_background_name_database_key(const string &name) {
return PSTRING() << "bgn" << name;
}
BackgroundId BackgroundManager::on_get_background(BackgroundId expected_background_id, BackgroundId BackgroundManager::on_get_background(BackgroundId expected_background_id,
const string &expected_background_name,
telegram_api::object_ptr<telegram_api::wallPaper> wallpaper) { telegram_api::object_ptr<telegram_api::wallPaper> wallpaper) {
CHECK(wallpaper != nullptr); CHECK(wallpaper != nullptr);
@ -883,6 +942,17 @@ BackgroundId BackgroundManager::on_get_background(BackgroundId expected_backgrou
background.file_id = document.file_id; background.file_id = document.file_id;
add_background(background); add_background(background);
if (!expected_background_name.empty() && background.name != expected_background_name) {
LOG(ERROR) << "Expected background " << expected_background_name << ", but receive " << background.name;
name_to_background_id_.emplace(expected_background_name, id);
}
if (G()->parameters().use_file_db && background.name.size() > 6) {
LOG(INFO) << "Save " << id << " to database with name " << background.name;
G()->td_db()->get_sqlite_pmc()->set(get_background_name_database_key(background.name),
log_event_store(background).as_slice().str(), Auto());
}
return id; return id;
} }
@ -913,7 +983,7 @@ void BackgroundManager::on_get_backgrounds(Result<telegram_api::object_ptr<teleg
installed_background_ids_.clear(); installed_background_ids_.clear();
auto wallpapers = telegram_api::move_object_as<telegram_api::account_wallPapers>(wallpapers_ptr); auto wallpapers = telegram_api::move_object_as<telegram_api::account_wallPapers>(wallpapers_ptr);
for (auto &wallpaper : wallpapers->wallpapers_) { for (auto &wallpaper : wallpapers->wallpapers_) {
auto background_id = on_get_background(BackgroundId(), std::move(wallpaper)); auto background_id = on_get_background(BackgroundId(), string(), std::move(wallpaper));
if (background_id.is_valid()) { if (background_id.is_valid()) {
installed_background_ids_.push_back(background_id); installed_background_ids_.push_back(background_id);
} }

View File

@ -22,6 +22,7 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <utility> #include <utility>
namespace td { namespace td {
@ -53,7 +54,7 @@ class BackgroundManager : public Actor {
td_api::object_ptr<td_api::backgrounds> get_backgrounds_object(bool for_dark_theme) const; td_api::object_ptr<td_api::backgrounds> get_backgrounds_object(bool for_dark_theme) const;
BackgroundId on_get_background(BackgroundId expected_background_id, BackgroundId on_get_background(BackgroundId expected_background_id, const string &expected_background_name,
telegram_api::object_ptr<telegram_api::wallPaper> wallpaper); telegram_api::object_ptr<telegram_api::wallPaper> wallpaper);
FileSourceId get_background_file_source_id(BackgroundId background_id, int64 access_hash); FileSourceId get_background_file_source_id(BackgroundId background_id, int64 access_hash);
@ -95,7 +96,7 @@ class BackgroundManager : public Actor {
void save_background_id(bool for_dark_theme) const; void save_background_id(bool for_dark_theme) const;
void reload_background_from_server(BackgroundId background_id, void reload_background_from_server(BackgroundId background_id, const string &background_name,
telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper,
Promise<Unit> &&promise) const; Promise<Unit> &&promise) const;
@ -111,6 +112,10 @@ class BackgroundManager : public Actor {
const Background *get_background(BackgroundId background_id) const; const Background *get_background(BackgroundId background_id) const;
static string get_background_name_database_key(const string &name);
void on_load_background_from_database(string name, string value);
void on_get_backgrounds(Result<telegram_api::object_ptr<telegram_api::account_WallPapers>> result); void on_get_backgrounds(Result<telegram_api::object_ptr<telegram_api::account_WallPapers>> result);
Result<FileId> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file); Result<FileId> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file);
@ -145,6 +150,9 @@ class BackgroundManager : public Actor {
std::unordered_map<FileId, BackgroundId, FileIdHash> file_id_to_background_id_; std::unordered_map<FileId, BackgroundId, FileIdHash> file_id_to_background_id_;
std::unordered_set<string> loaded_from_database_backgrounds_;
std::unordered_map<string, vector<Promise<Unit>>> being_loaded_from_database_backgrounds_;
BackgroundId set_background_id_[2]; BackgroundId set_background_id_[2];
BackgroundType set_background_type_[2]; BackgroundType set_background_type_[2];

View File

@ -2961,6 +2961,7 @@ class SearchBackgroundRequest : public RequestActor<> {
public: public:
SearchBackgroundRequest(ActorShared<Td> td, uint64 request_id, string &&name) SearchBackgroundRequest(ActorShared<Td> td, uint64 request_id, string &&name)
: RequestActor(std::move(td), request_id), name_(std::move(name)) { : RequestActor(std::move(td), request_id), name_(std::move(name)) {
set_tries(3);
} }
}; };