use arguments to configure instead of hardcoded paths

This commit is contained in:
Lily Tsuru 2024-10-22 02:59:58 -04:00
parent 9af77c6159
commit 59ac84466f
3 changed files with 58 additions and 28 deletions

View file

@ -72,6 +72,8 @@ struct ThreadPool {
/// Used to notify on shutdown /// Used to notify on shutdown
std::atomic_bool threadsShouldShutdown { false }; std::atomic_bool threadsShouldShutdown { false };
// implement these out of line
std::size_t QueueLength(std::size_t worker) const { std::size_t QueueLength(std::size_t worker) const {
std::unique_lock lk(this->taskQueues[worker].lock); std::unique_lock lk(this->taskQueues[worker].lock);
return this->taskQueues[worker].queue.size(); return this->taskQueues[worker].queue.size();

View file

@ -1,10 +1,13 @@
#pragma once #pragma once
#include <vector> #include <vector>
/// Port of tree.py to C++ /// A simplistic N-ary/generic tree. Probably not very good for data locality.
template <class T> template <class T>
struct Tree { struct Tree {
// FIXME make T not require default constructability // FIXME:
// - make T not require default constructability
// - move instead of copy into leaf
// - use "btree-like" repressentation of N-ary nodes to save memory
struct Node { struct Node {
protected: protected:
friend Tree; friend Tree;

View file

@ -1,3 +1,4 @@
#include <cstring>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <indicators/progress_bar.hpp> #include <indicators/progress_bar.hpp>
@ -11,26 +12,45 @@
namespace ind = indicators; namespace ind = indicators;
int main() { int main(int argc, char** argv) {
std::ifstream ifs("./testdata/samples.sort"); if(argc != 4) {
vxorg::VxHeavenTree tree; std::fprintf(stderr, "usage: %s [path to list] [source path] [destination path]\n", argv[0]);
return 1;
}
vxorg::VxHeavenTree sample_tree;
// used for os filesystem ops // used for os filesystem ops
ThreadPool fsPool(4); ThreadPool filesystem_threadpool(4);
vxorg::parse_into_tree(tree, ifs); // Parse into the sample tree
std::ifstream ifs(argv[1]);
std::filesystem::path root = std::filesystem::current_path() / "testdata"; if(!ifs) {
std::filesystem::path unorg = root / "unorg"; char err[256]{};
std::filesystem::path org = root / "org"; strerror_r(errno, &err[0], sizeof(err)-1);
std::fprintf(stderr, "Could not open sample list \"%s\": %s", argv[1], err);
return 1;
}
if(!std::filesystem::exists(org)) vxorg::parse_into_tree(sample_tree, ifs);
std::filesystem::create_directories(org);
std::filesystem::path unorganized_source_path = argv[2];
std::filesystem::path organized_destination_path = argv[3];
if(!std::filesystem::exists(unorganized_source_path)) {
std::fprintf(stderr, "Source path \"%s\" does not exist", argv[2]);
return 1;
}
if(!std::filesystem::exists(organized_destination_path))
std::filesystem::create_directories(organized_destination_path);
std::size_t sampleCount = 0; std::size_t sampleCount = 0;
// Walk the tree to get the amount of sample nodes // Walk the tree to get the amount of sample nodes
tree.walk([&](auto* node) { sample_tree.walk([&](auto* node) {
if(node->data().is_sample) if(node->data().is_sample)
sampleCount++; sampleCount++;
}); });
@ -41,16 +61,17 @@ int main() {
ind::option::Lead { "" }, ind::option::Lead { "" },
ind::option::Remainder { "-" }, ind::option::Remainder { "-" },
ind::option::End { " ]" }, ind::option::End { " ]" },
ind::option::ForegroundColor { ind::Color::cyan }, ind::option::ForegroundColor { ind::Color::red },
ind::option::FontStyles { std::vector<ind::FontStyle> { ind::FontStyle::bold } }, ind::option::FontStyles { std::vector<ind::FontStyle> { ind::FontStyle::bold } },
ind::option::MaxProgress { sampleCount } }; ind::option::MaxProgress { sampleCount } };
// Walk the tree to perform the operation // Walk the tree to perform the operation
tree.walk([&](auto* node) { sample_tree.walk([&](auto* node) {
auto tabulation_level = node->parent_count();
auto& data = node->data(); auto& data = node->data();
#if 0 #if 0
auto tabulation_level = node->parent_count();
if(tabulation_level != 0) { if(tabulation_level != 0) {
for(auto i = 0; i < tabulation_level; ++i) { for(auto i = 0; i < tabulation_level; ++i) {
std::printf("\t"); std::printf("\t");
@ -75,26 +96,26 @@ int main() {
std::string sample_name = vxorg::get_sample_name(node); std::string sample_name = vxorg::get_sample_name(node);
// paths // paths
auto path = org / vxorg::get_sample_path(node); auto path = organized_destination_path / vxorg::get_sample_path(node);
auto source_path = unorg / vxorg::get_sample_name(node); auto source_path = unorganized_source_path / vxorg::get_sample_name(node);
if(!std::filesystem::exists(source_path)) { if(!std::filesystem::exists(source_path)) {
std::printf("WARNING: sample %s/%s in tree (source disk file %s) does not exist\n", path.string().c_str(), sample_name.c_str(), std::printf("WARNING: sample %s in tree (source disk file %s) does not exist\n", sample_name.c_str(),
source_path.string().c_str()); source_path.string().c_str());
} else { } else {
fsPool.add_task([path, source_path, sample_name, &bar]() { filesystem_threadpool.add_task([path, source_path, sample_name, &bar]() {
bar.set_option(ind::option::PostfixText { std::format("Moving {}", sample_name) }); bar.set_option(ind::option::PostfixText { std::format("Moving {}", sample_name) });
auto dest_path = path / sample_name; auto dest_path = path / sample_name;
// possibly TOCTOUable but it should:tm: be fine? // possibly TOCTOUable but it should:tm: be fine?
if(!std::filesystem::exists(path)) { if(!std::filesystem::exists(path)) {
std::filesystem::create_directories(path); std::filesystem::create_directories(path);
} }
if(std::filesystem::exists(dest_path)) { if(std::filesystem::exists(dest_path)) {
std::filesystem::remove(dest_path); std::filesystem::remove(dest_path);
} }
std::filesystem::rename(source_path, dest_path); std::filesystem::rename(source_path, dest_path);
bar.tick(); bar.tick();
@ -105,5 +126,9 @@ int main() {
#endif #endif
}); });
filesystem_threadpool.shutdown();
bar.mark_as_completed();
std::printf("Done.\n");
return 0; return 0;
} }