|
/********************************************************************
|
|
* 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>
|
|
#include <system_error>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include "CopyManager.h"
|
|
|
|
|
|
DBS::CopyManager::CopyManager(CopyManagerOptions& options)
|
|
: r_options(options),
|
|
m_terminate(false),
|
|
p_mainThread(nullptr)
|
|
{
|
|
}
|
|
|
|
DBS::CopyManager::~CopyManager()
|
|
{
|
|
// Add processor thread terminators
|
|
for (uint32_t idx = 0; idx < r_options.getNumProcThreads(); ++idx)
|
|
{
|
|
m_entryQueue.push_back(ENTRY_TERMINATOR);
|
|
}
|
|
|
|
// Join and delete thread terminators
|
|
for (auto& thread : m_procThreads)
|
|
{
|
|
thread->join();
|
|
delete thread;
|
|
}
|
|
m_procThreads.clear();
|
|
|
|
// Cleanup the main thread
|
|
if (p_mainThread != nullptr)
|
|
{
|
|
if (p_mainThread->joinable())
|
|
{
|
|
p_mainThread->join();
|
|
}
|
|
delete p_mainThread;
|
|
p_mainThread = nullptr;
|
|
}
|
|
}
|
|
|
|
int DBS::CopyManager::run()
|
|
{
|
|
// Spawn processor threads
|
|
for (uint32_t idx = 0; idx < r_options.getNumProcThreads(); ++idx)
|
|
{
|
|
m_procThreads.push_back(
|
|
new std::thread(&CopyManager::processThreadBody, this));
|
|
}
|
|
|
|
// Spawn the main thread
|
|
p_mainThread = new std::thread(&CopyManager::mainThreadBody, this);
|
|
|
|
|
|
p_mainThread->join();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void DBS::CopyManager::mainThreadBody()
|
|
{
|
|
const std::string& srcPath(r_options.getSrcPath());
|
|
for (const auto& dirEntry : sfs::recursive_directory_iterator(srcPath))
|
|
{
|
|
// Flow control
|
|
while (m_entryQueue.size() >= r_options.getFlowControlThreshold())
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
}
|
|
|
|
// std::cout << "PATH: " << dirEntry << std::endl;
|
|
m_entryQueue.push_back(dirEntry);
|
|
}
|
|
|
|
// Add processor thread terminators
|
|
for (uint32_t idx = 0; idx < r_options.getNumProcThreads(); ++idx)
|
|
{
|
|
m_entryQueue.push_back(ENTRY_TERMINATOR);
|
|
}
|
|
}
|
|
|
|
|
|
void DBS::CopyManager::processThreadBody()
|
|
{
|
|
sfs::directory_entry entry;
|
|
struct stat statBuf{};
|
|
int rc = 0;
|
|
std::error_code errorCode;
|
|
|
|
while (true)
|
|
{
|
|
// Grab entry from queue
|
|
entry = m_entryQueue.pop_front();
|
|
if (entry == ENTRY_TERMINATOR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (entry.is_directory())
|
|
{
|
|
// Directory entry
|
|
const char* dirPath = entry.path().string().c_str();
|
|
rc = stat(dirPath, &statBuf);
|
|
|
|
if (! sfs::create_directories(entry.path(), errorCode))
|
|
{
|
|
// TODO: log it
|
|
}
|
|
}
|
|
else if (entry.is_regular_file())
|
|
{
|
|
// Regular file entry
|
|
}
|
|
else
|
|
{
|
|
// Unsupported entry type
|
|
// TODO: log it?
|
|
}
|
|
|
|
|
|
std::cout << "PATH: " << entry << std::endl;
|
|
}
|
|
}
|