FileReference: better infinity loop protection

GitOrigin-RevId: 068fdbbb574eae03f3bb4b5b06ac3960aaca59c0
This commit is contained in:
Arseny Smirnov 2018-12-09 10:05:26 +03:00
parent bbecdcda20
commit b53cd5d76a
3 changed files with 33 additions and 17 deletions

View File

@ -37,7 +37,7 @@ void FileReferenceManager::update_file_reference(FileId file_id, std::vector<Fil
for (auto source_id : sources) { for (auto source_id : sources) {
auto it = to_full_message_id_.find(source_id); auto it = to_full_message_id_.find(source_id);
auto new_promise = PromiseCreator::lambda([promise = mpas.get_promise(), file_id, source_id, auto new_promise = PromiseCreator::lambda([promise = mpas.get_promise(), file_id, source_id,
file_manager = G()->file_manager()](Result<Unit> res) mutable { file_manager = G()->file_manager()](Result<Unit> res) mutable {
if (res.is_error()) { if (res.is_error()) {
LOG(INFO) << "Invalid source id " << source_id << " " << res.error(); LOG(INFO) << "Invalid source id " << source_id << " " << res.error();
send_closure(file_manager, &FileManager::remove_file_source, file_id, source_id); send_closure(file_manager, &FileManager::remove_file_source, file_id, source_id);

View File

@ -161,6 +161,8 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio
void FileNode::delete_file_reference(Slice file_reference) { void 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 && remote_.full().delete_file_reference(file_reference)) {
upload_may_update_file_reference_ = true;
download_may_update_file_reference_ = true;
on_pmc_changed(); on_pmc_changed();
} }
} }
@ -257,6 +259,8 @@ void FileNode::add_file_source(FileSourceId file_source_id) {
if (std::find(file_source_ids_.begin(), file_source_ids_.end(), file_source_id) != file_source_ids_.end()) { if (std::find(file_source_ids_.begin(), file_source_ids_.end(), file_source_id) != file_source_ids_.end()) {
return; return;
} }
upload_may_update_file_reference_ = true;
download_may_update_file_reference_ = true;
file_source_ids_.push_back(file_source_id); file_source_ids_.push_back(file_source_id);
} }
@ -1080,6 +1084,7 @@ void FileManager::cancel_download(FileNodePtr node) {
send_closure(file_load_manager_, &FileLoadManager::cancel, node->download_id_); send_closure(file_load_manager_, &FileLoadManager::cancel, node->download_id_);
node->download_id_ = 0; node->download_id_ = 0;
node->is_download_started_ = false; node->is_download_started_ = false;
node->download_may_update_file_reference_ = !node->file_source_ids_.empty();
node->set_download_priority(0); node->set_download_priority(0);
} }
@ -1089,6 +1094,7 @@ void FileManager::cancel_upload(FileNodePtr node) {
} }
send_closure(file_load_manager_, &FileLoadManager::cancel, node->upload_id_); send_closure(file_load_manager_, &FileLoadManager::cancel, node->upload_id_);
node->upload_id_ = 0; node->upload_id_ = 0;
node->upload_may_update_file_reference_ = !node->file_source_ids_.empty();
node->set_upload_priority(0); node->set_upload_priority(0);
} }
@ -1746,12 +1752,17 @@ void FileManager::run_download(FileNodePtr node) {
// If file reference is needed // If file reference is needed
if (!file_view.has_active_remote_location()) { if (!file_view.has_active_remote_location()) {
LOG(INFO) << "run_download: Do not have valid file_reference " << file_id; LOG(INFO) << "run_download: Do not have valid file_reference " << file_id;
QueryId id = queries_container_.create(Query{file_id, Query::Download}); QueryId id = queries_container_.create(Query{file_id, Query::DownloadWaitFileReferece});
node->download_id_ = id; node->download_id_ = id;
if (node->file_source_ids_.empty()) { if (node->file_source_ids_.empty()) {
on_error(id, Status::Error("Can't download file: have valid file reference and no valid source id")); on_error(id, Status::Error("Can't download file: have no valid file reference and no valid source id"));
return; return;
} }
if (!node->download_may_update_file_reference_) {
on_error(id, Status::Error("Can't download file: have valid source id, but do not allowed to use id"));
return;
}
node->download_may_update_file_reference_ = false;
send_closure( send_closure(
G()->file_reference_manager(), &FileReferenceManager::update_file_reference, file_id, node->file_source_ids_, G()->file_reference_manager(), &FileReferenceManager::update_file_reference, file_id, node->file_source_ids_,
@ -2029,9 +2040,11 @@ void FileManager::run_upload(FileNodePtr node, std::vector<int> bad_parts) {
CHECK(node->upload_id_ == 0); CHECK(node->upload_id_ == 0);
if (file_view.has_remote_location() && !file_view.has_active_remote_location() && if (file_view.has_remote_location() && !file_view.has_active_remote_location() &&
file_view.get_type() != FileType::Thumbnail && file_view.get_type() != FileType::EncryptedThumbnail && file_view.get_type() != FileType::Thumbnail && file_view.get_type() != FileType::EncryptedThumbnail &&
!node->file_source_ids_.empty()) { !node->file_source_ids_.empty() && node->upload_may_update_file_reference_) {
QueryId id = queries_container_.create(Query{file_id, Query::Upload}); QueryId id = queries_container_.create(Query{file_id, Query::UploadWaitFileReference});
node->upload_id_ = id; node->upload_id_ = id;
node->upload_may_update_file_reference_ = false;
send_closure(G()->file_reference_manager(), &FileReferenceManager::update_file_reference, file_id, send_closure(G()->file_reference_manager(), &FileReferenceManager::update_file_reference, file_id,
node->file_source_ids_, PromiseCreator::lambda([id, actor_id = actor_id(this)](Result<Unit> res) { node->file_source_ids_, PromiseCreator::lambda([id, actor_id = actor_id(this)](Result<Unit> res) {
send_closure(actor_id, &FileManager::on_error, id, Status::Error("FILE_UPLOAD_RESTART")); send_closure(actor_id, &FileManager::on_error, id, Status::Error("FILE_UPLOAD_RESTART"));
@ -2777,19 +2790,11 @@ void FileManager::on_error_impl(FileNodePtr node, FileManager::Query::Type type,
return; return;
} }
if (begins_with(status.message(), "FILE_DOWNLOAD_RESTART")) { if (begins_with(status.message(), "FILE_DOWNLOAD_RESTART")) {
if (ends_with(status.message(), "WITH_FILE_REFERENCE")) { if (!ends_with(status.message(), "WITH_FILE_REFERENCE")) {
if (FileView(node).has_active_remote_location()) {
run_download(node);
return;
}
LOG_IF(WARNING, !node->file_source_ids_.empty())
<< "Got no active remote locations, but have file_source_ids, download will be cancelled "
<< FileView(node).remote_location();
} else {
node->can_search_locally_ = false; node->can_search_locally_ = false;
run_download(node);
return;
} }
run_download(node);
return;
} }
if (!was_active) { if (!was_active) {

View File

@ -151,6 +151,9 @@ class FileNode {
bool pmc_changed_flag_{false}; bool pmc_changed_flag_{false};
bool info_changed_flag_{false}; bool info_changed_flag_{false};
bool upload_may_update_file_reference_{false};
bool download_may_update_file_reference_{false};
void init_ready_size(); void init_ready_size();
void recalc_ready_prefix_size(int64 prefix_offset, int64 ready_prefix_size); void recalc_ready_prefix_size(int64 prefix_offset, int64 ready_prefix_size);
@ -408,7 +411,15 @@ class FileManager : public FileLoadManager::Callback {
class Query { class Query {
public: public:
FileId file_id_; FileId file_id_;
enum Type : int32 { UploadByHash, Upload, Download, SetContent, Generate } type_; enum Type : int32 {
UploadByHash,
UploadWaitFileReference,
Upload,
DownloadWaitFileReferece,
Download,
SetContent,
Generate
} type_;
}; };
struct FileIdInfo { struct FileIdInfo {
FileNodeId node_id_{0}; FileNodeId node_id_{0};