mirror of
https://github.com/nestriness/cdc-file-transfer.git
synced 2026-01-31 00:45:35 +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.
245 lines
9.0 KiB
C++
245 lines
9.0 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.
|
|
*/
|
|
|
|
#ifndef CDC_RSYNC_PROGRESS_TRACKER_H_
|
|
#define CDC_RSYNC_PROGRESS_TRACKER_H_
|
|
|
|
#include <string>
|
|
|
|
#include "cdc_rsync/base/cdc_interface.h"
|
|
#include "cdc_rsync/file_finder_and_sender.h"
|
|
#include "common/stopwatch.h"
|
|
|
|
namespace Json {
|
|
class Value;
|
|
}
|
|
|
|
namespace cdc_ft {
|
|
|
|
class ProgressPrinter {
|
|
public:
|
|
ProgressPrinter(bool quiet, bool is_tty) : quiet_(quiet), is_tty_(is_tty) {}
|
|
virtual ~ProgressPrinter() = default;
|
|
|
|
virtual void Print(std::string text, bool newline, int output_width) = 0;
|
|
|
|
bool quiet() const { return quiet_; }
|
|
bool is_tty() const { return is_tty_; }
|
|
|
|
private:
|
|
const bool quiet_;
|
|
const bool is_tty_;
|
|
};
|
|
|
|
class ConsoleProgressPrinter : public ProgressPrinter {
|
|
public:
|
|
ConsoleProgressPrinter(bool quiet, bool is_tty);
|
|
|
|
// Prints |text| to stdout. Adds a line feed (\n) if |newline| is true or
|
|
// is_tty() is false (e.g. logging to a file). Otherwise, just adds a carriage
|
|
// return (\r), so that the next call to Output overwrites the current line.
|
|
// Fills the rest of the line up to |output_width| characters with spaces to
|
|
// properly overwrite the last line.
|
|
// No-op if quiet().
|
|
void Print(std::string text, bool newline, int output_width) override;
|
|
};
|
|
|
|
// Tracks progress of the various stages of rsync and displays them in a human-
|
|
// readable manner.
|
|
class ProgressTracker : public ReportCdcProgress,
|
|
public ReportFindFilesProgress {
|
|
public:
|
|
// |verbosity| (number of -v arguments) impacts the display verbosity.
|
|
// 0 only prints total progress and ETA/time.
|
|
// 1 prints per-file process and ETA/time.
|
|
// |json| prints JSON progress.
|
|
// If |fixed_output_width| > 0, formats output to that width, otherwise, uses
|
|
// the console width.
|
|
ProgressTracker(ProgressPrinter* printer, int verbosity, bool json,
|
|
int fixed_output_width = 0,
|
|
SteadyClock* clock = DefaultSteadyClock::GetInstance());
|
|
~ProgressTracker();
|
|
|
|
// Starts reporting finding all source files to copy.
|
|
// Must be in idle state. Must be called before ReportFileFound().
|
|
void StartFindFiles();
|
|
|
|
// Reports that a file has been found.
|
|
void ReportFileFound();
|
|
|
|
// Reports that a directory has been found.
|
|
void ReportDirFound();
|
|
|
|
// Prints out the 4 files numbers and stores the total bytes for progress
|
|
// calculations. See SendFileStatsResponse in messages.proto for more info.
|
|
void ReportFileStats(uint32_t num_missing_files,
|
|
uint32_t num_extraneous_files,
|
|
uint32_t num_matching_files, uint32_t num_changed_files,
|
|
uint64_t total_missing_bytes,
|
|
uint64_t total_changed_client_bytes,
|
|
uint64_t total_changed_server_bytes,
|
|
uint32_t num_missing_dirs, uint32_t num_extraneous_dirs,
|
|
uint32_t num_matching_dirs, bool whole_file_arg = false,
|
|
bool checksum_arg = false, bool delete_arg = false);
|
|
|
|
// Starts reporting the copy of the file at |filepath| of size |filesize|.
|
|
// Must be in idle state. Must be called before ReportCopyProgress().
|
|
void StartCopy(const std::string& filepath, uint64_t filesize);
|
|
|
|
// Reports that |num_bytes_copied| have been copied for the current file.
|
|
void ReportCopyProgress(uint64_t num_bytes_copied);
|
|
|
|
// Starts reporting the delta sync of the file at |filepath| of size
|
|
// |client_size|. |server_size| is the size of the corresponding file on the
|
|
// server.
|
|
// Must be in idle state. Must be called before ReportSyncProgress().
|
|
void StartSync(const std::string& filepath, uint64_t client_size,
|
|
uint64_t server_size);
|
|
|
|
// ReportCdcProgress:
|
|
|
|
// Reports that |num_client_bytes_processed| of the current client-side file
|
|
// have been read and processed by the delta-transfer algorithm, and that
|
|
// |num_server_bytes_processed| of the current server-side file have been
|
|
// read and processed.
|
|
void ReportSyncProgress(uint64_t num_client_bytes_processed,
|
|
uint64_t num_server_bytes_processed) override;
|
|
|
|
// Starts reporting deletion of extraneous files.
|
|
// Must be in idle state. Must be called before ReportFileDeleted().
|
|
void StartDeleteFiles();
|
|
|
|
// Reports that a file has been deleted.
|
|
void ReportFileDeleted(const std::string& filepath);
|
|
|
|
// Reports that a directory has been deleted.
|
|
void ReportDirDeleted(const std::string& filepath);
|
|
|
|
// Prints final stats (e.g. 100% progress for copy/diff), feeds line and
|
|
// resets state to idle. Must be called
|
|
// - when all files have been found,
|
|
// - after each file copy and
|
|
// - after each diff.
|
|
void Finish();
|
|
|
|
// Gets the time delay (in seconds) between two display updates. Returns a
|
|
// lower number (more updates) in TTY mode, e.g. when running from a terminal,
|
|
// and a higher number otherwise, e.g. when piping stdout to a file.
|
|
double GetDisplayDelaySecForTesting() const { return display_delay_sec_; }
|
|
|
|
private:
|
|
// Prints progress to the console. Rate-limited, so that it can be called
|
|
// often without performance overhead. |finished| should be set if the current
|
|
// item is finished. It adds a line feed.
|
|
// No-op if printer_->quiet().
|
|
void UpdateOutput(bool finished);
|
|
|
|
enum class OutputType { kCopy, kSig, kDiff };
|
|
|
|
// Prints out the progress of the current file (for copy/diff state).
|
|
// Used if |verbosity_| > 0 and not printer_->quiet().
|
|
void OutputFileProgress(OutputType type, double progress,
|
|
bool finished) const;
|
|
|
|
// Wrapper for printer_->Print(), but checks printer_->quiet().
|
|
void Print(std::string text, bool finished) const;
|
|
|
|
// Prints the JSON value |val|.
|
|
void PrintJson(const Json::Value& val, bool finished) const;
|
|
|
|
// Returns the total progress (between 0 and 1).
|
|
double GetTotalProgress() const;
|
|
|
|
// Gets the |total_progress| (between 0 and 1), the total duration so far in
|
|
// |total_sec| and the estimated ETA (time left) in |total_eta_sec|.
|
|
void GetTotalProgressStats(double* total_progress, double* total_sec,
|
|
double* total_eta_sec) const;
|
|
|
|
// Returns a string with the total progress, e.g. " 19% TOT 03:59 ETA".
|
|
std::string GetTotalProgressText() const;
|
|
|
|
// Returns |fixed_output_width_| if > 0 or Util::GetConsoleWidth().
|
|
int GetOutputWidth() const;
|
|
|
|
ProgressPrinter* const printer_;
|
|
const bool only_total_progress_ = false;
|
|
const bool json_ = false;
|
|
const int fixed_output_width_;
|
|
const double display_delay_sec_;
|
|
|
|
// Timer for total copy and diff time (not file search, that's not timed).
|
|
Stopwatch total_timer_;
|
|
// Timer for single file copy and diff time.
|
|
Stopwatch file_timer_;
|
|
// Timer for processing signatures of server files.
|
|
Stopwatch sig_timer_;
|
|
// Timer to limit the rate of console outputs.
|
|
Stopwatch print_timer_;
|
|
|
|
enum class State { kIdle, kSearch, kCopy, kSyncSig, kSyncDiff, kDelete };
|
|
|
|
State state_ = State::kIdle;
|
|
|
|
// Number of files found so far.
|
|
uint32_t files_found_ = 0;
|
|
|
|
// Number of directories found so far.
|
|
uint32_t dirs_found_ = 0;
|
|
|
|
// Path of the file currently copied or synced.
|
|
std::string curr_filepath_;
|
|
// Size of the file at |current_filepath_|.
|
|
uint64_t curr_filesize_ = 0;
|
|
|
|
// Number of bytes of the file at |current_filepath_| already copied.
|
|
uint64_t curr_bytes_copied_ = 0;
|
|
// Total number of bytes already copied.
|
|
uint64_t total_bytes_copied_ = 0;
|
|
// Total number of bytes to copy.
|
|
uint64_t total_bytes_to_copy_ = 0;
|
|
|
|
// Number of signature bytes read so far on the server.
|
|
uint64_t curr_sig_bytes_read_ = 0;
|
|
// Total number of signature bytes already processed on the server.
|
|
uint64_t total_sig_bytes_read_ = 0;
|
|
// Total number of signature bytes.
|
|
uint64_t total_sig_bytes_ = 0;
|
|
// Total size of the server-side file.
|
|
uint64_t server_filesize_ = 0;
|
|
// Duration for signature computation.
|
|
double sig_time_sec_ = 0.0;
|
|
|
|
// Number of bytes of the file at |current_filepath_| already diffed.
|
|
uint64_t curr_bytes_diffed_ = 0;
|
|
// Total number of bytes already diffed.
|
|
uint64_t total_bytes_diffed_ = 0;
|
|
// Total number of bytes to diff.
|
|
uint64_t total_bytes_to_diff_ = 0;
|
|
|
|
// Number of files deleted so far.
|
|
uint32_t files_deleted_ = 0;
|
|
// Total number of files to be deleted.
|
|
uint32_t total_files_to_delete_ = 0;
|
|
// Number of directories deleted so far.
|
|
uint32_t dirs_deleted_ = 0;
|
|
// Total number of directories to be deleted.
|
|
uint32_t total_dirs_to_delete_ = 0;
|
|
};
|
|
|
|
} // namespace cdc_ft
|
|
|
|
#endif // CDC_RSYNC_PROGRESS_TRACKER_H_
|