Project

General

Profile

Download (6.39 KB) Statistics
| Branch: | Revision:
6248f75f david.sorber
/********************************************************************
* CONFIDENTIAL - All source code is the propriety and confidential *
* information of David Sorber. *
* *
* Copyright 2024 David Sorber *
* Unpublished -- all rights reserved under the copyright laws *
* of the United States. *
********************************************************************/

#include <chrono>
1309de5c david.sorber
#include <cstdint>
#include <filesystem>
#include <iostream>
#include <string>
#include <thread>

eee13fa3 david.sorber
#include "CLI11.hpp"
6248f75f david.sorber
#include "indicators.hpp"
eee13fa3 david.sorber
2c54c4c3 david.sorber
#include "CopyManagerOptions.h"
#include "CopyManager.h"
eee13fa3 david.sorber
#include "Logger.h"
2c54c4c3 david.sorber
1309de5c david.sorber
namespace sfs = std::filesystem;

4fd46efa david.sorber
const std::string VERSION("v0.2.1");
eee13fa3 david.sorber
const std::string BOLD{"\033[1m"};
const std::string ENDC{"\033[0m"};
const std::string RED{"\033[31m"};
const std::string YELLOW{"\033[33m"};
const std::string PURPLE{"\033[35m"};
const std::string LBLUE{"\033[1;34m"};
6248f75f david.sorber
const std::string UP_ONE = "\033[1A";
1309de5c david.sorber
2c54c4c3 david.sorber
1309de5c david.sorber
int main(int argc, char** argv)
{
eee13fa3 david.sorber
std::cout << "copytool -- " << VERSION << "\n" << std::endl;
CLI::App app{"copytool"};

// Required fundamental options
std::string srcPath;
std::string destPath;

// Add required positional arguments
app.add_option("source_path", srcPath,
"source path; copy files FROM this path")->required()
->check(CLI::ExistingDirectory);
app.add_option("dest_path", destPath,
"destination path; copy files TO this path")->required()
->check(CLI::ExistingDirectory);

// Logging related options
4fd46efa david.sorber
bool enableLog = DBS::CopyManagerOptions::DEFAULT_ENABLE_LOG;
eee13fa3 david.sorber
bool logToStderr = DBS::CopyManagerOptions::DEFAULT_LOG_TO_STDERR;
std::string logFilePath{DBS::CopyManagerOptions::DEFAULT_LOG_FILE_PATH};
int logLevel = DBS::CopyManagerOptions::DEFAULT_LOG_LEVEL;

// Add logging options
4fd46efa david.sorber
app.add_flag("--enable-log", enableLog, "enable the log (default: disabled)");
eee13fa3 david.sorber
app.add_flag("--log-to-stderr", logToStderr, "write log messages to stderr");
app.add_option("-l,--log-file-path", logFilePath, "log file path");
app.add_option("--log-level", logLevel,
"default log message level (error=0, warn=1, info=2, debug=3, trace=4)")
->check(CLI::Range(0, 4));
1309de5c david.sorber
eee13fa3 david.sorber
// Other options
uint32_t flowControlThreshold = DBS::CopyManagerOptions::DEFAULT_FC_THRESHOLD;
uint32_t numCopyThreads = DBS::CopyManagerOptions::DEFAULT_NUM_COPY_THREADS;
bool copyTopLevel = DBS::CopyManagerOptions::DEFAULT_COPY_TOPLEVEL;

app.add_option("--flow-control-threshold", flowControlThreshold,
4fd46efa david.sorber
"flow control threshold (default: "
+ std::to_string(flowControlThreshold) + ")")
eee13fa3 david.sorber
->check(CLI::Range(100,65535));
app.add_option("-n,--num-copy-threads", numCopyThreads,
4fd46efa david.sorber
"number of copy threads to spawn (default: "
+ std::to_string(numCopyThreads) + ")")
eee13fa3 david.sorber
->check(CLI::Range(1, 512));
app.add_flag("--copy-top-level", copyTopLevel,
"copy top level source directory to destination rather then "
"the contents of the top level source directory (which is "
"the default behavior)");

// Parse options
CLI11_PARSE(app, argc, argv);

// Build options object
DBS::CopyManagerOptions options(srcPath,
destPath,
4fd46efa david.sorber
enableLog,
eee13fa3 david.sorber
logToStderr,
logFilePath,
logLevel,
flowControlThreshold,
numCopyThreads,
copyTopLevel);

// Prime the logger
DBS::Logger::getInstance(DBS::off, &options);
LOG(DBS::info) << "copytool -- DBS";

// Display a warning if the specified number of copy threads exceeds the
// number of cores in the system
uint32_t numCores = std::thread::hardware_concurrency();
if (numCopyThreads > numCores)
1309de5c david.sorber
{
eee13fa3 david.sorber
std::cout << BOLD << YELLOW << "WARNING: " << ENDC
<< "The number of copy threads specified ("
<< numCopyThreads << ") exceeds the number of cores in the "
<< "system (" << numCores << "); proceed with caution.\n"
<< std::endl;
1309de5c david.sorber
}

eee13fa3 david.sorber
// Create the copy manager and run it
2c54c4c3 david.sorber
DBS::CopyManager manager(options);
6248f75f david.sorber
// The callback structure requires a global
indicators::BlockProgressBar pBarEta{
4fd46efa david.sorber
indicators::option::BarWidth{80},
indicators::option::Start{"["},
indicators::option::End{"]"},
indicators::option::PrefixText{"Complete: "},
indicators::option::ShowElapsedTime{true},
indicators::option::ShowRemainingTime{true},
6248f75f david.sorber
};

// Run the manager
manager.run();

indicators::show_console_cursor(false);
while (manager.isRunning())
{
// Calculate percent complete
double percent = (static_cast<double>(manager.getProcessedEntries()) /
manager.getTotalEntries()) * 100;

pBarEta.set_progress(percent);
pBarEta.set_option(indicators::option::PostfixText{ " -- " +
std::to_string(manager.getProcessedEntries()) + "/" +
std::to_string(manager.getTotalEntries())
});


std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << std::endl << UP_ONE;
}

int rc = manager.waitForComplete();

pBarEta.set_progress(100.0);
pBarEta.set_option(indicators::option::PostfixText{" -- " +
std::to_string(manager.getProcessedEntries()) + "/" +
std::to_string(manager.getTotalEntries())
});
pBarEta.mark_as_completed();
indicators::show_console_cursor(true);
std::cout << std::endl;
1309de5c david.sorber
4fd46efa david.sorber
// Display warning to user if any invalid/unsupported directory entries were
// found while copying
if (manager.getInvalidEntries() > 0)
{
std::cout << BOLD << YELLOW << "WARNING: " << ENDC
<< manager.getInvalidEntries() << " unsupported directory "
<< "entries (symlinks, FIFOs, etc.) were NOT copied.\n"
<< std::endl;
}

eee13fa3 david.sorber
return rc;
1309de5c david.sorber
}