[Groonga-commit] groonga/grnxx [master] Remove grnxx::alpha::DoubleArray2.

アーカイブの一覧に戻る

susumu.yata null+****@clear*****
Fri Feb 22 13:20:06 JST 2013


susumu.yata	2013-02-22 13:20:06 +0900 (Fri, 22 Feb 2013)

  New Revision: 9bf75ee30ea726b76b9769d5412c1da720f8848e
  https://github.com/groonga/grnxx/commit/9bf75ee30ea726b76b9769d5412c1da720f8848e

  Log:
    Remove grnxx::alpha::DoubleArray2.

  Removed files:
    lib/alpha/double_array2.cpp
    lib/alpha/double_array2.hpp
    test/test_alpha_double_array2.cpp
  Modified files:
    .gitignore
    lib/alpha/Makefile.am
    test/Makefile.am

  Modified: .gitignore (+0 -1)
===================================================================
--- .gitignore    2013-02-20 14:19:56 +0900 (1511e64)
+++ .gitignore    2013-02-22 13:20:06 +0900 (edbe982)
@@ -28,7 +28,6 @@ src/grnxx
 stamp-h1
 temp/
 test/test_alpha_double_array
-test/test_alpha_double_array2
 test/test_backtrace
 test/test_db_array
 test/test_db_blob_vector

  Modified: lib/alpha/Makefile.am (+0 -2)
===================================================================
--- lib/alpha/Makefile.am    2013-02-20 14:19:56 +0900 (1f6c068)
+++ lib/alpha/Makefile.am    2013-02-22 13:20:06 +0900 (2e9a91a)
@@ -4,11 +4,9 @@ libgrnxx_alpha_la_LDFLAGS = @AM_LTLDFLAGS@
 
 libgrnxx_alpha_la_SOURCES =		\
 	double_array.cpp		\
-	double_array2.cpp		\
 	sample.cpp
 
 libgrnxx_alpha_includedir = ${includedir}/grnxx/alpha
 libgrnxx_alpha_include_HEADERS =	\
 	double_array.hpp		\
-	double_array2.hpp		\
 	sample.hpp

  Deleted: lib/alpha/double_array2.cpp (+0 -1247) 100644
===================================================================
--- lib/alpha/double_array2.cpp    2013-02-20 14:19:56 +0900 (fd7e424)
+++ /dev/null
@@ -1,1247 +0,0 @@
-/*
-  Copyright (C) 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 "double_array2.hpp"
-
-#include "../db/vector.hpp"
-#include "../exception.hpp"
-#include "../lock.hpp"
-#include "../logger.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace {
-
-// FIXME: To be removed in future.
-using namespace grnxx::db;
-
-constexpr  int64_t MAX_ID         = 0xFFFFFFFFLL;
-constexpr  int64_t INVALID_ID     = -1;
-constexpr uint64_t INVALID_OFFSET = 0;
-
-constexpr uint64_t ROOT_NODE_ID   = 0;
-
-constexpr uint16_t TERMINAL_LABEL = 0x100;
-constexpr uint16_t MAX_LABEL      = TERMINAL_LABEL;
-constexpr uint16_t INVALID_LABEL  = 0x1FF;
-
-constexpr uint64_t CHUNK_SIZE     = 0x200;
-constexpr uint64_t CHUNK_MASK     = 0x1FF;
-
-// Chunks are grouped by the level which indicates how easily update operations
-// can find a good offset in that chunk. The chunk level rises when
-// find_offset() fails in that chunk many times. MAX_FAILURE_COUNT
-// is the threshold. Also, in order to limit the time cost, find_offset() scans
-// at most MAX_CHUNK_COUNT chunks.
-// Larger parameters bring more chances of finding good offsets but it leads to
-// more node renumberings, which are costly operations, and thus results in
-// degradation of space/time efficiencies.
-constexpr uint64_t MAX_FAILURE_COUNT = 4;
-constexpr uint64_t MAX_CHUNK_COUNT   = 16;
-constexpr uint64_t MAX_CHUNK_LEVEL   = 5;
-
-// Chunks in the same level compose a doubly linked list. The entry chunk of
-// a linked list is called a leader. INVALID_LEADER means that
-// the linked list is empty and there exists no leader.
-constexpr uint64_t INVALID_LEADER    = 0x7FFFFFFFU;
-
-struct Header {
-  uint32_t nodes_block_id;
-  uint32_t chunks_block_id;
-  uint32_t entries_block_id;
-  uint32_t keys_block_id;
-  uint32_t root_node_id;
-  uint64_t total_key_length;
-  int64_t next_key_id;
-  uint64_t next_key_pos;
-  int64_t max_key_id;
-  uint64_t num_keys;
-  uint64_t num_chunks;
-  uint64_t num_phantoms;
-  uint64_t num_zombies;
-  uint64_t leaders[MAX_CHUNK_LEVEL + 1];
-  Mutex inter_process_mutex;
-
-  Header();
-};
-
-Header::Header()
-  : nodes_block_id(io::BLOCK_INVALID_ID),
-    chunks_block_id(io::BLOCK_INVALID_ID),
-    entries_block_id(io::BLOCK_INVALID_ID),
-    keys_block_id(io::BLOCK_INVALID_ID),
-    root_node_id(0),
-    total_key_length(0),
-    next_key_id(0),
-    next_key_pos(0),
-    max_key_id(-1),
-    num_keys(0),
-    num_chunks(0),
-    num_phantoms(0),
-    num_zombies(0),
-    leaders(),
-    inter_process_mutex() {
-  for (uint32_t i = 0; i <= MAX_CHUNK_LEVEL; ++i) {
-    leaders[i] = INVALID_LEADER;
-  }
-}
-
-class Node {
- public:
-  Node() : qword_(IS_PHANTOM_FLAG) {}
-
-  // The ID of this node is used as an offset (true) or not (false).
-  bool is_origin() const {
-    // 1 bit.
-    return qword_ & IS_ORIGIN_FLAG;
-  }
-  // This node is valid (false) or not (true).
-  bool is_phantom() const {
-    // 1 bit.
-    return qword_ & IS_PHANTOM_FLAG;
-  }
-  // This node is associated with a key (true) or not (false).
-  bool is_leaf() const {
-    // 1 bit.
-    return qword_ & IS_LEAF_FLAG;
-  }
-
-  void set_is_origin(bool value) {
-    if (value) {
-      qword_ |= IS_ORIGIN_FLAG;
-    } else {
-      qword_ &= ~IS_ORIGIN_FLAG;
-    }
-  }
-  void set_is_phantom(bool value) {
-    if (value) {
-      qword_ = (qword_ & IS_ORIGIN_FLAG) | IS_PHANTOM_FLAG;
-    } else {
-      qword_ = (qword_ & IS_ORIGIN_FLAG) | (INVALID_OFFSET << OFFSET_SHIFT) |
-               (uint64_t(INVALID_LABEL) << CHILD_SHIFT) |
-               (uint64_t(INVALID_LABEL) << SIBLING_SHIFT) | INVALID_LABEL;
-    }
-  }
-
-  // Phantom nodes are doubly linked in each chunk.
-  // Each chunk consists of 512 nodes.
-  uint16_t next() const {
-    // 9 bits.
-    return static_cast<uint16_t>((qword_ >> NEXT_SHIFT) & NEXT_MASK);
-  }
-  uint16_t prev() const {
-    // 9 bits.
-    return static_cast<uint16_t>((qword_ >> PREV_SHIFT) & PREV_MASK);
-  }
-
-  void set_next(uint16_t value) {
-    qword_ = (qword_ & ~(NEXT_MASK << NEXT_SHIFT)) |
-             (static_cast<uint64_t>(value) << NEXT_SHIFT);
-  }
-  void set_prev(uint16_t value) {
-    qword_ = (qword_ & ~(PREV_MASK << PREV_SHIFT)) |
-             (static_cast<uint64_t>(value) << PREV_SHIFT);
-  }
-
-  // A non-phantom node stores its label.
-  // A phantom node returns an invalid label with IS_PHANTOM_FLAG.
-  uint64_t label() const {
-    // 9 bits.
-    return qword_ & (IS_PHANTOM_FLAG | LABEL_MASK);
-  }
-  uint16_t sibling() const {
-    // 9 bits.
-    return static_cast<uint16_t>((qword_ >> SIBLING_SHIFT) & SIBLING_MASK);
-  }
-
-  void set_label(uint16_t value) {
-    qword_ = (qword_ & ~LABEL_MASK) | value;
-  }
-  void set_sibling(uint16_t value) {
-    qword_ = (qword_ & ~(SIBLING_MASK << SIBLING_SHIFT)) |
-             (static_cast<uint64_t>(value) << SIBLING_SHIFT);
-  }
-
-  // A leaf node stores the start position and the length of the associated
-  // key.
-  uint64_t key_pos() const {
-    // 43 bits.
-    return (qword_ >> KEY_POS_SHIFT) & KEY_POS_MASK;
-  }
-
-  void set_key_pos(uint64_t key_pos) {
-    qword_ = (qword_ & ~(KEY_POS_MASK << KEY_POS_SHIFT)) |
-             (key_pos << KEY_POS_SHIFT) | IS_LEAF_FLAG;
-  }
-
-  // A non-phantom and non-leaf node stores the offset to its children,
-  // the label of its next sibling, and the label of its first child.
-  uint64_t offset() const {
-    // 33 bits.
-    return (qword_ >> OFFSET_SHIFT) & OFFSET_MASK;
-  }
-  uint16_t child() const {
-    // 9 bits.
-    return static_cast<uint16_t>((qword_ >> CHILD_SHIFT) & CHILD_MASK);
-  }
-
-  void set_offset(uint64_t value) {
-    if (qword_ & IS_LEAF_FLAG) {
-      qword_ = ((qword_ & ~IS_LEAF_FLAG) & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (value << OFFSET_SHIFT) |
-               (uint64_t(INVALID_LABEL) << CHILD_SHIFT);
-    } else {
-      qword_ = (qword_ & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (value << OFFSET_SHIFT);
-    }
-  }
-  void set_child(uint16_t value) {
-    qword_ = (qword_ & ~(CHILD_MASK << CHILD_SHIFT)) |
-             (static_cast<uint64_t>(value) << CHILD_SHIFT);
-  }
-
- private:
-  uint64_t qword_;
-
-  // 61 - 63 (common).
-  static constexpr uint64_t IS_ORIGIN_FLAG   = uint64_t(1) << 63;
-  static constexpr uint64_t IS_PHANTOM_FLAG  = uint64_t(1) << 62;
-  static constexpr uint64_t IS_LEAF_FLAG     = uint64_t(1) << 61;
-
-  // 0 - 17 (phantom).
-  static constexpr uint64_t NEXT_MASK  = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  NEXT_SHIFT = 0;
-  static constexpr uint64_t PREV_MASK  = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  PREV_SHIFT = 9;
-
-  // 0 - 17 (non-phantom).
-  static constexpr uint64_t LABEL_MASK    = (uint64_t(1) << 9) - 1;
-  static constexpr uint64_t SIBLING_MASK  = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  SIBLING_SHIFT = 9;
-
-  // 18 - 60 (leaf)
-  static constexpr uint64_t KEY_POS_MASK     = (uint64_t(1) << 43) - 1;
-  static constexpr uint8_t  KEY_POS_SHIFT    = 18;
-
-  // 18 - 60 (non-leaf)
-  static constexpr uint64_t OFFSET_MASK  = (uint64_t(1) << 34) - 1;
-  static constexpr uint8_t  OFFSET_SHIFT = 18;
-  static constexpr uint64_t CHILD_MASK   = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  CHILD_SHIFT  = 52;
-};
-
-class Chunk {
- public:
-  Chunk() : qwords_{ 0, 0 } {}
-
-  // Chunks in the same level are doubly linked.
-  uint64_t next() const {
-    // 44 bits.
-    return (qwords_[0] & UPPER_MASK) >> UPPER_SHIFT;
-  }
-  uint64_t prev() const {
-    // 44 bits.
-    return (qwords_[1] & UPPER_MASK) >> UPPER_SHIFT;
-  }
-
-  void set_next(uint64_t value) {
-    qwords_[0] = (qwords_[0] & ~UPPER_MASK) | (value << UPPER_SHIFT);
-  }
-  void set_prev(uint64_t value) {
-    qwords_[1] = (qwords_[1] & ~UPPER_MASK) | (value << UPPER_SHIFT);
-  }
-
-  // The chunk level indicates how easily nodes can be put in this chunk.
-  uint64_t level() const {
-    // 10 bits.
-    return (qwords_[0] & MIDDLE_MASK) >> MIDDLE_SHIFT;
-  }
-  uint64_t failure_count() const {
-    // 10 bits.
-    return (qwords_[1] & MIDDLE_MASK) >> MIDDLE_SHIFT;
-  }
-
-  void set_level(uint64_t value) {
-    qwords_[0] = (qwords_[0] & ~MIDDLE_MASK) | (value << MIDDLE_SHIFT);
-  }
-  void set_failure_count(uint64_t value) {
-    qwords_[1] = (qwords_[1] & ~MIDDLE_MASK) | (value << MIDDLE_SHIFT);
-  }
-
-  // The first phantom node and the number of phantom nodes in this chunk.
-  uint64_t first_phantom() const {
-    // 10 bits.
-    return (qwords_[0] & LOWER_MASK) >> LOWER_SHIFT;
-  }
-  uint64_t num_phantoms() const {
-    // 10 bits.
-    return (qwords_[1] & LOWER_MASK) >> LOWER_SHIFT;
-  }
-
-  void set_first_phantom(uint64_t value) {
-    qwords_[0] = (qwords_[0] & ~LOWER_MASK) | (value << LOWER_SHIFT);
-  }
-  void set_num_phantoms(uint64_t value) {
-    qwords_[1] = (qwords_[1] & ~LOWER_MASK) | (value << LOWER_SHIFT);
-  }
-
- private:
-  uint64_t qwords_[2];
-
-  static constexpr uint8_t  UPPER_SHIFT  = 20;
-  static constexpr uint64_t UPPER_MASK   =
-      ((uint64_t(1) << 44) - 1) << UPPER_SHIFT;
-  static constexpr uint8_t  MIDDLE_SHIFT = 10;
-  static constexpr uint64_t MIDDLE_MASK  =
-      ((uint64_t(1) << 10) - 1) << MIDDLE_SHIFT;
-  static constexpr uint8_t  LOWER_SHIFT  = 0;
-  static constexpr uint64_t LOWER_MASK   =
-      ((uint64_t(1) << 10) - 1) << LOWER_SHIFT;
-};
-
-class Entry {
- public:
-  Entry() : dword_(0) {}
-
-  // This entry is associated with a key (true) or not (false).
-  explicit operator bool() const {
-    return dword_ & IS_VALID_FLAG;
-  }
-
-  // A valid entry stores the offset and the length of its associated key.
-  uint64_t key_pos() const {
-    // 31-bit.
-    return dword_ & ~IS_VALID_FLAG;
-  }
-
-  void set_key_pos(uint64_t value) {
-    dword_ = IS_VALID_FLAG | value;
-  }
-
-  // An invalid entry stores the index of the next invalid entry.
-  uint64_t next() const {
-    return dword_;
-  }
-
-  void set_next(uint64_t next) {
-    dword_ = next;
-  }
-
- private:
-  uint32_t dword_;
-
-  static constexpr uint32_t IS_VALID_FLAG = uint32_t(1) << 31;
-};
-
-class Key {
- public:
-  Key(uint64_t id, const void *address, uint64_t length)
-    : id_(id), length_(length), buf_{ '\0', '\0' } {
-    std::memcpy(buf_, address, length);
-  }
-
-  explicit operator bool() const {
-    return id() != INVALID_ID;
-  }
-
-  const uint8_t &operator[](uint64_t i) const {
-    return buf_[i];
-  }
-
-  int64_t id() const {
-    return id_;
-  }
-  uint16_t length() const {
-    return length_;
-  }
-  const void *ptr() const {
-    return buf_;
-  }
-
-  bool equals_to(const void *ptr, uint64_t length, uint64_t offset = 0) const {
-    if (length != length_) {
-      return false;
-    }
-    for ( ; offset < length; ++offset) {
-      if (buf_[offset] != static_cast<const uint8_t *>(ptr)[offset]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  static const Key &invalid_key() {
-    static const Key invalid_key(INVALID_ID, nullptr, 0);
-    return invalid_key;
-  }
-
-  static uint64_t estimate_size(uint64_t length) {
-    return (9 + length) / sizeof(uint32_t);
-  }
-
- private:
-  int32_t id_;
-  uint16_t length_;
-  uint8_t buf_[2];
-};
-
-class Impl : public DoubleArray2 {
- public:
-  ~Impl();
-
-  static Impl *create(io::Pool pool);
-  static Impl *open(io::Pool pool, uint32_t block_id);
-
-  uint32_t block_id() const {
-    return block_info_->id();
-  }
-
-  bool search_by_id(int64_t key_id, const void **ptr, uint64_t *length);
-  bool search_by_key(const void *ptr, uint64_t length, int64_t *key_id);
-
-  bool insert(const void *ptr, uint64_t length, int64_t *key_id);
-
-  bool remove_by_id(int64_t key_id);
-  bool remove_by_key(const void *ptr, uint64_t length);
-
-  bool update_by_id(int64_t key_id, const void *ptr, uint64_t length);
-  bool update_by_key(const void *src_ptr, uint64_t src_length,
-                     const void *dest_ptr, uint64_t dest_length,
-                     int64_t *key_id);
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  Header *header_;
-  Recycler *recycler_;
-  Node *nodes_;
-  Chunk *chunks_;
-  Entry *entries_;
-  uint32_t *keys_;
-  bool initialized_;
-
-  Impl();
-
-  void create_double_array(io::Pool pool);
-  void open_double_array(io::Pool pool, uint32_t block_id);
-
-  const Key &get_key(uint64_t key_pos) {
-    return *reinterpret_cast<const Key *>(&keys_[key_pos]);
-  }
-
-  bool remove_key(const uint8_t *ptr, uint64_t length);
-  bool update_key(const uint8_t *src_ptr, uint64_t src_length,
-                  int64_t src_key_id, const uint8_t *dest_ptr,
-                  uint64_t dest_length);
-
-  bool search_leaf(const uint8_t *ptr, uint64_t length,
-                   uint64_t &node_id, uint64_t &query_pos);
-
-  bool insert_leaf(const uint8_t *ptr, uint64_t length,
-                   uint64_t &node_id, uint64_t query_pos);
-
-  uint64_t insert_node(uint64_t node_id, uint16_t label);
-  uint64_t append_key(const uint8_t *ptr, uint64_t length, uint64_t key_id);
-
-  uint64_t separate(const uint8_t *ptr, uint64_t length,
-                    uint64_t node_id, uint64_t i);
-  void resolve(uint64_t node_id, uint16_t label);
-  void migrate_nodes(uint64_t node_id, uint64_t dest_offset,
-                     const uint16_t *labels, uint16_t num_labels);
-
-  uint64_t find_offset(const uint16_t *labels, uint16_t num_labels);
-
-  void reserve_node(uint64_t node_id);
-  void reserve_chunk(uint64_t chunk_id);
-
-  void update_chunk_level(uint64_t chunk_id, uint32_t level);
-  void set_chunk_level(uint64_t chunk_id, uint32_t level);
-  void unset_chunk_level(uint64_t chunk_id);
-};
-
-Impl::~Impl() {
-  if (!initialized_) try {
-    // Allocated blocks are unlinked if initialization failed.
-    if (header_->nodes_block_id != io::BLOCK_INVALID_ID) {
-      pool_.free_block(header_->nodes_block_id);
-    }
-    if (header_->chunks_block_id != io::BLOCK_INVALID_ID) {
-      pool_.free_block(header_->chunks_block_id);
-    }
-    if (header_->entries_block_id != io::BLOCK_INVALID_ID) {
-      pool_.free_block(header_->entries_block_id);
-    }
-    if (header_->keys_block_id != io::BLOCK_INVALID_ID) {
-      pool_.free_block(header_->keys_block_id);
-    }
-    if (block_info_) {
-      pool_.free_block(*block_info_);
-    }
-  } catch (...) {
-  }
-}
-
-Impl *Impl::create(io::Pool pool) {
-  std::unique_ptr<Impl> impl(new (std::nothrow) Impl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::alpha::Impl failed";
-    GRNXX_THROW();
-  }
-  impl->create_double_array(pool);
-  return impl.release();
-}
-
-Impl *Impl::open(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<Impl> impl(new (std::nothrow) Impl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::alpha::Impl failed";
-    GRNXX_THROW();
-  }
-  impl->open_double_array(pool, block_id);
-  return impl.release();
-}
-
-bool Impl::search_by_id(int64_t key_id, const void **ptr, uint64_t *length) {
-  if (!entries_[key_id]) {
-    return false;
-  }
-  if (ptr || length) {
-    const Key &key = get_key(entries_[key_id].key_pos());
-    if (ptr) {
-      *ptr = key.ptr();
-    }
-    if (length) {
-      *length = key.length();
-    }
-  }
-  return true;
-}
-
-bool Impl::search_by_key(const void *ptr, uint64_t length, int64_t *key_id) {
-  uint64_t node_id = ROOT_NODE_ID;
-  uint64_t query_pos = 0;
-  if (!search_leaf(static_cast<const uint8_t *>(ptr), length,
-                   node_id, query_pos)) {
-    return false;
-  }
-
-  // Note that nodes_[node_id] might be updated by other threads/processes.
-  const Node node = nodes_[node_id];
-  if (!node.is_leaf()) {
-    return false;
-  }
-
-  const Key &key = get_key(node.key_pos());
-  if (key.equals_to(ptr, length, query_pos)) {
-    if (key_id) {
-      *key_id = key.id();
-    }
-    return true;
-  }
-  return false;
-}
-
-bool Impl::insert(const void *ptr, uint64_t length, int64_t *key_id) {
-  // TODO: Exclusive access control is required.
-
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, INSERTING_FLAG);
-
-//  GRN_DAT_DEBUG_THROW_IF(!ptr && (length != 0));
-
-  uint64_t node_id = ROOT_NODE_ID;
-  uint64_t query_pos = 0;
-
-  search_leaf(static_cast<const uint8_t *>(ptr), length, node_id, query_pos);
-  if (!insert_leaf(static_cast<const uint8_t *>(ptr), length,
-                   node_id, query_pos)) {
-    if (key_id) {
-      *key_id = get_key(nodes_[node_id].key_pos()).id();
-    }
-    return false;
-  }
-
-  const int64_t new_key_id = header_->next_key_id;
-  const uint64_t new_key_pos =
-      append_key(static_cast<const uint8_t *>(ptr), length, new_key_id);
-
-  header_->total_key_length += length;
-  ++header_->num_keys;
-
-  // TODO: The first key ID should be fixed to 0 or 1.
-  //       Currently, 0 is used.
-  if (new_key_id > header_->max_key_id) {
-    header_->max_key_id = new_key_id;
-    header_->next_key_id = new_key_id + 1;
-  } else {
-    header_->next_key_id = entries_[new_key_id].next();
-  }
-
-  entries_[new_key_id].set_key_pos(new_key_pos);
-  nodes_[node_id].set_key_pos(new_key_pos);
-  if (key_id) {
-    *key_id = new_key_id;
-  }
-  return true;
-}
-
-bool Impl::remove_by_id(int64_t key_id) {
-  // TODO: Exclusive access control is required.
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const Entry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const Key &key = get_key(entry.key_pos());
-  return remove_key(static_cast<const uint8_t *>(key.ptr()), key.length());
-}
-
-bool Impl::remove_by_key(const void *ptr, uint64_t length) {
-  // TODO: Exclusive access control is required.
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, REMOVING_FLAG);
-
-//  GRN_DAT_DEBUG_THROW_IF((ptr == nullptr) && (length != 0));
-  return remove_key(static_cast<const uint8_t *>(ptr), length);
-}
-
-bool Impl::update_by_id(int64_t key_id, const void *ptr, uint64_t length) {
-  // TODO: Exclusive access control is required.
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const Entry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const Key &key = get_key(entry.key_pos());
-  return update_key(static_cast<const uint8_t *>(key.ptr()), key.length(),
-                    key_id, static_cast<const uint8_t *>(ptr), length);
-}
-
-bool Impl::update_by_key(const void *src_ptr, uint64_t src_length,
-                         const void *dest_ptr, uint64_t dest_length,
-                         int64_t *key_id) {
-  // TODO: Exclusive access control is required.
-  int64_t src_key_id;
-  if (!search_by_key(static_cast<const uint8_t *>(src_ptr), src_length,
-                     &src_key_id)) {
-    return false;
-  }
-  if (update_key(static_cast<const uint8_t *>(src_ptr), src_length,
-                 src_key_id, static_cast<const uint8_t *>(dest_ptr),
-                 dest_length)) {
-    if (key_id) {
-      *key_id = src_key_id;
-    }
-    return true;
-  }
-  return false;
-}
-
-bool Impl::update_key(const uint8_t *src_ptr, uint64_t src_length,
-                      int64_t src_key_id, const uint8_t *dest_ptr,
-                      uint64_t dest_length) {
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, UPDATING_FLAG);
-
-//  GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0));
-
-  uint64_t node_id = ROOT_NODE_ID;
-  uint64_t query_pos = 0;
-
-  search_leaf(dest_ptr, dest_length, node_id, query_pos);
-  if (!insert_leaf(dest_ptr, dest_length, node_id, query_pos)) {
-    return false;
-  }
-
-  const uint64_t new_key_pos = append_key(dest_ptr, dest_length, src_key_id);
-  header_->total_key_length =
-      header_->total_key_length + dest_length - src_length;
-  entries_[src_key_id].set_key_pos(new_key_pos);
-  nodes_[node_id].set_key_pos(new_key_pos);
-
-  node_id = ROOT_NODE_ID;
-  query_pos = 0;
-  if (!search_leaf(src_ptr, src_length, node_id, query_pos)) {
-    // TODO: Unexpected error!
-  }
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  return true;
-}
-
-Impl::Impl()
-  : pool_(),
-    block_info_(nullptr),
-    header_(nullptr),
-    recycler_(nullptr),
-    nodes_(nullptr),
-    chunks_(nullptr),
-    entries_(nullptr),
-    keys_(nullptr),
-    initialized_(false) {}
-
-void Impl::create_double_array(io::Pool pool) {
-  pool_ = pool;
-
-  block_info_ = pool_.create_block(sizeof(Header));
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<Header *>(block_address);
-  *header_ = Header();
-
-  recycler_ = pool_.mutable_recycler();
-
-  // TODO: Tell me the size of buffers!
-  const io::BlockInfo *block_info;
-
-  block_info = pool_.create_block(sizeof(Node) * (1 << 27));
-  header_->nodes_block_id = block_info->id();
-  nodes_ = static_cast<Node *>(pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(sizeof(Chunk) * (1 << 18));
-  header_->chunks_block_id = block_info->id();
-  chunks_ = static_cast<Chunk *>(pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(sizeof(Entry) * (1 << 25));
-  header_->entries_block_id = block_info->id();
-  entries_ = static_cast<Entry *>(pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(sizeof(uint32_t) * (1 << 27));
-  header_->keys_block_id = block_info->id();
-  keys_ = static_cast<uint32_t *>(pool_.get_block_address(*block_info));
-
-  reserve_node(ROOT_NODE_ID);
-  nodes_[INVALID_OFFSET].set_is_origin(true);
-
-  initialized_ = true;
-}
-
-void Impl::open_double_array(io::Pool pool, uint32_t block_id) {
-  pool_ = pool;
-  initialized_ = true;
-
-  block_info_ = pool_.get_block_info(block_id);
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<Header *>(block_address);
-
-  // TODO: Check the format.
-
-  recycler_ = pool_.mutable_recycler();
-
-  nodes_ = static_cast<Node *>(
-      pool_.get_block_address(header_->nodes_block_id));
-  chunks_ = static_cast<Chunk *>(
-      pool_.get_block_address(header_->chunks_block_id));
-  entries_ = static_cast<Entry *>(
-      pool_.get_block_address(header_->entries_block_id));
-  keys_ = static_cast<uint32_t *>(
-      pool_.get_block_address(header_->keys_block_id));
-}
-
-bool Impl::remove_key(const uint8_t *ptr, uint64_t length) {
-  uint64_t node_id = ROOT_NODE_ID;
-  uint64_t query_pos = 0;
-  if (!search_leaf(ptr, length, node_id, query_pos)) {
-    return false;
-  }
-
-  const uint64_t key_pos = nodes_[node_id].key_pos();
-  const Key &key = get_key(key_pos);
-  if (!key.equals_to(ptr, length, query_pos)) {
-    return false;
-  }
-
-  const uint64_t key_id = key.id();
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  entries_[key_id].set_next(header_->next_key_id);
-
-  header_->next_key_id = key_id;
-  header_->total_key_length -= length;
-  --header_->num_keys;
-  return true;
-}
-
-bool Impl::search_leaf(const uint8_t *ptr, uint64_t length,
-                       uint64_t &node_id, uint64_t &query_pos) {
-  for ( ; query_pos < length; ++query_pos) {
-    const Node node = nodes_[node_id];
-    if (node.is_leaf()) {
-      return true;
-    }
-
-    const uint64_t next = node.offset() ^ ptr[query_pos];
-    if (nodes_[next].label() != ptr[query_pos]) {
-      return false;
-    }
-    node_id = next;
-  }
-
-  const Node node = nodes_[node_id];
-  if (node.is_leaf()) {
-    return true;
-  }
-
-  if (node.child() != TERMINAL_LABEL) {
-    return false;
-  }
-  node_id = node.offset() ^ TERMINAL_LABEL;
-  return nodes_[node_id].is_leaf();
-}
-
-bool Impl::insert_leaf(const uint8_t *ptr, uint64_t length,
-                       uint64_t &node_id, uint64_t query_pos) {
-  const Node node = nodes_[node_id];
-  if (node.is_leaf()) {
-    const Key &key = get_key(node.key_pos());
-    uint64_t i = query_pos;
-    while ((i < length) && (i < key.length())) {
-      if (ptr[i] != key[i]) {
-        break;
-      }
-      ++i;
-    }
-    if ((i == length) && (i == key.length())) {
-      return false;
-    }
-    // TODO
-//    GRN_DAT_THROW_IF(SIZE_ERROR, num_keys() >= max_num_keys());
-//    GRN_DAT_DEBUG_THROW_IF(next_key_id() > max_num_keys());
-
-    for (uint64_t j = query_pos; j < i; ++j) {
-      node_id = insert_node(node_id, ptr[j]);
-    }
-    node_id = separate(ptr, length, node_id, i);
-    return true;
-  } else if (node.label() == TERMINAL_LABEL) {
-    return true;
-  } else {
-    // TODO
-//    GRN_DAT_THROW_IF(SIZE_ERROR, num_keys() >= max_num_keys());
-    const uint16_t label = (query_pos < length) ?
-        static_cast<uint16_t>(ptr[query_pos]) : TERMINAL_LABEL;
-    if ((node.offset() == INVALID_OFFSET) ||
-        !nodes_[node.offset() ^ label].is_phantom()) {
-      // The offset of this node must be updated.
-      resolve(node_id, label);
-    }
-    // The new node will be the leaf node associated with the query.
-    node_id = insert_node(node_id, label);
-    return true;
-  }
-}
-
-uint64_t Impl::insert_node(uint64_t node_id, uint16_t label) {
-//  GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes());
-//  GRN_DAT_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  const Node node = nodes_[node_id];
-  uint64_t offset;
-  if (node.is_leaf() || (node.offset() == INVALID_OFFSET)) {
-    offset = find_offset(&label, 1);
-  } else {
-    offset = node.offset();
-  }
-
-  const uint64_t next = offset ^ label;
-  reserve_node(next);
-
-  nodes_[next].set_label(label);
-  if (node.is_leaf()) {
-//    GRN_DAT_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-    nodes_[next].set_key_pos(node.key_pos());
-    // TODO: Must be update at once.
-  } else if (node.offset() == INVALID_OFFSET) {
-//    GRN_DAT_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-//  } else {
-//    GRN_DAT_DEBUG_THROW_IF(!nodes_[offset].is_origin());
-  }
-  nodes_[node_id].set_offset(offset);
-
-  const uint16_t child_label = nodes_[node_id].child();
-//  GRN_DAT_DEBUG_THROW_IF(child_label == label);
-  if (child_label == INVALID_LABEL) {
-    nodes_[node_id].set_child(label);
-  } else if ((label == TERMINAL_LABEL) ||
-             ((child_label != TERMINAL_LABEL) &&
-              (label < child_label))) {
-    // The next node becomes the first child.
-//    GRN_DAT_DEBUG_THROW_IF(nodes_[offset ^ child_label).is_phantom());
-//    GRN_DAT_DEBUG_THROW_IF(nodes_[offset ^ child_label).label() != child_label);
-    nodes_[next].set_sibling(child_label);
-    nodes_[node_id].set_child(label);
-  } else {
-    uint64_t prev = offset ^ child_label;
-//    GRN_DAT_DEBUG_THROW_IF(nodes_[prev).label() != child_label);
-    uint16_t sibling_label = nodes_[prev].sibling();
-    while (label > sibling_label) {
-      prev = offset ^ sibling_label;
-//      GRN_DAT_DEBUG_THROW_IF(nodes_[prev].label() != sibling_label);
-      sibling_label = nodes_[prev].sibling();
-    }
-//    GRN_DAT_DEBUG_THROW_IF(label == sibling_label);
-    nodes_[next].set_sibling(nodes_[prev].sibling());
-    nodes_[prev].set_sibling(label);
-  }
-  return next;
-}
-
-uint64_t Impl::append_key(const uint8_t *ptr, uint64_t length,
-                                     uint64_t key_id) {
-  // TODO
-//  GRN_DAT_THROW_IF(SIZE_ERROR, key_id > max_num_keys());
-
-  uint64_t key_pos = header_->next_key_pos;
-  const uint64_t key_size = Key::estimate_size(length);
-
-  // TODO
-//  GRN_DAT_THROW_IF(SIZE_ERROR, key_size > (key_buf_size() - key_pos));
-  new (&keys_[key_pos]) Key(key_id, ptr, length);
-
-  header_->next_key_pos = key_pos + key_size;
-  return key_pos;
-}
-
-uint64_t Impl::separate(const uint8_t *ptr, uint64_t length,
-                        uint64_t node_id, uint64_t i) {
-//  GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes());
-//  GRN_DAT_DEBUG_THROW_IF(!nodes_[node_id].is_leaf());
-//  GRN_DAT_DEBUG_THROW_IF(i > length);
-
-  const Node node = nodes_[node_id];
-  const Key &key = get_key(node.key_pos());
-
-  uint16_t labels[2];
-  labels[0] = (i < key.length()) ?
-      static_cast<uint16_t>(key[i]) : TERMINAL_LABEL;
-  labels[1] = (i < length) ?
-      static_cast<uint16_t>(ptr[i]) : TERMINAL_LABEL;
-//  GRN_DAT_DEBUG_THROW_IF(labels[0] == labels[1]);
-
-  const uint64_t offset = find_offset(labels, 2);
-
-  uint64_t next = offset ^ labels[0];
-  reserve_node(next);
-//  GRN_DAT_DEBUG_THROW_IF(nodes_[offset).is_origin());
-
-  nodes_[next].set_label(labels[0]);
-  nodes_[next].set_key_pos(node.key_pos());
-
-  next = offset ^ labels[1];
-  reserve_node(next);
-
-  nodes_[next].set_label(labels[1]);
-
-  nodes_[offset].set_is_origin(true);
-  nodes_[node_id].set_offset(offset);
-
-  if ((labels[0] == TERMINAL_LABEL) ||
-      ((labels[1] != TERMINAL_LABEL) &&
-       (labels[0] < labels[1]))) {
-    nodes_[offset ^ labels[0]].set_sibling(labels[1]);
-    nodes_[node_id].set_child(labels[0]);
-  } else {
-    nodes_[offset ^ labels[1]].set_sibling(labels[0]);
-    nodes_[node_id].set_child(labels[1]);
-  }
-  return next;
-}
-
-void Impl::resolve(uint64_t node_id, uint16_t label) {
-//  GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes());
-//  GRN_DAT_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRN_DAT_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  uint64_t offset = nodes_[node_id].offset();
-  if (offset != INVALID_OFFSET) {
-    uint16_t labels[MAX_LABEL + 1];
-    uint16_t num_labels = 0;
-
-    uint16_t next_label = nodes_[node_id].child();
-    // FIXME: How to check if the node has children or not.
-//    GRN_DAT_DEBUG_THROW_IF(next_label == INVALID_LABEL);
-    while (next_label != INVALID_LABEL) {
-//      GRN_DAT_DEBUG_THROW_IF(next_label > MAX_LABEL);
-      labels[num_labels++] = next_label;
-      next_label = nodes_[offset ^ next_label].sibling();
-    }
-//    GRN_DAT_DEBUG_THROW_IF(num_labels == 0);
-
-    labels[num_labels] = label;
-    offset = find_offset(labels, num_labels + 1);
-    migrate_nodes(node_id, offset, labels, num_labels);
-  } else {
-    offset = find_offset(&label, 1);
-    if (offset >= (header_->num_chunks * CHUNK_SIZE)) {
-//      GRN_DAT_DEBUG_THROW_IF((offset / BLOCK_SIZE) != num_blocks());
-      reserve_chunk(header_->num_chunks);
-    }
-    nodes_[offset].set_is_origin(true);
-    nodes_[node_id].set_offset(offset);
-  }
-}
-
-void Impl::migrate_nodes(uint64_t node_id, uint64_t dest_offset,
-                         const uint16_t *labels, uint16_t num_labels) {
-//  GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes());
-//  GRN_DAT_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRN_DAT_DEBUG_THROW_IF(labels == nullptr);
-//  GRN_DAT_DEBUG_THROW_IF(num_labels == 0);
-//  GRN_DAT_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1));
-
-  const uint64_t src_offset = nodes_[node_id].offset();
-//  GRN_DAT_DEBUG_THROW_IF(src_offset == INVALID_OFFSET);
-//  GRN_DAT_DEBUG_THROW_IF(!nodes_[src_offset].is_origin());
-
-  for (uint16_t i = 0; i < num_labels; ++i) {
-    const uint64_t src_node_id = src_offset ^ labels[i];
-    const uint64_t dest_node_id = dest_offset ^ labels[i];
-//    GRN_DAT_DEBUG_THROW_IF(ith_node(src_node_id).is_phantom());
-//    GRN_DAT_DEBUG_THROW_IF(ith_node(src_node_id).label() != labels[i]);
-
-    reserve_node(dest_node_id);
-    Node dest_node = nodes_[src_node_id];
-    dest_node.set_is_origin(nodes_[dest_node_id].is_origin());
-    nodes_[dest_node_id] = dest_node;
-  }
-  header_->num_zombies += num_labels;
-
-//  GRN_DAT_DEBUG_THROW_IF(nodes_[dest_offset].is_origin());
-  nodes_[dest_offset].set_is_origin(true);
-  nodes_[node_id].set_offset(dest_offset);
-}
-
-uint64_t Impl::find_offset(const uint16_t *labels, uint16_t num_labels) {
-//  GRN_DAT_DEBUG_THROW_IF(labels == nullptr);
-//  GRN_DAT_DEBUG_THROW_IF(num_labels == 0);
-//  GRN_DAT_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1));
-
-  // Chunks are tested in descending order of level. Basically, lower level
-  // chunks contain more phantom nodes.
-  uint32_t level = 1;
-  while (num_labels >= (1U << level)) {
-    ++level;
-  }
-  level = (level < MAX_CHUNK_LEVEL) ? (MAX_CHUNK_LEVEL - level) : 0;
-
-  uint64_t chunk_count = 0;
-  do {
-    uint64_t leader = header_->leaders[level];
-    if (leader == INVALID_LEADER) {
-      // This level group is skipped because it is empty.
-      continue;
-    }
-
-    uint64_t chunk_id = leader;
-    do {
-      const Chunk &chunk = chunks_[chunk_id];
-//      GRN_DAT_DEBUG_THROW_IF(chunk.level() != level);
-
-      const uint64_t first = (chunk_id * CHUNK_SIZE) | chunk.first_phantom();
-      uint64_t node_id = first;
-      do {
-//        GRN_DAT_DEBUG_THROW_IF(!nodes_[node_id=]).is_phantom());
-        const uint64_t offset = node_id ^ labels[0];
-        if (!nodes_[offset].is_origin()) {
-          uint16_t i = 1;
-          for ( ; i < num_labels; ++i) {
-            if (!nodes_[offset ^ labels[i]].is_phantom()) {
-              break;
-            }
-          }
-          if (i >= num_labels) {
-            return offset;
-          }
-        }
-        node_id = (chunk_id * CHUNK_SIZE) | nodes_[node_id].next();
-      } while (node_id != first);
-
-      const uint64_t prev = chunk_id;
-      const uint64_t next = chunk.next();
-      chunk_id = next;
-      chunks_[prev].set_failure_count(chunks_[prev].failure_count() + 1);
-
-      // The level of a chunk is updated when this function fails many times,
-      // actually MAX_FAILURE_COUNT times, in that chunk.
-      if (chunks_[prev].failure_count() == MAX_FAILURE_COUNT) {
-        update_chunk_level(prev, level + 1);
-        if (next == leader) {
-          break;
-        } else {
-          // Note that the leader might be updated in the level update.
-          leader = header_->leaders[level];
-          continue;
-        }
-      }
-    } while ((++chunk_count < MAX_CHUNK_COUNT) &&
-             (chunk_id != leader));
-  } while ((chunk_count < MAX_CHUNK_COUNT) && (level-- != 0));
-
-  return (header_->num_chunks * CHUNK_SIZE) ^ labels[0];
-}
-
-void Impl::reserve_node(uint64_t node_id) {
-  if (node_id >= (header_->num_chunks * CHUNK_SIZE)) {
-    reserve_chunk(node_id / CHUNK_SIZE);
-  }
-
-  Node &node = nodes_[node_id];
-//  GRN_DAT_DEBUG_THROW_IF(!node.is_phantom());
-
-  const uint64_t chunk_id = node_id / CHUNK_SIZE;
-  Chunk &chunk = chunks_[chunk_id];
-//  GRN_DAT_DEBUG_THROW_IF(chunk.num_phantoms() == 0);
-
-  const uint64_t next = (chunk_id * CHUNK_SIZE) | node.next();
-  const uint64_t prev = (chunk_id * CHUNK_SIZE) | node.prev();
-//  GRN_DAT_DEBUG_THROW_IF(next >= header_->num_nodes());
-//  GRN_DAT_DEBUG_THROW_IF(prev >= header_->num_nodes());
-
-  if ((node_id & CHUNK_MASK) == chunk.first_phantom()) {
-    // The first phantom node is removed from the chunk and the second phantom
-    // node comes first.
-    chunk.set_first_phantom(next & CHUNK_MASK);
-  }
-
-  nodes_[next].set_prev(prev & CHUNK_MASK);
-  nodes_[prev].set_next(next & CHUNK_MASK);
-
-  if (chunk.level() != MAX_CHUNK_LEVEL) {
-    const uint64_t threshold =
-        uint64_t(1) << ((MAX_CHUNK_LEVEL - chunk.level() - 1) * 2);
-    if (chunk.num_phantoms() == threshold) {
-      update_chunk_level(chunk_id, chunk.level() + 1);
-    }
-  }
-  chunk.set_num_phantoms(chunk.num_phantoms() - 1);
-
-  node.set_is_phantom(false);
-
-//  GRN_DAT_DEBUG_THROW_IF(node.offset() != INVALID_OFFSET);
-//  GRN_DAT_DEBUG_THROW_IF(node.label() != INVALID_LABEL);
-
-  --header_->num_phantoms;
-}
-
-void Impl::reserve_chunk(uint64_t chunk_id) {
-//  GRN_DAT_DEBUG_THROW_IF(chunk_id != num_chunks());
-  // TODO
-//  GRN_DAT_THROW_IF(SIZE_ERROR, chunk_id >= max_num_chunks());
-
-  header_->num_chunks = chunk_id + 1;
-  chunks_[chunk_id].set_failure_count(0);
-  chunks_[chunk_id].set_first_phantom(0);
-  chunks_[chunk_id].set_num_phantoms(CHUNK_SIZE);
-
-  const uint64_t begin = chunk_id * CHUNK_SIZE;
-  const uint64_t end = begin + CHUNK_SIZE;
-//  GRN_DAT_DEBUG_THROW_IF(end != num_nodes());
-
-  Node node;
-  node.set_is_phantom(true);
-
-  for (uint64_t i = begin; i < end; ++i) {
-    node.set_prev((i - 1) & CHUNK_MASK);
-    node.set_next((i + 1) & CHUNK_MASK);
-    nodes_[i] = node;
-  }
-
-  // The level of the new chunk is 0.
-  set_chunk_level(chunk_id, 0);
-  header_->num_phantoms += CHUNK_SIZE;
-}
-
-void Impl::update_chunk_level(uint64_t chunk_id, uint32_t level) {
-//  GRN_DAT_DEBUG_THROW_IF(chunk_id >= num_chunks());
-//  GRN_DAT_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  unset_chunk_level(chunk_id);
-  set_chunk_level(chunk_id, level);
-}
-
-void Impl::set_chunk_level(uint64_t chunk_id, uint32_t level) {
-//  GRN_DAT_DEBUG_THROW_IF(chunk_id >= num_chunks());
-//  GRN_DAT_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  const uint64_t leader = header_->leaders[level];
-  if (leader == INVALID_LEADER) {
-    // The chunk becomes the only one member of the level group.
-    chunks_[chunk_id].set_next(chunk_id);
-    chunks_[chunk_id].set_prev(chunk_id);
-    header_->leaders[level] = chunk_id;
-  } else {
-    // The chunk is appended to the level group, in practice.
-    const uint64_t next = leader;
-    const uint64_t prev = chunks_[leader].prev();
-//    GRN_DAT_DEBUG_THROW_IF(next >= num_chunks());
-//    GRN_DAT_DEBUG_THROW_IF(prev >= num_chunks());
-    chunks_[chunk_id].set_next(next);
-    chunks_[chunk_id].set_prev(prev);
-    chunks_[next].set_prev(chunk_id);
-    chunks_[prev].set_next(chunk_id);
-  }
-  chunks_[chunk_id].set_level(level);
-  chunks_[chunk_id].set_failure_count(0);
-}
-
-void Impl::unset_chunk_level(uint64_t chunk_id) {
-//  GRN_DAT_DEBUG_THROW_IF(chunk_id >= num_chunk());
-
-  const uint32_t level = chunks_[chunk_id].level();
-//  GRN_DAT_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  const uint64_t leader = header_->leaders[level];
-//  GRN_DAT_DEBUG_THROW_IF(leader == INVALID_LEADER);
-
-  const uint64_t next = chunks_[chunk_id].next();
-  const uint64_t prev = chunks_[chunk_id].prev();
-//  GRN_DAT_DEBUG_THROW_IF(next >= num_chunks());
-//  GRN_DAT_DEBUG_THROW_IF(prev >= num_chunks());
-
-  if (next == chunk_id) {
-    // The level group becomes empty.
-    header_->leaders[level] = INVALID_LEADER;
-  } else {
-    chunks_[next].set_prev(prev);
-    chunks_[prev].set_next(next);
-    if (chunk_id == leader) {
-      // The second chunk becomes the leader of the level group.
-      header_->leaders[level] = next;
-    }
-  }
-}
-
-}  // namespace
-
-DoubleArray2::DoubleArray2() {}
-DoubleArray2::~DoubleArray2() {}
-
-DoubleArray2 *DoubleArray2::create(io::Pool pool) {
-  return Impl::create(pool);
-}
-
-DoubleArray2 *DoubleArray2::open(io::Pool pool, uint32_t block_id) {
-  return Impl::open(pool, block_id);
-}
-
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: lib/alpha/double_array2.hpp (+0 -57) 100644
===================================================================
--- lib/alpha/double_array2.hpp    2013-02-20 14:19:56 +0900 (ab3d0c4)
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-  Copyright (C) 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
-*/
-#ifndef GRNXX_ALPHA_DOUBLE_ARRAY2_HPP
-#define GRNXX_ALPHA_DOUBLE_ARRAY2_HPP
-
-#include "../io/pool.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-class DoubleArray2 {
- public:
-  DoubleArray2();
-  virtual ~DoubleArray2();
-
-  static DoubleArray2 *create(io::Pool pool);
-  static DoubleArray2 *open(io::Pool pool, uint32_t block_id);
-
-  virtual uint32_t block_id() const = 0;
-
-  virtual bool search_by_id(int64_t key_id, const void **ptr,
-                            uint64_t *length) = 0;
-  virtual bool search_by_key(const void *ptr, uint64_t length,
-                             int64_t *key_id = nullptr) = 0;
-
-  virtual bool insert(const void *ptr, uint64_t length,
-                      int64_t *key_id = nullptr) = 0;
-
-  virtual bool remove_by_id(int64_t key_id) = 0;
-  virtual bool remove_by_key(const void *ptr, uint64_t length) = 0;
-
-  virtual bool update_by_id(int64_t key_id, const void *ptr,
-                            uint64_t length) = 0;
-  virtual bool update_by_key(const void *src_ptr, uint64_t src_length,
-                             const void *dest_ptr, uint64_t dest_length,
-                             int64_t *key_id = nullptr) = 0;
-};
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_DOUBLE_ARRAY2_HPP

  Modified: test/Makefile.am (+0 -4)
===================================================================
--- test/Makefile.am    2013-02-20 14:19:56 +0900 (c7d6877)
+++ test/Makefile.am    2013-02-22 13:20:06 +0900 (8997a62)
@@ -2,7 +2,6 @@ AM_CXXFLAGS = @AM_CXXFLAGS@ -I$(top_srcdir)/lib
 
 TESTS =					\
 	test_alpha_double_array		\
-	test_alpha_double_array2	\
 	test_backtrace			\
 	test_db_array			\
 	test_db_blob_vector		\
@@ -38,9 +37,6 @@ check_PROGRAMS = $(TESTS)
 test_alpha_double_array_SOURCES = test_alpha_double_array.cpp
 test_alpha_double_array_LDADD = ../lib/libgrnxx.la
 
-test_alpha_double_array2_SOURCES = test_alpha_double_array2.cpp
-test_alpha_double_array2_LDADD = ../lib/libgrnxx.la
-
 test_backtrace_SOURCES = test_backtrace.cpp
 test_backtrace_LDADD = ../lib/libgrnxx.la
 

  Deleted: test/test_alpha_double_array2.cpp (+0 -295) 100644
===================================================================
--- test/test_alpha_double_array2.cpp    2013-02-20 14:19:56 +0900 (503e8b3)
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
-  Copyright (C) 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 <cassert>
-#include <random>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include "alpha/double_array2.hpp"
-#include "logger.hpp"
-#include "time.hpp"
-
-void test_basics() {
-  grnxx::io::Pool pool;
-  pool.open(grnxx::io::POOL_TEMPORARY);
-
-  std::unique_ptr<grnxx::alpha::DoubleArray2> da(
-      grnxx::alpha::DoubleArray2::create(pool));
-
-  std::vector<std::string> keys;
-  keys.push_back("apple");
-  keys.push_back("banana");
-  keys.push_back("strawberry");
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(!da->search_by_key(keys[i].c_str(), keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    std::int64_t key_id;
-    assert(da->insert(keys[i].c_str(), keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    std::int64_t key_id;
-    assert(da->search_by_key(keys[i].c_str(), keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(!da->insert(keys[i].c_str(), keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(da->remove_by_key(keys[i].c_str(), keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(!da->search_by_key(keys[i].c_str(), keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(!da->remove_by_key(keys[i].c_str(), keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(da->insert(keys[i].c_str(), keys[i].length()));
-  }
-
-  std::vector<std::string> new_keys;
-  new_keys.push_back("dog");
-  new_keys.push_back("monkey");
-  new_keys.push_back("bird");
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(da->update_by_key(keys[i].c_str(), keys[i].length(),
-                             new_keys[i].c_str(), new_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < keys.size(); ++i) {
-    assert(!da->search_by_key(keys[i].c_str(), keys[i].length()));
-    assert(da->search_by_key(new_keys[i].c_str(), new_keys[i].length()));
-  }
-}
-
-void test_insert() {
-  constexpr std::size_t NUM_KEYS = 1 << 12;
-  constexpr std::size_t MIN_LENGTH = 1;
-  constexpr std::size_t MAX_LENGTH = 10;
-
-  std::mt19937 random;
-
-  grnxx::io::Pool pool;
-  pool.open(grnxx::io::POOL_TEMPORARY);
-
-  std::unique_ptr<grnxx::alpha::DoubleArray2> da(
-      grnxx::alpha::DoubleArray2::create(pool));
-
-  std::vector<std::string> true_keys(NUM_KEYS);
-  std::vector<std::string> false_keys(NUM_KEYS);
-  {
-    std::unordered_set<std::string> keys;
-    while (keys.size() < (NUM_KEYS * 2)) {
-      std::string key;
-      key.resize(MIN_LENGTH + (random() % (MAX_LENGTH - MIN_LENGTH + 1)));
-      for (std::size_t j = 0; j < key.length(); ++j) {
-        key[j] = '0' + (random() % 10);
-      }
-      keys.insert(key);
-    }
-    auto it = keys.begin();
-    for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-      true_keys[i] = *it;
-      ++it;
-      false_keys[i] = *it;
-      ++it;
-    }
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    std::int64_t key_id;
-    assert(da->insert(true_keys[i].c_str(), true_keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-
-    assert(!da->insert(true_keys[i].c_str(), true_keys[i].length(), &key_id));
-
-    key_id = i + 1;
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length(),
-                             &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    std::int64_t key_id;
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length(),
-                             &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-
-    assert(!da->search_by_key(false_keys[i].c_str(), false_keys[i].length(),
-                              &key_id));
-  }
-}
-
-void test_remove() {
-  constexpr std::size_t NUM_KEYS = 1 << 12;
-  constexpr std::size_t MIN_LENGTH = 1;
-  constexpr std::size_t MAX_LENGTH = 10;
-
-  std::mt19937 random;
-
-  grnxx::io::Pool pool;
-  pool.open(grnxx::io::POOL_TEMPORARY);
-
-  std::unique_ptr<grnxx::alpha::DoubleArray2> da(
-      grnxx::alpha::DoubleArray2::create(pool));
-
-  std::vector<std::string> true_keys(NUM_KEYS);
-  std::vector<std::string> false_keys(NUM_KEYS);
-  {
-    std::unordered_set<std::string> keys;
-    while (keys.size() < (NUM_KEYS * 2)) {
-      std::string key;
-      key.resize(MIN_LENGTH + (random() % (MAX_LENGTH - MIN_LENGTH + 1)));
-      for (std::size_t j = 0; j < key.length(); ++j) {
-        key[j] = '0' + (random() % 10);
-      }
-      keys.insert(key);
-    }
-    auto it = keys.begin();
-    for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-      true_keys[i] = *it;
-      ++it;
-      false_keys[i] = *it;
-      ++it;
-    }
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    std::int64_t key_id;
-    assert(da->insert(true_keys[i].c_str(), true_keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>(i * 2));
-    assert(da->insert(false_keys[i].c_str(), false_keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>((i * 2) + 1));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->remove_by_id((i * 2) + 1));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length()));
-    assert(!da->search_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->insert(false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length()));
-    assert(da->search_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->remove_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length()));
-    assert(!da->search_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-}
-
-void test_update() {
-  constexpr std::size_t NUM_KEYS = 1 << 12;
-  constexpr std::size_t MIN_LENGTH = 1;
-  constexpr std::size_t MAX_LENGTH = 10;
-
-  std::mt19937 random;
-
-  grnxx::io::Pool pool;
-  pool.open(grnxx::io::POOL_TEMPORARY);
-
-  std::unique_ptr<grnxx::alpha::DoubleArray2> da(
-      grnxx::alpha::DoubleArray2::create(pool));
-
-  std::vector<std::string> true_keys(NUM_KEYS);
-  std::vector<std::string> false_keys(NUM_KEYS);
-  {
-    std::unordered_set<std::string> keys;
-    while (keys.size() < (NUM_KEYS * 2)) {
-      std::string key;
-      key.resize(MIN_LENGTH + (random() % (MAX_LENGTH - MIN_LENGTH + 1)));
-      for (std::size_t j = 0; j < key.length(); ++j) {
-        key[j] = '0' + (random() % 10);
-      }
-      keys.insert(key);
-    }
-    auto it = keys.begin();
-    for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-      true_keys[i] = *it;
-      ++it;
-      false_keys[i] = *it;
-      ++it;
-    }
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    std::int64_t key_id;
-    assert(da->insert(true_keys[i].c_str(), true_keys[i].length(), &key_id));
-    assert(key_id == static_cast<std::int64_t>(i));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(!da->update_by_id(i, true_keys[i].c_str(), true_keys[i].length()));
-    assert(da->update_by_id(i, false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(!da->search_by_key(true_keys[i].c_str(), true_keys[i].length()));
-    assert(da->search_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(!da->update_by_key(true_keys[i].c_str(), true_keys[i].length(),
-                              false_keys[i].c_str(), false_keys[i].length()));
-    assert(da->update_by_key(false_keys[i].c_str(), false_keys[i].length(),
-                             true_keys[i].c_str(), true_keys[i].length()));
-  }
-
-  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
-    assert(da->search_by_key(true_keys[i].c_str(), true_keys[i].length()));
-    assert(!da->search_by_key(false_keys[i].c_str(), false_keys[i].length()));
-  }
-}
-
-int main() {
-  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
-                           grnxx::LOGGER_ENABLE_COUT);
-  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
-
-  test_basics();
-
-  test_insert();
-  test_remove();
-  test_update();
-
-  return 0;
-}
-------------- next part --------------
HTML����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る