// 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.


#ifndef IMPALA_EXEC_BLOCKING_JOIN_NODE_H
#define IMPALA_EXEC_BLOCKING_JOIN_NODE_H

#include <boost/scoped_ptr.hpp>
#include <string>

#include "exec/exec-node.h"
#include "exec/join-op.h"
#include "runtime/runtime-state.h"
#include "util/promise.h"
#include "util/stopwatch.h"

namespace impala {

class JoinBuilder;
class RowBatch;
class TupleRow;

class BlockingJoinPlanNode : public PlanNode {
 public:
  /// Subclasses should call BlockingJoinNode::Init() and then perform any other Init()
  /// work, e.g. creating expr trees.
  virtual Status Init(const TPlanNode& tnode, FragmentState* state) override;
  virtual Status CreateExecNode(RuntimeState* state, ExecNode** node) const override = 0;

  /// Returns true if this join node will use a separate builder that is the root sink
  /// of a different fragment. Otherwise the builder is owned by this node and consumes
  /// input from the second child node.
  /// Note: This depends on the containing subplan being initialized, and isn't accurate
  /// until the whole PlanNode tree has been initialized.
  bool UseSeparateBuild(const TQueryOptions& query_options) const {
    return !IsInSubplan() && query_options.num_nodes != 1 && is_mt_fragment();
  }

  TJoinOp::type join_op() const { return join_op_; }

  const RowDescriptor& probe_row_desc() const { return *children_[0]->row_descriptor_; }
  const RowDescriptor& build_row_desc() const {
    DCHECK(build_row_desc_ != nullptr);
    return *build_row_desc_;
  }

 protected:
  TJoinOp::type join_op_;

  /// This is the same as the RowDescriptor of the build sink, if the join build is
  /// separate, or the right child, if the join build is integrated into the node.
  /// Owned by RuntimeState's object pool.
  RowDescriptor* build_row_desc_ = nullptr;
};

/// Abstract base class for join nodes that block in Open() until all rows from the
/// right input plan tree have been processed.
///
/// BlockingJoinNode and JoinBuilder subclasses interact together to implement a blocking
/// join: the builder. Two modes are supported: an integrated join build, where the
/// JoinBuilder is owned by the BlockingJoinNode, and a separate join build, where the
/// JoinBuilder is owned by a separate build fragment co-located in the same Impala
/// daemon, and the join node synchronizes with the builder to access build-side data
/// structures.
///
/// TODO: Remove the restriction that the tuples in the join's output row have to
/// correspond to the order of its child exec nodes. See the DCHECKs in Init().

class BlockingJoinNode : public ExecNode {
 public:
  BlockingJoinNode(const std::string& node_name, ObjectPool* pool,
      const BlockingJoinPlanNode& pnode, const DescriptorTbl& descs);

  virtual ~BlockingJoinNode();

  /// Subclasses should call BlockingJoinNode::Prepare() and then perform any other
  /// Prepare() work, e.g. codegen.
  virtual Status Prepare(RuntimeState* state);

  /// Helper called by subclass's Open() implementation.
  /// Calls ExecNode::Open() and initializes 'eos_' and 'probe_side_eos_'.
  /// If the join build is separate, the join builder is returned in *separate_builder.
  Status OpenImpl(RuntimeState* state, JoinBuilder** separate_builder);

  /// Transfers resources from 'probe_batch_' to 'row_batch'.
  virtual Status Reset(RuntimeState* state, RowBatch* row_batch);

  /// Subclasses should close any other structures and then call
  /// BlockingJoinNode::Close().
  virtual void Close(RuntimeState* state);

  static const char* LLVM_CLASS_NAME;

 protected:
  const std::string node_name_;
  TJoinOp::type join_op_;

  /// True if OpenImpl() was called.
  bool open_called_ = false;

  /// True if this join node has called WaitForInitialBuild() on the corresponding
  /// separate join builder. This means that CloseFromProbe() needs to be called
  /// on the builder.
  bool waited_for_build_ = false;

  /// True if Prepare() exited successfully. This is used to avoid deadlocks where
  /// a thread calls WaitForPrepare() without having successfully finished Prepare().
  bool prepare_succeeded_ = false;

  /// Store in node to avoid reallocating. Cleared after build completes.
  boost::scoped_ptr<RowBatch> build_batch_;

  /// probe_batch_ must be cleared before calling GetNext().  The child node
  /// does not initialize all tuple ptrs in the row, only the ones that it
  /// is responsible for.
  boost::scoped_ptr<RowBatch> probe_batch_;

  bool eos_;  // if true, nothing left to return in GetNext()
  bool probe_side_eos_;  // if true, left child has no more rows to process

  int probe_batch_pos_;  // current scan pos in probe_batch_
  TupleRow* current_probe_row_;  // The row currently being probed
  bool matched_probe_;  // if true, the current probe row is matched

  /// Size of the TupleRow (just the Tuple ptrs) from the build (right) and probe (left)
  /// sides. Set to zero if the build/probe tuples are not returned, e.g., for semi joins.
  /// Cached because it is used in the hot path.
  int probe_tuple_row_size_;
  int build_tuple_row_size_;

  /// Row assembled from all lhs and rhs tuples used for evaluating the non-equi-join
  /// conjuncts for semi joins. Semi joins only return the lhs or rhs output tuples,
  /// so this tuple is temporarily assembled for evaluating the conjuncts.
  TupleRow* semi_join_staging_row_;

  RuntimeProfile::Counter* probe_timer_;   // time to process the probe (left child) batch
  RuntimeProfile::Counter* probe_row_counter_;   // num probe (left child) rows

  /// Stopwatch that measures the build child's Open/GetNext time that overlaps
  /// with the probe child Open(). Not used for separate join builds.
  ConcurrentStopWatch built_probe_overlap_stop_watch_;

  // True for a join node subclass if the build side can be closed before the probe
  // side is opened. Should be true wherever possible to reduce resource consumption.
  // E.g. this is true or PartitionedHashJoinNode because it rematerializes the build rows
  // and false for NestedLoopJoinNode because it accumulates RowBatches that may reference
  // memory still owned by the build-side ExecNode tree.
  // Changes here must be kept in sync with the planner's resource profile computation.
  // TODO: IMPALA-4179: this should always be true once resource transfer has been fixed.
  virtual bool CanCloseBuildEarly() const { return false; }

  /// Acquire resources for this ExecNode required for the build phase.
  /// Called by BlockingJoinNode after opening child(1) succeeds and before
  /// this node either waits for the separate build or calls SendBuildInputToSink().
  virtual Status AcquireResourcesForBuild(RuntimeState* state) { return Status::OK(); }

  /// Processes the build-side input, which should be already open, by sending it to
  /// 'build_sink', and opens the probe side. Will do both concurrently if not in a
  /// subplan and an extra thread token is available.
  Status ProcessBuildInputAndOpenProbe(RuntimeState* state, JoinBuilder* build_sink);

  /// Set up 'current_probe_row_' to point to the first input row from the left child
  /// (probe side). Fills 'probe_batch_' with rows from the left child and updates
  /// 'probe_batch_pos_' to the index of the row in 'probe_batch_' after
  /// 'current_probe_row_'. 'probe_side_eos_' is set to true if 'probe_batch_' is the
  /// last batch to be returned from the child.
  /// If eos of the left child is reached and no rows are returned, 'current_probe_row_'
  /// is set to NULL and 'eos_' is set to true for join modes where unmatched rows from
  /// the build side do not need to be returned.
  Status GetFirstProbeRow(RuntimeState* state);

  /// Gives subclasses an opportunity to add debug output to the debug string printed by
  /// DebugString().
  virtual void AddToDebugString(int indentation_level, std::stringstream* out) const {
  }

  /// Subclasses should not override, use AddToDebugString() to add to the result.
  virtual void DebugString(int indentation_level, std::stringstream* out) const;

  /// Returns a debug string for the left child's 'row'. They have tuple ptrs that are
  /// uninitialized; the left child only populates the tuple ptrs it is responsible
  /// for.  This function outputs just the row values and leaves the build
  /// side values as NULL.
  /// This is only used for debugging and outputting the left child rows before
  /// doing the join.
  std::string GetLeftChildRowString(TupleRow* row);

  /// Write combined row, consisting of the left child's 'probe_row' and right child's
  /// 'build_row' to 'out_row'.
  /// This is replaced by codegen.
  inline void CreateOutputRow(
      TupleRow* out_row, TupleRow* probe_row, TupleRow* build_row);

  /// This function calculates the "local time" spent in the join node.
  ///
  /// The definition of "local time" is the wall clock time where this exec node is
  /// processing and it is not blocked by any of its children.
  ///
  /// The join node has two execution models:
  ///   1. The entire join execution is in a single thread.
  ///   2. The build(right) side is executed on a different thread while the main thread
  ///      opens the probe(left) side.
  ///
  /// In case 1, the "local time" spent in this node is as simple as:
  ///     total_time - left child time - right child time
  /// Because the entire right child time blocks the execution, the right child time is
  /// the same as right_child_blocking_stop_watch_.
  ///
  /// Case 2 is more complicated. The build thread is started first and then
  /// the main thread will "open" the left child. When the left child is ready
  /// (i.e. Open() returned), the main thread will wait for the build thread to finish.
  /// Because the left child is always executed in the main thread, all the left child
  /// time should not be counted towards the hash join "local time".
  /// For the right child (the build side), the child time in the build thread up to the
  /// point when the left child Open() returns should not be counted towards the hash
  /// join local time. This time period completely overlaps with the left child time.
  /// From the time when left child Open() returned, the right child time should be
  /// removed from the total time because this is the only child that is blocking the
  /// join execution.
  ///
  /// Here's the calculation:
  ///   total_time - left child time - (right child time - overlapped period)
  ///
  /// The "overlapped period" is measured by built_probe_overlap_stop_watch_. Using this
  /// overlap method, both children's "Prepare" time are also excluded.
  static int64_t LocalTimeCounterFn(const RuntimeProfile::Counter* total_time,
      const RuntimeProfile::Counter* left_child_time,
      const RuntimeProfile::Counter* right_child_time,
      const ConcurrentStopWatch* child_overlap_timer);

  const BlockingJoinPlanNode& plan_node() const {
    return static_cast<const BlockingJoinPlanNode&>(plan_node_);
  }

  /// Returns true if this join node is using a separate builder that is the root sink
  /// of a different fragment. Otherwise the builder is owned by this node and consumes
  /// input from the second child node.
  bool UseSeparateBuild(const TQueryOptions& query_options) const {
    return plan_node().UseSeparateBuild(query_options);
  }

  /// Find the build sink for the separate builder fragment. This is only valid when
  /// there is a separate builder fragment. Currently, this cannot be used during the
  /// Prepare() phase, because it uses QueryState::WaitForPrepare(), which waits for
  /// Prepare() to finish for all fragment instances.
  Status LookupSeparateJoinBuilder(RuntimeState* state, JoinBuilder** separate_builder);

  /// Shared logic to properly unregister from the builder during Close(). This should
  /// be called from the Close() function for all subclasses. Calling this function is
  /// crucial for avoiding delays / hangs, particularly for cases where the probe side
  /// can terminate early, like the tuple cache.
  ///
  /// This looks up the builder if needed (e.g. if this is called before starting probe),
  /// then it unregisters itself from the builder. If this looked up the builder, it
  /// returns it via the builder argument. This is useful for subclasses that need to
  /// perform additional steps to unregister with the builder.
  template<typename T>
  void UnregisterFromBuilder(RuntimeState* state, T** builder) {
    DCHECK(state != nullptr);
    DCHECK(builder != nullptr);
    bool separate_build = UseSeparateBuild(state->query_options());
    if (prepare_succeeded_ && *builder == nullptr && separate_build) {
      DCHECK(!waited_for_build_);
      // Find the separate join builder. This can return an error status if the Prepare()
      // phase failed. In that case, there is no need to notify the builder and it can
      // be skipped.
      JoinBuilder* separate_builder;
      Status status = LookupSeparateJoinBuilder(state, &separate_builder);
      if (status.ok()) {
        *builder = dynamic_cast<T*>(separate_builder);
        DCHECK(*builder != nullptr);
      }
    }
    if (*builder != nullptr) {
      if (separate_build && !waited_for_build_) {
        // There is a separate build and we never reached the probe phase
        (*builder)->CloseBeforeProbe(state);
      } else {
        (*builder)->CloseFromProbe(state);
        waited_for_build_ = false;
      }
    }
  }

  const RowDescriptor& probe_row_desc() const {
    return plan_node().probe_row_desc();
  }

  const RowDescriptor& build_row_desc() const {
    return plan_node().build_row_desc();
  }

 private:
  /// Helper function to process the build input by sending it to the integrated
  /// JoinBuilder. The build input must already be open before calling this. ASYNC_BUILD
  /// enables timers that impose some overhead but are required if the build is processed
  /// concurrently with the Open() of the left child.
  template <bool ASYNC_BUILD>
  Status SendBuildInputToSink(RuntimeState* state, JoinBuilder* build_sink);

  /// The main function for the thread that opens the build side and processes the build
  /// input asynchronously.  Its status is returned in the 'status' promise. If
  /// 'build_sink' is non-NULL, it is used for the build. Otherwise, ProcessBuildInput()
  /// is called on the subclass.
  void ProcessBuildInputAsync(
      RuntimeState* state, JoinBuilder* build_sink, Status* status);
};
} // namespace impala

#endif
