susumu.yata
null+****@clear*****
Wed May 29 11:45:43 JST 2013
susumu.yata 2013-05-29 11:45:43 +0900 (Wed, 29 May 2013) New Revision: 9cf5d2f46e3c005066985b6d257ba6ae55df8914 https://github.com/groonga/grnxx/commit/9cf5d2f46e3c005066985b6d257ba6ae55df8914 Message: Change the interface of grnxx::Array. Added files: lib/grnxx/array.cpp Modified files: lib/grnxx/Makefile.am lib/grnxx/array.hpp lib/grnxx/array_impl.cpp lib/grnxx/array_impl.hpp lib/grnxx/bit_array.hpp lib/grnxx/map/array_map.cpp lib/grnxx/map/array_map.hpp lib/grnxx/map/bytes_store.cpp test/test_array.cpp test/test_bit_array.cpp Modified: lib/grnxx/Makefile.am (+1 -0) =================================================================== --- lib/grnxx/Makefile.am 2013-05-28 20:32:56 +0900 (f97e3e8) +++ lib/grnxx/Makefile.am 2013-05-29 11:45:43 +0900 (97e8ef8) @@ -19,6 +19,7 @@ libgrnxx_la_LIBADD = \ libgrnxx_la_LDFLAGS = @AM_LTLDFLAGS@ libgrnxx_la_SOURCES = \ + array.cpp \ array_impl.cpp \ backtrace.cpp \ broken_down_time.cpp \ Added: lib/grnxx/array.cpp (+24 -0) 100644 =================================================================== --- /dev/null +++ lib/grnxx/array.cpp 2013-05-29 11:45:43 +0900 (2c81e02) @@ -0,0 +1,24 @@ +/* + Copyright (C) 2012-2013 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 "grnxx/array.hpp" + +namespace grnxx { + +// Nothing to do. + +} // namespace grnxx Modified: lib/grnxx/array.hpp (+53 -361) =================================================================== --- lib/grnxx/array.hpp 2013-05-28 20:32:56 +0900 (477b8fb) +++ lib/grnxx/array.hpp 2013-05-29 11:45:43 +0900 (a23ebdb) @@ -22,9 +22,10 @@ #include <cstring> #include <memory> +#include <new> #include "grnxx/array_impl.hpp" -#include "grnxx/traits.hpp" +#include "grnxx/logger.hpp" #include "grnxx/types.hpp" namespace grnxx { @@ -39,284 +40,6 @@ template <typename T, uint64_t PAGE_SIZE = ARRAY_DEFAULT_PAGE_SIZE, uint64_t TABLE_SIZE = ARRAY_DEFAULT_TABLE_SIZE, uint64_t SECONDARY_TABLE_SIZE = ARRAY_DEFAULT_SECONDARY_TABLE_SIZE> -class Array; - -// 1D array. -template <typename T, uint64_t PAGE_SIZE> -class Array<T, PAGE_SIZE, 1, 1> { - static_assert(PAGE_SIZE > 0, "PAGE_SIZE <= 0"); - - using ArrayImpl = Array1D; - - public: - using Value = typename Traits<T>::Type; - using ValueArg = typename Traits<T>::ArgumentType; - - Array() : impl_() {} - ~Array() {} - - // Return true iff the array is valid. - explicit operator bool() const { - return static_cast<bool>(impl_); - } - - // Create an array. - bool create(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Create an array with the default value. - bool create(Storage *storage, uint32_t storage_node_id, - ValueArg default_value) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - &default_value, fill_page)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Open an array. - bool open(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::open(storage, storage_node_id, sizeof(Value), PAGE_SIZE)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Unlink an array. - static bool unlink(Storage *storage, uint32_t storage_node_id) { - return ArrayImpl::unlink(storage, storage_node_id, sizeof(Value), - PAGE_SIZE); - } - - // Return the number of values in each page. - static constexpr uint64_t page_size() { - return PAGE_SIZE; - } - // Return the number of pages in each table. - static constexpr uint64_t table_size() { - return 1; - } - // Return the number of tables in each secondary table. - static constexpr uint64_t secondary_table_size() { - return 1; - } - // Return the number of values in Array. - static constexpr uint64_t size() { - return page_size() * table_size() * secondary_table_size(); - } - - // Return the storage node ID. - uint32_t storage_node_id() const { - return impl_->storage_node_id(); - } - - // Get a reference to a value. - Value &operator[](uint64_t value_id) { - Value * const page = get_page(value_id / PAGE_SIZE); - return page[value_id % PAGE_SIZE]; - } - - // Get a value and return true. - // The value is assigned to "*value" iff "value" != nullptr. - bool get(uint64_t value_id, Value *value) { - const Value * const page = get_page(value_id / PAGE_SIZE); - if (value) { - *value = page[value_id % PAGE_SIZE]; - } - return true; - } - - // Set a value and return true. - bool set(uint64_t value_id, ValueArg value) { - Value * const page = get_page(value_id / PAGE_SIZE); - page[value_id % PAGE_SIZE] = value; - return true; - } - - // Get a value and return its address. - Value *get_value(uint64_t value_id) { - Value * const page = get_page(value_id / PAGE_SIZE); - return &page[value_id % PAGE_SIZE]; - } - - // Get a page and return its starting address. - Value *get_page(uint64_t) { - return impl_->get_page<Value>(); - } - - private: - std::unique_ptr<ArrayImpl> impl_; - - // This function is used to fill a new page with the default value. - static void fill_page(void *page, const void *value) { - Value *values = static_cast<Value *>(page); - for (uint64_t i = 0; i < PAGE_SIZE; ++i) { - std::memcpy(&values[i], value, sizeof(Value)); - } - } -}; - -// 2D array. -template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE> -class Array<T, PAGE_SIZE, TABLE_SIZE, 1> { - static_assert((PAGE_SIZE > 0) && ((PAGE_SIZE & (PAGE_SIZE - 1)) == 0), - "PAGE_SIZE must be a power of two"); - static_assert(TABLE_SIZE > 0, "TABLE_SIZE <= 0"); - - using ArrayImpl = Array2D; - - public: - using Value = typename Traits<T>::Type; - using ValueArg = typename Traits<T>::ArgumentType; - - Array() : impl_() {} - ~Array() {} - - // Return true iff the array is valid. - explicit operator bool() const { - return static_cast<bool>(impl_); - } - - // Create an array. - bool create(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Create an array with the default value. - bool create(Storage *storage, uint32_t storage_node_id, - ValueArg default_value) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE, &default_value, fill_page)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Open an array. - bool open(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::open(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE, fill_page)); - if (!impl) { - return false; - } - impl_ = std::move(impl); - return true; - } - - // Unlink an array. - static bool unlink(Storage *storage, uint32_t storage_node_id) { - return ArrayImpl::unlink(storage, storage_node_id, sizeof(Value), - PAGE_SIZE, TABLE_SIZE); - } - - // Return the number of values in each page. - static constexpr uint64_t page_size() { - return PAGE_SIZE; - } - // Return the number of pages in each table. - static constexpr uint64_t table_size() { - return TABLE_SIZE; - } - // Return the number of tables in each secondary table. - static constexpr uint64_t secondary_table_size() { - return 1; - } - // Return the number of values in Array. - static constexpr uint64_t size() { - return page_size() * table_size() * secondary_table_size(); - } - - // Return the storage node ID. - uint32_t storage_node_id() const { - return impl_->storage_node_id(); - } - - // Get a reference to a value. - // This function throws an exception on failure. - Value &operator[](uint64_t value_id) { - Value * const page = - impl_->get_page<Value, TABLE_SIZE>(value_id / PAGE_SIZE); - return page[value_id % PAGE_SIZE]; - } - - // Get a value and return true on success. - // The value is assigned to "*value" iff "value" != nullptr. - bool get(uint64_t value_id, Value *value) { - const Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return false; - } - if (value) { - *value = page[value_id % PAGE_SIZE]; - } - return true; - } - - // Set a value and return true on success. - bool set(uint64_t value_id, ValueArg value) { - Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return false; - } - page[value_id % PAGE_SIZE] = value; - return true; - } - - // Get a value and return its address on success. - Value *get_value(uint64_t value_id) { - Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return nullptr; - } - return &page[value_id % PAGE_SIZE]; - } - - // Get a page and return its starting address on success. - Value *get_page(uint64_t page_id) { - return impl_->get_page_nothrow<Value, TABLE_SIZE>(page_id); - } - - private: - std::unique_ptr<ArrayImpl> impl_; - - // This function is used to fill a new page with the default value. - static void fill_page(void *page, const void *value) { - Value *values = static_cast<Value *>(page); - for (uint64_t i = 0; i < PAGE_SIZE; ++i) { - std::memcpy(&values[i], value, sizeof(Value)); - } - } -}; - -// 3D array. -template <typename T, - uint64_t PAGE_SIZE, - uint64_t TABLE_SIZE, - uint64_t SECONDARY_TABLE_SIZE> class Array { static_assert((PAGE_SIZE > 0) && ((PAGE_SIZE & (PAGE_SIZE - 1)) == 0), "PAGE_SIZE must be a power of two"); @@ -324,142 +47,111 @@ class Array { "TABLE_SIZE must be a power of two"); static_assert(SECONDARY_TABLE_SIZE > 0, "SECONDARY_TABLE_SIZE <= 0"); - using ArrayImpl = Array3D; + using ArrayImpl = ArrayImpl<T, PAGE_SIZE, TABLE_SIZE, SECONDARY_TABLE_SIZE>; public: - using Value = typename Traits<T>::Type; - using ValueArg = typename Traits<T>::ArgumentType; + using Value = typename ArrayImpl::Value; + using ValueArg = typename ArrayImpl::ValueArg; - Array() : impl_() {} ~Array() {} - // Return true iff the array is valid. - explicit operator bool() const { - return static_cast<bool>(impl_); - } - // Create an array. - bool create(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE, SECONDARY_TABLE_SIZE)); - if (!impl) { - return false; + static Array *create(Storage *storage, uint32_t storage_node_id) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; } - impl_ = std::move(impl); - return true; + if (!array->impl_.create(storage, storage_node_id)) { + return nullptr; + } + return array.release(); } // Create an array with the default value. - bool create(Storage *storage, uint32_t storage_node_id, - ValueArg default_value) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE, SECONDARY_TABLE_SIZE, &default_value, - fill_page)); - if (!impl) { - return false; + static Array *create(Storage *storage, uint32_t storage_node_id, + ValueArg default_value) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; + } + if (!array->impl_.create(storage, storage_node_id, default_value)) { + return nullptr; } - impl_ = std::move(impl); - return true; + return array.release(); } // Open an array. - bool open(Storage *storage, uint32_t storage_node_id) { - std::unique_ptr<ArrayImpl> impl( - ArrayImpl::open(storage, storage_node_id, sizeof(Value), PAGE_SIZE, - TABLE_SIZE, SECONDARY_TABLE_SIZE, fill_page)); - if (!impl) { - return false; + static Array *open(Storage *storage, uint32_t storage_node_id) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; + } + if (!array->impl_.open(storage, storage_node_id)) { + return nullptr; } - impl_ = std::move(impl); - return true; + return array.release(); } // Unlink an array. static bool unlink(Storage *storage, uint32_t storage_node_id) { - return ArrayImpl::unlink(storage, storage_node_id, sizeof(Value), - PAGE_SIZE, TABLE_SIZE, SECONDARY_TABLE_SIZE); + return ArrayImpl::unlink(storage, storage_node_id); } // Return the number of values in each page. static constexpr uint64_t page_size() { - return PAGE_SIZE; + return ArrayImpl::page_size(); } // Return the number of pages in each table. static constexpr uint64_t table_size() { - return TABLE_SIZE; + return ArrayImpl::table_size(); } // Return the number of tables in each secondary table. static constexpr uint64_t secondary_table_size() { - return SECONDARY_TABLE_SIZE; + return ArrayImpl::secondary_table_size(); } // Return the number of values in Array. static constexpr uint64_t size() { - return page_size() * table_size() * secondary_table_size(); + return ArrayImpl::size(); } // Return the storage node ID. uint32_t storage_node_id() const { - return impl_->storage_node_id(); - } - - // Get a reference to a value. - // This function throws an exception on failure. - Value &operator[](uint64_t value_id) { - Value * const page = - impl_->get_page<Value, TABLE_SIZE, - SECONDARY_TABLE_SIZE>(value_id / PAGE_SIZE); - return page[value_id % PAGE_SIZE]; + return impl_.storage_node_id(); } // Get a value and return true on success. // The value is assigned to "*value" iff "value" != nullptr. bool get(uint64_t value_id, Value *value) { - const Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return false; - } - if (value) { - *value = page[value_id % PAGE_SIZE]; - } - return true; + return impl_.get(value_id, value); } - // Set a value and return true on success. bool set(uint64_t value_id, ValueArg value) { - Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return false; - } - page[value_id % PAGE_SIZE] = value; - return true; + return impl_.set(value_id, value); } - // Get a value and return its address on success. - Value *get_value(uint64_t value_id) { - Value * const page = get_page(value_id / PAGE_SIZE); - if (!page) { - return nullptr; - } - return &page[value_id % PAGE_SIZE]; + Value *get_pointer(uint64_t value_id) { + return impl_.get_pointer(value_id); } - // Get a page and return its starting address on success. Value *get_page(uint64_t page_id) { - return impl_->get_page_nothrow<Value, TABLE_SIZE, - SECONDARY_TABLE_SIZE>(page_id); + return impl_.get_page(page_id); } private: - std::unique_ptr<ArrayImpl> impl_; + ArrayImpl impl_; + + Array() : impl_() {} - // This function is used to fill a new page with the default value. - static void fill_page(void *page, const void *value) { - Value *values = static_cast<Value *>(page); - for (uint64_t i = 0; i < PAGE_SIZE; ++i) { - std::memcpy(&values[i], value, sizeof(Value)); + static Array *create_instance() { + Array * const array = new (std::nothrow) Array; + if (!array) { + GRNXX_ERROR() << "new grnxx::Array failed: " + << "value_size = " << sizeof(Value) + << ", page_size = " << PAGE_SIZE + << ", table_size = " << TABLE_SIZE + << ", secondary_table_size = " << SECONDARY_TABLE_SIZE; } + return array; } }; Modified: lib/grnxx/array_impl.cpp (+59 -196) =================================================================== --- lib/grnxx/array_impl.cpp 2013-05-28 20:32:56 +0900 (9276522) +++ lib/grnxx/array_impl.cpp 2013-05-29 11:45:43 +0900 (bb04e0f) @@ -20,7 +20,6 @@ #include <cstring> #include <new> -#include "grnxx/exception.hpp" #include "grnxx/lock.hpp" #include "grnxx/logger.hpp" #include "grnxx/storage.hpp" @@ -97,61 +96,13 @@ Array1D::Array1D() Array1D::~Array1D() {} -Array1D *Array1D::create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - const void *default_value, FillPage fill_page) { - if (!storage) { - GRNXX_ERROR() << "invalid argument: storage = nullptr"; - return nullptr; - } - std::unique_ptr<Array1D> array(new (std::nothrow) Array1D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array1D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size - << ", has_default_value = " << (default_value != nullptr); - return nullptr; - } - if (!array->create_array(storage, storage_node_id, value_size, page_size, - default_value, fill_page)) { - return nullptr; - } - return array.release(); -} - -Array1D *Array1D::open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size) { +bool Array1D::create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + const void *default_value, FillPage fill_page) { if (!storage) { GRNXX_ERROR() << "invalid argument: storage = nullptr"; - return nullptr; - } - std::unique_ptr<Array1D> array(new (std::nothrow) Array1D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array1D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size; - return nullptr; - } - if (!array->open_array(storage, storage_node_id, value_size, page_size)) { - return nullptr; - } - return array.release(); -} - -bool Array1D::unlink(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size) { - Array1D array; - if (!array.open(storage, storage_node_id, value_size, page_size)) { return false; } - return storage->unlink_node(storage_node_id); -} - -bool Array1D::create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - const void *default_value, FillPage fill_page) { StorageNode storage_node = storage->create_node(storage_node_id, sizeof(Array1DHeader)); if (!storage_node) { @@ -174,8 +125,12 @@ bool Array1D::create_array(Storage *storage, uint32_t storage_node_id, return true; } -bool Array1D::open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size) { +bool Array1D::open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size) { + if (!storage) { + GRNXX_ERROR() << "invalid argument: storage = nullptr"; + return false; + } StorageNode storage_node = storage->open_node(storage_node_id); if (!storage_node) { return false; @@ -205,6 +160,15 @@ bool Array1D::open_array(Storage *storage, uint32_t storage_node_id, return true; } +bool Array1D::unlink(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size) { + Array1D array; + if (!array.open(storage, storage_node_id, value_size, page_size)) { + return false; + } + return storage->unlink_node(storage_node_id); +} + Array2D::Array2D() : storage_(nullptr), storage_node_id_(STORAGE_INVALID_NODE_ID), @@ -217,71 +181,14 @@ Array2D::Array2D() Array2D::~Array2D() {} -Array2D *Array2D::create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, - const void *default_value, FillPage fill_page) { - if (!storage) { - GRNXX_ERROR() << "invalid argument: storage = nullptr"; - return nullptr; - } - std::unique_ptr<Array2D> array(new (std::nothrow) Array2D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array2D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size - << ", table_size = " << table_size - << ", has_default_value = " << (default_value != nullptr); - return nullptr; - } - if (!array->create_array(storage, storage_node_id, - value_size, page_size, table_size, - default_value, fill_page)) { - return nullptr; - } - return array.release(); -} - -Array2D *Array2D::open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, FillPage fill_page) { +bool Array2D::create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, + const void *default_value, FillPage fill_page) { if (!storage) { GRNXX_ERROR() << "invalid argument: storage = nullptr"; return nullptr; } - std::unique_ptr<Array2D> array(new (std::nothrow) Array2D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array2D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size - << ", table_size = " << table_size; - return nullptr; - } - if (!array->open_array(storage, storage_node_id, - value_size, page_size, table_size, - fill_page)) { - return nullptr; - } - return array.release(); -} - -bool Array2D::unlink(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size) { - Array2D array; - if (!array.open(storage, storage_node_id, - value_size, page_size, table_size, nullptr)) { - return false; - } - return storage->unlink_node(storage_node_id); -} - -bool Array2D::create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, - const void *default_value, FillPage fill_page) { storage_ = storage; uint64_t storage_node_size = sizeof(Array2DHeader); if (default_value) { @@ -323,9 +230,13 @@ bool Array2D::create_array(Storage *storage, uint32_t storage_node_id, return true; } -bool Array2D::open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, FillPage fill_page) { +bool Array2D::open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, FillPage fill_page) { + if (!storage) { + GRNXX_ERROR() << "invalid argument: storage = nullptr"; + return false; + } storage_ = storage; StorageNode storage_node = storage->open_node(storage_node_id); if (!storage_node) { @@ -371,14 +282,18 @@ bool Array2D::open_array(Storage *storage, uint32_t storage_node_id, return true; } -void Array2D::initialize_page(uint64_t page_id) { - if (!initialize_page_nothrow(page_id)) { - GRNXX_ERROR() << "failed to initialize page: page_id = " << page_id; - GRNXX_THROW(); +bool Array2D::unlink(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size) { + Array2D array; + if (!array.open(storage, storage_node_id, + value_size, page_size, table_size, nullptr)) { + return false; } + return storage->unlink_node(storage_node_id); } -bool Array2D::initialize_page_nothrow(uint64_t page_id) { +bool Array2D::initialize_page(uint64_t page_id) { Lock inter_thread_lock(&mutex_); if (!table_cache_[page_id]) { StorageNode page_node; @@ -422,73 +337,14 @@ Array3D::Array3D() Array3D::~Array3D() {} -Array3D *Array3D::create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - const void *default_value, FillPage fill_page) { - if (!storage) { - GRNXX_ERROR() << "invalid argument: storage = nullptr"; - return nullptr; - } - std::unique_ptr<Array3D> array(new (std::nothrow) Array3D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array3D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size - << ", table_size = " << table_size - << ", secondary_table_size = " << secondary_table_size - << ", has_default_value = " << (default_value != nullptr); - return nullptr; - } - if (!array->create_array(storage, storage_node_id, value_size, page_size, - table_size, secondary_table_size, - default_value, fill_page)) { - return nullptr; - } - return array.release(); -} - -Array3D *Array3D::open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - FillPage fill_page) { +bool Array3D::create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, uint64_t secondary_table_size, + const void *default_value, FillPage fill_page) { if (!storage) { GRNXX_ERROR() << "invalid argument: storage = nullptr"; return nullptr; } - std::unique_ptr<Array3D> array(new (std::nothrow) Array3D); - if (!array) { - GRNXX_ERROR() << "new grnxx::Array3D failed: " - << "storage_node_id = " << storage_node_id - << ", value_size = " << value_size - << ", page_size = " << page_size - << ", table_size = " << table_size - << ", secondary_table_size = " << secondary_table_size; - return nullptr; - } - if (!array->open_array(storage, storage_node_id, value_size, page_size, - table_size, secondary_table_size, fill_page)) { - return nullptr; - } - return array.release(); -} - -bool Array3D::unlink(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size) { - Array3D array; - if (!array.open(storage, storage_node_id, value_size, page_size, - table_size, secondary_table_size, nullptr)) { - return false; - } - return storage->unlink_node(storage_node_id); -} - -bool Array3D::create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - const void *default_value, FillPage fill_page) { storage_ = storage; uint64_t storage_node_size = sizeof(Array3DHeader); if (default_value) { @@ -519,10 +375,14 @@ bool Array3D::create_array(Storage *storage, uint32_t storage_node_id, return true; } -bool Array3D::open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - FillPage fill_page) { +bool Array3D::open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, uint64_t secondary_table_size, + FillPage fill_page) { + if (!storage) { + GRNXX_ERROR() << "invalid argument: storage = nullptr"; + return nullptr; + } storage_ = storage; StorageNode storage_node = storage->open_node(storage_node_id); if (!storage_node) { @@ -569,15 +429,18 @@ bool Array3D::open_array(Storage *storage, uint32_t storage_node_id, return true; } -void Array3D::initialize_page(uint64_t table_id, uint64_t page_id) { - if (!initialize_page_nothrow(table_id, page_id)) { - GRNXX_ERROR() << "failed to initialize page: table_id = " << table_id - << ", page_id = " << page_id; - GRNXX_THROW(); +bool Array3D::unlink(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, uint64_t secondary_table_size) { + Array3D array; + if (!array.open(storage, storage_node_id, value_size, page_size, + table_size, secondary_table_size, nullptr)) { + return false; } + return storage->unlink_node(storage_node_id); } -bool Array3D::initialize_page_nothrow(uint64_t table_id, uint64_t page_id) { +bool Array3D::initialize_page(uint64_t table_id, uint64_t page_id) { if (!table_caches_[table_id]) { if (!initialize_table(table_id)) { return false; Modified: lib/grnxx/array_impl.hpp (+366 -73) =================================================================== --- lib/grnxx/array_impl.hpp 2013-05-28 20:32:56 +0900 (e623075) +++ lib/grnxx/array_impl.hpp 2013-05-29 11:45:43 +0900 (b972d99) @@ -20,9 +20,11 @@ #include "grnxx/features.hpp" +#include <cstring> #include <memory> #include "grnxx/mutex.hpp" +#include "grnxx/traits.hpp" #include "grnxx/types.hpp" namespace grnxx { @@ -40,13 +42,12 @@ class Array1D { Array1D(); ~Array1D(); - static Array1D *create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - const void *default_value = nullptr, - FillPage fill_page = nullptr); - - static Array1D *open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size); + bool create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + const void *default_value = nullptr, + FillPage fill_page = nullptr); + bool open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size); static bool unlink(Storage *storage, uint32_t storage_node_id, uint64_t value_size, uint64_t page_size); @@ -64,13 +65,6 @@ class Array1D { uint32_t storage_node_id_; Array1DHeader *header_; void *page_; - - bool create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - const void *default_value, FillPage fill_page); - bool open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size); - }; class Array2D { @@ -80,15 +74,14 @@ class Array2D { Array2D(); ~Array2D(); - static Array2D *create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, - const void *default_value = nullptr, - FillPage fill_page = nullptr); - - static Array2D *open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, FillPage fill_page); + bool create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, + const void *default_value = nullptr, + FillPage fill_page = nullptr); + bool open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, FillPage fill_page); static bool unlink(Storage *storage, uint32_t storage_node_id, uint64_t value_size, uint64_t page_size, @@ -101,15 +94,7 @@ class Array2D { template <typename T, uint64_t TABLE_SIZE> T *get_page(uint64_t page_id) { if (!table_cache_[page_id]) { - initialize_page(page_id); - } - return static_cast<T *>(table_cache_[page_id]); - } - - template <typename T, uint64_t TABLE_SIZE> - T *get_page_nothrow(uint64_t page_id) { - if (!table_cache_[page_id]) { - if (!initialize_page_nothrow(page_id)) { + if (!initialize_page(page_id)) { return nullptr; } } @@ -126,16 +111,7 @@ class Array2D { std::unique_ptr<void *[]> table_cache_; Mutex mutex_; - bool create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, - const void *default_value, FillPage fill_page); - bool open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, uint64_t table_size, - FillPage fill_page); - - void initialize_page(uint64_t page_id); - bool initialize_page_nothrow(uint64_t page_id); + bool initialize_page(uint64_t page_id); }; class Array3D { @@ -145,16 +121,16 @@ class Array3D { Array3D(); ~Array3D(); - static Array3D *create(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - const void *default_value = nullptr, - FillPage fill_page = nullptr); + bool create(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, uint64_t secondary_table_size, + const void *default_value = nullptr, + FillPage fill_page = nullptr); - static Array3D *open(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - FillPage fill_page); + bool open(Storage *storage, uint32_t storage_node_id, + uint64_t value_size, uint64_t page_size, + uint64_t table_size, uint64_t secondary_table_size, + FillPage fill_page); static bool unlink(Storage *storage, uint32_t storage_node_id, uint64_t value_size, uint64_t page_size, @@ -169,17 +145,7 @@ class Array3D { const uint64_t table_id = page_id / TABLE_SIZE; page_id %= TABLE_SIZE; if (!table_caches_[table_id] || !table_caches_[table_id][page_id]) { - initialize_page(table_id, page_id); - } - return static_cast<T *>(table_caches_[table_id][page_id]); - } - - template <typename T, uint64_t TABLE_SIZE, uint64_t SECONDARY_TABLE_SIZE> - T *get_page_nothrow(uint64_t page_id) { - const uint64_t table_id = page_id / TABLE_SIZE; - page_id %= TABLE_SIZE; - if (!table_caches_[table_id] || !table_caches_[table_id][page_id]) { - if (!initialize_page_nothrow(table_id, page_id)) { + if (!initialize_page(table_id, page_id)) { return nullptr; } } @@ -198,21 +164,348 @@ class Array3D { Mutex table_mutex_; Mutex secondary_table_mutex_; - bool create_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - const void *default_value, FillPage fill_page); - bool open_array(Storage *storage, uint32_t storage_node_id, - uint64_t value_size, uint64_t page_size, - uint64_t table_size, uint64_t secondary_table_size, - FillPage fill_page); - - void initialize_page(uint64_t table_id, uint64_t page_id); - bool initialize_page_nothrow(uint64_t table_id, uint64_t page_id); + bool initialize_page(uint64_t table_id, uint64_t page_id); bool initialize_table(uint64_t table_id); bool initialize_secondary_table(); }; +template <typename T, + uint64_t PAGE_SIZE, + uint64_t TABLE_SIZE, + uint64_t SECONDARY_TABLE_SIZE> +class ArrayImpl; + +// 1D array. +template <typename T, uint64_t PAGE_SIZE> +class ArrayImpl<T, PAGE_SIZE, 1, 1> { + static_assert(PAGE_SIZE > 0, "PAGE_SIZE <= 0"); + + public: + using Value = typename Traits<T>::Type; + using ValueArg = typename Traits<T>::ArgumentType; + + ArrayImpl() : impl_() {} + ~ArrayImpl() {} + + // Return true iff the array is valid. + explicit operator bool() const { + return static_cast<bool>(impl_); + } + + // Create an array. + bool create(Storage *storage, uint32_t storage_node_id) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE); + } + // Create an array with the default value. + bool create(Storage *storage, uint32_t storage_node_id, + ValueArg default_value) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + &default_value, fill_page); + } + // Open an array. + bool open(Storage *storage, uint32_t storage_node_id) { + return impl_.open(storage, storage_node_id, sizeof(Value), PAGE_SIZE); + } + + // Unlink an array. + static bool unlink(Storage *storage, uint32_t storage_node_id) { + return Array1D::unlink(storage, storage_node_id, sizeof(Value), PAGE_SIZE); + } + + // Return the number of values in each page. + static constexpr uint64_t page_size() { + return PAGE_SIZE; + } + // Return the number of pages in each table. + static constexpr uint64_t table_size() { + return 1; + } + // Return the number of tables in each secondary table. + static constexpr uint64_t secondary_table_size() { + return 1; + } + // Return the number of values in Array. + static constexpr uint64_t size() { + return page_size() * table_size() * secondary_table_size(); + } + + // Return the storage node ID. + uint32_t storage_node_id() const { + return impl_.storage_node_id(); + } + + // Get a value and return true. + // The value is assigned to "*value" iff "value" != nullptr. + bool get(uint64_t value_id, Value *value) { + const Value * const page = get_page(value_id / PAGE_SIZE); + if (value) { + *value = page[value_id % PAGE_SIZE]; + } + return true; + } + + // Set a value and return true. + bool set(uint64_t value_id, ValueArg value) { + Value * const page = get_page(value_id / PAGE_SIZE); + page[value_id % PAGE_SIZE] = value; + return true; + } + + // Get a value and return its address. + Value *get_pointer(uint64_t value_id) { + Value * const page = get_page(value_id / PAGE_SIZE); + return &page[value_id % PAGE_SIZE]; + } + + // Get a page and return its starting address. + Value *get_page(uint64_t) { + return impl_.get_page<Value>(); + } + + private: + Array1D impl_; + + // This function is used to fill a new page with the default value. + static void fill_page(void *page, const void *value) { + Value *values = static_cast<Value *>(page); + for (uint64_t i = 0; i < PAGE_SIZE; ++i) { + std::memcpy(&values[i], value, sizeof(Value)); + } + } +}; + +// 2D array. +template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE> +class ArrayImpl<T, PAGE_SIZE, TABLE_SIZE, 1> { + static_assert((PAGE_SIZE > 0) && ((PAGE_SIZE & (PAGE_SIZE - 1)) == 0), + "PAGE_SIZE must be a power of two"); + static_assert(TABLE_SIZE > 0, "TABLE_SIZE <= 0"); + + public: + using Value = typename Traits<T>::Type; + using ValueArg = typename Traits<T>::ArgumentType; + + ArrayImpl() : impl_() {} + ~ArrayImpl() {} + + // Return true iff the array is valid. + explicit operator bool() const { + return static_cast<bool>(impl_); + } + + // Create an array. + bool create(Storage *storage, uint32_t storage_node_id) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE); + } + // Create an array with the default value. + bool create(Storage *storage, uint32_t storage_node_id, + ValueArg default_value) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE, &default_value, fill_page); + } + // Open an array. + bool open(Storage *storage, uint32_t storage_node_id) { + return impl_.open(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE, fill_page); + } + + // Unlink an array. + static bool unlink(Storage *storage, uint32_t storage_node_id) { + return Array2D::unlink(storage, storage_node_id, sizeof(Value), + PAGE_SIZE, TABLE_SIZE); + } + + // Return the number of values in each page. + static constexpr uint64_t page_size() { + return PAGE_SIZE; + } + // Return the number of pages in each table. + static constexpr uint64_t table_size() { + return TABLE_SIZE; + } + // Return the number of tables in each secondary table. + static constexpr uint64_t secondary_table_size() { + return 1; + } + // Return the number of values in Array. + static constexpr uint64_t size() { + return page_size() * table_size() * secondary_table_size(); + } + + // Return the storage node ID. + uint32_t storage_node_id() const { + return impl_.storage_node_id(); + } + + // Get a value and return true on success. + // The value is assigned to "*value" iff "value" != nullptr. + bool get(uint64_t value_id, Value *value) { + const Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return false; + } + if (value) { + *value = page[value_id % PAGE_SIZE]; + } + return true; + } + + // Set a value and return true on success. + bool set(uint64_t value_id, ValueArg value) { + Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return false; + } + page[value_id % PAGE_SIZE] = value; + return true; + } + + // Get a value and return its address on success. + Value *get_pointer(uint64_t value_id) { + Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return nullptr; + } + return &page[value_id % PAGE_SIZE]; + } + + // Get a page and return its starting address on success. + Value *get_page(uint64_t page_id) { + return impl_.get_page<Value, TABLE_SIZE>(page_id); + } + + private: + Array2D impl_; + + // This function is used to fill a new page with the default value. + static void fill_page(void *page, const void *value) { + Value *values = static_cast<Value *>(page); + for (uint64_t i = 0; i < PAGE_SIZE; ++i) { + std::memcpy(&values[i], value, sizeof(Value)); + } + } +}; + +// 3D array. +template <typename T, + uint64_t PAGE_SIZE, + uint64_t TABLE_SIZE, + uint64_t SECONDARY_TABLE_SIZE> +class ArrayImpl { + static_assert((PAGE_SIZE > 0) && ((PAGE_SIZE & (PAGE_SIZE - 1)) == 0), + "PAGE_SIZE must be a power of two"); + static_assert((TABLE_SIZE > 0) && ((TABLE_SIZE & (TABLE_SIZE - 1)) == 0), + "TABLE_SIZE must be a power of two"); + static_assert(SECONDARY_TABLE_SIZE > 0, "SECONDARY_TABLE_SIZE <= 0"); + + public: + using Value = typename Traits<T>::Type; + using ValueArg = typename Traits<T>::ArgumentType; + + ArrayImpl() : impl_() {} + ~ArrayImpl() {} + + // Return true iff the array is valid. + explicit operator bool() const { + return static_cast<bool>(impl_); + } + + // Create an array. + bool create(Storage *storage, uint32_t storage_node_id) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE, SECONDARY_TABLE_SIZE); + } + // Create an array with the default value. + bool create(Storage *storage, uint32_t storage_node_id, + ValueArg default_value) { + return impl_.create(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE, SECONDARY_TABLE_SIZE, &default_value, + fill_page); + } + // Open an array. + bool open(Storage *storage, uint32_t storage_node_id) { + return impl_.open(storage, storage_node_id, sizeof(Value), PAGE_SIZE, + TABLE_SIZE, SECONDARY_TABLE_SIZE, fill_page); + } + + // Unlink an array. + static bool unlink(Storage *storage, uint32_t storage_node_id) { + return Array3D::unlink(storage, storage_node_id, sizeof(Value), + PAGE_SIZE, TABLE_SIZE, SECONDARY_TABLE_SIZE); + } + + // Return the number of values in each page. + static constexpr uint64_t page_size() { + return PAGE_SIZE; + } + // Return the number of pages in each table. + static constexpr uint64_t table_size() { + return TABLE_SIZE; + } + // Return the number of tables in each secondary table. + static constexpr uint64_t secondary_table_size() { + return SECONDARY_TABLE_SIZE; + } + // Return the number of values in Array. + static constexpr uint64_t size() { + return page_size() * table_size() * secondary_table_size(); + } + + // Return the storage node ID. + uint32_t storage_node_id() const { + return impl_.storage_node_id(); + } + + // Get a value and return true on success. + // The value is assigned to "*value" iff "value" != nullptr. + bool get(uint64_t value_id, Value *value) { + const Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return false; + } + if (value) { + *value = page[value_id % PAGE_SIZE]; + } + return true; + } + + // Set a value and return true on success. + bool set(uint64_t value_id, ValueArg value) { + Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return false; + } + page[value_id % PAGE_SIZE] = value; + return true; + } + + // Get a value and return its address on success. + Value *get_pointer(uint64_t value_id) { + Value * const page = get_page(value_id / PAGE_SIZE); + if (!page) { + return nullptr; + } + return &page[value_id % PAGE_SIZE]; + } + + // Get a page and return its starting address on success. + Value *get_page(uint64_t page_id) { + return impl_.get_page<Value, TABLE_SIZE, SECONDARY_TABLE_SIZE>(page_id); + } + + private: + Array3D impl_; + + // This function is used to fill a new page with the default value. + static void fill_page(void *page, const void *value) { + Value *values = static_cast<Value *>(page); + for (uint64_t i = 0; i < PAGE_SIZE; ++i) { + std::memcpy(&values[i], value, sizeof(Value)); + } + } +}; + } // namespace grnxx #endif // GRNXX_ARRAY_IMPL_HPP Modified: lib/grnxx/bit_array.hpp (+13 -15) =================================================================== --- lib/grnxx/bit_array.hpp 2013-05-28 20:32:56 +0900 (f76590e) +++ lib/grnxx/bit_array.hpp 2013-05-29 11:45:43 +0900 (45573c2) @@ -20,6 +20,8 @@ #include "grnxx/features.hpp" +#include <memory> + #include "grnxx/array.hpp" #include "grnxx/traits.hpp" #include "grnxx/types.hpp" @@ -59,19 +61,22 @@ class BitArray { // Create an array. bool create(Storage *storage, uint32_t storage_node_id) { - return impl_.create(storage, storage_node_id); + impl_.reset(ArrayImpl::create(storage, storage_node_id)); + return static_cast<bool>(impl_); } // Create an array with the default value. bool create(Storage *storage, uint32_t storage_node_id, ValueArg default_value) { - return impl_.create(storage, storage_node_id, - default_value ? ~Unit(0) : Unit(0)); + impl_.reset(ArrayImpl::create(storage, storage_node_id, + default_value ? ~Unit(0) : Unit(0))); + return static_cast<bool>(impl_); } // Open an array. bool open(Storage *storage, uint32_t storage_node_id) { - return impl_.open(storage, storage_node_id); + impl_.reset(ArrayImpl::open(storage, storage_node_id)); + return static_cast<bool>(impl_); } // Unlink an array. @@ -102,14 +107,7 @@ class BitArray { // Return the storage node ID. uint32_t storage_node_id() const { - return impl_.storage_node_id(); - } - - // Get a value. - // This function throws an exception on failure. - Value operator[](uint64_t value_id) { - return (impl_[value_id / UNIT_SIZE] & - (Unit(1) << (value_id % UNIT_SIZE))) != 0; + return impl_->storage_node_id(); } // Get a value and return true on success. @@ -146,16 +144,16 @@ class BitArray { // Get a unit and return its address on success. Unit *get_unit(uint64_t unit_id) { - return impl_.get_value(unit_id); + return impl_->get_pointer(unit_id); } // Get a page and return its starting address on success. Unit *get_page(uint64_t page_id) { - return impl_.get_page(page_id); + return impl_->get_page(page_id); } private: - ArrayImpl impl_; + std::unique_ptr<ArrayImpl> impl_; }; } // namespace grnxx Modified: lib/grnxx/map/array_map.cpp (+15 -11) =================================================================== --- lib/grnxx/map/array_map.cpp 2013-05-28 20:32:56 +0900 (411596a) +++ lib/grnxx/map/array_map.cpp 2013-05-29 11:45:43 +0900 (67c92bd) @@ -125,7 +125,7 @@ bool ArrayMap<T>::get(int64_t key_id, Key *key) { if (!key) { return true; } - return keys_.get(key_id, key); + return keys_->get(key_id, key); } template <typename T> @@ -169,7 +169,7 @@ bool ArrayMap<T>::reset(int64_t key_id, KeyArg dest_key) { // GRNXX_WARNING() << "found: dest_key = " << dest_key; return false; } - if (!keys_.set(key_id, Helper<T>::normalize(dest_key))) { + if (!keys_->set(key_id, Helper<T>::normalize(dest_key))) { return false; } return true; @@ -185,7 +185,7 @@ bool ArrayMap<T>::find(KeyArg key, int64_t *key_id) { } if (bit) { Key stored_key; - if (!keys_.get(i, &stored_key)) { + if (!keys_->get(i, &stored_key)) { return false; } if (Helper<T>::equal_to(normalized_key, stored_key)) { @@ -211,7 +211,7 @@ bool ArrayMap<T>::add(KeyArg key, int64_t *key_id) { } if (bit) { Key stored_key; - if (!keys_.get(i, &stored_key)) { + if (!keys_->get(i, &stored_key)) { return false; } if (Helper<T>::equal_to(normalized_key, stored_key)) { @@ -226,7 +226,7 @@ bool ArrayMap<T>::add(KeyArg key, int64_t *key_id) { next_next_key_id = i; } } - if (!keys_.set(next_key_id, normalized_key) || + if (!keys_->set(next_key_id, normalized_key) || !bitmap_.set(next_key_id, true)) { return false; } @@ -272,7 +272,7 @@ bool ArrayMap<T>::replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id) { } if (bit) { Key stored_key; - if (!keys_.get(i, &stored_key)) { + if (!keys_->get(i, &stored_key)) { return false; } if (Helper<T>::equal_to(normalized_src_key, stored_key)) { @@ -288,7 +288,7 @@ bool ArrayMap<T>::replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id) { // GRNXX_WARNING() << "not found: src_key = " << src_key; return false; } - if (!keys_.set(src_key_id, normalized_dest_key)) { + if (!keys_->set(src_key_id, normalized_dest_key)) { return false; } if (key_id) { @@ -322,11 +322,12 @@ bool ArrayMap<T>::create_map(Storage *storage, uint32_t storage_node_id, return false; } header_->bitmap_storage_node_id = bitmap_.storage_node_id(); - if (!keys_.create(storage, storage_node_id_)) { + keys_.reset(Array<T>::create(storage, storage_node_id_)); + if (!keys_) { storage->unlink_node(storage_node_id_); return false; } - header_->keys_storage_node_id = keys_.storage_node_id(); + header_->keys_storage_node_id = keys_->storage_node_id(); return true; } @@ -344,8 +345,11 @@ bool ArrayMap<T>::open_map(Storage *storage, uint32_t storage_node_id) { } storage_node_id_ = storage_node_id; header_ = static_cast<ArrayMapHeader *>(storage_node.body()); - if (!bitmap_.open(storage, header_->bitmap_storage_node_id) || - !keys_.open(storage, header_->keys_storage_node_id)) { + if (!bitmap_.open(storage, header_->bitmap_storage_node_id)) { + return false; + } + keys_.reset(Array<T>::open(storage, header_->keys_storage_node_id)); + if (!keys_) { return false; } return true; Modified: lib/grnxx/map/array_map.hpp (+2 -2) =================================================================== --- lib/grnxx/map/array_map.hpp 2013-05-28 20:32:56 +0900 (63d6c53) +++ lib/grnxx/map/array_map.hpp 2013-05-29 11:45:43 +0900 (4d87bfa) @@ -20,9 +20,9 @@ #include "grnxx/features.hpp" +#include "grnxx/array.hpp" #include "grnxx/map.hpp" #include "grnxx/map/bitmap.hpp" -#include "grnxx/map/key_array.hpp" #include "grnxx/types.hpp" namespace grnxx { @@ -72,7 +72,7 @@ class ArrayMap : public Map<T> { uint32_t storage_node_id_; ArrayMapHeader *header_; Bitmap<T> bitmap_; - KeyArray<T> keys_; + std::unique_ptr<Array<T>> keys_; bool create_map(Storage *storage, uint32_t storage_node_id, const MapOptions &options); Modified: lib/grnxx/map/bytes_store.cpp (+24 -20) =================================================================== --- lib/grnxx/map/bytes_store.cpp 2013-05-28 20:32:56 +0900 (52b0338) +++ lib/grnxx/map/bytes_store.cpp 2013-05-29 11:45:43 +0900 (57159d1) @@ -151,8 +151,8 @@ class BytesStoreImpl : public BytesStore { Storage *storage_; uint32_t storage_node_id_; BytesStoreHeader *header_; - BytesArray pages_; - PageHeaderArray page_headers_; + std::unique_ptr<BytesArray> pages_; + std::unique_ptr<PageHeaderArray> page_headers_; PeriodicClock clock_; bool create_store(Storage *storage, uint32_t storage_node_id); @@ -239,7 +239,7 @@ bool BytesStoreImpl::get(uint64_t bytes_id, Value *bytes) { << ", max_page_id = " << header_->max_page_id; return false; } - const uint8_t * const page = pages_.get_page(page_id); + const uint8_t * const page = pages_->get_page(page_id); if (!page) { return false; } @@ -262,7 +262,8 @@ bool BytesStoreImpl::unset(uint64_t bytes_id) { << ", max_page_id = " << header_->max_page_id; return false; } - BytesStorePageHeader * const page_header = page_headers_.get_value(page_id); + BytesStorePageHeader * const page_header = + page_headers_->get_pointer(page_id); if (!page_header) { return false; } @@ -298,7 +299,7 @@ bool BytesStoreImpl::add(ValueArg bytes, uint64_t *bytes_id) { uint64_t offset = header_->next_offset; uint32_t size = static_cast<uint32_t>(bytes.size()); uint32_t page_id = get_page_id(offset); - BytesStorePageHeader *page_header = page_headers_.get_value(page_id); + BytesStorePageHeader *page_header = page_headers_->get_pointer(page_id); if (!page_header) { return false; } @@ -323,7 +324,7 @@ bool BytesStoreImpl::add(ValueArg bytes, uint64_t *bytes_id) { page_header->modified_time = clock_.now(); } // Use the new ACTIVE page. - header_->next_offset = next_page_id * pages_.page_size(); + header_->next_offset = next_page_id * pages_->page_size(); offset = header_->next_offset; page_id = next_page_id; page_header = next_page_header; @@ -332,10 +333,10 @@ bool BytesStoreImpl::add(ValueArg bytes, uint64_t *bytes_id) { // Use the previous ACTIVE page. page_header->status = BYTES_STORE_PAGE_IN_USE; page_header->modified_time = clock_.now(); - header_->next_offset = next_page_id * pages_.page_size(); + header_->next_offset = next_page_id * pages_->page_size(); } } - uint8_t * const page = pages_.get_page(page_id); + uint8_t * const page = pages_->get_page(page_id); if (!page) { return false; } @@ -354,7 +355,7 @@ bool BytesStoreImpl::sweep(Duration lifetime) { return true; } BytesStorePageHeader * const latest_empty_page_header = - page_headers_.get_value(header_->latest_empty_page_id); + page_headers_->get_pointer(header_->latest_empty_page_id); if (!latest_empty_page_header) { return false; } @@ -363,7 +364,7 @@ bool BytesStoreImpl::sweep(Duration lifetime) { const uint32_t oldest_empty_page_id = latest_empty_page_header->next_page_id; BytesStorePageHeader * const oldest_empty_page_header = - page_headers_.get_value(oldest_empty_page_id); + page_headers_->get_pointer(oldest_empty_page_id); if (!oldest_empty_page_header) { return false; } @@ -400,13 +401,14 @@ bool BytesStoreImpl::create_store(Storage *storage, uint32_t storage_node_id) { storage_node_id_ = storage_node.id(); header_ = static_cast<BytesStoreHeader *>(storage_node.body()); *header_ = BytesStoreHeader(); - if (!pages_.create(storage, storage_node_id_) || - !page_headers_.create(storage, storage_node_id_)) { + pages_.reset(BytesArray::create(storage, storage_node_id_)); + page_headers_.reset(PageHeaderArray::create(storage, storage_node_id)); + if (!pages_ || !page_headers_) { storage->unlink_node(storage_node_id_); return false; } - header_->pages_storage_node_id = pages_.storage_node_id(); - header_->page_headers_storage_node_id = page_headers_.storage_node_id(); + header_->pages_storage_node_id = pages_->storage_node_id(); + header_->page_headers_storage_node_id = page_headers_->storage_node_id(); return true; } @@ -418,8 +420,10 @@ bool BytesStoreImpl::open_store(Storage *storage, uint32_t storage_node_id) { } storage_node_id_ = storage_node.id(); header_ = static_cast<BytesStoreHeader *>(storage_node.body()); - if (!pages_.open(storage, header_->pages_storage_node_id) || - !page_headers_.open(storage, header_->page_headers_storage_node_id)) { + pages_.reset(BytesArray::open(storage, header_->pages_storage_node_id)); + page_headers_.reset( + PageHeaderArray::open(storage, header_->page_headers_storage_node_id)); + if (!pages_ || !page_headers_) { return false; } return true; @@ -432,7 +436,7 @@ bool BytesStoreImpl::reserve_active_page(uint32_t *page_id, if (header_->latest_idle_page_id != BYTES_STORE_INVALID_PAGE_ID) { // Use the oldest IDLE page. latest_idle_page_header = - page_headers_.get_value(header_->latest_idle_page_id); + page_headers_->get_pointer(header_->latest_idle_page_id); if (!latest_idle_page_header) { return false; } @@ -442,7 +446,7 @@ bool BytesStoreImpl::reserve_active_page(uint32_t *page_id, next_page_id = header_->max_page_id + 1; } BytesStorePageHeader * const next_page_header = - page_headers_.get_value(next_page_id); + page_headers_->get_pointer(next_page_id); if (!next_page_header) { return false; } @@ -467,7 +471,7 @@ bool BytesStoreImpl::make_page_empty(uint32_t page_id, BytesStorePageHeader *latest_empty_page_header = nullptr; if (header_->latest_empty_page_id != BYTES_STORE_INVALID_PAGE_ID) { latest_empty_page_header = - page_headers_.get_value(header_->latest_empty_page_id); + page_headers_->get_pointer(header_->latest_empty_page_id); if (!latest_empty_page_header) { return false; } @@ -489,7 +493,7 @@ bool BytesStoreImpl::make_page_idle(uint32_t page_id, BytesStorePageHeader *latest_idle_page_header = nullptr; if (header_->latest_idle_page_id != BYTES_STORE_INVALID_PAGE_ID) { BytesStorePageHeader * const latest_idle_page_header = - page_headers_.get_value(header_->latest_idle_page_id); + page_headers_->get_pointer(header_->latest_idle_page_id); if (!latest_idle_page_header) { return false; } Modified: test/test_array.cpp (+27 -27) =================================================================== --- test/test_array.cpp 2013-05-28 20:32:56 +0900 (9d47932) +++ test/test_array.cpp 2013-05-29 11:45:43 +0900 (5ad4d61) @@ -32,50 +32,50 @@ void test_array() { // Create an anonymous Storage. std::unique_ptr<grnxx::Storage> storage(grnxx::Storage::create(nullptr)); - grnxx::Array<int, PAGE_SIZE, TABLE_SIZE, SECONDARY_TABLE_SIZE> array; + std::unique_ptr<grnxx::Array<int, PAGE_SIZE, TABLE_SIZE, + SECONDARY_TABLE_SIZE>> array; uint32_t storage_node_id; // Create an Array and test its member functions. - assert(array.create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID)); + array.reset(array->create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID)); assert(array); - assert(array.page_size() == PAGE_SIZE); - assert(array.table_size() == TABLE_SIZE); - assert(array.secondary_table_size() == SECONDARY_TABLE_SIZE); - assert(array.size() == (PAGE_SIZE * TABLE_SIZE * SECONDARY_TABLE_SIZE)); - storage_node_id = array.storage_node_id(); - - for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(array.set(i, static_cast<int>(i))); + assert(array->page_size() == PAGE_SIZE); + assert(array->table_size() == TABLE_SIZE); + assert(array->secondary_table_size() == SECONDARY_TABLE_SIZE); + assert(array->size() == (PAGE_SIZE * TABLE_SIZE * SECONDARY_TABLE_SIZE)); + storage_node_id = array->storage_node_id(); + + for (std::uint64_t i = 0; i < array->size(); ++i) { + assert(array->set(i, static_cast<int>(i))); } - for (std::uint64_t i = 0; i < array.size(); ++i) { + for (std::uint64_t i = 0; i < array->size(); ++i) { int value; - assert(array.get(i, &value)); + assert(array->get(i, &value)); assert(value == static_cast<int>(i)); } - for (std::uint64_t i = 0; i < (array.size() / array.page_size()); ++i) { - assert(array.get_page(i)); + for (std::uint64_t i = 0; i < (array->size() / array->page_size()); ++i) { + assert(array->get_page(i)); } // Open the Array. - assert(array.open(storage.get(), storage_node_id)); - for (std::uint64_t i = 0; i < array.size(); ++i) { + assert(array->open(storage.get(), storage_node_id)); + for (std::uint64_t i = 0; i < array->size(); ++i) { int value; - assert(array.get(i, &value)); + assert(array->get(i, &value)); assert(value == static_cast<int>(i)); } // Create an Array with default value. - assert(array.create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID, 1)); + array.reset(array->create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID, 123)); assert(array); - for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(array[i] == 1); - array[i] = static_cast<int>(i); - } - for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(array[i] == static_cast<int>(i)); - } - for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(&array[i] == array.get_value(i)); + for (std::uint64_t i = 0; i < array->size(); ++i) { + int value; + assert(array->get(i, &value)); + assert(value == 123); + + int * const pointer = array->get_pointer(i); + assert(pointer); + assert(*pointer == 123); } } Modified: test/test_bit_array.cpp (+6 -6) =================================================================== --- test/test_bit_array.cpp 2013-05-28 20:32:56 +0900 (434557e) +++ test/test_bit_array.cpp 2013-05-29 11:45:43 +0900 (e7689f1) @@ -67,10 +67,6 @@ void test_bit_array() { assert(array.get(i, &stored_bit)); assert(stored_bit == expected_bit); } - for (std::uint64_t i = 0; i < array.size(); ++i) { - const bool expected_bit = (units[i / 64] >> (i % 64)) & 1; - assert(array[i] == expected_bit); - } for (std::uint64_t i = 0; i < (array.size() / array.unit_size()); ++i) { const Unit * const unit = array.get_unit(i); assert(unit); @@ -93,12 +89,16 @@ void test_bit_array() { assert(array.create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID, false)); assert(array); for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(!array[i]); + bool bit; + assert(array.get(i, &bit)); + assert(!bit); } assert(array.create(storage.get(), grnxx::STORAGE_ROOT_NODE_ID, true)); assert(array); for (std::uint64_t i = 0; i < array.size(); ++i) { - assert(array[i]); + bool bit; + assert(array.get(i, &bit)); + assert(bit); } } -------------- next part -------------- HTML����������������������������... Télécharger