mirror of
https://github.com/nestriness/cdc-file-transfer.git
synced 2026-01-30 14:35:37 +02:00
The tools allow efficient and fast synchronization of large directory trees from a Windows workstation to a Linux target machine. cdc_rsync* support efficient copy of files by using content-defined chunking (CDC) to identify chunks within files that can be reused. asset_stream_manager + cdc_fuse_fs support efficient streaming of a local directory to a remote virtual file system based on FUSE. It also employs CDC to identify and reuse unchanged data chunks.
112 lines
3.5 KiB
C++
112 lines
3.5 KiB
C++
// Copyright 2022 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "cdc_rsync_server/file_deleter_and_sender.h"
|
|
|
|
#include "cdc_rsync/base/message_pump.h"
|
|
#include "common/log.h"
|
|
#include "common/path.h"
|
|
#include "common/status.h"
|
|
|
|
namespace cdc_ft {
|
|
|
|
FileDeleterAndSender::FileDeleterAndSender(MessagePump* message_pump,
|
|
size_t request_size_threshold)
|
|
: message_pump_(message_pump),
|
|
request_size_threshold_(request_size_threshold) {
|
|
assert(message_pump_);
|
|
}
|
|
|
|
FileDeleterAndSender::~FileDeleterAndSender() = default;
|
|
|
|
absl::Status FileDeleterAndSender::DeleteAndSendFileOrDir(
|
|
const std::string& base_dir, const std::string& relative_path, bool dry_run,
|
|
bool is_directory) {
|
|
std::string filepath = path::Join(base_dir, relative_path);
|
|
if (!dry_run) {
|
|
LOG_INFO("Removing %s", filepath.c_str());
|
|
absl::Status status = path::RemoveFile(filepath);
|
|
if (!status.ok()) {
|
|
return WrapStatus(status, "Failed to remove '%s'", filepath);
|
|
}
|
|
}
|
|
|
|
std::string relative_dir = path::DirName(relative_path);
|
|
if (!relative_dir.empty()) path::EnsureEndsWithPathSeparator(&relative_dir);
|
|
if (response_.directory() != relative_dir) {
|
|
// Flush files in previous directory.
|
|
absl::Status status = SendFilesAndDirs();
|
|
if (!status.ok()) {
|
|
return WrapStatus(
|
|
status, "Failed to send deleted files and directories to client");
|
|
}
|
|
|
|
// Set new directory.
|
|
response_.set_directory(relative_dir);
|
|
response_size_ = response_.directory().length();
|
|
}
|
|
|
|
std::string filename = path::BaseName(relative_path);
|
|
if (is_directory) {
|
|
*response_.add_dirs() = filename;
|
|
} else {
|
|
*response_.add_files() = filename;
|
|
}
|
|
response_size_ += filename.size();
|
|
|
|
if (response_size_ >= request_size_threshold_) {
|
|
absl::Status status = SendFilesAndDirs();
|
|
if (!status.ok()) {
|
|
return WrapStatus(
|
|
status, "Failed to send deleted files and directories to client");
|
|
}
|
|
}
|
|
|
|
return absl::OkStatus();
|
|
}
|
|
|
|
absl::Status FileDeleterAndSender::Flush() {
|
|
absl::Status status = SendFilesAndDirs();
|
|
if (!status.ok()) {
|
|
return WrapStatus(status,
|
|
"Failed to send deleted files and directories to client");
|
|
}
|
|
|
|
// Send an empty batch as EOF indicator.
|
|
assert(response_.files_size() == 0 && response_.dirs_size() == 0);
|
|
status = message_pump_->SendMessage(PacketType::kAddDeletedFiles, response_);
|
|
if (!status.ok()) {
|
|
return WrapStatus(status, "Failed to send EOF indicator");
|
|
}
|
|
|
|
return absl::OkStatus();
|
|
}
|
|
|
|
absl::Status FileDeleterAndSender::SendFilesAndDirs() {
|
|
if (response_.files_size() == 0 && response_.dirs_size() == 0) {
|
|
return absl::OkStatus();
|
|
}
|
|
|
|
absl::Status status =
|
|
message_pump_->SendMessage(PacketType::kAddDeletedFiles, response_);
|
|
if (!status.ok()) {
|
|
return WrapStatus(status, "Failed to send AddDeletedFilesResponse");
|
|
}
|
|
response_.Clear();
|
|
response_size_ = response_.directory().length();
|
|
return absl::OkStatus();
|
|
}
|
|
|
|
} // namespace cdc_ft
|