susumu.yata
null+****@clear*****
Fri Nov 30 17:58:49 JST 2012
susumu.yata 2012-11-30 17:58:49 +0900 (Fri, 30 Nov 2012) New Revision: d2d9a9eab55449b4ae8c5178f13fcb5c8ddfb953 https://github.com/groonga/grnxx/commit/d2d9a9eab55449b4ae8c5178f13fcb5c8ddfb953 Log: Implement grnxx::alpha::BlobVector (incomplete). Modified files: lib/alpha/blob_vector.cpp lib/alpha/blob_vector.hpp Modified: lib/alpha/blob_vector.cpp (+191 -0) =================================================================== --- lib/alpha/blob_vector.cpp 2012-11-30 12:58:52 +0900 (e69de29) +++ lib/alpha/blob_vector.cpp 2012-11-30 17:58:49 +0900 (01b0445) @@ -0,0 +1,191 @@ +/* + Copyright (C) 2012 Brazil, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "blob_vector.hpp" + +#include "../exception.hpp" +#include "../lock.hpp" +#include "../logger.hpp" + +namespace grnxx { +namespace alpha { + +BlobVectorHeader::BlobVectorHeader(uint32_t cells_block_id) + : cells_block_id_(cells_block_id), + inter_process_mutex_() {} + +StringBuilder &operator<<(StringBuilder &builder, + BlobVectorValueType value_type) { + switch (value_type) { + case BLOB_VECTOR_VALUE_NULL: { + return builder << "BLOB_VECTOR_VALUE_NULL"; + } + case BLOB_VECTOR_VALUE_SMALL: { + return builder << "BLOB_VECTOR_VALUE_SMALL"; + } + case BLOB_VECTOR_VALUE_MEDIUM: { + return builder << "BLOB_VECTOR_VALUE_MEDIUM"; + } + case BLOB_VECTOR_VALUE_LARGE: { + return builder << "BLOB_VECTOR_VALUE_LARGE"; + } + default: { + return builder << "n/a"; + } + } +} + +StringBuilder &operator<<(StringBuilder &builder, + BlobVectorValueAttribute value_attribute) { + switch (value_attribute) { + case BLOB_VECTOR_VALUE_APPENDABLE: { + return builder << "BLOB_VECTOR_VALUE_APPENDABLE"; + } + case BLOB_VECTOR_VALUE_PREPENDABLE: { + return builder << "BLOB_VECTOR_VALUE_PREPENDABLE"; + } + default: { + return builder << "n/a"; + } + } +} + +std::unique_ptr<BlobVectorImpl> BlobVectorImpl::create(io::Pool pool) { + std::unique_ptr<BlobVectorImpl> vector(new (std::nothrow) BlobVectorImpl); + if (!vector) { + GRNXX_ERROR() << "new grnxx::io::VectorImpl failed"; + GRNXX_THROW(); + } + vector->create_vector(pool); + return vector; +} + +std::unique_ptr<BlobVectorImpl> BlobVectorImpl::open(io::Pool pool, + uint32_t block_id) { + std::unique_ptr<BlobVectorImpl> vector(new (std::nothrow) BlobVectorImpl); + if (!vector) { + GRNXX_ERROR() << "new grnxx::io::VectorImpl failed"; + GRNXX_THROW(); + } + vector->open_vector(pool, block_id); + return vector; +} + +const void *BlobVectorImpl::get_value(uint64_t id, uint64_t *length) { + if (id > BLOB_VECTOR_MAX_ID) { + GRNXX_ERROR() << "invalid argument: id = " << id + << ", max_id = " << BLOB_VECTOR_MAX_ID; + GRNXX_THROW(); + } + + const BlobVectorCell cell = cells_[id]; + switch (cell.value_type()) { + case BLOB_VECTOR_VALUE_NULL: { + if (length) { + *length = 0; + } + return nullptr; + } + case BLOB_VECTOR_VALUE_SMALL: { + if (length) { + *length = cell.small().length(); + } + // FIXME: The cell might be updated by other threads and processes. + // This interface cannot solve this problem. + return cells_[id].small().value(); + } + case BLOB_VECTOR_VALUE_MEDIUM: { + // TODO: Not implemented yet. + return nullptr; + } + case BLOB_VECTOR_VALUE_LARGE: { + void * const block_address = + pool_.get_block_address(cell.large().block_id()); + if (length) { + *length = *static_cast<uint64_t *>(block_address); + } + return static_cast<uint64_t *>(block_address) + 1; + } + default: { + GRNXX_ERROR() << "invalid value type"; + GRNXX_THROW(); + } + } +} + +StringBuilder &BlobVectorImpl::write_to(StringBuilder &builder) const { + if (!builder) { + return builder; + } + + // TODO + return builder; +} + +void BlobVectorImpl::unlink(io::Pool pool, uint32_t block_id) { + // TODO +} + +BlobVectorImpl::BlobVectorImpl() + : pool_(), + block_info_(nullptr), + header_(nullptr), + recycler_(nullptr), + cells_(), + inter_thread_mutex_() {} + +void BlobVectorImpl::create_vector(io::Pool pool) { + pool_ = pool; + block_info_ = pool.create_block(sizeof(BlobVectorHeader)); + + try { + cells_ = Vector<BlobVectorCell>(VECTOR_CREATE, pool_, BlobVectorCell()); + } catch (...) { + pool_.free_block(*block_info_); + throw; + } + + void * const block_address = pool_.get_block_address(*block_info_); + header_ = static_cast<BlobVectorHeader *>(block_address); + *header_ = BlobVectorHeader(cells_.block_id()); + + recycler_ = pool.mutable_recycler(); +} + +void BlobVectorImpl::open_vector(io::Pool pool, uint32_t block_id) { + pool_ = pool; + block_info_ = pool.get_block_info(block_id); + if (block_info_->size() < sizeof(BlobVectorHeader)) { + GRNXX_ERROR() << "invalid argument: block_info = " << *block_info_ + << ", header_size = " << sizeof(BlobVectorHeader); + GRNXX_THROW(); + } + + void * const block_address = pool_.get_block_address(*block_info_); + header_ = static_cast<BlobVectorHeader *>(block_address); + + // TODO: Check the format! + + recycler_ = pool.mutable_recycler(); + + // Open the core table. + cells_ = Vector<BlobVectorCell>(VECTOR_OPEN, pool, + header_->cells_block_id()); +} + +} // namespace alpha +} // namespace grnxx Modified: lib/alpha/blob_vector.hpp (+357 -0) =================================================================== --- lib/alpha/blob_vector.hpp 2012-11-30 12:58:52 +0900 (e69de29) +++ lib/alpha/blob_vector.hpp 2012-11-30 17:58:49 +0900 (2e9e0e7) @@ -0,0 +1,357 @@ +/* + Copyright (C) 2012 Brazil, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRNXX_ALPHA_BLOB_VECTOR_HPP +#define GRNXX_ALPHA_BLOB_VECTOR_HPP + +#include "vector.hpp" + +namespace grnxx { +namespace alpha { + +const uint64_t BLOB_VECTOR_MAX_ID = uint64_t(1) << 40; + +const uint64_t BLOB_VECTOR_MAX_SMALL_VALUE_LENGTH = 7; + +const uint64_t BLOB_VECTOR_MIN_MEDIUM_VALUE_LENGTH = + BLOB_VECTOR_MAX_SMALL_VALUE_LENGTH + 1; +const uint64_t BLOB_VECTOR_MAX_MEDIUM_VALUE_LENGTH = 65535; + +const uint64_t BLOB_VECTOR_MIN_LARGE_VALUE_LENGTH = + BLOB_VECTOR_MAX_MEDIUM_VALUE_LENGTH + 1; + +const uint8_t BLOB_VECTOR_MEDIUM_VALUE_UNIT_SIZE_BITS = 3; +const uint64_t BLOB_VECTOR_MEDIUM_VALUE_UNIT_SIZE = + uint64_t(1) << BLOB_VECTOR_MEDIUM_VALUE_UNIT_SIZE_BITS; + +const uint8_t BLOB_VECTOR_MEDIUM_VALUE_STORE_PAGE_SIZE_BITS = 19; +const uint8_t BLOB_VECTOR_MEDIUM_VALUE_STORE_TABLE_SIZE_BITS = 12; +const uint8_t BLOB_VECTOR_MEDIUM_VALUE_STORE_SECONDARY_TABLE_SIZE_BITS = 16; + +const uint64_t BLOB_VECTOR_MEDIUM_VALUE_STORE_PAGE_SIZE = + uint64_t(1) << BLOB_VECTOR_MEDIUM_VALUE_STORE_PAGE_SIZE_BITS; +const uint64_t BLOB_VECTOR_MEDIUM_VALUE_STORE_TABLE_SIZE = + uint64_t(1) << BLOB_VECTOR_MEDIUM_VALUE_STORE_TABLE_SIZE_BITS; +const uint64_t BLOB_VECTOR_MEDIUM_VALUE_STORE_SECONDARY_TABLE_SIZE = + uint64_t(1) << BLOB_VECTOR_MEDIUM_VALUE_STORE_SECONDARY_TABLE_SIZE_BITS; + +typedef Vector<char, BLOB_VECTOR_MEDIUM_VALUE_STORE_PAGE_SIZE, + BLOB_VECTOR_MEDIUM_VALUE_STORE_TABLE_SIZE, + BLOB_VECTOR_MEDIUM_VALUE_STORE_SECONDARY_TABLE_SIZE> +BlobVectorMediumValueStore; + +extern class BlobVectorCreate {} BLOB_VECTOR_CREATE; +extern class BlobVectorOpen {} BLOB_VECTOR_OPEN; + +class BlobVectorHeader { + public: + explicit BlobVectorHeader(uint32_t cells_block_id); + + uint32_t cells_block_id() const { + return cells_block_id_; + } + + Mutex *mutable_inter_process_mutex() { + return &inter_process_mutex_; + } + + private: + uint32_t cells_block_id_; + Mutex inter_process_mutex_; +}; + +enum BlobVectorValueType : uint8_t { + BLOB_VECTOR_VALUE_NULL = 0x00, + BLOB_VECTOR_VALUE_SMALL = 0x10, + BLOB_VECTOR_VALUE_MEDIUM = 0x20, // TODO: Not implemented yet. + BLOB_VECTOR_VALUE_LARGE = 0x30 +}; + +const uint8_t BLOB_VECTOR_VALUE_TYPE_MASK = 0x30; + +StringBuilder &operator<<(StringBuilder &builder, + BlobVectorValueType value_type); + +// TODO: Not implemented yet. +enum BlobVectorValueAttribute : uint8_t { + BLOB_VECTOR_VALUE_APPENDABLE = 0x00, + BLOB_VECTOR_VALUE_PREPENDABLE = 0x40 +}; + +const uint8_t BLOB_VECTOR_VALUE_ATTRIBUTE_MASK = 0x40; + +StringBuilder &operator<<(StringBuilder &builder, + BlobVectorValueAttribute value_attribute); + +const uint8_t BLOB_VECTOR_CELL_FLAGS_MASK = 0xF0; + +class BlobVectorNullValueCell { + public: + explicit BlobVectorNullValueCell(BlobVectorValueAttribute attribute) + : qword_(0) { + bytes_[0] = BLOB_VECTOR_VALUE_NULL | attribute; + } + + private: + union { + uint8_t bytes_[8]; + uint64_t qword_; + }; +}; + +class BlobVectorSmallValueCell { + public: + BlobVectorSmallValueCell(const void *ptr, uint64_t length, + BlobVectorValueAttribute attribute) : qword_(0) { + bytes_[0] = BLOB_VECTOR_VALUE_SMALL | attribute | + static_cast<uint8_t>(length); + std::memcpy(&bytes_[1], ptr, length); + } + + uint64_t length() const { + return bytes_[0] & ~BLOB_VECTOR_CELL_FLAGS_MASK; + } + const void *value() const { + return &bytes_[1]; + } + + private: + union { + uint8_t bytes_[8]; + uint64_t qword_; + }; +}; + +class BlobVectorMediumValueCell { + public: + BlobVectorMediumValueCell(uint64_t offset, uint64_t length, + BlobVectorValueAttribute attribute) : qword_(0) { + bytes_[0] = BLOB_VECTOR_VALUE_MEDIUM | attribute | + static_cast<uint8_t>(offset >> 40); + bytes_[1] = static_cast<uint8_t>(offset >> 32); + words_[1] = static_cast<uint16_t>(length); + dwords_[1] = static_cast<uint32_t>(offset); + } + + uint64_t length() const { + return words_[1]; + } + uint64_t offset() const { + return (static_cast<uint64_t>(bytes_[0] & + ~BLOB_VECTOR_CELL_FLAGS_MASK) << 40) | + (static_cast<uint64_t>(bytes_[1]) << 32) | dwords_[1]; + } + + private: + union { + uint8_t bytes_[8]; + uint16_t words_[4]; + uint32_t dwords_[2]; + uint64_t qword_; + }; +}; + +class BlobVectorLargeValueCell { + public: + BlobVectorLargeValueCell(uint32_t block_id, + BlobVectorValueAttribute attribute) : qword_(0) { + bytes_[0] = BLOB_VECTOR_VALUE_LARGE | attribute; + dwords_[1] = block_id; + } + + uint32_t block_id() const { + return dwords_[1]; + } + + private: + union { + uint8_t bytes_[8]; + uint32_t dwords_[2]; + uint64_t qword_; + }; +}; + +class BlobVectorCell { + public: + BlobVectorCell() : qword_(0) {} + + BlobVectorCell &operator=(const BlobVectorNullValueCell &rhs) { + null_value_cell_ = rhs; + return *this; + } + BlobVectorCell &operator=(const BlobVectorSmallValueCell &rhs) { + small_value_cell_ = rhs; + return *this; + } + BlobVectorCell &operator=(const BlobVectorMediumValueCell &rhs) { + medium_value_cell_ = rhs; + return *this; + } + BlobVectorCell &operator=(const BlobVectorLargeValueCell &rhs) { + large_value_cell_ = rhs; + return *this; + } + + BlobVectorValueType value_type() const { + Flags flags; + flags.byte = flags_.byte & BLOB_VECTOR_VALUE_TYPE_MASK; + return flags.value_type; + } + BlobVectorValueAttribute value_attribute() const { + Flags flags; + flags.byte = flags_.byte & BLOB_VECTOR_VALUE_ATTRIBUTE_MASK; + return flags.value_attribute; + }; + + const BlobVectorNullValueCell &null() const { + return null_value_cell_; + } + const BlobVectorSmallValueCell &small() const { + return small_value_cell_; + } + const BlobVectorMediumValueCell &medium() const { + return medium_value_cell_; + } + const BlobVectorLargeValueCell &large() const { + return large_value_cell_; + } + + StringBuilder &write_to(StringBuilder &builder) const; + + private: + union Flags { + uint8_t byte; + BlobVectorValueType value_type; + BlobVectorValueAttribute value_attribute; + }; + + union { + Flags flags_; + uint64_t qword_; + BlobVectorNullValueCell null_value_cell_; + BlobVectorSmallValueCell small_value_cell_; + BlobVectorMediumValueCell medium_value_cell_; + BlobVectorLargeValueCell large_value_cell_; + }; +}; + +static_assert(sizeof(BlobVectorCell) == sizeof(uint64_t), + "sizeof(BlobVectorCell) != sizeof(uint64_t)"); + +class BlobVectorImpl { + public: + static std::unique_ptr<BlobVectorImpl> create(io::Pool pool); + static std::unique_ptr<BlobVectorImpl> open(io::Pool pool, + uint32_t block_id); + + const void *get_value(uint64_t id, uint64_t *length); + + void set_value(uint64_t id, const void *ptr, uint64_t length, + uint64_t capacity, BlobVectorValueAttribute value_attribute); + + // TODO + + uint32_t block_id() const { + return block_info_->id(); + } + + StringBuilder &write_to(StringBuilder &builder) const; + + static void unlink(io::Pool pool, uint32_t block_id); + + private: + io::Pool pool_; + const io::BlockInfo *block_info_; + BlobVectorHeader *header_; + Recycler *recycler_; + Vector<BlobVectorCell> cells_; + Mutex inter_thread_mutex_; + + BlobVectorImpl(); + + void create_vector(io::Pool pool); + void open_vector(io::Pool pool, uint32_t block_id); +}; + +inline StringBuilder &operator<<(StringBuilder &builder, + const BlobVectorImpl &vector) { + return vector.write_to(builder); +} + +class BlobVector { + public: + BlobVector() : impl_() {} + BlobVector(const BlobVectorCreate &, io::Pool pool); + BlobVector(const BlobVectorOpen &, io::Pool pool, uint32_t block_id); + ~BlobVector() {} + + BlobVector(const BlobVector &vector) : impl_(vector.impl_) {} + BlobVector &operator=(const BlobVector &vector) { + impl_ = vector.impl_; + return *this; + } + + BlobVector(BlobVector &&vector) : impl_(std::move(vector.impl_)) {} + BlobVector &operator=(BlobVector &&vector) { + impl_ = std::move(vector.impl_); + return *this; + } + + GRNXX_EXPLICIT_CONVERSION operator bool() const { + return static_cast<bool>(impl_); + } + + // TODO +// BlobVectorValueRef operator[](uint64_t id); + + uint32_t block_id() const { + return impl_->block_id(); + } + + void swap(BlobVector &rhs) { + impl_.swap(rhs.impl_); + } + + StringBuilder &write_to(StringBuilder &builder) const { + return impl_ ? impl_->write_to(builder) : (builder << "n/a"); + } + + static GRNXX_CONSTEXPR uint64_t max_id() { + return BLOB_VECTOR_MAX_ID; + } + + static void unlink(io::Pool pool, uint32_t block_id) { + BlobVectorImpl::unlink(pool, block_id); + } + + private: + std::shared_ptr<BlobVectorImpl> impl_; +}; + +inline void swap(BlobVector &lhs, BlobVector &rhs) { + lhs.swap(rhs); +} + +inline StringBuilder &operator<<(StringBuilder &builder, + const BlobVector &vector) { + return vector.write_to(builder); +} + +} // namespace alpha +} // namespace grnxx + +#endif // GRNXX_ALPHA_BLOB_VECTOR_HPP -------------- next part -------------- HTML����������������������������... Download