blob: 2d928293da59fd290b6073ca1cc36fa5691f40de [file] [log] [blame]
// 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_HDFS_TABLE_WRITER_H
#define IMPALA_EXEC_HDFS_TABLE_WRITER_H
#include <vector>
#include <hdfs.h>
#include "common/status.h"
#include "gen-cpp/control_service.pb.h"
namespace impala {
class HdfsPartitionDescriptor;
class HdfsTableDescriptor;
class HdfsTableSink;
struct OutputPartition;
class RowBatch;
class RuntimeState;
class ScalarExprEvaluator;
/// Pure virtual class for writing to hdfs table partition files.
/// Subclasses implement the code needed to write to a specific file type.
/// A subclass needs to implement functions to format and add rows to the file
/// and to do whatever processing is needed prior to closing the file.
class HdfsTableWriter {
public:
/// The implementation of a writer may reference the parameters to the constructor
/// during the lifetime of the object.
/// output_partition -- Information on the output partition file.
/// partition -- the descriptor for the partition being written
/// table_desc -- the descriptor for the table being written.
HdfsTableWriter(HdfsTableSink* parent,
RuntimeState* state, OutputPartition* output_partition,
const HdfsPartitionDescriptor* partition_desc,
const HdfsTableDescriptor* table_desc);
virtual ~HdfsTableWriter() { }
/// The sequence of calls to this object are:
/// 1. Init()
/// 2. InitNewFile()
/// 3. AppendRows() - called repeatedly
/// 4. Finalize()
/// For files formats that are splittable (and therefore can be written to an
/// arbitrarily large file), 1-4 is called once.
/// For files formats that are not splittable (i.e. columnar formats, compressed
/// text), 1) is called once and 2-4) is called repeatedly for each file.
/// Do initialization of writer.
virtual Status Init() WARN_UNUSED_RESULT = 0;
/// Called when a new file is started.
virtual Status InitNewFile() WARN_UNUSED_RESULT = 0;
/// Appends rows of 'batch' to the partition that are selected via 'row_group_indices',
/// and if the latter is empty, appends every row.
/// If the current file is full, the writer stops appending and returns with
/// *new_file == true. A new file will be opened and the same row batch will be passed
/// again. The writer must track how much of the batch it had already processed asking
/// for a new file. Otherwise the writer will return with *newfile == false.
virtual Status AppendRows(RowBatch* batch,
const std::vector<int32_t>& row_group_indices,
bool* new_file) WARN_UNUSED_RESULT = 0;
/// Finalize this partition. The writer needs to finish processing
/// all data have written out after the return from this call.
/// This is called once for each call to InitNewFile()
virtual Status Finalize() WARN_UNUSED_RESULT = 0;
/// Called once when this writer should cleanup any resources.
virtual void Close() = 0;
/// Returns the stats for this writer.
const DmlStatsPB& stats() const { return stats_; }
/// Default block size to use for this file format. If the file format doesn't
/// care, it should return 0 and the hdfs config default will be used.
virtual uint64_t default_block_size() const = 0;
/// Returns the file extension for this writer.
virtual std::string file_extension() const = 0;
protected:
/// Size to buffer output before calling Write() (which calls hdfsWrite), in bytes
/// to minimize the overhead of Write()
static const int HDFS_FLUSH_WRITE_SIZE = 50 * 1024;
/// Write to the current hdfs file.
Status Write(const char* data, int32_t len) {
return Write(reinterpret_cast<const uint8_t*>(data), len);
}
Status Write(const uint8_t* data, int32_t len);
template<typename T>
Status Write(T v) {
return Write(reinterpret_cast<uint8_t*>(&v), sizeof(T));
}
/// Parent table sink object
HdfsTableSink* parent_;
/// Runtime state.
RuntimeState* state_;
/// Structure describing partition written to by this writer.
/// NOTE: OutputPartition is usually accessed with a unique_ptr. It is safe to use
/// a raw pointer here, because the OutputPartition maintains a scoped_ptr to
/// the HdfsTableWriter objects. This will never outlive the OutputPartition.
OutputPartition* output_;
/// Table descriptor of table to be written.
const HdfsTableDescriptor* table_desc_;
/// Reference to the evaluators of expressions which generate the output value.
/// The evaluators are owned by sink which owns this table writer.
const std::vector<ScalarExprEvaluator*>& output_expr_evals_;
/// Subclass should populate any file format specific stats.
DmlStatsPB stats_;
};
}
#endif