blob: 1e7c14f9547b0a5f2a9b7962e5da666c5d64bb7e [file]
// 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 "exec/hdfs-scanner.h"
#include <boost/scoped_ptr.hpp>
namespace impala {
class CollectionValueBuilder;
class HdfsScanNodeBase;
class HdfsScanPlanNode;
class RowBatch;
class RuntimeState;
struct ScratchTupleBatch;
/// Parent class for scanners that read values into a scratch batch before applying
/// conjuncts and runtime filters.
class HdfsColumnarScanner : public HdfsScanner {
public:
HdfsColumnarScanner(HdfsScanNodeBase* scan_node, RuntimeState* state);
virtual ~HdfsColumnarScanner();
virtual Status Open(ScannerContext* context) override WARN_UNUSED_RESULT;
virtual void CloseInternal() override;
/// Codegen ProcessScratchBatch(). Stores the resulting function in
/// 'process_scratch_batch_fn' if codegen was successful or NULL otherwise.
static Status Codegen(HdfsScanPlanNode* node, FragmentState* state,
llvm::Function** process_scratch_batch_fn);
/// Add sync read related counters.
void AddSyncReadBytesCounter(int64_t total_bytes);
/// Add async read related counters.
void AddAsyncReadBytesCounter(int64_t total_bytes);
/// Add skipped bytes related counters.
void AddSkippedReadBytesCounter(int64_t total_bytes);
/// Class name in LLVM IR.
static const char* LLVM_CLASS_NAME;
protected:
/// Column readers will write slot values into this scratch batch for
/// top-level tuples. See AssembleRows() in the derived classes.
boost::scoped_ptr<ScratchTupleBatch> scratch_batch_;
/// Indicate whether this is a footer scanner or not.
/// Assigned in HdfsColumnarScanner::Open().
bool is_footer_scanner_ = false;
/// Scan range for the metadata.
const io::ScanRange* metadata_range_ = nullptr;
typedef int (*ProcessScratchBatchFn)(HdfsColumnarScanner*, RowBatch*);
/// The codegen'd version of ProcessScratchBatch() if available, NULL otherwise.
/// Function type: ProcessScratchBatchFn
const CodegenFnPtrBase* codegend_process_scratch_batch_fn_ = nullptr;
/// Filters out tuples from 'scratch_batch_' and adds the surviving tuples
/// to the given batch. Finalizing transfer of batch is not done here.
/// Returns the number of tuples that should be committed to the given batch.
int FilterScratchBatch(RowBatch* row_batch);
/// Get filename of the scan range.
const char* filename() const { return metadata_range_->file(); }
/// Evaluates runtime filters and conjuncts (if any) against the tuples in
/// 'scratch_batch_', and adds the surviving tuples to the given batch.
/// Transfers the ownership of tuple memory to the target batch when the
/// scratch batch is exhausted.
/// Returns the number of rows that should be committed to the given batch.
int TransferScratchTuples(RowBatch* row_batch);
/// Processes a single row batch for TransferScratchTuples, looping over scratch_batch_
/// until it is exhausted or the output is full. Called for the case when there are
/// materialized tuples. This is a separate function so it can be codegened.
int ProcessScratchBatch(RowBatch* dst_batch);
/// List of pair of (column index, reservation allocated).
typedef std::vector<std::pair<int, int64_t>> ColumnReservations;
/// List of column range lengths.
typedef std::vector<int64_t> ColumnRangeLengths;
/// Decides how to divide stream_->reservation() between the columns. May increase
/// the reservation if more reservation would enable more efficient I/O for the
/// current columns being scanned. Sets the reservation on each corresponding reader
/// in 'column_readers'.
Status DivideReservationBetweenColumns(const ColumnRangeLengths& col_range_lengths,
ColumnReservations& reservation_per_column);
/// Helper for DivideReservationBetweenColumns(). Implements the core algorithm for
/// dividing a reservation of 'reservation_to_distribute' bytes between columns with
/// scan range lengths 'col_range_lengths' given a min and max buffer size. Returns
/// a vector with an entry per column with the index into 'col_range_lengths' and the
/// amount of reservation in bytes to give to that column.
static ColumnReservations DivideReservationBetweenColumnsHelper(int64_t min_buffer_size,
int64_t max_buffer_size, const ColumnRangeLengths& col_range_lengths,
int64_t reservation_to_distribute);
/// Compute the ideal reservation to scan a file with scan range lengths
/// 'col_range_lengths' given the min and max buffer size of the singleton DiskIoMgr
/// in ExecEnv.
static int64_t ComputeIdealReservation(const ColumnRangeLengths& col_range_lengths);
/// Gets memory for outputting tuples into the CollectionValue being constructed via
/// 'builder'. If memory limit is exceeded, an error status is returned. Otherwise,
/// returns the maximum number of tuples that can be output in 'num_rows'.
///
/// The returned TupleRow* should not be incremented (i.e. don't call next_row() on
/// it). Instead, incrementing *tuple_mem will update *tuple_row_mem to be pointing at
/// the next tuple. This also means its unnecessary to call
/// (*tuple_row_mem)->SetTuple().
Status GetCollectionMemory(CollectionValueBuilder* builder, MemPool** pool,
Tuple** tuple_mem, TupleRow** tuple_row_mem, int64_t* num_rows) WARN_UNUSED_RESULT;
/// Number of columns that need to be read.
RuntimeProfile::Counter* num_cols_counter_;
/// Number of scanners that end up doing no reads because their splits don't overlap
/// with the midpoint of any row-group/stripe in the file.
RuntimeProfile::Counter* num_scanners_with_no_reads_counter_;
/// Average and min/max time spent processing the footer by each split.
RuntimeProfile::SummaryStatsCounter* process_footer_timer_stats_;
/// Average and min/max memory reservation for a scanning a row group (parquet) or
/// stripe (orc), both ideal (calculated based on min and max buffer size) and actual.
RuntimeProfile::SummaryStatsCounter* columnar_scanner_ideal_reservation_counter_;
RuntimeProfile::SummaryStatsCounter* columnar_scanner_actual_reservation_counter_;
/// Number of stream read request done in in sync and async manners and the total.
RuntimeProfile::Counter* io_sync_request_;
RuntimeProfile::Counter* io_async_request_;
RuntimeProfile::Counter* io_total_request_;
/// Number of stream read bytes done in in sync and async manners and the total.
RuntimeProfile::Counter* io_sync_bytes_;
RuntimeProfile::Counter* io_async_bytes_;
RuntimeProfile::Counter* io_total_bytes_;
/// Total number of bytes skipped during stream reading.
RuntimeProfile::Counter* io_skipped_bytes_;
/// Total file metadata reads done.
/// Incremented when serving query from metadata instead of iterating rows or
/// row groups / stripes.
RuntimeProfile::Counter* num_file_metadata_read_;
/// MemPool counters for the scratch batch
RuntimeProfile::SummaryStatsCounter* scratch_mem_alloc_duration_;
RuntimeProfile::SummaryStatsCounter* scratch_mem_free_duration_;
RuntimeProfile::SummaryStatsCounter* scratch_mem_alloc_bytes_;
/// Time spent in allocating collection memory and copying memory in doubling
/// the tuple buffer
RuntimeProfile::Counter* get_collection_mem_timer_ = nullptr;
private:
int ProcessScratchBatchCodegenOrInterpret(RowBatch* dst_batch);
};
}