Revision 6248f75f
Added by david.sorber over 2 years ago
| src/CopyManager.cc | ||
|---|---|---|
|
DBS::CopyManager::CopyManager(CopyManagerOptions& options)
|
||
|
: r_options(options),
|
||
|
m_terminate(false),
|
||
|
p_mainThread(nullptr)
|
||
|
m_running(false),
|
||
|
p_mainThread(nullptr),
|
||
|
p_counterThread(nullptr),
|
||
|
m_totalEntries(0),
|
||
|
m_invalidEntries(0),
|
||
|
m_processedEntries(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
DBS::CopyManager::~CopyManager()
|
||
|
{
|
||
|
// Add processor thread terminators
|
||
|
// Add copy thread terminators
|
||
|
for (uint32_t idx = 0; idx < r_options.getNumCopyThreads(); ++idx)
|
||
|
{
|
||
|
m_entryQueue.push_back(ENTRY_TERMINATOR);
|
||
|
}
|
||
|
|
||
|
// Join and delete thread terminators
|
||
|
// Join and delete the counter thread
|
||
|
if (p_counterThread != nullptr)
|
||
|
{
|
||
|
p_counterThread->join();
|
||
|
delete p_counterThread;
|
||
|
p_counterThread = nullptr;
|
||
|
}
|
||
|
|
||
|
// Join and delete thread copy threads
|
||
|
for (auto& thread : m_copyThreads)
|
||
|
{
|
||
|
thread->join();
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
int DBS::CopyManager::run()
|
||
|
void DBS::CopyManager::run()
|
||
|
{
|
||
|
// Spawn the main thread and return
|
||
|
m_running = true;
|
||
|
p_mainThread = new std::thread(&CopyManager::mainThreadBody, this);
|
||
|
}
|
||
|
|
||
|
int DBS::CopyManager::waitForComplete()
|
||
|
{
|
||
|
// Cleanup the main thread
|
||
|
if (p_mainThread != nullptr)
|
||
|
{
|
||
|
if (p_mainThread->joinable())
|
||
|
{
|
||
|
p_mainThread->join();
|
||
|
}
|
||
|
delete p_mainThread;
|
||
|
p_mainThread = nullptr;
|
||
|
}
|
||
|
m_running = false;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void DBS::CopyManager::mainThreadBody()
|
||
|
{
|
||
|
// Spawn counter thread which runs in the background to count source
|
||
|
// directory entries
|
||
|
p_counterThread = new std::thread(&CopyManager::counterThreadBody, this);
|
||
|
|
||
|
// Copy top level source directory itself to destination directory rather
|
||
|
// than just the contents of the source directory. To support this option
|
||
|
// modify the destination directory path and pre-create the top level
|
||
| ... | ... | |
|
{
|
||
|
LOG(error) << "create_directories(" << newDestPath << ") -- "
|
||
|
<< errorCode.value() << " -- " << errorCode.message();
|
||
|
return -1;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
// TODO: handle top level directory metadata
|
||
| ... | ... | |
|
new std::thread(&CopyManager::copyThreadBody, this));
|
||
|
}
|
||
|
|
||
|
// Spawn the main thread
|
||
|
p_mainThread = new std::thread(&CopyManager::mainThreadBody, this);
|
||
|
p_mainThread->join();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void DBS::CopyManager::mainThreadBody()
|
||
|
{
|
||
|
// Recursively iterate over the source directory and add each entry to the
|
||
|
// queue
|
||
|
const std::string& srcPath(r_options.getSrcPath());
|
||
|
for (const auto& dirEntry : sfs::recursive_directory_iterator(srcPath))
|
||
|
{
|
||
|
// Flow control -- delay until the entry queue is bewlo the specified
|
||
|
// Flow control -- delay until the entry queue is below the specified
|
||
|
// threshold size before proceeding
|
||
|
while (m_entryQueue.size() >= r_options.getFlowControlThreshold())
|
||
|
{
|
||
| ... | ... | |
|
m_entryQueue.push_back(dirEntry);
|
||
|
}
|
||
|
|
||
|
// Add processor thread terminators
|
||
|
// Add copy thread terminators
|
||
|
for (uint32_t idx = 0; idx < r_options.getNumCopyThreads(); ++idx)
|
||
|
{
|
||
|
m_entryQueue.push_back(ENTRY_TERMINATOR);
|
||
|
}
|
||
|
|
||
|
// Join and delete the counter thread
|
||
|
if (p_counterThread != nullptr)
|
||
|
{
|
||
|
p_counterThread->join();
|
||
|
delete p_counterThread;
|
||
|
p_counterThread = nullptr;
|
||
|
}
|
||
|
|
||
|
// Join and delete thread copy threads
|
||
|
for (auto& thread : m_copyThreads)
|
||
|
{
|
||
|
thread->join();
|
||
|
delete thread;
|
||
|
}
|
||
|
m_copyThreads.clear();
|
||
|
|
||
|
// No longer running
|
||
|
m_running = false;
|
||
|
}
|
||
|
|
||
|
void DBS::CopyManager::copyThreadBody()
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
incProcessedEntries();
|
||
|
LOG(debug) << "Created directory: " << entry.path();
|
||
|
}
|
||
|
else if (entry.is_regular_file())
|
||
| ... | ... | |
|
continue;
|
||
|
}
|
||
|
|
||
|
close(fromFd);
|
||
|
close(toFd);
|
||
|
close(fromFd);
|
||
|
close(toFd);
|
||
|
incProcessedEntries();
|
||
|
|
||
|
LOG(debug) << "Copy: " << entry.path().string()
|
||
|
<< " to: " << destFilePath.string();
|
||
|
}
|
||
| ... | ... | |
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DBS::CopyManager::counterThreadBody()
|
||
|
{
|
||
|
const std::string& srcPath(r_options.getSrcPath());
|
||
|
for (const auto& dirEntry : sfs::recursive_directory_iterator(srcPath))
|
||
|
{
|
||
|
if (dirEntry.is_directory() || dirEntry.is_regular_file())
|
||
|
{
|
||
|
incTotalEntries();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
incInvalidEntries();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
Add progress bar; version: 0.2.0.