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

#include "exec/exec-node-util.h"
#include "exec/hdfs-scan-node-base.h"
#include "exec/tuple-cache-node.h"
#include "exec/tuple-file-reader.h"
#include "exec/tuple-file-writer.h"
#include "exec/tuple-text-file-reader.h"
#include "exec/tuple-text-file-util.h"
#include "exec/tuple-text-file-writer.h"
#include "runtime/exec-env.h"
#include "runtime/row-batch.h"
#include "runtime/runtime-state.h"
#include "runtime/tuple-cache-mgr.h"
#include "util/hash-util.h"
#include "util/runtime-profile-counters.h"
#include "util/runtime-profile.h"

#include "common/names.h"

namespace impala {

Status TupleCachePlanNode::CreateExecNode(
    RuntimeState* state, ExecNode** node) const {
  ObjectPool* pool = state->obj_pool();
  *node = pool->Add(new TupleCacheNode(pool, *this, state->desc_tbl()));
  return Status::OK();
}

TupleCacheNode::TupleCacheNode(
    ObjectPool* pool, const TupleCachePlanNode& pnode, const DescriptorTbl& descs)
  : ExecNode(pool, pnode, descs) {
}

TupleCacheNode::~TupleCacheNode() = default;

static bool TupleCacheVerificationEnabled(RuntimeState* state) {
  DCHECK(state != nullptr);
  return state->query_options().enable_tuple_cache_verification;
}

Status TupleCacheNode::Prepare(RuntimeState* state) {
  RETURN_IF_ERROR(ExecNode::Prepare(state));
  num_hits_counter_ = ADD_COUNTER(runtime_profile(), "NumTupleCacheHits", TUnit::UNIT);
  num_halted_counter_ =
      ADD_COUNTER(runtime_profile(), "NumTupleCacheHalted", TUnit::UNIT);
  num_backpressure_halted_counter_ =
      ADD_COUNTER(runtime_profile(), "NumTupleCacheBackpressureHalted", TUnit::UNIT);
  num_skipped_counter_ =
      ADD_COUNTER(runtime_profile(), "NumTupleCacheSkipped", TUnit::UNIT);
  // If correctness verification is enabled, add a counter to indicate whether it was
  // actually performing correctness verification.
  if (TupleCacheVerificationEnabled(state)) {
    num_correctness_verification_counter_ =
      ADD_COUNTER(runtime_profile(), "NumTupleCacheCorrectnessVerification", TUnit::UNIT);
  }
  // Compute the combined cache key by computing the fragment instance key and
  // fusing it with the compile time key.
  ComputeFragmentInstanceKey(state);
  combined_key_ = plan_node().tnode_->tuple_cache_node.compile_time_key + "_" +
      std::to_string(fragment_instance_key_);
  skip_correctness_verification_ =
      plan_node().tnode_->tuple_cache_node.skip_correctness_verification;
  runtime_profile()->AddInfoString("Combined Key", combined_key_);

  return Status::OK();
}

Status TupleCacheNode::Open(RuntimeState* state) {
  SCOPED_TIMER(runtime_profile()->total_time_counter());
  ScopedOpenEventAdder ea(this);
  RETURN_IF_ERROR(ExecNode::Open(state));

  // The frontend cannot create a TupleCacheNode if enable_tuple_cache=false
  // Fail the query if we see this.
  if (!state->query_options().enable_tuple_cache) {
    return Status("Invalid tuple caching configuration: enable_tuple_cache=false");
  }

  TupleCacheMgr* tuple_cache_mgr = ExecEnv::GetInstance()->tuple_cache_mgr();
  handle_ = tuple_cache_mgr->Lookup(combined_key_, true);
  if (tuple_cache_mgr->IsAvailableForRead(handle_)) {
    if (tuple_cache_mgr->DebugDumpEnabled() && TupleCacheVerificationEnabled(state)) {
      // If the node is marked to skip correctness verification, we don't want to read
      // from the cache as that would prevent its children from executing.
      if (!skip_correctness_verification_) {
        VLOG_FILE << "Tuple Cache: correctness verification for " << combined_key_;
        DCHECK(num_correctness_verification_counter_ != nullptr);
        COUNTER_ADD(num_correctness_verification_counter_, 1);
        // We need the original fragment id to construct the path for the reference debug
        // cache file. If it's missing from the metadata, we return an error status
        // immediately.
        string org_fragment_id =
            tuple_cache_mgr->GetFragmentIdForTupleCache(combined_key_);
        if (org_fragment_id.empty()) {
          return Status(TErrorCode::TUPLE_CACHE_INCONSISTENCY,
              Substitute("Metadata of tuple cache '$0' is missing for correctness check",
                  combined_key_));
        }
        string ref_sub_dir;
        string sub_dir;
        string ref_file_path = GetDebugDumpPath(state, org_fragment_id, &ref_sub_dir);
        string file_path = GetDebugDumpPath(state, string(), &sub_dir);
        DCHECK_EQ(ref_sub_dir, sub_dir);
        DCHECK(!ref_sub_dir.empty());
        DCHECK(!ref_file_path.empty());
        DCHECK(!file_path.empty());
        // Create the subdirectory for the debug caches if needed.
        RETURN_IF_ERROR(tuple_cache_mgr->CreateDebugDumpSubdir(ref_sub_dir));
        // Open the writer for writing the tuple data from the cache entries to be
        // the reference cache data.
        debug_dump_text_writer_ref_ = make_unique<TupleTextFileWriter>(ref_file_path);
        RETURN_IF_ERROR(debug_dump_text_writer_ref_->Open());
        // Open the writer for writing the tuple data from children in GetNext() to
        // compare with the reference debug cache file.
        debug_dump_text_writer_ = make_unique<TupleTextFileWriter>(file_path);
        RETURN_IF_ERROR(debug_dump_text_writer_->Open());
      }
    } else {
      reader_ = make_unique<TupleFileReader>(
          tuple_cache_mgr->GetPath(handle_), mem_tracker(), runtime_profile());
      Status status = reader_->Open(state);
      // Clear reader if it's not usable
      if (!status.ok()) {
        LOG(WARNING) << "Could not read cache entry for "
                     << tuple_cache_mgr->GetPath(handle_);
        reader_.reset();
      }
    }
  } else if (tuple_cache_mgr->IsAvailableForWrite(handle_)) {
    writer_ = make_unique<TupleFileWriter>(tuple_cache_mgr->GetPath(handle_),
        mem_tracker(), runtime_profile(),
        [this, tuple_cache_mgr] (size_t new_size) {
            return tuple_cache_mgr->RequestWriteSize(&this->handle_, new_size);
        });
    Status status = writer_->Open(state);
    if (!status.ok()) {
      LOG(WARNING) << "Could not write cache entry for "
                   << tuple_cache_mgr->GetPath(handle_);
      tuple_cache_mgr->AbortWrite(move(handle_), false);
      writer_.reset();
    }
  }

  if (reader_) {
    COUNTER_ADD(num_hits_counter_, 1);
    tuple_cache_mgr->IncrementMetric(TupleCacheMgr::MetricType::HIT);
  } else {
    if (!writer_) {
      // May be skipped due to any of:
      // - the query requests caching but cache is disabled via startup option
      // - another fragment is currently writing this cache entry
      // - the cache entry is a tombstone to prevent retries for too large entries
      VLOG_FILE << "Tuple Cache: skipped for " << combined_key_;
      COUNTER_ADD(num_skipped_counter_, 1);
      tuple_cache_mgr->IncrementMetric(TupleCacheMgr::MetricType::SKIPPED);
    }
    tuple_cache_mgr->IncrementMetric(TupleCacheMgr::MetricType::MISS);
    // No reader, so open the child.
    RETURN_IF_ERROR(child(0)->Open(state));
  }

  // Claim reservation after the child has been opened to reduce the peak reservation
  // requirement.
  if (!buffer_pool_client()->is_registered()) {
    RETURN_IF_ERROR(ClaimBufferReservation(state));
  }

  return Status::OK();
}

// Helper function to rename the bad file.
static void MoveBadDebugCacheFile(const string& file_path) {
  DCHECK(!file_path.empty());
  string new_path = file_path + DEBUG_TUPLE_CACHE_BAD_POSTFIX;
  int result = rename(file_path.c_str(), new_path.c_str());
  if (result != 0) {
    string error_msg = GetStrErrMsg();
    LOG(ERROR) << "Failed to move debug tuple cache file from " << file_path << " to "
               << new_path << ". Error message: " << error_msg << ": " << result;
  } else {
    LOG(INFO) << "Moved bad debug tuple cache file from " << file_path << " to "
              << new_path;
  }
}

// Move the debug dump cache after verification.
// If the verification passed, we clear the cache file.
// Otherwise, we will move the file with a "bad" postfix.
// The writer will be reset after the function.
static void MoveDebugCache(bool suc, unique_ptr<TupleTextFileWriter>& writer) {
  DCHECK(writer != nullptr);
  if (suc) {
    writer->Delete();
  } else {
    MoveBadDebugCacheFile(writer->GetPath());
  }
  writer.reset();
}

Status TupleCacheNode::VerifyAndMoveDebugCache(RuntimeState* state) {
  DCHECK(debug_dump_text_writer_ref_ != nullptr);
  DCHECK(ExecEnv::GetInstance()->tuple_cache_mgr()->DebugDumpEnabled());
  DCHECK(TupleCacheVerificationEnabled(state));
  if (debug_dump_text_writer_->IsEmpty()) {
    return Status::OK();
  }
  string ref_file_path = debug_dump_text_writer_ref_->GetPath();
  string dump_file_path = debug_dump_text_writer_->GetPath();
  bool passed = false;

  DCHECK(!ref_file_path.empty());
  DCHECK(!dump_file_path.empty());

  VLOG_FILE << "Verify debug tuple cache file ref_file_path: " << ref_file_path
            << " and dump_file_path: " << dump_file_path
            << " with cache key:" << combined_key_;

  // Fast path to verify the cache.
  Status verify_status =
      TupleTextFileUtil::VerifyDebugDumpCache(dump_file_path, ref_file_path, &passed);
  if (verify_status.ok() && !passed) {
    // Slow path to compare all rows in an order-insensitive way if the files are not the
    // same.
    verify_status = TupleTextFileUtil::VerifyRows(dump_file_path, ref_file_path);
    passed = verify_status.ok();
  }

  // Move or clear the file after verification.
  MoveDebugCache(passed, debug_dump_text_writer_ref_);
  MoveDebugCache(passed, debug_dump_text_writer_);
  return verify_status;
}

// Helper function to generate the unique id based on fragment instance id and node id.
static string GenerateFragmentNodeId(
    const RuntimeState* state, const TupleCacheNode* node) {
  DCHECK(state != nullptr);
  DCHECK(node != nullptr);
  return Substitute("$0_$1", PrintId(state->fragment_instance_id()), node->id());
}

Status TupleCacheNode::GetNext(
    RuntimeState* state, RowBatch* output_row_batch, bool* eos) {
  SCOPED_TIMER(runtime_profile()->total_time_counter());
  ScopedGetNextEventAdder ea(this, eos);
  RETURN_IF_ERROR(ExecDebugAction(TExecNodePhase::GETNEXT, state));
  RETURN_IF_CANCELLED(state);
  RETURN_IF_ERROR(QueryMaintenance(state));

  // Save the number of rows in case GetNext() is called with a non-empty batch,
  // which can happen in a subplan.
  int num_rows_before = output_row_batch->num_rows();

  // If we have a Reader, return the next batch from it.
  // Else GetNext from child, write to Writer, and return the batch.
  if (reader_) {
    Status status = reader_->GetNext(state, buffer_pool_client(), output_row_batch, eos);
    if (status.ok()) {
      cached_rowbatch_returned_to_caller_ = true;
      // Close the child now that there is no hope of recovery in case of failure. This
      // allows it to tear down any state and notify any affected threads that the
      // children won't ever reach Open().
      child(0)->Close(state);
    } else {
      // If we have returned a cached row batch to the caller, then it is not safe
      // to try to get any rows from the child as they could be duplicates. Any
      // error needs to end the query.
      if (cached_rowbatch_returned_to_caller_) return status;

      // We haven't returned a RowBatch to the caller yet, so we can recover by aborting
      // the read from the cache and fetching from the child. We won't try to write to
      // the cache.
      LOG(WARNING) << "Unable to read cache file: " << status.GetDetail()
                   << "Falling back to regular non-cached path.";
      reader_.reset();
      // If reader_ is set, then the child was never opened and needs to be opened now
      RETURN_IF_ERROR(child(0)->Open(state));
      RETURN_IF_ERROR(child(0)->GetNext(state, output_row_batch, eos));
    }
  } else {
    RETURN_IF_ERROR(child(0)->GetNext(state, output_row_batch, eos));
    if (writer_) {
      Status status = writer_->Write(state, output_row_batch);
      TupleCacheMgr* tuple_cache_mgr = ExecEnv::GetInstance()->tuple_cache_mgr();
      // If there was an error or we exceeded the file size limit, stop caching but
      // continue reading from the child node.
      if (!status.ok()) {
        bool set_tombstone = false;
        if (status.code() == TErrorCode::TUPLE_CACHE_ENTRY_SIZE_LIMIT_EXCEEDED) {
          VLOG_FILE << "Tuple Cache entry for " << combined_key_
                    << " hit the maximum file size: " << status.GetDetail();
          COUNTER_ADD(num_halted_counter_, 1);
          set_tombstone = true;
        } else if (status.code() ==
            TErrorCode::TUPLE_CACHE_OUTSTANDING_WRITE_LIMIT_EXCEEDED) {
          VLOG_FILE << "Tuple Cache entry for " << combined_key_
                    << " hit the outstanding writes limit: " << status.GetDetail();
          COUNTER_ADD(num_backpressure_halted_counter_, 1);
        } else {
          // This is an unknown error (e.g. an IO error), so write a warning.
          LOG(WARNING) << "Unable to write cache file: " << status.GetDetail();
        }
        writer_->Abort();
        tuple_cache_mgr->AbortWrite(move(handle_), set_tombstone);
        writer_.reset();
      } else if (*eos) {
        // If we hit end of stream, then we can complete the cache entry
        // If the child did not reach end of stream, then it clearly isn't the complete
        // result set. This is currently the only way a cache entry can be completed.
        size_t bytes_written = writer_->BytesWritten();
        Status status = writer_->Commit(state);
        if (status.ok()) {
          if (tuple_cache_mgr->DebugDumpEnabled()) {
            // Store the metadata whenever the debug dump path is set, regardless of
            // whether the correctness verification is enabled in the query option. This
            // is because the tuple cache eviction function does not account for the query
            // option when removing metadata. Keeping this consistent ensures proper
            // handling.
            tuple_cache_mgr->StoreMetadataForTupleCache(
                combined_key_, GenerateFragmentNodeId(state, this));
          }
          tuple_cache_mgr->CompleteWrite(move(handle_), bytes_written);
        } else {
          writer_->Abort();
          tuple_cache_mgr->AbortWrite(move(handle_), false);
        }
        writer_.reset();
      }
    }
    if (debug_dump_text_writer_) {
      RETURN_IF_ERROR(debug_dump_text_writer_->Write(output_row_batch));
      if (*eos) debug_dump_text_writer_->Commit();
    }
  }

  // Note: TupleCacheNode does not alter its child's output (or the equivalent
  // output from the cache), so it does not enforce its own limit on the output.
  // Any limit should be enforced elsewhere, and this code omits the logic
  // to enforce a limit.
  int num_rows_added = output_row_batch->num_rows() - num_rows_before;
  DCHECK_GE(num_rows_added, 0);
  IncrementNumRowsReturned(num_rows_added);
  if (*eos && debug_dump_text_writer_) {
    DCHECK(debug_dump_text_writer_ref_ != nullptr);
    TupleFileReader cache_reader(
        ExecEnv::GetInstance()->tuple_cache_mgr()->GetPath(handle_), mem_tracker(),
        runtime_profile());
    RETURN_IF_ERROR(cache_reader.Open(state));
    // Read the cache entries from the cache reader, and write as the reference
    // debug cache file. If an error occurs, abort the verification, and return the
    // error status.
    RowBatch row_batch(child(0)->row_desc(), state->batch_size(), mem_tracker());
    bool cache_eos = false;
    while (!cache_eos) {
      RETURN_IF_ERROR(
          cache_reader.GetNext(state, buffer_pool_client(), &row_batch, &cache_eos));
      DCHECK(row_batch.num_rows() > 0 || cache_eos);
      RETURN_IF_ERROR(debug_dump_text_writer_ref_->Write(&row_batch));
      row_batch.Reset();
    }
    DCHECK(cache_eos);
    debug_dump_text_writer_ref_->Commit();
    RETURN_IF_ERROR(VerifyAndMoveDebugCache(state));
  }
  COUNTER_SET(rows_returned_counter_, rows_returned());
  return Status::OK();
}

void TupleCacheNode::ReleaseResult() {
  reader_.reset();
  writer_.reset();
  handle_.reset();
}

Status TupleCacheNode::Reset(RuntimeState* state, RowBatch* row_batch) {
  // Reset() is not supported.
  DCHECK(false) << "Internal error: Tuple cache nodes should not appear in subplans.";
  return Status("Internal error: Tuple cache nodes should not appear in subplans.");
}

void TupleCacheNode::Close(RuntimeState* state) {
  if (is_closed()) return;
  // If we reach this point with an open writer_, then this cache entry is invalid. We
  // will delete the file and abort the write. This can happen if the query is cancelled,
  // if the query hits an error, or if a parent node has a limit and doesn't complete
  // fetching. This is intentionally restrictive.
  if (writer_) {
    TupleCacheMgr* tuple_cache_mgr = ExecEnv::GetInstance()->tuple_cache_mgr();
    writer_->Abort();
    tuple_cache_mgr->AbortWrite(move(handle_), false);
  }
  if (debug_dump_text_writer_) {
    debug_dump_text_writer_->Delete();
    debug_dump_text_writer_.reset();
  }
  if (debug_dump_text_writer_ref_) {
    debug_dump_text_writer_ref_->Delete();
    debug_dump_text_writer_ref_.reset();
  }
  ReleaseResult();
  ExecNode::Close(state);
}

string TupleCacheNode::GetDebugDumpPath(const RuntimeState* state,
    const string& org_fragment_id, string* sub_dir_full_path) const {
  // The name of the subdirectory is hash key.
  // For non-reference files, the file name is the fragment instance node id.
  // For reference files, the name includes the current fragment instance node id, the
  // original fragment node id, and a "ref" suffix.
  string file_name = GenerateFragmentNodeId(state, this);
  if (!org_fragment_id.empty()) {
    // Adds the original fragment id of the cache to the path for debugging purpose.
    file_name = Substitute("$0_$1_ref", file_name, org_fragment_id);
  }
  return ExecEnv::GetInstance()->tuple_cache_mgr()->GetDebugDumpPath(
      combined_key_, file_name, sub_dir_full_path);
}

void TupleCacheNode::DebugString(int indentation_level, stringstream* out) const {
  *out << string(indentation_level * 2, ' ');
  *out << "TupleCacheNode(" << combined_key_;
  ExecNode::DebugString(indentation_level, out);
  *out << ")";
}

// This hashes all the fields of the HdfsPartitionDescriptor, except:
// 1. block_size: Only used for writing, so it doesn't matter for reading
// 2. location: The location is hashed as part of the scan range
// 3. id: The partition id is not stable over time
// As a substitute for the "id", this uses the partition key expr hash, which
// is a stable identifier for the partition.
uint32_t TupleCacheNode::HashHdfsPartitionDescriptor(
    const HdfsPartitionDescriptor* partition_desc, uint32_t seed) {
  uint32_t hash = seed;
  char line_delim = partition_desc->line_delim();
  hash = HashUtil::Hash(&line_delim, sizeof(line_delim), hash);
  char field_delim = partition_desc->field_delim();
  hash = HashUtil::Hash(&field_delim, sizeof(field_delim), hash);
  char collection_delim = partition_desc->collection_delim();
  hash = HashUtil::Hash(&collection_delim, sizeof(collection_delim), hash);
  char escape_char = partition_desc->escape_char();
  hash = HashUtil::Hash(&escape_char, sizeof(escape_char), hash);
  std::string file_format = to_string(partition_desc->file_format());
  hash = HashUtil::Hash(file_format.data(), file_format.length(), hash);
  hash = HashUtil::Hash(partition_desc->encoding_value().data(),
      partition_desc->encoding_value().length(), hash);
  std::string json_binary_format = to_string(partition_desc->json_binary_format());
  hash = HashUtil::Hash(json_binary_format.data(), json_binary_format.length(), hash);
  uint32_t partition_key_expr_hash = partition_desc->partition_key_expr_hash();
  hash = HashUtil::Hash(&partition_key_expr_hash, sizeof(partition_key_expr_hash), hash);
  return hash;
}

uint32_t TupleCacheNode::HashHdfsFileSplit(const HdfsFileSplitPB& split, uint32_t seed) {
  uint32_t hash = seed;
  if (split.has_relative_path() && !split.relative_path().empty()) {
    hash = HashUtil::Hash(
        split.relative_path().data(), split.relative_path().length(), hash);
    DCHECK(split.has_partition_path_hash());
    int32_t partition_path_hash = split.partition_path_hash();
    hash = HashUtil::Hash(&partition_path_hash, sizeof(partition_path_hash), hash);
  } else if (split.has_absolute_path() && !split.absolute_path().empty()) {
    hash = HashUtil::Hash(
        split.absolute_path().data(), split.absolute_path().length(), hash);
  } else {
    DCHECK("Either relative_path or absolute_path must be set");
  }
  DCHECK(split.has_offset());
  int64_t offset = split.offset();
  hash = HashUtil::Hash(&offset, sizeof(offset), hash);
  DCHECK(split.has_length());
  int64_t length = split.length();
  hash = HashUtil::Hash(&length, sizeof(length), hash);
  DCHECK(split.has_mtime());
  int64_t mtime = split.mtime();
  hash = HashUtil::Hash(&mtime, sizeof(mtime), hash);
  return hash;
}

void TupleCacheNode::ComputeFragmentInstanceKey(const RuntimeState* state) {
  const PlanFragmentInstanceCtxPB& ctx = state->instance_ctx_pb();
  uint32_t hash = 0;
  // Collect the HdfsScanNodes below this point. The HdfsScanNodes have information about
  // the partitions that we need to include in the fragment instance key. Some locations
  // may have a large number of scan nodes below them, so construct a map from the node
  // id to the HdfsScanNodeBase.
  vector<ExecNode*> scan_nodes;
  CollectNodes(TPlanNodeType::HDFS_SCAN_NODE, &scan_nodes);
  unordered_map<int, const HdfsScanNodeBase*> id_to_scan_node_map;
  for (const ExecNode* exec_node : scan_nodes) {
    const HdfsScanNodeBase* scan_node =
        static_cast<const HdfsScanNodeBase*>(exec_node);
    int node_id = exec_node->plan_node().tnode_->node_id;
    DCHECK(id_to_scan_node_map.find(node_id) == id_to_scan_node_map.end())
        << "Duplicate scan node id: " << node_id;
    id_to_scan_node_map[node_id] = scan_node;
  }
  for (int32_t node_id : plan_node().tnode_->tuple_cache_node.input_scan_node_ids) {
    const HdfsTableDescriptor* hdfs_table = id_to_scan_node_map[node_id]->hdfs_table();
    DCHECK(hdfs_table != nullptr);
    auto ranges = ctx.per_node_scan_ranges().find(node_id);
    if (ranges == ctx.per_node_scan_ranges().end()) continue;
    for (const ScanRangeParamsPB& params : ranges->second.scan_ranges()) {
      // This only supports HDFS right now
      DCHECK(params.scan_range().has_hdfs_file_split());
      const HdfsFileSplitPB& split = params.scan_range().hdfs_file_split();
      // Information on the partition can influence how files are processed. For example,
      // for text files, the delimiter can be specified on the partition level. There
      // are several such attributes. We need to incorporate the partition information
      // into the hash for each file split.
      const HdfsPartitionDescriptor* partition_desc =
          hdfs_table->GetPartition(split.partition_id());
      DCHECK(partition_desc != nullptr);
      if (partition_desc != nullptr) {
        hash = HashHdfsPartitionDescriptor(partition_desc, hash);
      } else {
        LOG(WARNING) << "Partition id " << split.partition_id()
                     << " not found in table " << hdfs_table->fully_qualified_name()
                     << " split filename: " << split.relative_path();
      }
      hash = HashHdfsFileSplit(split, hash);
    }
  }
  fragment_instance_key_ = hash;
}

}
