// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "exec/nested-loop-join-builder.h"
#include "exprs/scalar-expr.h"
#include "exprs/scalar-expr-evaluator.h"

#include <utility>

#include "runtime/fragment-state.h"
#include "runtime/mem-tracker.h"
#include "runtime/query-state.h"
#include "runtime/row-batch.h"
#include "runtime/runtime-state.h"
#include "service/hs2-util.h"
#include "util/min-max-filter.h"
#include "util/runtime-profile-counters.h"

#include "common/names.h"

using namespace impala;

DataSink* NljBuilderConfig::CreateSink(RuntimeState* state) const {
  // We have one fragment per sink, so we can use the fragment index as the sink ID.
  TDataSinkId sink_id = state->fragment().idx;
  return NljBuilder::CreateSeparateBuilder(sink_id, *this, state);
}

Status NljBuilderConfig::Init(
    const TDataSink& tsink, const RowDescriptor* input_row_desc, FragmentState* state) {
  RETURN_IF_ERROR(JoinBuilderConfig::Init(tsink, input_row_desc, state));
  const TJoinBuildSink& join_build_sink = tsink.join_build_sink;
  const vector<TRuntimeFilterDesc>& filter_descs = join_build_sink.runtime_filters;
  RETURN_IF_ERROR(InitExprsAndFilters(filter_descs, state));
  return Status::OK();
}

Status NljBuilderConfig::DoInitExprsAndFilters(
    const vector<TRuntimeFilterDesc>& filter_descs,
    const vector<TRuntimeFilterSource>& filters_produced, FragmentState* state) {
  // Skip over filters that are not produced by the instances of the builder, i.e.
  // broadcast filters where this instance was not selected as a filter producer.
  for (const TRuntimeFilterDesc& filter_desc : filter_descs) {
    DCHECK(state->query_options().runtime_filter_mode == TRuntimeFilterMode::GLOBAL
        || filter_desc.is_broadcast_join || state->query_options().num_nodes == 1);
    DCHECK(!state->query_options().disable_row_runtime_filtering
        || filter_desc.applied_on_partition_columns);
    auto it = std::find_if(filters_produced.begin(), filters_produced.end(),
        [this, &filter_desc](const TRuntimeFilterSource f) {
          return f.src_node_id == join_node_id_ && f.filter_id == filter_desc.filter_id;
        });
    if (it == filters_produced.end()) continue;
    filter_descs_.push_back(filter_desc);

    ScalarExpr* filter_expr = nullptr;
    RETURN_IF_ERROR(
        ScalarExpr::Create(filter_desc.src_expr, *input_row_desc_, state, &filter_expr));
    filter_exprs_.push_back(filter_expr);
  }
  return Status::OK();
}

Status NljBuilderConfig::InitExprsAndFilters(
    const vector<TRuntimeFilterDesc>& filter_descs, FragmentState* state) {
  const std::vector<const TPlanFragmentInstanceCtx*>& instance_ctxs =
      state->instance_ctxs();
  // Skip over filters that are not produced by the instances of the builder, i.e.
  // broadcast filters where this instance was not selected as a filter producer.
  // We can pick any instance since the filters produced should be the same for all
  // instances.
  if (instance_ctxs.size() > 0) {
    const TPlanFragmentInstanceCtx& instance_ctx = *instance_ctxs[0];
    const vector<TRuntimeFilterSource>& filters_produced = instance_ctx.filters_produced;
    return DoInitExprsAndFilters(filter_descs, filters_produced, state);
  }
  return Status::OK();
}

Status NljBuilderConfig::InitExprsAndFilters(
    const vector<TRuntimeFilterDesc>& filter_descs, RuntimeState* state) {
  QueryState* queryState = state->query_state();
  FragmentState* fragmentState = queryState->findFragmentState(state->fragment().idx);
  DCHECK(fragmentState != nullptr);
  // Skip over filters that are not produced by the instances of the builder, i.e.
  // broadcast filters where this instance was not selected as a filter producer.
  const TPlanFragmentInstanceCtx& instance_ctx = state->instance_ctx();
  // We can pick any instance since the filters produced should be the same for all
  // instances.
  const vector<TRuntimeFilterSource>& filters_produced = instance_ctx.filters_produced;

  return DoInitExprsAndFilters(filter_descs, filters_produced, fragmentState);
}

void NljBuilderConfig::Close() {
  ScalarExpr::Close(filter_exprs_);
  DataSinkConfig::Close();
}

Status NljBuilder::CreateEmbeddedBuilder(const RowDescriptor* row_desc,
    RuntimeState* state, int join_node_id,
    const std::vector<TRuntimeFilterDesc>& filters, NljBuilder** nlj_builder) {
  ObjectPool* pool = state->obj_pool();
  NljBuilderConfig* sink_config = pool->Add(new NljBuilderConfig());
  sink_config->join_node_id_ = join_node_id;
  sink_config->tsink_ = pool->Add(new TDataSink());
  sink_config->input_row_desc_ = row_desc;
  RETURN_IF_ERROR(sink_config->InitExprsAndFilters(filters, state));
  *nlj_builder = pool->Add(new NljBuilder(*sink_config, state));
  return Status::OK();
}

NljBuilder* NljBuilder::CreateSeparateBuilder(
    TDataSinkId sink_id, const NljBuilderConfig& sink_config, RuntimeState* state) {
  return state->obj_pool()->Add(new NljBuilder(sink_id, sink_config, state));
}

void NljBuilder::InitFilterContexts(
    const NljBuilderConfig& sink_config, RuntimeState* state) {
  for (const TRuntimeFilterDesc& filter_desc : sink_config.filter_descs_) {
    filter_ctxs_.emplace_back();
    filter_ctxs_.back().filter = state->filter_bank()->RegisterProducer(filter_desc);
  }
}

NljBuilder::NljBuilder(
    TDataSinkId sink_id, const NljBuilderConfig& sink_config, RuntimeState* state)
  : JoinBuilder(sink_id, sink_config,
      ConstructBuilderName("Nested Loop", sink_config.join_node_id_), state),
    build_batch_cache_(row_desc_, state->batch_size()),
    filter_exprs_(sink_config.filter_exprs_),
    minmax_filter_threshold_(0.0),
    runtime_state_(state) {
  InitFilterContexts(sink_config, state);
}

NljBuilder::NljBuilder(const NljBuilderConfig& sink_config, RuntimeState* state)
  : JoinBuilder(-1, sink_config,
      ConstructBuilderName("Nested Loop", sink_config.join_node_id_), state),
    build_batch_cache_(row_desc_, state->batch_size()),
    filter_exprs_(sink_config.filter_exprs_),
    minmax_filter_threshold_(0.0),
    runtime_state_(state) {
  InitFilterContexts(sink_config, state);
}

NljBuilder::~NljBuilder() {}

Status NljBuilder::Prepare(RuntimeState* state, MemTracker* parent_mem_tracker) {
  RETURN_IF_ERROR(DataSink::Prepare(state, parent_mem_tracker));
  num_build_rows_ = ADD_COUNTER(profile(), "BuildRows", TUnit::UNIT);

  DCHECK_EQ(filter_exprs_.size(), filter_ctxs_.size());
  for (int i = 0; i < filter_exprs_.size(); ++i) {
    RETURN_IF_ERROR(
        ScalarExprEvaluator::Create(*filter_exprs_[i], state, state->obj_pool(),
            expr_perm_pool_.get(), expr_results_pool_.get(), &filter_ctxs_[i].expr_eval));
  }
  return Status::OK();
}

Status NljBuilder::Open(RuntimeState* state) {
  RETURN_IF_ERROR(DataSink::Open(state));

  for (const FilterContext& ctx : filter_ctxs_) {
    RETURN_IF_ERROR(ctx.expr_eval->Open(state));
  }

  AllocateRuntimeFilters();
  return Status::OK();
}

Status NljBuilder::Send(RuntimeState* state, RowBatch* batch) {
  SCOPED_TIMER(profile()->total_time_counter());
  int num_input_rows = batch->num_rows();
  // Swap the contents of the batch into a batch owned by the builder.
  RowBatch* build_batch = GetNextEmptyBatch();
  build_batch->AcquireState(batch);

  AddBuildBatch(build_batch);
  if (is_separate_build_
      || build_batch->flush_mode() == RowBatch::FlushMode::FLUSH_RESOURCES
      || build_batch->num_buffers() > 0) {
    // This batch and earlier batches may refer to resources passed from the child
    // that aren't owned by the row batch itself. Deep copying ensures that the row
    // batches are backed by memory owned by this node that is safe to hold on to.
    //
    // Acquiring ownership of attached Blocks or Buffers does not correctly update the
    // accounting, so also copy data in that cases to avoid stealing reservation
    // from whoever created the Block/Buffer. TODO: remove workaround when IMPALA-4179
    // is fixed.
    RETURN_IF_ERROR(DeepCopyBuildBatches(state));
  }
  COUNTER_ADD(num_build_rows_, num_input_rows);
  return Status::OK();
}

Status NljBuilder::FlushFinal(RuntimeState* state) {
  SCOPED_TIMER(profile()->total_time_counter());
  if (copied_build_batches_.total_num_rows() > 0) {
    // To simplify things, we only want to process one list, so we need to copy
    // the remaining input batches.
    RETURN_IF_ERROR(DeepCopyBuildBatches(state));
  }

  DCHECK(copied_build_batches_.total_num_rows() == 0 ||
      input_build_batches_.total_num_rows() == 0);

  PublishRuntimeFilters(
      copied_build_batches_.total_num_rows() + input_build_batches_.total_num_rows());

  if (is_separate_build_) HandoffToProbesAndWait(state);

  return Status::OK();
}

void NljBuilder::Reset() {
  DCHECK(!is_separate_build_);
  build_batch_cache_.Reset();
  input_build_batches_.Reset();
  copied_build_batches_.Reset();
}

void NljBuilder::Close(RuntimeState* state) {
  if (closed_) return;
  build_batch_cache_.Clear();
  input_build_batches_.Reset();
  copied_build_batches_.Reset();

  for (const FilterContext& ctx : filter_ctxs_) {
    if (ctx.expr_eval != nullptr) ctx.expr_eval->Close(state);
  }

  if (!is_separate_build_) {
    // If we are using embedded mode, the sink config is created by
    // NljBuilder::CreateEmbeddedBuilder, so we must close it ourselves.
    // TODO: Remove const-cast.
    const_cast<DataSinkConfig&>(sink_config_).Close();
  }

  DataSink::Close(state);
  closed_ = true;
}

Status NljBuilder::DeepCopyBuildBatches(RuntimeState* state) {
  for (RowBatchList::BatchIterator it = input_build_batches_.BatchesBegin();
    it != input_build_batches_.BatchesEnd(); ++it) {
    RowBatch* input_batch = *it;
    // TODO: it would be more efficient to do the deep copy within the same batch, rather
    // than to a new batch.
    RowBatch* copied_batch = build_batch_cache_.GetNextBatch(mem_tracker());
    input_batch->DeepCopyTo(copied_batch);
    copied_build_batches_.AddRowBatch(copied_batch);
    // Reset input batches as we go to free up memory if possible.
    input_batch->Reset();

    RETURN_IF_CANCELLED(state);
    RETURN_IF_ERROR(state->CheckQueryState());
  }
  input_build_batches_.Reset();
  return Status::OK();
}

void NljBuilder::AllocateRuntimeFilters() {
  for (int i = 0; i < filter_ctxs_.size(); ++i) {
    DCHECK(filter_ctxs_[i].filter->is_min_max_filter());
    filter_ctxs_[i].local_min_max_filter =
        runtime_state_->filter_bank()->AllocateScratchMinMaxFilter(
            filter_ctxs_[i].filter->id(), filter_ctxs_[i].expr_eval->root().type());
  }
  minmax_filter_threshold_ =
      (float)(runtime_state_->query_options().minmax_filter_threshold);
}

void NljBuilder::InsertRuntimeFilters(
    FilterContext filter_ctxs[], TupleRow* build_row) noexcept {
  // For the only interpreted path we can directly use the filter_ctxs_ member variable.
  DCHECK_EQ(filter_ctxs_.data(), filter_ctxs);
  for (const FilterContext& ctx : filter_ctxs_) ctx.InsertPerCompareOp(build_row);
}

void NljBuilder::PublishRuntimeFilters(int64_t num_build_rows) {
  JoinBuilder::PublishRuntimeFilters(
      filter_ctxs_, runtime_state_, minmax_filter_threshold_, num_build_rows);
}
