Fixes for delete_file_reference.

GitOrigin-RevId: 15ffa944a037d34954ce5e7b0cea22131e1e976e
This commit is contained in:
levlam 2019-01-31 02:57:14 +03:00
parent 996869d4ca
commit 346202fbaa
5 changed files with 66 additions and 47 deletions

View File

@ -6923,6 +6923,7 @@ void ContactsManager::add_user_photo_id(User *u, UserId user_id, int64 photo_id,
file_source_id = it->second; file_source_id = it->second;
user_profile_photo_file_source_ids_.erase(it); user_profile_photo_file_source_ids_.erase(it);
} else { } else {
VLOG(file_references) << "Need to create new file source for " << photo_id << " of " << user_id;
file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id); file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id);
} }
for (auto &file_id : photo_file_ids) { for (auto &file_id : photo_file_ids) {

View File

@ -2122,7 +2122,7 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
} }
if (!was_uploaded) { if (!was_uploaded) {
auto file_reference = FileManager::extract_file_reference(input_media); auto file_reference = FileManager::extract_file_reference(input_media);
if (file_reference == FileReferenceView::invalid_file_reference()) { if (!FileReferenceView(file_reference).has_upload()) {
return nullptr; return nullptr;
} }
} }
@ -2132,7 +2132,7 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl) { tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl) {
auto input_media = get_input_media(content, td, nullptr, nullptr, ttl); auto input_media = get_input_media(content, td, nullptr, nullptr, ttl);
auto file_reference = FileManager::extract_file_reference(input_media); auto file_reference = FileManager::extract_file_reference(input_media);
if (file_reference == FileReferenceView::invalid_file_reference()) { if (!FileReferenceView(file_reference).has_upload()) {
return nullptr; return nullptr;
} }
return input_media; return input_media;

View File

@ -481,9 +481,6 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
res.date = photo->date_; res.date = photo->date_;
res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0; res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0;
auto file_reference = photo->file_reference_.as_slice().str();
// TODO use file_reference
for (auto &size_ptr : photo->sizes_) { for (auto &size_ptr : photo->sizes_) {
res.photos.push_back(get_photo_size(file_manager, FileType::Photo, photo->id_, photo->access_hash_, res.photos.push_back(get_photo_size(file_manager, FileType::Photo, photo->id_, photo->access_hash_,
photo->file_reference_.as_slice().str(), owner_dialog_id, std::move(size_ptr), photo->file_reference_.as_slice().str(), owner_dialog_id, std::move(size_ptr),

View File

@ -23,35 +23,30 @@
#include "td/utils/Variant.h" #include "td/utils/Variant.h"
#include <tuple> #include <tuple>
#include <utility>
namespace td { namespace td {
class FileReferenceView { class FileReferenceView {
public: public:
static Slice invalid_file_reference() { static std::string create_invalid() {
return "#"; return create_one(invalid_file_reference());
} }
static std::string create_one(Slice first) { static std::string create_one(Slice first) {
unsigned char second_length = 255; unsigned char second_length = 255;
return PSTRING() << static_cast<char>(second_length) << first; return PSTRING() << static_cast<char>(second_length) << first;
} }
static std::string create_two(Slice first, Slice second = {}) { static std::string create_two(Slice first, Slice second) {
if (second.size() >= 255) { if (second.size() >= 255) {
LOG(ERROR) << "File reference is too big " << base64_encode(second); LOG(ERROR) << "File reference is too big " << base64_encode(second);
second = invalid_file_reference(); second = invalid_file_reference();
} }
char second_length = narrow_cast<unsigned char>(second.size()); char second_length = static_cast<char>(narrow_cast<unsigned char>(second.size()));
return PSTRING() << second_length << first << second; return PSTRING() << second_length << first << second;
} }
std::string create(Slice first, Slice second) const {
if (size() == 1) {
return create_one(first);
}
return create_two(first, second);
}
FileReferenceView(Slice data) { FileReferenceView(Slice data) {
if (data.empty()) { if (data.empty()) {
size_ = 1;
return; return;
} }
@ -59,10 +54,9 @@ class FileReferenceView {
if (second_size == 255) { if (second_size == 255) {
first_ = data.substr(1); first_ = data.substr(1);
second_ = data.substr(1); second_ = data.substr(1);
size_ = 1;
} else { } else {
if (second_size > data.size() - 1) { if (second_size > data.size() - 1) {
size_ = 1; first_ = second_ = data;
return; return;
} }
auto first_size = data.size() - 1 - second_size; auto first_size = data.size() - 1 - second_size;
@ -71,46 +65,54 @@ class FileReferenceView {
size_ = 2; size_ = 2;
} }
} }
size_t size() const { Slice upload() const {
return size_;
}
Slice first() const {
return first_; return first_;
} }
Slice second() const { Slice download() const {
return second_; return second_;
} }
bool has_first() const { bool has_upload() const {
return first() != invalid_file_reference(); return upload() != invalid_file_reference();
} }
bool has_second() const { bool has_download() const {
return second() != invalid_file_reference(); return download() != invalid_file_reference();
} }
std::pair<std::string, bool> delete_file_reference(Slice bad_file_reference) const { std::pair<std::string, bool> delete_file_reference(Slice bad_file_reference) const {
if (bad_file_reference == FileReferenceView::invalid_file_reference()) { if (bad_file_reference == FileReferenceView::invalid_file_reference()) {
return {"", false}; return {string(), false};
} }
auto first = this->first(); auto first = first_;
auto second = this->second(); auto second = second_;
bool changed = false; bool is_changed = false;
if (first == bad_file_reference) { if (first == bad_file_reference) {
first = invalid_file_reference(); first = invalid_file_reference();
changed = true; is_changed = true;
} }
if (second == bad_file_reference) { if (second == bad_file_reference) {
second = invalid_file_reference(); second = invalid_file_reference();
changed = true; is_changed = true;
} }
if (!changed) { if (!is_changed) {
return {"", false}; return {string(), false};
} }
return {create(first, second), true}; return {create(first, second), true};
} }
private: private:
static Slice invalid_file_reference() {
return Slice("#");
}
std::string create(Slice first, Slice second) const {
if (size_ == 1) {
return create_one(first);
}
return create_two(first, second);
}
Slice first_; Slice first_;
Slice second_; Slice second_;
int size_; int size_ = 1;
}; };
struct EmptyRemoteFileLocation { struct EmptyRemoteFileLocation {
@ -459,6 +461,7 @@ class FullRemoteFileLocation {
CHECK(!is_web()); CHECK(!is_web());
return dc_id_; return dc_id_;
} }
int64 get_access_hash() const { int64 get_access_hash() const {
switch (location_type()) { switch (location_type()) {
case LocationType::Photo: case LocationType::Photo:
@ -473,6 +476,7 @@ class FullRemoteFileLocation {
return 0; return 0;
} }
} }
int64 get_id() const { int64 get_id() const {
switch (location_type()) { switch (location_type()) {
case LocationType::Photo: case LocationType::Photo:
@ -486,18 +490,21 @@ class FullRemoteFileLocation {
return 0; return 0;
} }
} }
bool delete_file_reference(Slice bad_file_reference) { bool delete_file_reference(Slice bad_file_reference) {
auto res = FileReferenceView(file_reference_).delete_file_reference(bad_file_reference); auto res = FileReferenceView(file_reference_).delete_file_reference(bad_file_reference);
if (res.second) { if (res.second) {
file_reference_ = res.first; file_reference_ = res.first;
} else if (file_reference_ == bad_file_reference) {
file_reference_ = FileReferenceView::create_invalid();
} }
return res.second; return res.second;
} }
bool has_upload_file_reference() const { bool has_upload_file_reference() const {
return FileReferenceView(file_reference_).has_first(); return FileReferenceView(file_reference_).has_upload();
} }
bool has_download_file_reference() const { bool has_download_file_reference() const {
return FileReferenceView(file_reference_).has_second(); return FileReferenceView(file_reference_).has_download();
} }
bool has_any_file_reference() const { bool has_any_file_reference() const {
return has_upload_file_reference() || has_download_file_reference(); return has_upload_file_reference() || has_download_file_reference();
@ -506,11 +513,12 @@ class FullRemoteFileLocation {
return file_reference_; return file_reference_;
} }
Slice get_upload_file_reference() const { Slice get_upload_file_reference() const {
return FileReferenceView(file_reference_).first(); return FileReferenceView(file_reference_).upload();
} }
Slice get_download_file_reference() const { Slice get_download_file_reference() const {
return FileReferenceView(file_reference_).second(); return FileReferenceView(file_reference_).download();
} }
string get_url() const { string get_url() const {
if (is_web()) { if (is_web()) {
return web().url_; return web().url_;
@ -555,7 +563,7 @@ class FullRemoteFileLocation {
case LocationType::Photo: case LocationType::Photo:
return make_tl_object<telegram_api::inputFileLocation>( return make_tl_object<telegram_api::inputFileLocation>(
photo().volume_id_, photo().local_id_, photo().secret_, photo().volume_id_, photo().local_id_, photo().secret_,
BufferSlice(FileReferenceView(file_reference_).second())); BufferSlice(FileReferenceView(file_reference_).download()));
case LocationType::Common: case LocationType::Common:
if (is_encrypted_secret()) { if (is_encrypted_secret()) {
return make_tl_object<telegram_api::inputEncryptedFileLocation>(common().id_, common().access_hash_); return make_tl_object<telegram_api::inputEncryptedFileLocation>(common().id_, common().access_hash_);
@ -585,7 +593,7 @@ class FullRemoteFileLocation {
tl_object_ptr<telegram_api::inputPhoto> as_input_photo_impl(const char *file, int line) const { tl_object_ptr<telegram_api::inputPhoto> as_input_photo_impl(const char *file, int line) const {
CHECK(is_photo()) << file << ' ' << line; CHECK(is_photo()) << file << ' ' << line;
return make_tl_object<telegram_api::inputPhoto>(photo().id_, photo().access_hash_, return make_tl_object<telegram_api::inputPhoto>(photo().id_, photo().access_hash_,
BufferSlice(FileReferenceView(file_reference_).first())); BufferSlice(FileReferenceView(file_reference_).upload()));
} }
tl_object_ptr<telegram_api::inputEncryptedFile> as_input_encrypted_file() const { tl_object_ptr<telegram_api::inputEncryptedFile> as_input_encrypted_file() const {
@ -609,7 +617,7 @@ class FullRemoteFileLocation {
, variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, secret, local_id}) { , variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, secret, local_id}) {
CHECK(is_photo()); CHECK(is_photo());
FileReferenceView view(file_reference_); FileReferenceView view(file_reference_);
if (!view.has_first() || !view.has_second()) { if (!(view.has_upload() && view.has_download())) {
LOG(ERROR) << "Tried to register file with invalid file reference"; LOG(ERROR) << "Tried to register file with invalid file reference";
file_reference_.clear(); file_reference_.clear();
} }
@ -621,7 +629,7 @@ class FullRemoteFileLocation {
, variant_(CommonRemoteFileLocation{id, access_hash}) { , variant_(CommonRemoteFileLocation{id, access_hash}) {
CHECK(is_common()); CHECK(is_common());
FileReferenceView view(file_reference_); FileReferenceView view(file_reference_);
if (!view.has_first() || !view.has_second()) { if (!(view.has_upload() && view.has_download())) {
LOG(ERROR) << "Tried to register file with invalid file reference"; LOG(ERROR) << "Tried to register file with invalid file reference";
file_reference_.clear(); file_reference_.clear();
} }
@ -677,7 +685,7 @@ class FullRemoteFileLocation {
} }
static const int32 KEY_MAGIC = 0x64374632; static const int32 KEY_MAGIC = 0x64374632;
}; // namespace td };
inline StringBuilder &operator<<(StringBuilder &string_builder, inline StringBuilder &operator<<(StringBuilder &string_builder,
const FullRemoteFileLocation &full_remote_file_location) { const FullRemoteFileLocation &full_remote_file_location) {

View File

@ -162,7 +162,11 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio
} }
bool FileNode::delete_file_reference(Slice file_reference) { bool FileNode::delete_file_reference(Slice file_reference) {
if (remote_.type() == RemoteFileLocation::Type::Full && remote_.full().delete_file_reference(file_reference)) { if (remote_.type() != RemoteFileLocation::Type::Full) {
return false;
}
if (remote_.full().delete_file_reference(file_reference)) {
VLOG(file_references) << "Do delete file reference of main file " << main_file_id_; VLOG(file_references) << "Do delete file reference of main file " << main_file_id_;
upload_was_update_file_reference_ = false; upload_was_update_file_reference_ = false;
download_was_update_file_reference_ = false; download_was_update_file_reference_ = false;
@ -1531,7 +1535,7 @@ void FileManager::flush_to_pmc(FileNodePtr node, bool new_remote, bool new_local
data.url_ = node->url_; data.url_ = node->url_;
data.owner_dialog_id_ = node->owner_dialog_id_; data.owner_dialog_id_ = node->owner_dialog_id_;
data.file_source_ids_ = context_->get_some_file_sources(view.file_id()); data.file_source_ids_ = context_->get_some_file_sources(view.file_id());
VLOG(file_references) << "Save " << data.file_source_ids_ << " to database for file " << view.file_id() << " from " VLOG(file_references) << "Save file " << view.file_id() << " to database with " << data.file_source_ids_ << " from "
<< source; << source;
file_db_->set_file_data(node->pmc_id_, data, (create_flag || new_remote), (create_flag || new_local), file_db_->set_file_data(node->pmc_id_, data, (create_flag || new_remote), (create_flag || new_local),
@ -1950,6 +1954,15 @@ void FileManager::delete_file_reference(FileId file_id, string file_reference) {
return; return;
} }
node->delete_file_reference(file_reference); node->delete_file_reference(file_reference);
auto remote = get_remote(file_id.get_remote());
if (remote != nullptr) {
VLOG(file_references) << "Do delete file reference of remote file " << file_id;
if (remote->delete_file_reference(file_reference)) {
node->upload_was_update_file_reference_ = false;
node->download_was_update_file_reference_ = false;
node->on_pmc_changed();
}
}
try_flush_node_pmc(node, "delete_file_reference"); try_flush_node_pmc(node, "delete_file_reference");
} }