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

#pragma once

#include <string>

#include "exec/exec-node.h"
#include "runtime/tuple-cache-mgr.h"

namespace impala {

class TupleFileReader;
class TupleFileWriter;
class TupleTextFileWriter;
class HdfsFileSplitPB;
class HdfsPartitionDescriptor;

class TupleCachePlanNode : public PlanNode {
 public:
  Status CreateExecNode(RuntimeState* state, ExecNode** node) const override;
  ~TupleCachePlanNode(){}
};

/// Node that caches rows produced by a child node.
///
/// If the combined_key_ matches an existing cache entry, returns result rows from the
/// cache rather than from the child. Otherwise reads results from the child, writes them
/// to cache, and returns them.

class TupleCacheNode : public ExecNode {
 public:
  TupleCacheNode(ObjectPool* pool, const TupleCachePlanNode& pnode,
      const DescriptorTbl& descs);
  ~TupleCacheNode();

  Status Prepare(RuntimeState* state) override;
  Status Open(RuntimeState* state) override;
  Status GetNext(RuntimeState* state, RowBatch* row_batch, bool* eos) override;
  Status Reset(RuntimeState* state, RowBatch* row_batch) override;
  void Close(RuntimeState* state) override;
  void DebugString(int indentation_level, std::stringstream* out) const override;
private:
  // Fragment instance cache key. This is calculated at runtime by combining information
  // about the input nodes for this fragment. It currently focuses on hashing the
  // scan ranges from scan nodes. In future, it will need to handle exchanges.
  uint32_t fragment_instance_key_;

  // This is a string containing the compile time key and the fragment_instance_key_.
  // This combination is unique for a given fragment instance.
  std::string combined_key_;

  // This caching location should skip correctness verification. This can be true when a
  // location has variability in its results that is tolerated by nodes higher in the
  // plan (e.g. streaming aggregations can produce variable results that do not change
  // the result out of the finalization phase).
  bool skip_correctness_verification_;

  /// Number of results that were found in the tuple cache
  RuntimeProfile::Counter* num_hits_counter_ = nullptr;
  /// Number of results that were too large for the cache
  RuntimeProfile::Counter* num_halted_counter_ = nullptr;
  /// Number of results that were halted due to backpressure (i.e. hitting the
  /// outstanding writes limit)
  RuntimeProfile::Counter* num_backpressure_halted_counter_ = nullptr;
  /// Number of results that skip the cache due to a tombstone
  RuntimeProfile::Counter* num_skipped_counter_ = nullptr;
  /// Number of results that are running correctness verification
  RuntimeProfile::Counter* num_correctness_verification_counter_ = nullptr;

  /// Whether any RowBatch from a cache file has been returned to a caller
  /// It is possible to recover from an error reading a cache file if no
  /// cached RowBatch has been returned to a caller.
  bool cached_rowbatch_returned_to_caller_ = false;

  void ReleaseResult();

  // Hash the relevant attributes from an HdfsPartitionDescriptor using the specified
  // seed.
  uint32_t HashHdfsPartitionDescriptor(const HdfsPartitionDescriptor* partition_desc,
      uint32_t seed);

  // Hash the relevant attributes from an HdfsFileSplit using the specified seed.
  uint32_t HashHdfsFileSplit(const HdfsFileSplitPB& split, uint32_t seed);

  // Construct the fragment instance part of the cache key by hashing information about
  // inputs to this fragment (e.g. scan ranges and partition settings).
  void ComputeFragmentInstanceKey(const RuntimeState *state);

  /// Reader/Writer for caching
  TupleCacheMgr::UniqueHandle handle_;
  std::unique_ptr<TupleFileReader> reader_;
  std::unique_ptr<TupleFileWriter> writer_;
  std::unique_ptr<TupleTextFileWriter> debug_dump_text_writer_;
  std::unique_ptr<TupleTextFileWriter> debug_dump_text_writer_ref_;

  /// Helper function to generate the path for debug dumping the tuple cache.
  /// If sub_dir_full_path is not nullptr, the subdirectory path will be returned,
  /// allowing the caller to create the subdirectory if necessary.
  string GetDebugDumpPath(const RuntimeState* state, const string& fragment_id,
      string* sub_dir_full_path = nullptr) const;

  /// Helper function to verify the correctness of the debug tuple cache.
  Status VerifyAndMoveDebugCache(RuntimeState* state);
};

}
