| 152 | } |
| 153 | |
| 154 | void BlockingJoinNode::ProcessBuildInputAsync( |
| 155 | RuntimeState* state, JoinBuilder* build_sink, Status* status) { |
| 156 | DCHECK(!UseSeparateBuild(state->query_options())); |
| 157 | DCHECK(status != nullptr); |
| 158 | SCOPED_THREAD_COUNTER_MEASUREMENT(state->total_thread_statistics()); |
| 159 | { |
| 160 | SCOPED_CONCURRENT_STOP_WATCH(&built_probe_overlap_stop_watch_); |
| 161 | *status = child(1)->Open(state); |
| 162 | } |
| 163 | if (status->ok()) *status = AcquireResourcesForBuild(state); |
| 164 | if (status->ok()) *status = SendBuildInputToSink<true>(state, build_sink); |
| 165 | // IMPALA-1863: If the build-side thread failed, then we need to close the right |
| 166 | // (build-side) child to avoid a potential deadlock between fragment instances. This |
| 167 | // is safe to do because while the build may have partially completed, it will not be |
| 168 | // probed. BlockingJoinNode::Open() will return failure as soon as child(0)->Open() |
| 169 | // completes. |
| 170 | if (CanCloseBuildEarly() || !status->ok()) { |
| 171 | // Release resources in 'build_batch_' and 'build_sink' before closing the children |
| 172 | // as some of the resources are still accounted towards the children node. |
| 173 | build_batch_.reset(); |
| 174 | if (!status->ok()) build_sink->Close(state); |
| 175 | child(1)->Close(state); |
| 176 | } |
| 177 | |
| 178 | // Release the thread token as soon as possible (before the main thread joins |
| 179 | // on it). This way, if we had a chain of 10 joins using 1 additional thread, |
| 180 | // we'd keep the additional thread busy the whole time. |
| 181 | state->resource_pool()->ReleaseThreadToken(false); |
| 182 | } |
| 183 | |
| 184 | Status BlockingJoinNode::LookupSeparateJoinBuilder(RuntimeState* state, |
| 185 | JoinBuilder** separate_builder) { |
nothing calls this directly
no test coverage detected