ClickHouse/dbms/src/Processors/ResizeProcessor.cpp

135 lines
3.1 KiB
C++
Raw Normal View History

#include <Processors/ResizeProcessor.h>
namespace DB
{
ResizeProcessor::Status ResizeProcessor::prepare()
{
2019-02-07 18:51:53 +00:00
auto cur_output = outputs.begin();
bool all_outs_full_or_unneeded = true;
bool all_outs_finished = true;
2019-02-07 18:51:53 +00:00
/// Find next output where can push.
auto get_next_out = [&, this]() -> OutputPorts::iterator
{
while (cur_output != outputs.end())
{
2019-02-07 18:51:53 +00:00
if (!cur_output->isFinished())
{
all_outs_finished = false;
if (cur_output->canPush())
{
all_outs_full_or_unneeded = false;
++cur_output;
return std::prev(cur_output);
}
}
2019-02-07 18:51:53 +00:00
++cur_output;
}
2019-02-07 18:51:53 +00:00
return cur_output;
};
2019-02-07 18:51:53 +00:00
auto cur_input = inputs.begin();
bool all_inputs_finished = true;
/// Find next input from where can pull.
auto get_next_input = [&, this]() -> InputPorts::iterator
{
while (cur_input != inputs.end())
{
2019-02-07 18:51:53 +00:00
if (!cur_input->isFinished())
{
all_inputs_finished = false;
2019-02-07 18:51:53 +00:00
cur_input->setNeeded();
if (cur_input->hasData())
{
++cur_input;
return std::prev(cur_input);
}
}
++cur_input;
}
2019-02-07 18:51:53 +00:00
return cur_input;
};
2019-02-07 18:51:53 +00:00
auto get_status_if_no_outputs = [&]() -> Status
{
if (all_outs_finished)
{
2019-02-07 18:51:53 +00:00
for (auto & in : inputs)
in.close();
2019-02-07 18:51:53 +00:00
return Status::Finished;
}
2019-02-07 18:51:53 +00:00
if (all_outs_full_or_unneeded)
{
2019-02-07 18:51:53 +00:00
for (auto & in : inputs)
in.setNotNeeded();
return Status::PortFull;
}
2019-02-07 18:51:53 +00:00
/// Now, we pushed to output, and it must be full.
return Status::PortFull;
};
auto get_status_if_no_inputs = [&]() -> Status
{
if (all_inputs_finished)
{
2019-02-07 18:51:53 +00:00
for (auto & out : outputs)
out.finish();
return Status::Finished;
}
2019-02-07 18:51:53 +00:00
return Status::NeedData;
};
/// Set all inputs needed in order to evenly process them.
/// Otherwise, in case num_outputs < num_inputs and chunks are consumed faster than produced,
/// some inputs can be skipped.
auto set_all_unprocessed_inputs_needed = [&]()
{
for (; cur_input != inputs.end(); ++cur_input)
if (!cur_input->isFinished())
cur_input->setNeeded();
};
2019-02-07 18:51:53 +00:00
while (cur_input != inputs.end() && cur_output != outputs.end())
{
auto output = get_next_out();
if (output == outputs.end())
{
set_all_unprocessed_inputs_needed();
2019-02-07 18:51:53 +00:00
return get_status_if_no_outputs();
}
2019-02-07 18:51:53 +00:00
auto input = get_next_input();
if (input == inputs.end())
return get_status_if_no_inputs();
output->push(input->pull());
}
2019-02-07 18:51:53 +00:00
if (cur_output == outputs.end())
{
set_all_unprocessed_inputs_needed();
2019-02-07 18:51:53 +00:00
return get_status_if_no_outputs();
}
2019-02-07 18:51:53 +00:00
/// cur_input == inputs_end()
return get_status_if_no_inputs();
}
}