2424 */
2525#include < executor/LoadExecutor.h>
2626#include < iostream>
27+ #include < fstream>
28+ #include < filesystem>
2729#include < encoding/EncodingLevel.h>
2830#include < physical/storage/LocalFS.h>
2931#include < load/Parameters.h>
3032#include < chrono>
33+ #include < thread>
3134#include < load/PixelsConsumer.h>
3235
3336void LoadExecutor::execute (const bpo::variables_map &ns, const std::string &command)
3437{
3538 std::string schema = ns[" schema" ].as <std::string>();
39+ if (std::filesystem::exists (schema) && std::filesystem::is_regular_file (schema))
40+ {
41+ std::ifstream ifs (schema);
42+ if (ifs.is_open ())
43+ {
44+ std::stringstream buffer;
45+ buffer << ifs.rdbuf ();
46+ schema = buffer.str ();
47+ }
48+ }
3649 std::string origin = ns[" origin" ].as <std::string>();
3750 std::string target = ns[" target" ].as <std::string>();
3851 int rowNum = ns[" row_num" ].as <int >();
3952 std::string regex = ns[" row_regex" ].as <std::string>();
4053 EncodingLevel encodingLevel = EncodingLevel::from (ns[" encoding_level" ].as <int >());
4154 bool nullPadding = ns[" nulls_padding" ].as <bool >();
55+ int concurrency = ns[" concurrency" ].as <int >();
4256
4357 if (origin.back () != ' /' )
4458 {
@@ -55,7 +69,7 @@ void LoadExecutor::execute(const bpo::variables_map &ns, const std::string &comm
5569 }
5670
5771 auto startTime = std::chrono::system_clock::now ();
58- if (startConsumers (inputFiles, parameters, loadedFiles))
72+ if (startConsumers (inputFiles, parameters, loadedFiles, concurrency ))
5973 {
6074 std::cout << command << " is successful" << std::endl;
6175 }
@@ -65,14 +79,47 @@ void LoadExecutor::execute(const bpo::variables_map &ns, const std::string &comm
6579 }
6680 auto endTime = std::chrono::system_clock::now ();
6781 std::chrono::duration<double > elapsedSeconds = endTime - startTime;
68- std::cout << " Text file in " << origin << " are loaded by 1 thread in "
82+ std::cout << " Text file in " << origin << " are loaded by " << concurrency << " thread(s) in "
6983 << elapsedSeconds.count () << " seconds." << std::endl;
7084}
7185
7286bool LoadExecutor::startConsumers (const std::vector <std::string> &inputFiles, Parameters parameters,
73- const std::vector <std::string> &loadedFiles)
87+ const std::vector <std::string> &loadedFiles, int concurrency )
7488{
75- PixelsConsumer consumer (inputFiles, parameters, loadedFiles);
76- consumer.run ();
89+ if (concurrency <= 1 || inputFiles.size () <= 1 )
90+ {
91+ // Single-threaded mode
92+ PixelsConsumer consumer (inputFiles, parameters, loadedFiles);
93+ consumer.run ();
94+ }
95+ else
96+ {
97+ // Multi-threaded mode: each thread processes one file
98+ std::vector<std::thread> threads;
99+ int numThreads = std::min (concurrency, static_cast <int >(inputFiles.size ()));
100+ std::vector<std::vector<std::string>> inputfilesQueue (numThreads);
101+ int currentThread=0 ;
102+ for (int i = 0 ; i < inputFiles.size (); ++i)
103+ {
104+ inputfilesQueue[(currentThread++)%numThreads].push_back (inputFiles[i]);
105+ }
106+ // Each thread gets one file queue to process
107+ for (int i=0 ;i<numThreads;i++)
108+ {
109+ auto queue=inputfilesQueue[i];
110+ threads.emplace_back ([queue, parameters, loadedFiles]() {
111+ PixelsConsumer consumer (queue, parameters, loadedFiles);
112+ consumer.run ();
113+ });
114+ }
115+ // Wait for all threads to complete
116+ for (auto &thread : threads)
117+ {
118+ if (thread.joinable ())
119+ {
120+ thread.join ();
121+ }
122+ }
123+ }
77124 return true ;
78- }
125+ }
0 commit comments