blob: 6fae578b0927ce59d933b85dc7f172dd6d255d23 [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 KUDU_COMMON_COLUMNBLOCK_H
#define KUDU_COMMON_COLUMNBLOCK_H
#include "kudu/common/types.h"
#include "kudu/common/row.h"
#include "kudu/gutil/gscoped_ptr.h"
#include "kudu/util/bitmap.h"
#include "kudu/util/memory/arena.h"
#include "kudu/util/memory/overwrite.h"
#include "kudu/util/status.h"
namespace kudu {
class ColumnBlockCell;
// A block of data all belonging to a single column.
// This is simply a view into a buffer - it does not have any associated
// storage in and of itself. It does, however, maintain its type
// information, which can be used for extra type safety in debug mode.
class ColumnBlock {
public:
typedef ColumnBlockCell Cell;
ColumnBlock(const TypeInfo* type,
uint8_t *null_bitmap,
void *data,
size_t nrows,
Arena *arena)
: type_(type),
null_bitmap_(null_bitmap),
data_(reinterpret_cast<uint8_t *>(data)),
nrows_(nrows),
arena_(arena) {
DCHECK(data_) << "null data";
}
void SetCellIsNull(size_t idx, bool is_null) {
DCHECK(is_nullable());
BitmapChange(null_bitmap_, idx, !is_null);
}
void SetCellValue(size_t idx, const void *new_val) {
strings::memcpy_inlined(mutable_cell_ptr(idx), new_val, type_->size());
}
#ifndef NDEBUG
void OverwriteWithPattern(size_t idx, StringPiece pattern) {
char *col_data = reinterpret_cast<char *>(mutable_cell_ptr(idx));
kudu::OverwriteWithPattern(col_data, type_->size(), pattern);
}
#endif
// Return a pointer to the given cell.
const uint8_t *cell_ptr(size_t idx) const {
DCHECK_LT(idx, nrows_);
return data_ + type_->size() * idx;
}
// Returns a pointer to the given cell or NULL.
const uint8_t *nullable_cell_ptr(size_t idx) const {
return is_null(idx) ? NULL : cell_ptr(idx);
}
Cell cell(size_t idx) const;
uint8_t *null_bitmap() const {
return null_bitmap_;
}
bool is_nullable() const {
return null_bitmap_ != NULL;
}
bool is_null(size_t idx) const {
DCHECK(is_nullable());
DCHECK_LT(idx, nrows_);
return !BitmapTest(null_bitmap_, idx);
}
const size_t stride() const { return type_->size(); }
const uint8_t * data() const { return data_; }
uint8_t *data() { return data_; }
const size_t nrows() const { return nrows_; }
Arena *arena() { return arena_; }
const TypeInfo* type_info() const {
return type_;
}
private:
friend class ColumnBlockCell;
friend class ColumnDataView;
// Return a pointer to the given cell.
uint8_t *mutable_cell_ptr(size_t idx) {
DCHECK_LT(idx, nrows_);
return data_ + type_->size() * idx;
}
const TypeInfo *type_;
uint8_t *null_bitmap_;
uint8_t *data_;
size_t nrows_;
Arena *arena_;
};
// One of the cells in a ColumnBlock.
class ColumnBlockCell {
public:
ColumnBlockCell(ColumnBlock block, size_t row_idx)
: block_(std::move(block)), row_idx_(row_idx) {}
const TypeInfo* typeinfo() const { return block_.type_info(); }
size_t size() const { return block_.type_info()->size(); }
const void* ptr() const {
return is_nullable() ? block_.nullable_cell_ptr(row_idx_)
: block_.cell_ptr(row_idx_);
}
void* mutable_ptr() { return block_.mutable_cell_ptr(row_idx_); }
bool is_nullable() const { return block_.is_nullable(); }
bool is_null() const { return block_.is_null(row_idx_); }
void set_null(bool is_null) { block_.SetCellIsNull(row_idx_, is_null); }
protected:
ColumnBlock block_;
size_t row_idx_;
};
inline ColumnBlockCell ColumnBlock::cell(size_t idx) const {
return ColumnBlockCell(*this, idx);
}
// Wrap the ColumnBlock to expose a directly raw block at the specified offset.
// Used by the reader and block encoders to read/write raw data.
class ColumnDataView {
public:
explicit ColumnDataView(ColumnBlock *column_block, size_t first_row_idx = 0)
: column_block_(column_block), row_offset_(0) {
Advance(first_row_idx);
}
void Advance(size_t skip) {
// Check <= here, not <, since you can skip to
// the very end of the data (leaving an empty block)
DCHECK_LE(skip, column_block_->nrows());
row_offset_ += skip;
}
size_t first_row_index() const {
return row_offset_;
}
// Set 'nrows' bits of the the null-bitmap to "value"
// true if not null, false if null.
void SetNullBits(size_t nrows, bool value) {
BitmapChangeBits(column_block_->null_bitmap(), row_offset_, nrows, value);
}
uint8_t *data() {
return column_block_->mutable_cell_ptr(row_offset_);
}
const uint8_t *data() const {
return column_block_->cell_ptr(row_offset_);
}
Arena *arena() { return column_block_->arena(); }
size_t nrows() const {
return column_block_->nrows() - row_offset_;
}
const size_t stride() const {
return column_block_->stride();
}
const TypeInfo* type_info() const {
return column_block_->type_info();
}
private:
ColumnBlock *column_block_;
size_t row_offset_;
};
// Utility class which allocates temporary storage for a
// dense block of column data, freeing it when it goes
// out of scope.
//
// This is more useful in test code than production code,
// since it doesn't allocate from an arena, etc.
template<DataType type>
class ScopedColumnBlock : public ColumnBlock {
public:
typedef typename TypeTraits<type>::cpp_type cpp_type;
explicit ScopedColumnBlock(size_t n_rows)
: ColumnBlock(GetTypeInfo(type),
new uint8_t[BitmapSize(n_rows)],
new cpp_type[n_rows],
n_rows,
new Arena(1024, 1*1024*1024)),
null_bitmap_(null_bitmap()),
data_(reinterpret_cast<cpp_type *>(data())),
arena_(arena()) {
}
const cpp_type &operator[](size_t idx) const {
return data_[idx];
}
cpp_type &operator[](size_t idx) {
return data_[idx];
}
private:
gscoped_array<uint8_t> null_bitmap_;
gscoped_array<cpp_type> data_;
gscoped_ptr<Arena> arena_;
};
} // namespace kudu
#endif