[Groonga-commit] groonga/grnxx at e33209c [master] Clear the repository for newly designed implementations.

Back to archive index

susumu.yata null+****@clear*****
Mon Feb 24 15:43:11 JST 2014


susumu.yata	2014-02-24 15:43:11 +0900 (Mon, 24 Feb 2014)

  New Revision: e33209c9c4cb1cf4b45aeff625a9342797a233bb
  https://github.com/groonga/grnxx/commit/e33209c9c4cb1cf4b45aeff625a9342797a233bb

  Message:
    Clear the repository for newly designed implementations.

  Added files:
    lib/grnxx/library.cpp
    lib/grnxx/library.hpp
  Removed files:
    lib/grnxx/array.cpp
    lib/grnxx/array.hpp
    lib/grnxx/array_impl.cpp
    lib/grnxx/array_impl.hpp
    lib/grnxx/backtrace.cpp
    lib/grnxx/backtrace.hpp
    lib/grnxx/broken_down_time.cpp
    lib/grnxx/broken_down_time.hpp
    lib/grnxx/bytes.hpp
    lib/grnxx/charset.cpp
    lib/grnxx/charset.hpp
    lib/grnxx/charset/Makefile.am
    lib/grnxx/charset/euc-jp.cpp
    lib/grnxx/charset/euc-jp.hpp
    lib/grnxx/charset/shift_jis.cpp
    lib/grnxx/charset/shift_jis.hpp
    lib/grnxx/charset/utf-8.cpp
    lib/grnxx/charset/utf-8.hpp
    lib/grnxx/common_header.cpp
    lib/grnxx/common_header.hpp
    lib/grnxx/duration.cpp
    lib/grnxx/duration.hpp
    lib/grnxx/errno.cpp
    lib/grnxx/errno.hpp
    lib/grnxx/exception.hpp
    lib/grnxx/features.hpp
    lib/grnxx/flags_impl.hpp
    lib/grnxx/geo_point.cpp
    lib/grnxx/geo_point.hpp
    lib/grnxx/grnxx.cpp
    lib/grnxx/grnxx.hpp
    lib/grnxx/intrinsic.hpp
    lib/grnxx/lock.hpp
    lib/grnxx/logger.cpp
    lib/grnxx/logger.hpp
    lib/grnxx/map.cpp
    lib/grnxx/map.hpp
    lib/grnxx/map/Makefile.am
    lib/grnxx/map/array_map.cpp
    lib/grnxx/map/array_map.hpp
    lib/grnxx/map/bytes_pool.cpp
    lib/grnxx/map/bytes_pool.hpp
    lib/grnxx/map/common_header.cpp
    lib/grnxx/map/common_header.hpp
    lib/grnxx/map/cursor_impl.cpp
    lib/grnxx/map/cursor_impl.hpp
    lib/grnxx/map/double_array.cpp
    lib/grnxx/map/double_array.hpp
    lib/grnxx/map/hash.hpp
    lib/grnxx/map/hash_table.cpp
    lib/grnxx/map/hash_table.hpp
    lib/grnxx/map/header.hpp
    lib/grnxx/map/helper.hpp
    lib/grnxx/map/key_pool.cpp
    lib/grnxx/map/key_pool.hpp
    lib/grnxx/map/patricia.cpp
    lib/grnxx/map/patricia.hpp
    lib/grnxx/map/pool.cpp
    lib/grnxx/map/pool.hpp
    lib/grnxx/map/scanner_impl.cpp
    lib/grnxx/map/scanner_impl.hpp
    lib/grnxx/map_cursor.cpp
    lib/grnxx/map_cursor.hpp
    lib/grnxx/map_cursor_query.hpp
    lib/grnxx/map_scanner.cpp
    lib/grnxx/map_scanner.hpp
    lib/grnxx/mutex.cpp
    lib/grnxx/mutex.hpp
    lib/grnxx/os.cpp
    lib/grnxx/os.hpp
    lib/grnxx/periodic_clock.cpp
    lib/grnxx/periodic_clock.hpp
    lib/grnxx/stopwatch.cpp
    lib/grnxx/stopwatch.hpp
    lib/grnxx/storage.cpp
    lib/grnxx/storage.hpp
    lib/grnxx/storage/Makefile.am
    lib/grnxx/storage/chunk-posix.cpp
    lib/grnxx/storage/chunk-posix.hpp
    lib/grnxx/storage/chunk-windows.cpp
    lib/grnxx/storage/chunk-windows.hpp
    lib/grnxx/storage/chunk.cpp
    lib/grnxx/storage/chunk.hpp
    lib/grnxx/storage/chunk_index.cpp
    lib/grnxx/storage/chunk_index.hpp
    lib/grnxx/storage/file-posix.cpp
    lib/grnxx/storage/file-posix.hpp
    lib/grnxx/storage/file-windows.cpp
    lib/grnxx/storage/file-windows.hpp
    lib/grnxx/storage/file.cpp
    lib/grnxx/storage/file.hpp
    lib/grnxx/storage/header.cpp
    lib/grnxx/storage/header.hpp
    lib/grnxx/storage/node_header.cpp
    lib/grnxx/storage/node_header.hpp
    lib/grnxx/storage/path.cpp
    lib/grnxx/storage/path.hpp
    lib/grnxx/storage/storage_impl.cpp
    lib/grnxx/storage/storage_impl.hpp
    lib/grnxx/string_builder.cpp
    lib/grnxx/string_builder.hpp
    lib/grnxx/string_format.hpp
    lib/grnxx/system_clock.cpp
    lib/grnxx/system_clock.hpp
    lib/grnxx/thread.cpp
    lib/grnxx/thread.hpp
    lib/grnxx/time.cpp
    lib/grnxx/time.hpp
    lib/grnxx/traits.hpp
    lib/grnxx/types.hpp
    obsolete/lib/grnxx/alpha/Makefile.am
    obsolete/lib/grnxx/alpha/double_array.cpp
    obsolete/lib/grnxx/alpha/double_array.hpp
    obsolete/lib/grnxx/alpha/dummy.cpp
    obsolete/lib/grnxx/alpha/dummy.hpp
    obsolete/lib/grnxx/alpha/map.cpp
    obsolete/lib/grnxx/alpha/map.hpp
    obsolete/lib/grnxx/alpha/map/Makefile.am
    obsolete/lib/grnxx/alpha/map/array.cpp
    obsolete/lib/grnxx/alpha/map/array.hpp
    obsolete/lib/grnxx/alpha/map/cursor.cpp
    obsolete/lib/grnxx/alpha/map/cursor.hpp
    obsolete/lib/grnxx/alpha/map/double_array-slice.cpp
    obsolete/lib/grnxx/alpha/map/double_array.cpp
    obsolete/lib/grnxx/alpha/map/double_array.hpp
    obsolete/lib/grnxx/alpha/map/header.hpp
    obsolete/lib/grnxx/alpha/map/scan.cpp
    obsolete/lib/grnxx/alpha/map/scan.hpp
    obsolete/lib/grnxx/alpha/map_range.hpp
    obsolete/lib/grnxx/alpha/paged_array.cpp
    obsolete/lib/grnxx/alpha/paged_array.hpp
    obsolete/lib/grnxx/basic.hpp
    obsolete/lib/grnxx/db/Makefile.am
    obsolete/lib/grnxx/db/blob_vector.cpp
    obsolete/lib/grnxx/db/blob_vector.hpp
    obsolete/lib/grnxx/db/vector.cpp
    obsolete/lib/grnxx/db/vector.hpp
    obsolete/lib/grnxx/io/Makefile.am
    obsolete/lib/grnxx/io/block.cpp
    obsolete/lib/grnxx/io/block.hpp
    obsolete/lib/grnxx/io/chunk.cpp
    obsolete/lib/grnxx/io/chunk.hpp
    obsolete/lib/grnxx/io/file-posix.cpp
    obsolete/lib/grnxx/io/file-posix.hpp
    obsolete/lib/grnxx/io/file-windows.cpp
    obsolete/lib/grnxx/io/file-windows.hpp
    obsolete/lib/grnxx/io/file.cpp
    obsolete/lib/grnxx/io/file.hpp
    obsolete/lib/grnxx/io/file_info.cpp
    obsolete/lib/grnxx/io/file_info.hpp
    obsolete/lib/grnxx/io/path.cpp
    obsolete/lib/grnxx/io/path.hpp
    obsolete/lib/grnxx/io/pool-impl.cpp
    obsolete/lib/grnxx/io/pool-impl.hpp
    obsolete/lib/grnxx/io/pool.cpp
    obsolete/lib/grnxx/io/pool.hpp
    obsolete/lib/grnxx/io/view-posix.cpp
    obsolete/lib/grnxx/io/view-posix.hpp
    obsolete/lib/grnxx/io/view-windows.cpp
    obsolete/lib/grnxx/io/view-windows.hpp
    obsolete/lib/grnxx/io/view.cpp
    obsolete/lib/grnxx/io/view.hpp
    obsolete/lib/grnxx/map.cpp
    obsolete/lib/grnxx/map.hpp
    obsolete/lib/grnxx/map/Makefile.am
    obsolete/lib/grnxx/map/da/Makefile.am
    obsolete/lib/grnxx/map/da/basic/Makefile.am
    obsolete/lib/grnxx/map/da/basic/id_cursor.cpp
    obsolete/lib/grnxx/map/da/basic/id_cursor.hpp
    obsolete/lib/grnxx/map/da/basic/key_cursor.cpp
    obsolete/lib/grnxx/map/da/basic/key_cursor.hpp
    obsolete/lib/grnxx/map/da/basic/predictive_cursor.cpp
    obsolete/lib/grnxx/map/da/basic/predictive_cursor.hpp
    obsolete/lib/grnxx/map/da/basic/prefix_cursor.cpp
    obsolete/lib/grnxx/map/da/basic/prefix_cursor.hpp
    obsolete/lib/grnxx/map/da/basic/trie.cpp
    obsolete/lib/grnxx/map/da/basic/trie.hpp
    obsolete/lib/grnxx/map/da/large/Makefile.am
    obsolete/lib/grnxx/map/da/large/id_cursor.cpp
    obsolete/lib/grnxx/map/da/large/id_cursor.hpp
    obsolete/lib/grnxx/map/da/large/key_cursor.cpp
    obsolete/lib/grnxx/map/da/large/key_cursor.hpp
    obsolete/lib/grnxx/map/da/large/predictive_cursor.cpp
    obsolete/lib/grnxx/map/da/large/predictive_cursor.hpp
    obsolete/lib/grnxx/map/da/large/prefix_cursor.cpp
    obsolete/lib/grnxx/map/da/large/prefix_cursor.hpp
    obsolete/lib/grnxx/map/da/large/trie.cpp
    obsolete/lib/grnxx/map/da/large/trie.hpp
    obsolete/lib/grnxx/map/da/trie.cpp
    obsolete/lib/grnxx/map/da/trie.hpp
    obsolete/lib/grnxx/map/double_array.cpp
    obsolete/lib/grnxx/map/double_array.hpp
    obsolete/lib/grnxx/recycler.cpp
    obsolete/lib/grnxx/recycler.hpp
    obsolete/lib/grnxx/slice.cpp
    obsolete/lib/grnxx/slice.hpp
    obsolete/lib/grnxx/string.cpp
    obsolete/lib/grnxx/string.hpp
    obsolete/test/test_alpha_double_array.cpp
    obsolete/test/test_alpha_map.cpp
    obsolete/test/test_io.cpp
    obsolete/test/test_map
    obsolete/test/test_map.cpp
    obsolete/test/test_map_da_basic_trie
    obsolete/test/test_map_da_basic_trie.cpp
    obsolete/test/test_map_da_large_trie
    obsolete/test/test_map_da_large_trie.cpp
    obsolete/test/test_map_double_array
    obsolete/test/test_map_double_array.cpp
    obsolete/test/test_recycler.cpp
    obsolete/test/test_slice.cpp
    obsolete/test/test_string.cpp
    test/test_array.cpp
    test/test_backtrace.cpp
    test/test_bytes.cpp
    test/test_charset.cpp
    test/test_db_blob_vector.cpp
    test/test_db_vector.cpp
    test/test_duration.cpp
    test/test_errno.cpp
    test/test_exception.cpp
    test/test_geo_point.cpp
    test/test_intrinsic.cpp
    test/test_logger.cpp
    test/test_map.cpp
    test/test_map_pool.cpp
    test/test_mutex.cpp
    test/test_os.cpp
    test/test_storage.cpp
    test/test_string_builder.cpp
    test/test_string_format.cpp
    test/test_thread.cpp
    test/test_time.cpp
    test/test_traits.cpp
    test/test_types.cpp
  Modified files:
    .gitignore
    configure.ac
    lib/grnxx/Makefile.am
    src/Makefile.am
    src/grnxx.cpp
    test/Makefile.am
    test/test_grnxx.cpp
  Renamed files:
    test/benchmark_grnxx.cpp
      (from test/test_features.cpp)

  Modified: .gitignore (+3 -24)
===================================================================
--- .gitignore    2013-08-23 10:46:34 +0900 (0f4b205)
+++ .gitignore    2014-02-24 15:43:11 +0900 (a2a80b1)
@@ -4,7 +4,6 @@
 *.dat
 *.dll
 *.exe
-*.grn
 *.la
 *.lai
 *.lo
@@ -26,27 +25,7 @@ ltmain.sh
 missing
 src/grnxx
 stamp-h1
-temp/
-test/test_array
-test/test_backtrace
-test/test_bytes
-test/test_charset
-test/test_duration
-test/test_errno
-test/test_exception
-test/test_features
-test/test_geo_point
+test/*.trs
 test/test_grnxx
-test/test_intrinsic
-test/test_logger
-test/test_map
-test/test_map_pool
-test/test_mutex
-test/test_os
-test/test_storage
-test/test_string_builder
-test/test_string_format
-test/test_thread
-test/test_time
-test/test_traits
-test/test_types
+test/benchmark_grnxx
+test-driver

  Modified: configure.ac (+9 -21)
===================================================================
--- configure.ac    2013-08-23 10:46:34 +0900 (06d5f23)
+++ configure.ac    2014-02-24 15:43:11 +0900 (c611975)
@@ -2,22 +2,19 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.67])
-AC_INIT([grnxx], [pre-alpha], [groonga �� razil.jp])
-AC_CONFIG_SRCDIR([lib/grnxx/grnxx.hpp])
-AC_CONFIG_HEADERS(config.h)
+AC_INIT([grnxx], [dummy12], [groonga �� razil.jp])
+AC_CONFIG_SRCDIR([lib/grnxx/library.hpp])
+AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE
 
 # Checks for programs.
 LT_INIT([win32-dll])
-AC_PROG_CXX
+AC_PROG_CXX([clang++ g++-4.8])
 AC_PROG_INSTALL
 
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_CXXFLAGS="-Wall -Wextra -std=c++11 -fno-strict-aliasing -I\${top_srcdir}/lib"
-
-AC_SUBST([AM_CXXFLAGS])
-AC_SUBST([AM_LTLDFLAGS])
+AM_CXXFLAGS="-Wall -std=c++11 -fno-strict-aliasing -I\${top_srcdir}/lib"
 
 AC_C_BIGENDIAN
 AC_CANONICAL_HOST
@@ -32,6 +29,9 @@ case "${host}" in
     ;;
 esac
 
+AC_SUBST([AM_CXXFLAGS])
+AC_SUBST([AM_LTLDFLAGS])
+
 # Checks for libraries.
 
 AC_ARG_ENABLE([backtrace],
@@ -47,22 +47,10 @@ if test "x$enable_backtrace" != "xno"; then
 fi
 
 AC_CHECK_LIB([rt], [clock_gettime])
-AC_CHECK_LIB([pthread], [pthread_create])
-AC_CHECK_LIB([pthread], [pthread_create],
-             [AM_CXXFLAGS="${AM_CXXFLAGS} -pthread"])
-
-# For std::this_thread::yield() and std::this_thread::sleep_for().
-#AC_CHECK_FUNC([sched_yield],
-#              [AM_CXXFLAGS="${AM_CXXFLAGS} -D_GLIBCXX_USE_SCHED_YIELD"])
-#AC_CHECK_FUNC([nanosleep],
-#              [AM_CXXFLAGS="${AM_CXXFLAGS} -D_GLIBCXX_USE_NANOSLEEP"])
 
 AC_CONFIG_FILES([Makefile
                  lib/Makefile
                  lib/grnxx/Makefile
-                 lib/grnxx/charset/Makefile
-                 lib/grnxx/map/Makefile
-                 lib/grnxx/storage/Makefile
                  src/Makefile
                  test/Makefile])
 AC_OUTPUT
@@ -79,4 +67,4 @@ echo "Paths:"
 echo "  Install path prefix:   ${prefix}"
 echo
 
-echo "Now type 'make' to build $PACKAGE_NAME $PACKAGE_VERSION!"
+echo "Now type 'make' to build ${PACKAGE_NAME} ${PACKAGE_VERSION}!"

  Modified: lib/grnxx/Makefile.am (+6 -64)
===================================================================
--- lib/grnxx/Makefile.am    2013-08-23 10:46:34 +0900 (0909220)
+++ lib/grnxx/Makefile.am    2014-02-24 15:43:11 +0900 (df693e0)
@@ -1,77 +1,19 @@
-SUBDIRS =				\
-	charset				\
-	map				\
-	storage
+#SUBDIRS =				\
+#	sub
 
 lib_LTLIBRARIES = libgrnxx.la
 
-libgrnxx_la_LIBADD =			\
-	charset/libgrnxx_charset.la	\
-	map/libgrnxx_map.la		\
-	storage/libgrnxx_storage.la
+#libgrnxx_la_LIBADD =			\
+#	sub/libgrnxx_sub.la
 
 libgrnxx_la_LDFLAGS = @AM_LTLDFLAGS@
 
 libgrnxx_la_SOURCES =			\
-	array.cpp			\
-	array_impl.cpp			\
-	backtrace.cpp			\
-	broken_down_time.cpp		\
-	charset.cpp			\
-	common_header.cpp		\
-	duration.cpp			\
-	errno.cpp			\
-	geo_point.cpp			\
-	grnxx.cpp			\
-	logger.cpp			\
-	map.cpp				\
-	map_cursor.cpp			\
-	map_scanner.cpp			\
-	mutex.cpp			\
-	os.cpp				\
-	periodic_clock.cpp		\
-	stopwatch.cpp			\
-	storage.cpp			\
-	string_builder.cpp		\
-	system_clock.cpp		\
-	thread.cpp			\
-	time.cpp
+	library.cpp
 
 libgrnxx_includedir = ${includedir}/grnxx
 libgrnxx_include_HEADERS =		\
-	array.hpp			\
-	array_impl.hpp			\
-	backtrace.hpp			\
-	broken_down_time.hpp		\
-	bytes.hpp			\
-	charset.hpp			\
-	common_header.hpp		\
-	duration.hpp			\
-	errno.hpp			\
-	exception.hpp			\
-	features.hpp			\
-	flags_impl.hpp			\
-	geo_point.hpp			\
-	grnxx.hpp			\
-	intrinsic.hpp			\
-	lock.hpp			\
-	logger.hpp			\
-	map.hpp				\
-	map_cursor.hpp			\
-	map_cursor_query.hpp		\
-	map_scanner.hpp			\
-	mutex.hpp			\
-	os.hpp				\
-	periodic_clock.hpp		\
-	stopwatch.hpp			\
-	storage.hpp			\
-	string_builder.hpp		\
-	string_format.hpp		\
-	system_clock.hpp		\
-	thread.hpp			\
-	time.hpp			\
-	traits.hpp			\
-	types.hpp			\
+	library.hpp			\
 	version.h
 
 EXTRA_DIST = version.sh

  Deleted: lib/grnxx/array.cpp (+0 -30) 100644
===================================================================
--- lib/grnxx/array.cpp    2013-08-23 10:46:34 +0900 (e33768b)
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  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"
-
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-
-void ArrayErrorHandler::throw_memory_error() {
-  GRNXX_ERROR() << "new grnxx::Array failed";
-  throw MemoryError();
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/array.hpp (+0 -118) 100644
===================================================================
--- lib/grnxx/array.hpp    2013-08-23 10:46:34 +0900 (550607c)
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ARRAY_HPP
-#define GRNXX_ARRAY_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-#include <new>
-
-#include "grnxx/array_impl.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-struct ArrayErrorHandler {
-  static void throw_memory_error();
-};
-
-template <typename T, uint64_t PAGE_SIZE = 0, uint64_t TABLE_SIZE = 0>
-class Array {
-  using Impl = ArrayImpl<T, PAGE_SIZE, TABLE_SIZE>;
-
- public:
-  using Value    = typename Impl::Value;
-  using ValueArg = typename Impl::ValueArg;
-  using ValueRef = typename Impl::ValueRef;
-  using Unit     = typename Impl::Unit;
-
-  // Create an array.
-  static Array *create(Storage *storage, uint32_t storage_node_id,
-                       uint64_t size) {
-    std::unique_ptr<Array> array(create_instance());
-    array->impl_.create(storage, storage_node_id, size);
-    return array.release();
-  }
-  // Create an array with default value.
-  static Array *create(Storage *storage, uint32_t storage_node_id,
-                       uint64_t size, ValueArg default_value) {
-    std::unique_ptr<Array> array(create_instance());
-    array->impl_.create(storage, storage_node_id, size, default_value);
-    return array.release();
-  }
-
-  // Open an array.
-  static Array *open(Storage *storage, uint32_t storage_node_id) {
-    std::unique_ptr<Array> array(create_instance());
-    array->impl_.open(storage, storage_node_id);
-    return array.release();
-  }
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id) {
-    Impl::unlink(storage, storage_node_id);
-  }
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return impl_.storage_node_id();
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return impl_.size();
-  }
-
-  // Get a value.
-  Value get(uint64_t value_id) {
-    return get_value(value_id);
-  }
-  // Set a value.
-  void set(uint64_t value_id, ValueArg value) {
-    get_value(value_id) = value;
-  }
-
-  // Get a reference to a value.
-  ValueRef get_value(uint64_t value_id) {
-    return impl_.get_value(value_id);
-  }
-  // Get a reference to a unit.
-  Unit &get_unit(uint64_t unit_id) {
-    return impl_.get_unit(unit_id);
-  }
-
- private:
-  Impl impl_;
-
-  Array() : impl_() {}
-
-  // Create an instance or throw an exception on failure.
-  static Array *create_instance() {
-    Array * const array = new (std::nothrow) Array;
-    if (!array) {
-      ArrayErrorHandler::throw_memory_error();
-    }
-    return array;
-  }
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_ARRAY_HPP

  Deleted: lib/grnxx/array_impl.cpp (+0 -599) 100644
===================================================================
--- lib/grnxx/array_impl.cpp    2013-08-23 10:46:34 +0900 (be98765)
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
-  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_impl.hpp"
-
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/common_header.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::Array";
-
-struct DummyTable {
-  void **pages;
-  uint32_t reference_count;
-  Mutex mutex;
-
-  DummyTable() : pages(nullptr), reference_count(0), mutex() {}
-};
-
-class DummyTableManager {
- public:
-  // Get a singleton.
-  static DummyTableManager &get();
-
-  // Get a dummy table.
-  void **get_dummy_table(uint64_t table_size);
-  // Free a dummy table.
-  void free_dummy_table(uint64_t table_size);
-
- private:
-  DummyTable dummy_tables_[64];
-
-  DummyTableManager() : dummy_tables_() {}
-
-  DummyTableManager(const DummyTableManager &) = delete;
-  DummyTableManager &operator=(const DummyTableManager &) = delete;
-};
-
-DummyTableManager &DummyTableManager::get() {
-  static DummyTableManager singleton;
-  return singleton;
-}
-
-void **DummyTableManager::get_dummy_table(uint64_t table_size) {
-  const uint64_t table_id = bit_scan_reverse(table_size);
-  DummyTable &dummy_table = dummy_tables_[table_id];
-  Lock lock(&dummy_table.mutex);
-  if (dummy_table.reference_count == 0) {
-    if (dummy_table.pages) {
-      GRNXX_ERROR() << "already exists: table_size = " << table_size;
-      throw LogicError();
-    }
-    // Create a dummy table.
-    dummy_table.pages = new (std::nothrow) void *[table_size];
-    if (!dummy_table.pages) {
-      GRNXX_ERROR() << "new void *[] failed: size = " << table_size;
-      throw MemoryError();
-    }
-    for (uint64_t i = 0; i < table_size; ++i) {
-      dummy_table.pages[i] = Array3D::invalid_page();
-    }
-  } else if (!dummy_table.pages) {
-    GRNXX_ERROR() << "invalid pages: table_size = " << table_size;
-    throw LogicError();
-  }
-  ++dummy_table.reference_count;
-  return dummy_table.pages;
-}
-
-void DummyTableManager::free_dummy_table(uint64_t table_size) {
-  const uint64_t table_id = bit_scan_reverse(table_size);
-  DummyTable &dummy_table = dummy_tables_[table_id];
-  Lock lock(&dummy_table.mutex);
-  if (!dummy_table.pages || (dummy_table.reference_count == 0)) {
-    GRNXX_ERROR() << "already freed: table_size = " << table_size;
-    throw LogicError();
-  }
-  if (dummy_table.reference_count == 1) {
-    // Free a dummy table.
-    delete [] dummy_table.pages;
-    dummy_table.pages = nullptr;
-  }
-  --dummy_table.reference_count;
-}
-
-}  // namespace
-
-struct ArrayHeader {
-  CommonHeader common_header;
-  uint64_t value_size;
-  uint64_t page_size;
-  uint64_t table_size;
-  uint64_t secondary_table_size;
-  uint64_t size;
-  uint32_t has_default_value;
-  union {
-    uint32_t page_storage_node_id;
-    uint32_t table_storage_node_id;
-    uint32_t secondary_table_storage_node_id;
-  };
-  Mutex page_mutex;
-  Mutex table_mutex;
-
-  // Initialize the members except "common_header".
-  ArrayHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-ArrayHeader::ArrayHeader()
-    : common_header(FORMAT_STRING),
-      value_size(0),
-      page_size(0),
-      table_size(0),
-      secondary_table_size(0),
-      size(0),
-      has_default_value(0),
-      page_storage_node_id(STORAGE_INVALID_NODE_ID),
-      page_mutex(),
-      table_mutex() {}
-
-ArrayHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-Array1D::Array1D()
-    : page_(nullptr),
-      size_(0),
-      storage_node_id_(STORAGE_INVALID_NODE_ID) {}
-
-Array1D::~Array1D() {}
-
-void Array1D::create(Storage *storage, uint32_t storage_node_id,
-                   uint64_t value_size, uint64_t,
-                   uint64_t, uint64_t size,
-                   const void *default_value, ArrayFillPage fill_page) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(ArrayHeader));
-  storage_node_id_ = storage_node.id();
-  try {
-    ArrayHeader * const header =
-        static_cast<ArrayHeader *>(storage_node.body());
-    *header = ArrayHeader();
-    header->value_size = value_size;
-    header->page_size = size;
-    header->size = size;
-    // Create a page.
-    StorageNode page_node =
-        storage->create_node(storage_node_id_, value_size * size);
-    header->page_storage_node_id = page_node.id();
-    page_ = page_node.body();
-    if (default_value) {
-      header->has_default_value = 1;
-      fill_page(page_, size, default_value);
-    }
-    size_ = size;
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void Array1D::open(Storage *storage, uint32_t storage_node_id,
-                   uint64_t value_size, uint64_t,
-                   uint64_t, ArrayFillPage) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(ArrayHeader)) {
-    GRNXX_ERROR() << "too small header: size = " << storage_node.size();
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node.id();
-  const ArrayHeader * const header =
-      static_cast<ArrayHeader *>(storage_node.body());
-  if (!*header) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header->common_header.format();
-    throw LogicError();
-  }
-  if (header->value_size != value_size) {
-    GRNXX_ERROR() << "wrong value_size: expected = " << value_size
-                  << ", actual = " << header->value_size;
-    throw LogicError();
-  }
-  StorageNode page_node = storage->open_node(header->page_storage_node_id);
-  page_ = page_node.body();
-  size_ = header->size;
-}
-
-void Array1D::unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size) {
-  Array1D array;
-  array.open(storage, storage_node_id,
-             value_size, page_size, table_size, nullptr);
-  storage->unlink_node(storage_node_id);
-}
-
-Array2D::Array2D()
-    : pages_(),
-      size_(0),
-      storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      fill_page_(nullptr),
-      table_(nullptr),
-      mutex_() {}
-
-Array2D::~Array2D() {}
-
-void Array2D::create(Storage *storage, uint32_t storage_node_id,
-                   uint64_t value_size, uint64_t page_size,
-                   uint64_t, uint64_t size,
-                   const void *default_value, ArrayFillPage fill_page) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  if ((size % page_size) != 0) {
-    const uint64_t adjusted_size = size + page_size - (size % page_size);
-    GRNXX_WARNING() << "size adjustment: before = " << size
-                    << ", after = " << adjusted_size
-                    << ", page_size = " << page_size;
-    size = adjusted_size;
-  }
-  storage_ = storage;
-  uint64_t storage_node_size = sizeof(ArrayHeader);
-  if (default_value) {
-    storage_node_size += value_size;
-  }
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, storage_node_size);
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<ArrayHeader *>(storage_node.body());
-    *header_ = ArrayHeader();
-    header_->value_size = value_size;
-    header_->page_size = page_size;
-    header_->table_size = size / page_size;
-    header_->size = size;
-    if (default_value) {
-      header_->has_default_value = 1;
-      std::memcpy(header_ + 1, default_value, value_size);
-      fill_page_ = fill_page;
-    }
-    // Create a table.
-    StorageNode table_node = storage->create_node(
-        storage_node_id_, sizeof(uint32_t) * header_->table_size);
-    header_->table_storage_node_id = table_node.id();
-    table_ = static_cast<uint32_t *>(table_node.body());
-    for (uint64_t i = 0; i < header_->table_size; ++i) {
-      table_[i] = STORAGE_INVALID_NODE_ID;
-    }
-    reserve_pages();
-    size_ = size;
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void Array2D::open(Storage *storage, uint32_t storage_node_id,
-                   uint64_t value_size, uint64_t page_size,
-                   uint64_t , ArrayFillPage fill_page) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(ArrayHeader)) {
-    GRNXX_ERROR() << "too small header: size = " << storage_node.size();
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<ArrayHeader *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  if (header_->value_size != value_size) {
-    GRNXX_ERROR() << "wrong value_size: expected = " << value_size
-                  << ", actual = " << header_->value_size;
-    throw LogicError();
-  }
-  if (header_->page_size != page_size) {
-    GRNXX_ERROR() << "wrong page_size: expected = " << page_size
-                  << ", actual = " << header_->page_size;
-    throw LogicError();
-  }
-  if (header_->has_default_value) {
-    fill_page_ = fill_page;
-  }
-  StorageNode table_node = storage->open_node(header_->table_storage_node_id);
-  table_ = static_cast<uint32_t *>(table_node.body());
-  reserve_pages();
-  size_ = header_->size;
-}
-
-void Array2D::unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size) {
-  Array2D array;
-  array.open(storage, storage_node_id,
-             value_size, page_size, table_size, nullptr);
-  storage->unlink_node(storage_node_id);
-}
-
-void Array2D::reserve_pages() {
-  // Create a table cache.
-  pages_.reset(new (std::nothrow) void *[header_->table_size]);
-  if (!pages_) {
-    GRNXX_ERROR() << "new void *[] failed: size = " << header_->table_size;
-    throw MemoryError();
-  }
-  for (uint64_t i = 0; i < header_->table_size; ++i) {
-    pages_[i] = invalid_page();
-  }
-}
-
-void Array2D::reserve_page(uint64_t page_id) {
-  Lock inter_thread_lock(&mutex_);
-  if (pages_[page_id] == invalid_page()) {
-    StorageNode page_node;
-    if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-      Lock inter_process_lock(&header_->table_mutex);
-      if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-        // Create a page.
-        page_node =
-            storage_->create_node(header_->table_storage_node_id,
-                                  header_->value_size * header_->page_size);
-        if (header_->has_default_value) {
-          fill_page_(page_node.body(), header_->page_size, header_ + 1);
-        }
-        table_[page_id] = page_node.id();
-      }
-    }
-    if (!page_node) {
-      page_node = storage_->open_node(table_[page_id]);
-    }
-    pages_[page_id] = static_cast<char *>(page_node.body())
-        - (header_->value_size * header_->page_size * page_id);
-  }
-}
-
-Array3D::Array3D()
-    : tables_(),
-      size_(0),
-      table_size_(0),
-      secondary_table_size_(0),
-      storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      fill_page_(nullptr),
-      secondary_table_(nullptr),
-      dummy_table_(nullptr),
-      page_mutex_(),
-      table_mutex_() {}
-
-Array3D::~Array3D() {
-  // A destructor must not access a header because it may be already lost.
-  if (tables_) {
-    uint64_t offset = 0;
-    for (uint64_t i = 0; i < secondary_table_size_; ++i) {
-      if (tables_[i] != (dummy_table_ - offset)) {
-        delete [] (tables_[i] + offset);
-      }
-      offset += table_size_;
-    }
-  }
-  if (dummy_table_) {
-    DummyTableManager::get().free_dummy_table(table_size_);
-  }
-}
-
-void Array3D::create(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size, uint64_t size,
-                     const void *default_value, ArrayFillPage fill_page) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  if ((size % (page_size * table_size)) != 0) {
-    const uint64_t adjusted_size =
-        size + (page_size * table_size) - (size % (page_size * table_size));
-    GRNXX_WARNING() << "size adjustment: before = " << size
-                    << ", after = " << adjusted_size
-                    << ", page_size = " << page_size
-                    << ", table_size = " << table_size;
-    size = adjusted_size;
-  }
-  storage_ = storage;
-  uint64_t storage_node_size = sizeof(ArrayHeader);
-  if (default_value) {
-    storage_node_size += value_size;
-  }
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, storage_node_size);
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<ArrayHeader *>(storage_node.body());
-    *header_ = ArrayHeader();
-    header_->value_size = value_size;
-    header_->page_size = page_size;
-    header_->table_size = table_size;
-    header_->secondary_table_size = size / (page_size * table_size);
-    header_->size = size;
-    if (default_value) {
-      header_->has_default_value = 1;
-      std::memcpy(header_ + 1, default_value, value_size);
-      fill_page_ = fill_page;
-    }
-    // Create a secondary table.
-    StorageNode secondary_table_node = storage->create_node(
-        storage_node_id_, sizeof(uint32_t) * header_->secondary_table_size);
-    header_->secondary_table_storage_node_id = secondary_table_node.id();
-    secondary_table_ = static_cast<uint32_t *>(secondary_table_node.body());
-    for (uint64_t i = 0; i < header_->secondary_table_size; ++i) {
-      secondary_table_[i] = STORAGE_INVALID_NODE_ID;
-    }
-    size_ = header_->size;
-    table_size_ = header_->table_size;
-    secondary_table_size_ = header_->secondary_table_size;
-    reserve_tables();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void Array3D::open(Storage *storage, uint32_t storage_node_id,
-                   uint64_t value_size, uint64_t page_size,
-                   uint64_t table_size, ArrayFillPage fill_page) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage = nullptr";
-    throw LogicError();
-  }
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(ArrayHeader)) {
-    GRNXX_ERROR() << "too small header: size = " << storage_node.size();
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<ArrayHeader *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  if (header_->value_size != value_size) {
-    GRNXX_ERROR() << "wrong value_size: expected = " << value_size
-                  << ", actual = " << header_->value_size;
-    throw LogicError();
-  }
-  if (header_->page_size != page_size) {
-    GRNXX_ERROR() << "wrong page_size: expected = " << page_size
-                  << ", actual = " << header_->page_size;
-    throw LogicError();
-  }
-  if (header_->table_size != table_size) {
-    GRNXX_ERROR() << "wrong table_size: expected = " << table_size
-                  << ", actual = " << header_->table_size;
-    throw LogicError();
-  }
-  if (header_->has_default_value) {
-    fill_page_ = fill_page;
-  }
-  StorageNode secondary_table_node =
-      storage->open_node(header_->secondary_table_storage_node_id);
-  secondary_table_ = static_cast<uint32_t *>(secondary_table_node.body());
-  size_ = header_->size;
-  table_size_ = header_->table_size;
-  secondary_table_size_ = header_->secondary_table_size;
-  reserve_tables();
-}
-
-void Array3D::unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size) {
-  Array3D array;
-  array.open(storage, storage_node_id,
-             value_size, page_size, table_size, nullptr);
-  storage->unlink_node(storage_node_id);
-}
-
-void Array3D::reserve_tables() {
-  dummy_table_ = DummyTableManager::get().get_dummy_table(header_->table_size);
-  // Create a secondary table cache.
-  tables_.reset(new (std::nothrow) void **[header_->secondary_table_size]);
-  if (!tables_) {
-    GRNXX_ERROR() << "new void **[] failed: size = "
-                  << header_->secondary_table_size;
-    throw MemoryError();
-  }
-  // Fill the secondary table cache with the dummy table cache.
-  uint64_t offset = 0;
-  for (uint64_t i = 0; i < header_->secondary_table_size; ++i) {
-    tables_[i] = dummy_table_ - offset;
-    offset += header_->table_size;
-  }
-}
-
-void Array3D::reserve_page(uint64_t page_id) {
-  const uint64_t table_id = page_id / header_->table_size;
-  if (tables_[table_id] == (dummy_table_ - (header_->table_size * table_id))) {
-    reserve_table(table_id);
-  }
-  Lock inter_thread_lock(&page_mutex_);
-  if (tables_[table_id][page_id] == invalid_page()) {
-    StorageNode page_node;
-    StorageNode table_node = storage_->open_node(secondary_table_[table_id]);
-    uint32_t * const table = static_cast<uint32_t *>(table_node.body())
-        - (header_->table_size * table_id);
-    if (table[page_id] == STORAGE_INVALID_NODE_ID) {
-      Lock inter_process_lock(&header_->page_mutex);
-      if (table[page_id] == STORAGE_INVALID_NODE_ID) {
-        // Create a page.
-        page_node = storage_->create_node(
-            secondary_table_[table_id],
-            header_->value_size * header_->page_size);
-        if (header_->has_default_value) {
-          fill_page_(page_node.body(), header_->page_size, header_ + 1);
-        }
-        table[page_id] = page_node.id();
-      }
-    }
-    if (!page_node) {
-      page_node = storage_->open_node(table[page_id]);
-    }
-    tables_[table_id][page_id] = static_cast<char *>(page_node.body())
-        - (header_->value_size * header_->page_size * page_id);
-  }
-}
-
-void Array3D::reserve_table(uint64_t table_id) {
-  Lock inter_thread_lock(&table_mutex_);
-  if (tables_[table_id] == (dummy_table_ - (header_->table_size * table_id))) {
-    if (secondary_table_[table_id] == STORAGE_INVALID_NODE_ID) {
-      Lock inter_process_lock(&header_->table_mutex);
-      if (secondary_table_[table_id] == STORAGE_INVALID_NODE_ID) {
-        // Create a table.
-        StorageNode table_node =
-            storage_->create_node(header_->secondary_table_storage_node_id,
-                                  sizeof(uint32_t) * header_->table_size);
-        uint32_t * const table = static_cast<uint32_t *>(table_node.body());
-        for (uint64_t i = 0; i < header_->table_size; ++i) {
-          table[i] = STORAGE_INVALID_NODE_ID;
-        }
-        secondary_table_[table_id] = table_node.id();
-      }
-    }
-    // Create a table cache.
-    void ** const pages = new (std::nothrow) void *[header_->table_size];
-    if (!pages) {
-      GRNXX_ERROR() << "new void *[] failed: size = " << header_->table_size;
-      throw MemoryError();
-    }
-    for (uint64_t i = 0; i < header_->table_size; ++i) {
-      pages[i] = invalid_page();
-    }
-    tables_[table_id] = pages - (header_->table_size * table_id);
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/array_impl.hpp (+0 -424) 100644
===================================================================
--- lib/grnxx/array_impl.hpp    2013-08-23 10:46:34 +0900 (b407bb4)
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ARRAY_IMPL_HPP
-#define GRNXX_ARRAY_IMPL_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/mutex.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-struct ArrayHeader;
-
-// Fill "page" with "value".
-using ArrayFillPage = void (*)(void *page, uint64_t page_size,
-                               const void *value);
-
-class Array1D {
- public:
-  Array1D();
-  ~Array1D();
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t value_size, uint64_t page_size,
-              uint64_t table_size, uint64_t size,
-              const void *default_value, ArrayFillPage fill_page);
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id,
-            uint64_t value_size, uint64_t page_size,
-            uint64_t table_size, ArrayFillPage fill_page);
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return size_;
-  }
-
-  // Return a reference to a value.
-  template <typename T, uint64_t, uint64_t>
-  T &get_value(uint64_t value_id) {
-    return static_cast<T *>(page_)[value_id];
-  }
-
- private:
-  void *page_;
-  uint64_t size_;
-  uint32_t storage_node_id_;
-};
-
-class Array2D {
- public:
-  Array2D();
-  ~Array2D();
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t value_size, uint64_t page_size,
-              uint64_t table_size, uint64_t size,
-              const void *default_value, ArrayFillPage fill_page);
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id,
-            uint64_t value_size, uint64_t page_size,
-            uint64_t table_size, ArrayFillPage fill_page);
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return size_;
-  }
-
-  // Return a reference to a value.
-  template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-  T &get_value(uint64_t value_id) {
-    const uint64_t page_id = value_id / PAGE_SIZE;
-    if (pages_[page_id] == invalid_page()) {
-      reserve_page(page_id);
-    }
-    return static_cast<T *>(pages_[page_id])[value_id];
-  }
-
- private:
-  std::unique_ptr<void *[]> pages_;
-  uint64_t size_;
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  ArrayHeader *header_;
-  ArrayFillPage fill_page_;
-  uint32_t *table_;
-  Mutex mutex_;
-
-  // Initialize "pages_".
-  void reserve_pages();
-  // Open or create a page.
-  void reserve_page(uint64_t page_id);
-
-  // Return a pointer to an invalid page.
-  static void *invalid_page() {
-    return static_cast<char *>(nullptr) - 1;
-  }
-};
-
-class Array3D {
-  using ArrayPageFiller = void (*)(void *page, const void *value);
-
- public:
-  Array3D();
-  ~Array3D();
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t value_size, uint64_t page_size,
-              uint64_t table_size, uint64_t size,
-              const void *default_value, ArrayFillPage fill_page);
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id,
-            uint64_t value_size, uint64_t page_size,
-            uint64_t table_size, ArrayFillPage fill_page);
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size, uint64_t page_size,
-                     uint64_t table_size);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return size_;
-  }
-
-  // Return a reference to a value.
-  template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-  T &get_value(uint64_t value_id) {
-    const uint64_t table_id = value_id / (PAGE_SIZE * TABLE_SIZE);
-    const uint64_t page_id = value_id / PAGE_SIZE;
-    if (tables_[table_id][page_id] == invalid_page()) {
-      reserve_page(page_id);
-    }
-    return static_cast<T *>(tables_[table_id][page_id])[value_id];
-  }
-
-  // Return a pointer to an invalid page.
-  static void *invalid_page() {
-    return static_cast<char *>(nullptr) + 1;
-  }
-
- private:
-  std::unique_ptr<void **[]> tables_;
-  uint64_t size_;
-  uint64_t table_size_;
-  uint64_t secondary_table_size_;
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  ArrayHeader *header_;
-  ArrayFillPage fill_page_;
-  uint32_t *secondary_table_;
-  void **dummy_table_;
-  Mutex page_mutex_;
-  Mutex table_mutex_;
-
-  // Initialize "tables_".
-  void reserve_tables();
-  // Open or create a page.
-  void reserve_page(uint64_t page_id);
-  // Open or create a table.
-  void reserve_table(uint64_t table_id);
-};
-
-template <uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-struct ArrayImplSelector;
-
-// Use Array1D.
-template <>
-struct ArrayImplSelector<0, 0> {
-  using Type = Array1D;
-};
-
-// Use Array2D.
-template <uint64_t PAGE_SIZE>
-struct ArrayImplSelector<PAGE_SIZE, 0> {
-  using Type = Array2D;
-};
-
-// Use Array3D.
-template <uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-struct ArrayImplSelector {
-  using Type = Array3D;
-};
-
-template <typename T>
-struct ArrayPageFiller {
-  // Fill "page" with "value".
-  // This function is used to initialize a page.
-  static void fill_page(void *page, uint64_t page_size, const void *value) {
-    for (uint64_t i = 0; i < page_size; ++i) {
-      static_cast<T *>(page)[i] = *static_cast<const T *>(value);
-    }
-  }
-};
-
-template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-class ArrayImpl {
-  // Test template parameters.
-  static_assert((PAGE_SIZE != 0) || (TABLE_SIZE == 0),
-                "TABLE_SIZE must be zero if PAGE_SIZE is zero");
-  static_assert((PAGE_SIZE & (PAGE_SIZE - 1)) == 0,
-                "PAGE_SIZE must be zero or a power of two");
-  static_assert((TABLE_SIZE & (TABLE_SIZE - 1)) == 0,
-                "TABLE_SIZE must be zero or a power of two");
-
-  using Impl = typename ArrayImplSelector<PAGE_SIZE, TABLE_SIZE>::Type;
-
- public:
-  using Value    = typename Traits<T>::Type;
-  using ValueArg = typename Traits<T>::ArgumentType;
-  using ValueRef = Value &;
-  using Unit     = Value;
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id, uint64_t size) {
-    impl_.create(storage, storage_node_id,
-                 sizeof(Value), PAGE_SIZE, TABLE_SIZE, size,
-                 nullptr, ArrayPageFiller<Value>::fill_page);
-  }
-  // Create an array with the default value.
-  void create(Storage *storage, uint32_t storage_node_id, uint64_t size,
-              ValueArg default_value) {
-    impl_.create(storage, storage_node_id,
-                 sizeof(Value), PAGE_SIZE, TABLE_SIZE, size,
-                 &default_value, ArrayPageFiller<Value>::fill_page);
-  }
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id) {
-    impl_.open(storage, storage_node_id,
-               sizeof(Value), PAGE_SIZE, TABLE_SIZE,
-               ArrayPageFiller<Value>::fill_page);
-  }
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id) {
-    Impl::unlink(storage, storage_node_id,
-                 sizeof(Value), PAGE_SIZE, TABLE_SIZE);
-  }
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return impl_.storage_node_id();
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return impl_.size();
-  }
-
-  // Return a reference to a value.
-  ValueRef get_value(uint64_t value_id) {
-    return impl_. template get_value<Value, PAGE_SIZE, TABLE_SIZE>(value_id);
-  }
-  // Return a reference to a unit.
-  Unit &get_unit(uint64_t unit_id) {
-    return get_value(unit_id);
-  }
-
- private:
-  Impl impl_;
-};
-
-// A reference to a bit.
-class ArrayBitRef {
- public:
-  using Unit = uint64_t;
-
-  // Create a reference to a bit.
-  ArrayBitRef(Unit &unit, Unit mask) : unit_(unit), mask_(mask) {}
-
-  // Get a bit.
-  operator bool() const {
-    return (unit_ & mask_) != 0;
-  }
-
-  // Set a bit.
-  ArrayBitRef &operator=(bool value) {
-    if (value) {
-      unit_ |= mask_;
-    } else {
-      unit_ &= ~mask_;
-    }
-    return *this;
-  }
-
-  // Copy a bit.
-  ArrayBitRef &operator=(const ArrayBitRef &rhs) {
-    return *this = bool(rhs);
-  }
-
-  // Compare bits.
-  bool operator==(bool rhs) const {
-    return bool(*this) == rhs;
-  }
-  bool operator!=(bool rhs) const {
-    return bool(*this) != rhs;
-  }
-
- private:
-  Unit &unit_;
-  Unit mask_;
-};
-
-// An array of bits.
-template <uint64_t PAGE_SIZE_IN_BITS, uint64_t TABLE_SIZE>
-class ArrayImpl<bool, PAGE_SIZE_IN_BITS, TABLE_SIZE> {
-  static constexpr uint64_t UNIT_SIZE = sizeof(ArrayBitRef::Unit) * 8;
-  static constexpr uint64_t PAGE_SIZE = PAGE_SIZE_IN_BITS / UNIT_SIZE;
-
-  // Test template parameters.
-  static_assert((PAGE_SIZE_IN_BITS % UNIT_SIZE) == 0,
-                "(PAGE_SIZE_IN_BITS % UNIT_SIZE) != 0");
-  static_assert((PAGE_SIZE != 0) || (TABLE_SIZE == 0),
-                "TABLE_SIZE must be zero if PAGE_SIZE is zero");
-  static_assert((PAGE_SIZE & (PAGE_SIZE - 1)) == 0,
-                "PAGE_SIZE must be zero or a power of two");
-  static_assert((TABLE_SIZE & (TABLE_SIZE - 1)) == 0,
-                "TABLE_SIZE must be zero or a power of two");
-
-  using Impl = typename ArrayImplSelector<PAGE_SIZE, TABLE_SIZE>::Type;
-
- public:
-  using Value    = typename Traits<bool>::Type;
-  using ValueArg = typename Traits<bool>::ArgumentType;
-  using ValueRef = ArrayBitRef;
-  using Unit     = ArrayBitRef::Unit;
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id, uint64_t size) {
-    impl_.create(storage, storage_node_id,
-                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE, size / UNIT_SIZE,
-                 nullptr, ArrayPageFiller<Unit>::fill_page);
-  }
-  // Create an array with the default value.
-  void create(Storage *storage, uint32_t storage_node_id, uint64_t size,
-              ValueArg default_value) {
-    const Unit default_unit = default_value ? ~(Unit)0 : (Unit)0;
-    impl_.create(storage, storage_node_id,
-                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE, size / UNIT_SIZE,
-                 &default_unit, ArrayPageFiller<Unit>::fill_page);
-  }
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id) {
-    impl_.open(storage, storage_node_id,
-               sizeof(Unit), PAGE_SIZE, TABLE_SIZE,
-               ArrayPageFiller<Unit>::fill_page);
-  }
-
-  // Unlink an array.
-  static void unlink(Storage *storage, uint32_t storage_node_id) {
-    Impl::unlink(storage, storage_node_id,
-                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE);
-  }
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return impl_.storage_node_id();
-  }
-  // Return the number of values.
-  uint64_t size() const {
-    return impl_.size() * UNIT_SIZE;
-  }
-
-  // Return a reference to a value.
-  ValueRef get_value(uint64_t value_id) {
-    return ValueRef(get_unit(value_id / UNIT_SIZE),
-                    Unit(1) << (value_id % UNIT_SIZE));
-  }
-  // Return a reference to a unit.
-  Unit &get_unit(uint64_t unit_id) {
-    return impl_. template get_value<Unit, PAGE_SIZE, TABLE_SIZE>(unit_id);
-  }
-
- private:
-  Impl impl_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_ARRAY_IMPL_HPP

  Deleted: lib/grnxx/backtrace.cpp (+0 -421) 100644
===================================================================
--- lib/grnxx/backtrace.cpp    2013-08-23 10:46:34 +0900 (361a154)
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "grnxx/backtrace.hpp"
-
-#include "../config.h"
-
-#ifdef HAVE_BACKTRACE
-
-#include <cxxabi.h>
-#include <dlfcn.h>
-#include <execinfo.h>
-
-#ifdef HAVE_LIBBFD
-# include <bfd.h>
-# ifdef GRNXX_APPLE
-#  include <mach-o/dyld.h>
-# else  // GRNXX_APPLE
-#  include <link.h>
-# endif  // GRNXX_APPLE
-#endif  // HAVE_LIBBFD
-
-#include <cstdlib>
-#include <cstring>
-#include <sstream>
-
-#include "grnxx/lock.hpp"
-#include "grnxx/mutex.hpp"
-
-namespace grnxx {
-namespace {
-
-class Resolver {
- public:
-  static bool resolve(void *address, std::ostream *stream);
-
- private:
-#ifdef HAVE_LIBBFD
-  bfd *bfd_;
-  asymbol **bfd_symbols_;
-
-  static bool bfd_initialized_;
-#endif  // HAVE_LIBBFD
-
-  Resolver();
-  ~Resolver();
-
-#ifdef HAVE_LIBBFD
-  bool resolve_(const char *image_name, bfd_vma address, std::ostream *stream);
-#endif  // HAVE_LIBBFD
-
-  Resolver(const Resolver &);
-  Resolver &operator=(const Resolver &);
-};
-
-#ifdef HAVE_LIBBFD
-struct Match {
-  const char *image_name;
-  uintptr_t address;
-};
-
-// FIXME: The default image name depends on the environment.
-// http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
-const char DEFAULT_IMAGE_NAME[] = "/proc/self/exe";
-
-# ifdef GRNXX_APPLE
-// TODO: Not tested yet.
-bool find_match(Match *match) {
-  const uint32_t image_count = ::_dyld_image_count();
-  for (uint32_t image_id = 0; image_id < image_count; ++image_id) {
-    const struct mach_header *header = ::_dyld_get_image_header(image_id);
-    const struct load_command *command;
-    if (header->magic == MH_MAGIC_64) {
-      command = reinterpret_cast<const struct load_command *>(
-          reinterpret_cast<const struct mach_header_64 *>(header) + 1);
-    } else {
-      command = reinterpret_cast<const struct load_command *>(header + 1);
-    }
-
-    const intptr_t slide = ::_dyld_get_image_vmaddr_slide(image_id);
-    for (uint32_t command_id = 0; command_id < header->ncmds; ++command_id) {
-      switch (command->cmd) {
-        case LC_SEGMENT: {
-          const struct segment_command *segment =
-              reinterpret_cast<const struct segment_command *>(command);
-          if ((address >= (segment->vmaddr + slide)) &&
-              (address < (segment->vmaddr + slide + segment->vmsize))) {
-            match.address = segment->vmaddr - slide;
-            match.image_name = ::_dyld_get_image_name(image_id);
-            return true;
-          }
-          break;
-        }
-        case LC_SEGMENT_64: {
-          const struct segment_command_64 *segment =
-              reinterpret_cast<const struct segment_command_64 *>(command);
-          if ((address >= (segment->vmaddr + slide)) &&
-              (address < (segment->vmaddr + slide + segment->vmsize))) {
-            match.address = segment->vmaddr - slide;
-            match.image_name = ::_dyld_get_image_name(i);
-            return true;
-          }
-          break;
-        }
-      }
-      command = reinterpret_cast<const struct load_command *>(
-          reinterpret_cast<const char *>(command) + cmd->cmdsize);
-    }
-  }
-  return false;
-}
-# else  // GRNXX_APPLE
-int find_match_callback(struct dl_phdr_info *info, size_t, void *user_data) {
-  Match * const match = static_cast<Match *>(user_data);
-  for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
-    if (info->dlpi_phdr[i].p_type == PT_LOAD) {
-      ElfW(Addr) address = info->dlpi_phdr[i].p_vaddr + info->dlpi_addr;
-      if ((match->address >= address) &&
-          (match->address < (address + info->dlpi_phdr[i].p_memsz))) {
-        if (!info->dlpi_name || (info->dlpi_name[0] == '\0')) {
-          match->image_name = DEFAULT_IMAGE_NAME;
-        } else {
-          match->image_name = info->dlpi_name;
-        }
-        match->address -= (uintptr_t)info->dlpi_addr;
-        return 1;
-      }
-    }
-  }
-  return 0;
-}
-
-bool find_match(Match *match) {
-  return dl_iterate_phdr(find_match_callback, match) != 0;
-}
-# endif  // GRNXX_APPLE
-
-bool Resolver::bfd_initialized_ = false;
-
-bool Resolver::resolve(void *address, std::ostream *stream) {
-  // Just to be safe, call ::bfd_init() only once.
-  if (!bfd_initialized_) {
-    ::bfd_init();
-    bfd_initialized_ = true;
-  }
-
-  Match match;
-  match.address = reinterpret_cast<uintptr_t>(address) - 1;
-  if (find_match(&match)) {
-    *stream << address;
-    return Resolver().resolve_(match.image_name,
-                               static_cast<bfd_vma>(match.address), stream);
-  }
-  return false;
-}
-
-class Detail {
- public:
-  Detail(asymbol **symbols_, bfd_vma address_)
-      : symbols(symbols_),
-        address(address_),
-        filename(nullptr),
-        function(nullptr),
-        line(0),
-        found(false) {}
-
-  asymbol **symbols;
-  bfd_vma address;
-  const char *filename;
-  const char *function;
-  unsigned int line;
-  bool found;
-};
-
-void callback_for_each_section(bfd *bfd_, asection *section, void *user_data) {
-  Detail * const detail = static_cast<Detail *>(user_data);
-  if (detail->found) {
-    return;
-  }
-
-  if ((bfd_get_section_flags(bfd_, section) & SEC_ALLOC) == 0) {
-    return;
-  }
-
-  bfd_vma address = bfd_get_section_vma(bfd_, section);
-  if (detail->address < address) {
-    return;
-  }
-
-  bfd_size_type size = bfd_section_size(bfd_, section);
-  if (detail->address >= (address + size)) {
-    return;
-  }
-
-  if (bfd_find_nearest_line(bfd_, section, detail->symbols,
-                            detail->address - address, &detail->filename,
-                            &detail->function, &detail->line) != 0) {
-    detail->found = true;
-  }
-}
-
-Resolver::Resolver() : bfd_(nullptr), bfd_symbols_(nullptr) {}
-
-Resolver::~Resolver() {
-  if (bfd_symbols_) {
-    std::free(bfd_symbols_);
-  }
-  if (bfd_) {
-    ::bfd_close(bfd_);
-  }
-}
-
-bool Resolver::resolve_(const char *image_name, bfd_vma address,
-                        std::ostream *stream) {
-  bfd_ = ::bfd_openr(image_name, nullptr);
-  if (!bfd_) {
-    return false;
-  }
-
-  if (::bfd_check_format(bfd_, ::bfd_archive)) {
-    return false;
-  }
-
-  char **matches = nullptr;
-  if (!::bfd_check_format_matches(bfd_, ::bfd_object, &matches)) {
-    if (::bfd_get_error() == ::bfd_error_file_ambiguously_recognized) {
-      std::free(matches);
-    }
-    return false;
-  }
-
-  if ((bfd_get_file_flags(bfd_) & HAS_SYMS) == 0) {
-    return false;
-  }
-
-  unsigned int size = 0;
-  long num_symbols = bfd_read_minisymbols(bfd_, false,
-                                          (void **)&bfd_symbols_, &size);
-  if (num_symbols == 0) {
-    std::free(bfd_symbols_);
-    bfd_symbols_ = nullptr;
-    num_symbols = bfd_read_minisymbols(bfd_, true,
-                                       (void**)&bfd_symbols_, &size);
-  }
-  if (num_symbols <= 0) {
-    return false;
-  }
-
-  Detail detail(bfd_symbols_, address);
-  ::bfd_map_over_sections(bfd_, callback_for_each_section, &detail);
-  if (!detail.found) {
-    return false;
-  }
-
-  *stream << ": ";
-  if (!detail.function || (detail.function[0] == '\0')) {
-    *stream << "???";
-  } else {
-    int status = 0;
-    char *demangled_function =
-        ::abi::__cxa_demangle(detail.function, 0, 0, &status);
-    if (demangled_function) {
-      *stream << demangled_function;
-      std::free(demangled_function);
-    } else {
-      *stream << detail.function;
-    }
-  }
-
-  *stream << " (";
-  if (!detail.filename || (detail.filename[0] == '\0') || (detail.line == 0)) {
-    *stream << "???:???";
-  } else {
-    *stream << ::basename(detail.filename) << ':' << detail.line;
-  }
-
-  if (std::strcmp(image_name, DEFAULT_IMAGE_NAME) != 0) {
-    *stream << " in " << image_name;
-  }
-  *stream << ')';
-
-//  bfd_find_inliner_info(bfd_, &detail.filename, &detail.function,
-//                        &detail.line);
-
-  return true;
-}
-#else  // HAVE_LIBBFD
-bool Resolver::resolve(void *, std::ostream *) {
-  return false;
-}
-#endif  // HAVE_LIBBFD
-
-}  // namespace
-
-bool Backtrace::backtrace(int skip_count, std::vector<void *> *addresses) try {
-  static Mutex mutex;
-  Lock lock(&mutex);
-
-  if ((skip_count < BACKTRACE_MIN_SKIP_COUNT) ||
-      (skip_count > BACKTRACE_MAX_SKIP_COUNT)) {
-    return false;
-  }
-  if (!addresses) {
-    return false;
-  }
-  ++skip_count;
-
-  std::vector<void *> buf(BACKTRACE_MIN_BUF_SIZE);
-  for ( ; ; ) {
-    const int depth = ::backtrace(&buf[0], static_cast<int>(buf.size()));
-    if (depth < static_cast<int>(buf.size())) {
-      if (depth <= skip_count) {
-        return false;
-      }
-      buf.resize(depth);
-      break;
-    }
-    if (buf.size() >= BACKTRACE_MAX_BUF_SIZE) {
-      break;
-    }
-    buf.resize(buf.size() * 2);
-  }
-  addresses->assign(buf.begin() + skip_count, buf.end());
-  return true;
-} catch (...) {
-  return false;
-}
-
-bool Backtrace::resolve(void *address, std::string *entry) try {
-  static Mutex mutex;
-  Lock lock(&mutex);
-
-  if (!address || !entry) {
-    return false;
-  }
-
-  std::ostringstream stream;
-  if (Resolver::resolve(address, &stream)) {
-    entry->assign(stream.str());
-    return true;
-  }
-
-  char **symbols = ::backtrace_symbols(&address, 1);
-  if (!symbols) {
-    return false;
-  }
-  char *first_symbol = symbols[0];
-  std::free(symbols);
-  if (!first_symbol) {
-    return false;
-  }
-  entry->append(first_symbol);
-  return true;
-} catch (...) {
-  return false;
-}
-
-bool Backtrace::pretty_backtrace(int skip_count,
-                                 std::vector<std::string> *entries) try {
-  if ((skip_count < BACKTRACE_MIN_SKIP_COUNT) ||
-      (skip_count > BACKTRACE_MAX_SKIP_COUNT)) {
-    return false;
-  }
-  if (!entries) {
-    return false;
-  }
-  ++skip_count;
-
-  std::vector<void *> addresses;
-  if (!backtrace(skip_count, &addresses)) {
-    return false;
-  }
-
-  entries->clear();
-  for (std::size_t i = 0; i < addresses.size(); ++i) {
-    std::string entry;
-    if (resolve(addresses[i], &entry)) {
-      entry.insert(0, (i == 0) ? "at " : "by ", 3);
-      entries->push_back(entry);
-    }
-  }
-  return true;
-} catch (...) {
-  return false;
-}
-
-}  // namespace grnxx
-
-#else  // HAVE_BACKTRACE
-
-namespace grnxx {
-
-bool Backtrace::backtrace(int, std::vector<void *> *) {
-  return false;
-}
-
-bool Backtrace::resolve(void *, std::string *) {
-  return false;
-}
-
-bool Backtrace::pretty_backtrace(int, std::vector<std::string> *) {
-  return false;
-}
-
-}  // namespace grnxx
-
-#endif  // HAVE_BACKTRACE

  Deleted: lib/grnxx/backtrace.hpp (+0 -56) 100644
===================================================================
--- lib/grnxx/backtrace.hpp    2013-08-23 10:46:34 +0900 (2707b03)
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_BACKTRACE_HPP
-#define GRNXX_BACKTRACE_HPP
-
-#include "grnxx/features.hpp"
-
-#include <string>
-#include <vector>
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-constexpr int BACKTRACE_MIN_SKIP_COUNT = 0;
-constexpr int BACKTRACE_MAX_SKIP_COUNT = 16;
-
-constexpr size_t BACKTRACE_MIN_BUF_SIZE = 16;
-constexpr size_t BACKTRACE_MAX_BUF_SIZE = 1024;
-
-class Backtrace {
- public:
-  // The following functions return true on success, false on failure.
-
-  // backtrace() writes a list of addresses to function calls into 'addresses'.
-  // 'skip_count' specfies the number of function calls to be skipped.
-  static bool backtrace(int skip_count, std::vector<void *> *addresses);
-
-  // resolve() writes a function call referred to by 'address' in
-  // human-readable format into 'entry'.
-  static bool resolve(void *address, std::string *entry);
-
-  // pretty_backtrace() writes a list of function calls in human-readable
-  // format. 'skip_count' specfies the number of function calls to be skipped.
-  static bool pretty_backtrace(int skip_count,
-                               std::vector<std::string> *entries);
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_BACKTRACE_HPP

  Deleted: lib/grnxx/broken_down_time.cpp (+0 -39) 100644
===================================================================
--- lib/grnxx/broken_down_time.cpp    2013-08-23 10:46:34 +0900 (14fad5c)
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-  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/broken_down_time.hpp"
-
-#include "grnxx/string_builder.hpp"
-#include "grnxx/string_format.hpp"
-
-namespace grnxx {
-
-StringBuilder &operator<<(StringBuilder &builder, const BrokenDownTime &time) {
-  if (!builder) {
-    return builder;
-  }
-  builder << (1900 + time.year) << '-'
-          << StringFormat::align_right(time.mon + 1, 2, '0') << '-'
-          << StringFormat::align_right(time.mday, 2, '0') << ' '
-          << StringFormat::align_right(time.hour, 2, '0') << ':'
-          << StringFormat::align_right(time.min, 2, '0') << ':'
-          << StringFormat::align_right(time.sec, 2, '0') << '.'
-          << StringFormat::align_right(time.usec, 6, '0');
-  return builder;
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/broken_down_time.hpp (+0 -48) 100644
===================================================================
--- lib/grnxx/broken_down_time.hpp    2013-08-23 10:46:34 +0900 (7ec2275)
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_BROKEN_DOWN_TIME_HPP
-#define GRNXX_BROKEN_DOWN_TIME_HPP
-
-#include "grnxx/features.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-struct BrokenDownTime {
-  int usec;   // Microseconds.
-  int sec;    // Seconds.
-  int min;    // Minutes.
-  int hour;   // Hours.
-  int mday;   // Day of the month.
-  int mon;    // Month.
-  int year;   // Year.
-  int wday;   // Day of the week.
-  int yday;   // Day in the year.
-  int isdst;  // Daylight saving time.
-
-  static constexpr BrokenDownTime invalid_value() {
-    return BrokenDownTime{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-  }
-};
-
-StringBuilder &operator<<(StringBuilder &builder, const BrokenDownTime &time);
-
-}  // namespace grnxx
-
-#endif  // GRNXX_BROKEN_DOWN_TIME_HPP

  Deleted: lib/grnxx/bytes.hpp (+0 -168) 100644
===================================================================
--- lib/grnxx/bytes.hpp    2013-08-23 10:46:34 +0900 (26c267c)
+++ /dev/null
@@ -1,168 +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_BYTES_HPP
-#define GRNXX_BYTES_HPP
-
-#include "grnxx/features.hpp"
-
-#include <cstring>
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-// A reference to a sequence of bytes.
-class Bytes {
- public:
-  // Trivial default constructor.
-  Bytes() = default;
-  // Create a reference to an empty (zero-size) sequence.
-  Bytes(nullptr_t) : data_(nullptr), size_(0) {}
-  // Create a reference to a zero-terminated string.
-  Bytes(const char *str)
-      : data_(reinterpret_cast<const uint8_t *>(str)),
-        size_(std::strlen(str)) {}
-  // Create a reference to a sequence of bytes.
-  Bytes(const void *data, uint64_t size)
-      : data_(static_cast<const uint8_t *>(data)),
-        size_(size) {}
-
-  // Return true iff the sequence is not empty.
-  explicit operator bool() const {
-    return size_ != 0;
-  }
-
-  // Skip the first "n" bytes and extract the subsequent "m" bytes.
-  Bytes extract(uint64_t n, uint64_t m) const {
-    return Bytes(data_ + n, m);
-  }
-  // Remove the first "n" bytes and the last "m" bytes.
-  Bytes trim(uint64_t n, uint64_t m) const {
-    return Bytes(data_ + n, size_ - n - m);
-  }
-
-  // Extract the first "n" bytes.
-  Bytes prefix(uint64_t n) const {
-    return Bytes(data_, n);
-  }
-  // Extract the last "n" bytes.
-  Bytes suffix(uint64_t n) const {
-    return Bytes(data_ + size_ - n, n);
-  }
-
-  // Remove the first "n" bytes.
-  Bytes except_prefix(uint64_t n) const {
-    return Bytes(data_ + n, size_ - n);
-  }
-  // Remove the last "n" bytes.
-  Bytes except_suffix(uint64_t n) const {
-    return Bytes(data_, size_ - n);
-  }
-
-  // Return true iff "*this" == "rhs".
-  bool operator==(const Bytes &rhs) const {
-    return (size_ == rhs.size_) && (std::memcmp(data_, rhs.data_, size_) == 0);
-  }
-  // Return true iff "*this" != "rhs".
-  bool operator!=(const Bytes &rhs) const {
-    return !operator==(rhs);
-  }
-  // Return true iff "*this" < "rhs".
-  bool operator<(const Bytes &rhs) const {
-    const uint64_t min_size = (size_ < rhs.size_) ? size_ : rhs.size_;
-    int result = std::memcmp(data_, rhs.data_, min_size);
-    return (result < 0) || ((result == 0) && (size_ < rhs.size_));
-  }
-  // Return true iff "*this" > "rhs".
-  bool operator>(const Bytes &rhs) const {
-    return rhs.operator<(*this);
-  }
-  // Return true iff "*this" <= "rhs".
-  bool operator<=(const Bytes &rhs) const {
-    return !operator>(rhs);
-  }
-  // Return true iff "*this" >= "rhs".
-  bool operator>=(const Bytes &rhs) const {
-    return !operator<(rhs);
-  }
-
-  // Compare "*this" and "bytes" and return a negative value
-  // if "*this" < "bytes", zero if "*this" == "bytes", or a positive value
-  // otherwise (if "*this" > "bytes").
-  int compare(const Bytes &bytes) const {
-    const uint64_t min_size = (size_ < bytes.size_) ? size_ : bytes.size_;
-    int result = std::memcmp(data_, bytes.data_, min_size);
-    if (result != 0) {
-      return result;
-    }
-    return (size_ < bytes.size_) ? -1 : (size_ > bytes.size_);
-  }
-
-  // Return true iff "bytes" is a prefix of "*this".
-  bool starts_with(const Bytes &bytes) const {
-    return (size_ >= bytes.size_) && (prefix(bytes.size_) == bytes);
-  }
-  // Return true iff "bytes" is a suffix of "*this".
-  bool ends_with(const Bytes &bytes) const {
-    return (size_ >= bytes.size_) && (suffix(bytes.size_) == bytes);
-  }
-
-  // Return the "i"-th byte.
-  uint8_t operator[](uint64_t i) const {
-    return data_[i];
-  }
-  // Return the starting address.
-  const void *address() const {
-    return data_;
-  }
-  // Return a pointer to the sequence.
-  const uint8_t *data() const {
-    return data_;
-  }
-  // Return the number of bytes.
-  uint64_t size() const {
-    return size_;
-  }
-
- private:
-  const uint8_t *data_;
-  uint64_t size_;
-};
-
-inline bool operator==(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) == rhs;
-}
-inline bool operator!=(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) != rhs;
-}
-inline bool operator<(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) < rhs;
-}
-inline bool operator>(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) > rhs;
-}
-inline bool operator<=(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) <= rhs;
-}
-inline bool operator>=(const char *lhs, const Bytes &rhs) {
-  return Bytes(lhs) >= rhs;
-}
-
-}  // namespace grnxx
-
-#endif  // GRNXX_BYTES_HPP

  Deleted: lib/grnxx/charset.cpp (+0 -68) 100644
===================================================================
--- lib/grnxx/charset.cpp    2013-08-23 10:46:34 +0900 (f7653be)
+++ /dev/null
@@ -1,68 +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 "grnxx/charset.hpp"
-
-#include "grnxx/charset/euc-jp.hpp"
-#include "grnxx/charset/shift_jis.hpp"
-#include "grnxx/charset/utf-8.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-
-StringBuilder &operator<<(StringBuilder &builder, CharsetCode code) {
-  switch (code) {
-    case CHARSET_SHIFT_JIS: {
-      return builder << "Shift_JIS";
-    }
-    case CHARSET_EUC_JP: {
-      return builder << "EUC-JP";
-    }
-    case CHARSET_UTF_8: {
-      return builder << "UTF-8";
-    }
-    case CHARSET_UNKNOWN: {
-      break;
-    }
-  }
-  return builder << "n/a";
-}
-
-Charset::Charset() {}
-Charset::~Charset() {}
-
-const Charset *Charset::get(CharsetCode code) {
-  switch (code) {
-    case CHARSET_SHIFT_JIS: {
-      return charset::Shift_JIS::get();
-    }
-    case CHARSET_EUC_JP: {
-      return charset::EUC_JP::get();
-    }
-    case CHARSET_UTF_8: {
-      return charset::UTF_8::get();
-    }
-    default: {
-      GRNXX_ERROR() << "invalid argument: code = " << code;
-      throw LogicError();
-    }
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/charset.hpp (+0 -62) 100644
===================================================================
--- lib/grnxx/charset.hpp    2013-08-23 10:46:34 +0900 (aa67228)
+++ /dev/null
@@ -1,62 +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_CHARSET_HPP
-#define GRNXX_CHARSET_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-// The values correspond to MIB enum numbers.
-// Reference: http://www.iana.org/assignments/character-sets/character-sets.xml
-enum CharsetCode : uint16_t {
-  CHARSET_SHIFT_JIS = 17,
-  CHARSET_EUC_JP    = 18,
-  CHARSET_UTF_8     = 106,
-  CHARSET_UNKNOWN   = 65535
-};
-
-StringBuilder &operator<<(StringBuilder &builder, CharsetCode code);
-
-class Charset {
- public:
-  Charset();
-  virtual ~Charset();
-
-  // Return a reference to a specific charset.
-  static const Charset *get(CharsetCode code);
-
-  // Return the charset code.
-  virtual CharsetCode code() const = 0;
-
-  // Return the first character of "bytes". This function may return an empty
-  // sequence if "bytes" is empty or an invalid sequence.
-  virtual Bytes get_char(const Bytes &bytes) const = 0;
-  // Return the size of the first character of "bytes". This function may
-  // return 0 if "bytes" is empty or an invalid sequence.
-  virtual size_t get_char_size(const Bytes &bytes) const = 0;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_CHARSET_HPP

  Deleted: lib/grnxx/charset/Makefile.am (+0 -14) 100644
===================================================================
--- lib/grnxx/charset/Makefile.am    2013-08-23 10:46:34 +0900 (25db000)
+++ /dev/null
@@ -1,14 +0,0 @@
-noinst_LTLIBRARIES = libgrnxx_charset.la
-
-libgrnxx_charset_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_charset_la_SOURCES =		\
-	euc-jp.cpp			\
-	shift_jis.cpp			\
-	utf-8.cpp
-
-libgrnxx_charset_includedir = ${includedir}/grnxx/charset
-libgrnxx_charset_include_HEADERS =	\
-	euc-jp.hpp			\
-	shift_jis.hpp			\
-	utf-8.hpp

  Deleted: lib/grnxx/charset/euc-jp.cpp (+0 -80) 100644
===================================================================
--- lib/grnxx/charset/euc-jp.cpp    2013-08-23 10:46:34 +0900 (ea4f287)
+++ /dev/null
@@ -1,80 +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 "grnxx/charset/euc-jp.hpp"
-
-namespace grnxx {
-namespace charset {
-
-const Charset *EUC_JP::get() {
-  static EUC_JP singleton;
-  return &singleton;
-}
-
-CharsetCode EUC_JP::code() const {
-  return CHARSET_EUC_JP;
-}
-
-Bytes EUC_JP::get_char(const Bytes &bytes) const {
-  return bytes.prefix(get_char_size(bytes));
-}
-
-size_t EUC_JP::get_char_size(const Bytes &bytes) const {
-  if (!bytes) {
-    return 0;
-  }
-  // Reference: http://ja.wikipedia.org/wiki/EUC-JP
-  if (bytes[0] & 0x80) {
-    // A 3-byte character starts with 0x8F.
-    if (bytes[0] == 0x8F) {
-      // Return 0 if the character is incomplete.
-      if (bytes.size() < 3) {
-        return 0;
-      }
-      // Return 0 if the 2nd byte is invalid.
-      // In fact, only bytes in [A1, A8], [B0, ED], and [F3, FE] are valid.
-      if (static_cast<unsigned>(bytes[1] - 0xA1) > (0xFE - 0xA1)) {
-        return 0;
-      }
-      // Return 0 if the 3rd byte is invalid.
-      if (static_cast<unsigned>(bytes[2] - 0xA1) > (0xFE - 0xA1)) {
-        return 0;
-      }
-      return 3;
-    } else {
-      // Return 0 if the 1st byte is invalid.
-      // In fact, only bytes in [A1, A8], [AD, AD], and [B0, FE] are valid.
-      if (static_cast<unsigned>(bytes[0] - 0xA1) > (0xFE - 0xA1)) {
-        return 0;
-      }
-      // Return 0 if the character is incomplete.
-      if (bytes.size() < 2) {
-        return 0;
-      }
-      // Return 0 if the 2nd byte is invalid.
-      if (static_cast<unsigned>(bytes[1] - 0xA1) > (0xFE - 0xA1)) {
-        return 0;
-      }
-      return 2;
-    }
-  }
-  // Return 1 for an ASCII character.
-  return 1;
-}
-
-}  // namespace charset
-}  // namespace grnxx

  Deleted: lib/grnxx/charset/euc-jp.hpp (+0 -43) 100644
===================================================================
--- lib/grnxx/charset/euc-jp.hpp    2013-08-23 10:46:34 +0900 (a997cd6)
+++ /dev/null
@@ -1,43 +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_CHARSET_EUC_JP_HPP
-#define GRNXX_CHARSET_EUC_JP_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/charset.hpp"
-
-namespace grnxx {
-namespace charset {
-
-// EUC-JP: Extended_UNIX_Code_Packed_Format_for_Japanese.
-class EUC_JP : public Charset {
- public:
-  static const Charset *get();
-
-  CharsetCode code() const;
-
-  Bytes get_char(const Bytes &bytes) const;
-  size_t get_char_size(const Bytes &bytes) const;
-};
-
-}  // namespace charset
-}  // namespace grnxx
-
-#endif  // GRNXX_CHARSET_EUC_JP_HPP

  Deleted: lib/grnxx/charset/shift_jis.cpp (+0 -58) 100644
===================================================================
--- lib/grnxx/charset/shift_jis.cpp    2013-08-23 10:46:34 +0900 (3e57265)
+++ /dev/null
@@ -1,58 +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 "grnxx/charset/shift_jis.hpp"
-
-namespace grnxx {
-namespace charset {
-
-const Charset *Shift_JIS::get() {
-  static Shift_JIS singleton;
-  return &singleton;
-}
-
-CharsetCode Shift_JIS::code() const {
-  return CHARSET_SHIFT_JIS;
-}
-
-Bytes Shift_JIS::get_char(const Bytes &bytes) const {
-  return bytes.prefix(get_char_size(bytes));
-}
-
-size_t Shift_JIS::get_char_size(const Bytes &bytes) const {
-  if (!bytes) {
-    return 0;
-  }
-  // The 1st byte of a multibyte character is in [81, 9F] or [E0, FC].
-  // Reference: http://www.st.rim.or.jp/~phinloda/cqa/cqa15.html#Q4
-  if (static_cast<unsigned>((bytes[0] ^ 0x20) - 0xA1) < 0x3C) {
-    // Return 0 if the character is incomplete.
-    if (bytes.size() < 2) {
-      return 0;
-    }
-    // Return 0 if the 2nd byte is invalid.
-    if (static_cast<unsigned>(bytes[1] - 0x40) > (0xFC - 0x40)) {
-      return 0;
-    }
-    return 2;
-  }
-  // Return 1 for an ASCII character.
-  return 1;
-}
-
-}  // namespace charset
-}  // namespace grnxx

  Deleted: lib/grnxx/charset/shift_jis.hpp (+0 -43) 100644
===================================================================
--- lib/grnxx/charset/shift_jis.hpp    2013-08-23 10:46:34 +0900 (910d6c3)
+++ /dev/null
@@ -1,43 +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_CHARSET_SHIFT_JIS_HPP
-#define GRNXX_CHARSET_SHIFT_JIS_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/charset.hpp"
-
-namespace grnxx {
-namespace charset {
-
-// Shift_JIS.
-class Shift_JIS : public Charset {
- public:
-  static const Charset *get();
-
-  CharsetCode code() const;
-
-  Bytes get_char(const Bytes &bytes) const;
-  size_t get_char_size(const Bytes &bytes) const;
-};
-
-}  // namespace charset
-}  // namespace grnxx
-
-#endif  // GRNXX_CHARSET_SHIFT_JIS_HPP

  Deleted: lib/grnxx/charset/utf-8.cpp (+0 -84) 100644
===================================================================
--- lib/grnxx/charset/utf-8.cpp    2013-08-23 10:46:34 +0900 (a833f2e)
+++ /dev/null
@@ -1,84 +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 "grnxx/charset/utf-8.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/intrinsic.hpp"
-
-namespace grnxx {
-namespace charset {
-
-const Charset *UTF_8::get() {
-  static UTF_8 singleton;
-  return &singleton;
-}
-
-CharsetCode UTF_8::code() const {
-  return CHARSET_UTF_8;
-}
-
-Bytes UTF_8::get_char(const Bytes &bytes) const {
-  return bytes.prefix(get_char_size(bytes));
-}
-
-size_t UTF_8::get_char_size(const Bytes &bytes) const {
-  if (!bytes) {
-    return 0;
-  }
-  if (bytes[0] & 0x80) {
-    // A multibyte character can be 2, 3, or 4 bytes long. Also, the 2nd,
-    // 3rd, and 4th byte must be 10xxxxxx, the most significant 2 bits must
-    // be 10.
-    const size_t char_size =
-        31 - bit_scan_reverse(~(static_cast<uint32_t>(bytes[0]) << 24));
-    // Return 0 if the character is incomplete.
-    if (char_size > bytes.size()) {
-      return 0;
-    }
-    switch (char_size) {
-      case 4: {
-        // Return 0 if the 4th byte is invalid.
-        if ((bytes[3] & 0xC0) != 0x80) {
-          return 0;
-        }
-      }
-      case 3: {
-        // Return 0 if the 3rd byte is invalid.
-        if ((bytes[2] & 0xC0) != 0x80) {
-          return 0;
-        }
-      }
-      case 2: {
-        // Return 0 if the 2nd byte is invalid.
-        if ((bytes[1] & 0xC0) != 0x80) {
-          return 0;
-        }
-        return char_size;
-      }
-      default: {
-        // Return 0 if the character size is invalid.
-        return 0;
-      }
-    }
-  }
-  // Return 1 for an ASCII character.
-  return 1;
-}
-
-}  // namespace charset
-}  // namespace grnxx

  Deleted: lib/grnxx/charset/utf-8.hpp (+0 -43) 100644
===================================================================
--- lib/grnxx/charset/utf-8.hpp    2013-08-23 10:46:34 +0900 (481a161)
+++ /dev/null
@@ -1,43 +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_CHARSET_UTF_8_HPP
-#define GRNXX_CHARSET_UTF_8_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/charset.hpp"
-
-namespace grnxx {
-namespace charset {
-
-// UTF-8.
-class UTF_8 : public Charset {
- public:
-  static const Charset *get();
-
-  CharsetCode code() const;
-
-  Bytes get_char(const Bytes &bytes) const;
-  size_t get_char_size(const Bytes &bytes) const;
-};
-
-}  // namespace charset
-}  // namespace grnxx
-
-#endif  // GRNXX_CHARSET_UTF_8_HPP

  Deleted: lib/grnxx/common_header.cpp (+0 -69) 100644
===================================================================
--- lib/grnxx/common_header.cpp    2013-08-23 10:46:34 +0900 (1339e6a)
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-  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/common_header.hpp"
-
-#include <cstring>
-
-#include "grnxx/exception.hpp"
-#include "grnxx/grnxx.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-
-CommonHeader::CommonHeader(const char *format) : format_{}, version_{} {
-  // Copy the format string.
-  if (!format) {
-    GRNXX_ERROR() << "invalid format: format = nullptr";
-    throw LogicError();
-  }
-  const std::size_t format_length = std::strlen(format);
-  if (format_length >= FORMAT_SIZE) {
-    GRNXX_ERROR() << "too long format: format = " << format;
-    throw LogicError();
-  }
-  std::memcpy(format_, format, format_length);
-
-  // Copy the current version string.
-  const char * const current_version = Grnxx::version();
-  if (!current_version) {
-    GRNXX_ERROR() << "invalid version: current_version = nullptr";
-    throw LogicError();
-  }
-  const std::size_t current_version_length = std::strlen(current_version);
-  if (current_version_length >= VERSION_SIZE) {
-    GRNXX_ERROR() << "too long version: current_version = " << current_version;
-    throw LogicError();
-  }
-  std::memcpy(version_, current_version, current_version_length);
-}
-
-Bytes CommonHeader::format() const {
-  if (format_[FORMAT_SIZE - 1] == '\0') {
-    return Bytes(format_);
-  }
-  return Bytes(format_, FORMAT_SIZE);
-}
-
-Bytes CommonHeader::version() const {
-  if (version_[VERSION_SIZE - 1] == '\0') {
-    return Bytes(version_);
-  }
-  return Bytes(version_, VERSION_SIZE);
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/common_header.hpp (+0 -51) 100644
===================================================================
--- lib/grnxx/common_header.hpp    2013-08-23 10:46:34 +0900 (cd3f0ec)
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_COMMON_HEADER_HPP
-#define GRNXX_COMMON_HEADER_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class CommonHeader {
- public:
-  // Buffer size for "format_" and "version_".
-  static constexpr size_t FORMAT_SIZE  = 64;
-  static constexpr size_t VERSION_SIZE = 32;
-
-  // Trivial default constructor.
-  CommonHeader() = default;
-  // Create a common header with "format" and the current version.
-  explicit CommonHeader(const char *format);
-
-  // Return the format string.
-  Bytes format() const;
-  // Return the version string.
-  Bytes version() const;
-
- private:
-  char format_[FORMAT_SIZE];
-  char version_[VERSION_SIZE];
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_COMMON_HEADER_HPP

  Deleted: lib/grnxx/duration.cpp (+0 -44) 100644
===================================================================
--- lib/grnxx/duration.cpp    2013-08-23 10:46:34 +0900 (01bc6be)
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-  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/duration.hpp"
-
-#include "grnxx/string_builder.hpp"
-#include "grnxx/string_format.hpp"
-
-namespace grnxx {
-
-StringBuilder &operator<<(StringBuilder &builder, Duration duration) {
-  if (!builder) {
-    return builder;
-  }
-  uint64_t count;
-  if (duration.count() >= 0) {
-    count = duration.count();
-  } else {
-    builder << '-';
-    count = -duration.count();
-  }
-  builder << (count / 1000000);
-  count %= 1000000;
-  if (count != 0) {
-    builder << '.' << StringFormat::align_right(count, 6, '0');
-  }
-  return builder;
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/duration.hpp (+0 -172) 100644
===================================================================
--- lib/grnxx/duration.hpp    2013-08-23 10:46:34 +0900 (f734d53)
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_DURATION_HPP
-#define GRNXX_DURATION_HPP
-
-#include "grnxx/features.hpp"
-
-#include <limits>
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-// Time difference in microseconds.
-// 64-bit tick count (usec) is used.
-class Duration {
- public:
-  // Trivial default constructor.
-  Duration() = default;
-  // Construct a duration object whose tick count is "count".
-  explicit constexpr Duration(int64_t count) : count_(count) {}
-
-  // Return the minimum tick count.
-  static constexpr Duration min() {
-    return Duration(std::numeric_limits<int64_t>::min());
-  }
-  // Return the maximum tick count.
-  static constexpr Duration max() {
-    return Duration(std::numeric_limits<int64_t>::max());
-  }
-
-  // Return a duration of "count" microseconds.
-  static constexpr Duration microseconds(int64_t count) {
-    return Duration(count);
-  }
-  // Return a duration of "count" milliseconds.
-  static constexpr Duration milliseconds(int64_t count) {
-    return Duration(count * 1000);
-  }
-  // Return a duration of "count" seconds.
-  static constexpr Duration seconds(int64_t count) {
-    return Duration(count * 1000000);
-  }
-  // Return a duration of "count" minutes.
-  static constexpr Duration minutes(int64_t count) {
-    return Duration(count * 1000000 * 60);
-  }
-  // Return a duration of "count" hours.
-  static constexpr Duration hours(int64_t count) {
-    return Duration(count * 1000000 * 60 * 60);
-  }
-  // Return a duration of "count" days.
-  static constexpr Duration days(int64_t count) {
-    return Duration(count * 1000000 * 60 * 60 * 24);
-  }
-  // Return a duration of "count" weeks.
-  static constexpr Duration weeks(int64_t count) {
-    return Duration(count * 1000000 * 60 * 60 * 24 * 7);
-  }
-
-  // Return the tick count.
-  constexpr int64_t count() const {
-    return count_;
-  }
-  // Set the tick count.
-  void set_count(int64_t count) {
-    count_ = count;
-  }
-
- private:
-  int64_t count_;
-
-  // Copyable.
-};
-
-inline constexpr Duration operator+(Duration duration) {
-  return duration;
-}
-inline constexpr Duration operator-(Duration duration) {
-  return Duration(-duration.count());
-}
-
-inline Duration &operator+=(Duration &lhs, Duration rhs) {
-  lhs.set_count(lhs.count() + rhs.count());
-  return lhs;
-}
-inline Duration &operator-=(Duration &lhs, Duration rhs) {
-  lhs.set_count(lhs.count() - rhs.count());
-  return lhs;
-}
-inline Duration &operator*=(Duration &lhs, int64_t rhs) {
-  lhs.set_count(lhs.count() * rhs);
-  return lhs;
-}
-inline Duration &operator/=(Duration &lhs, int64_t rhs) {
-  if (rhs == 0) {
-    lhs.set_count(0);
-  } else {
-    lhs.set_count(lhs.count() / rhs);
-  }
-  return lhs;
-}
-inline Duration &operator%=(Duration &lhs, Duration rhs) {
-  if (rhs.count() == 0) {
-    lhs.set_count(0);
-  } else {
-    lhs.set_count(lhs.count() % rhs.count());
-  }
-  return lhs;
-}
-
-inline constexpr Duration operator+(Duration lhs, Duration rhs) {
-  return Duration(lhs.count() + rhs.count());
-}
-inline constexpr Duration operator-(Duration lhs, Duration rhs) {
-  return Duration(lhs.count() - rhs.count());
-}
-inline constexpr Duration operator*(Duration lhs, int64_t rhs) {
-  return Duration(lhs.count() * rhs);
-}
-inline constexpr Duration operator*(int64_t lhs, Duration rhs) {
-  return Duration(lhs * rhs.count());
-}
-inline constexpr Duration operator/(Duration lhs, int64_t rhs) {
-  return (rhs != 0) ? Duration(lhs.count() / rhs) : Duration(0);
-}
-inline constexpr Duration operator%(Duration lhs, Duration rhs) {
-  return (rhs.count() != 0) ?
-      Duration(lhs.count() % rhs.count()) : Duration(0);
-}
-
-inline constexpr bool operator==(Duration lhs, Duration rhs) {
-  return lhs.count() == rhs.count();
-}
-inline constexpr bool operator!=(Duration lhs, Duration rhs) {
-  return lhs.count() != rhs.count();
-}
-inline constexpr bool operator<(Duration lhs, Duration rhs) {
-  return lhs.count() < rhs.count();
-}
-inline constexpr bool operator<=(Duration lhs, Duration rhs) {
-  return lhs.count() <= rhs.count();
-}
-inline constexpr bool operator>(Duration lhs, Duration rhs) {
-  return lhs.count() > rhs.count();
-}
-inline constexpr bool operator>=(Duration lhs, Duration rhs) {
-  return lhs.count() >= rhs.count();
-}
-
-StringBuilder &operator<<(StringBuilder &builder, Duration duration);
-
-}  // namespace grnxx
-
-#endif  // GRNXX_DURATION_HPP

  Deleted: lib/grnxx/errno.cpp (+0 -96) 100644
===================================================================
--- lib/grnxx/errno.cpp    2013-08-23 10:46:34 +0900 (b0e1b34)
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-  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/errno.hpp"
-
-#include <string.h>
-
-#ifdef GRNXX_WINDOWS
-# include <windows.h>
-#endif  // GRNXX_WINDOWS
-
-#include <memory>
-
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace {
-
-constexpr size_t MESSAGE_BUF_SIZE = 256;
-
-#ifdef GRNXX_WINDOWS
-class Freer {
- public:
-  void operator()(void *ptr) const {
-    ::LocalFree(ptr);
-  }
-};
-#endif  // GRNXX_WINDOWS
-
-}  // namespace
-
-StringBuilder &Errno::write_to(StringBuilder &builder) const {
-  switch (type_) {
-    case STANDARD_ERRNO: {
-      // Note that a string returned by ::strerror() may be modified by a
-      // subsequent call to ::perror() or ::strerror().
-      const char *message = "n/a";
-#ifdef GRNXX_MSC
-      char message_buf[MESSAGE_BUF_SIZE];
-      if (::strerror_s(message_buf, MESSAGE_BUF_SIZE, standard_errno_) == 0) {
-        message = message_buf;
-      }
-#elif defined(GRNXX_HAS_XSI_STRERROR)
-      char message_buf[MESSAGE_BUF_SIZE];
-      if (::strerror_r(standard_errno_, message_buf, MESSAGE_BUF_SIZE) == 0) {
-        message = message_buf;
-      }
-#elif defined(GRNXX_HAS_GNU_STRERROR)
-      // ::strerror_r() may not use "message_buf" when an immutable error
-      // message is available.
-      char message_buf[MESSAGE_BUF_SIZE];
-      message = ::strerror_r(standard_errno_, message_buf, MESSAGE_BUF_SIZE);
-#else  // defined(GRNXX_HAS_GNU_STRERROR)
-      message = ::strerror(standard_errno_);
-#endif  // defined(GRNXX_HAS_GNU_STRERROR)
-      return builder << standard_errno_ << " (" << message << ')';
-    }
-#ifdef GRNXX_WINDOWS
-    case WINDOWS_ERRNO: {
-      char *message;
-      if (::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                           FORMAT_MESSAGE_FROM_SYSTEM |
-                           FORMAT_MESSAGE_IGNORE_INSERTS,
-                           nullptr, windows_errno_,
-                           MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
-                           reinterpret_cast<LPSTR>(&message),
-                           0, nullptr) != 0) {
-        std::unique_ptr<char[], Freer> message_freer(message);
-        builder << windows_errno_ << " (" << message << ')';
-      } else {
-        builder << windows_errno << " (n/a)";
-      }
-      return builder;
-    }
-#endif  // GRNXX_WINDOWS
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/errno.hpp (+0 -82) 100644
===================================================================
--- lib/grnxx/errno.hpp    2013-08-23 10:46:34 +0900 (74e8124)
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ERRNO_HPP
-#define GRNXX_ERRNO_HPP
-
-#include "grnxx/features.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-enum ErrnoType {
-  STANDARD_ERRNO,
-#ifdef GRNXX_WINDOWS
-  WINDOWS_ERRNO
-#endif  // GRNXX_WINDOWS
-};
-
-class GRNXX_EXPORT Errno {
- public:
-  Errno() = default;
-  // For errno.
-  explicit Errno(int error_code)
-      : type_(STANDARD_ERRNO),
-        standard_errno_(error_code) {}
-#ifdef GRNXX_WINDOWS
-  // For DWORD returned by ::GetLastErrno().
-  explicit Errno(unsigned long error_code)
-      : type_(WINDOWS_ERRNO),
-        windows_errno_(error_code) {}
-#endif  // GRNXX_WINDOWS
-
-  // Return the errno type.
-  ErrnoType type() const {
-    return type_;
-  }
-  // Return the standard errno.
-  int standard_errno() const {
-    return standard_errno_;
-  }
-#ifdef GRNXX_WINDOWS
-  // Return the windows errno.
-  unsigned long windows_errno() const {
-    return windows_errno_;
-  }
-#endif  // GRNXX_WINDOWS
-
-  // Write a human-readable error message to "builder".
-  StringBuilder &write_to(StringBuilder &builder) const;
-
- private:
-  ErrnoType type_;
-  union {
-    int standard_errno_;
-#ifdef GRNXX_WINDOWS
-    unsigned long windows_errno_;
-#endif  // GRNXX_WINDOWS
-  };
-};
-
-inline StringBuilder &operator<<(StringBuilder &builder, const Errno &error) {
-  return error.write_to(builder);
-}
-
-}  // namespace grnxx
-
-#endif  // GRNXX_ERRNO_HPP

  Deleted: lib/grnxx/exception.hpp (+0 -97) 100644
===================================================================
--- lib/grnxx/exception.hpp    2013-08-23 10:46:34 +0900 (f831500)
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_EXCEPTION_HPP
-#define GRNXX_EXCEPTION_HPP
-
-#include "grnxx/features.hpp"
-
-#include <exception>
-
-#include "grnxx/errno.hpp"
-
-namespace grnxx {
-
-// The base exception class.
-class Exception : std::exception {
- public:
-  Exception() noexcept {}
-  virtual ~Exception() noexcept {}
-
-  virtual const char *what() const noexcept {
-    return "grnxx::Exception";
-  }
-};
-
-// Thrown as an exception when a logical error occurs.
-class LogicError : public Exception {
- public:
-  LogicError() noexcept {}
-  virtual ~LogicError() noexcept {}
-
-  virtual const char *what() const noexcept {
-    return "grnxx::LogicError";
-  }
-};
-
-// Thrown as an exception when memory allocation fails.
-class MemoryError : public Exception {
- public:
-  MemoryError() noexcept {}
-  virtual ~MemoryError() noexcept {}
-
-  virtual const char *what() const noexcept {
-    return "grnxx::MemoryError";
-  }
-};
-
-// Thrown as as exception when an exception generated by the standard library
-// is caught.
-class StandardError : public Exception {
- public:
-  StandardError(const std::exception &exception) noexcept
-      : exception_(exception) {}
-  virtual ~StandardError() noexcept {}
-
-  virtual const char *what() const noexcept {
-    return exception_.what();
-  }
-
- private:
-  const std::exception &exception_;
-};
-
-// Thrown as an exception when a system call fails.
-class SystemError : public Exception {
- public:
-  explicit SystemError(const Errno &code) noexcept : code_(code) {}
-  virtual ~SystemError() noexcept {}
-
-  const Errno &code() const noexcept {
-    return code_;
-  }
-  virtual const char *what() const noexcept {
-    return "grnxx::SystemError";
-  }
-
- private:
-  Errno code_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_EXCEPTION_HPP

  Deleted: lib/grnxx/features.hpp (+0 -238) 100644
===================================================================
--- lib/grnxx/features.hpp    2013-08-23 10:46:34 +0900 (60cc702)
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_FEATURES_HPP
-#define GRNXX_FEATURES_HPP
-
-// Operating system features.
-
-#ifdef _WIN32
-# define GRNXX_WINDOWS
-# ifdef _WIN64
-#  define GRNXX_WIN64 _WIN64
-# else  // _WIN64
-#  define GRNXX_WIN32 _WIN32
-# endif  // _WIN64
-#endif  // _WIN32
-
-#if defined(__APPLE__) && defined(__MACH__)
-# define GRNXX_APPLE
-#endif  // defined(__APPLE__) && defined(__MACH__)
-
-#if defined(sun) || defined(__sun)
-# define GRNXX_SOLARIS
-#endif  // defined(sun) || defined(__sun)
-
-// Compiler features.
-
-#ifdef _MSC_VER
-# define GRNXX_MSC
-# define GRNXX_MSC_VERSION _MSC_VER
-# ifdef GRNXX_WIN32
-#  define GRNXX_MSC32
-# else  // GRNXX_WIN32
-#  define GRNXX_MSC64
-# endif  // GRNXX_WIN32
-#endif  // _MSC_VER
-
-#ifdef __MINGW32__
-# define GRNXX_MINGW
-# ifdef __MINGW64__
-#  define GRNXX_MINGW64
-# else  // __MINGW64__
-#  define GRNXX_MINGW32
-# endif  // __MINGW64__
-#endif  // __MINGW32__
-
-#ifdef __clang__
-# define GRNXX_CLANG
-# define GRNXX_CLANG_MAJOR __clang_major__
-# define GRNXX_CLANG_MINOR __clang_minor__
-# define GRNXX_CLANG_PATCH_LEVEL __clang_patchlevel__
-# define GRNXX_CLANG_VERSION __clang_version__
-#endif  // __clang__
-
-#ifdef __GNUC__
-# define GRNXX_GNUC
-# define GRNXX_GNUC_MAJOR __GNUC__
-# ifdef __GNUC_MINOR__
-#  define GRNXX_GNUC_MINOR __GNUC_MINOR__
-# else  // __GNUC_MINOR__
-#  define GRNXX_GNUC_MINOR 0
-# endif  // __GNUC_MINOR__
-# ifdef __GNUC_PATCHLEVEL__
-#  define GRNXX_GNUC_PATCH_LEVEL __GNUC_PATCHLEVEL__
-# else  // __GNUC_PATCHLEVEL__
-#  define GRNXX_GNUC_PATCH_LEVEL 0
-# endif  // __GNUC_PATCHLEVEL__
-# define GRNXX_GNUC_MAKE_VERSION(major, minor, patch_level)\
-    ((major * 10000) + (minor * 100) + patch_level)
-# define GRNXX_GNUC_VERSION GRNXX_GNUC_MAKE_VERSION(\
-    GRNXX_GNUC_MAJOR, GRNXX_GNUC_MINOR, GRNXX_GNUC_PATCH_LEVEL)
-#endif  // defined(__GNUC__)
-
-#ifdef GRNXX_CLANG
-# ifdef __has_builtin
-#  define GRNXX_CLANG_HAS_BUILTIN(builtin) __has_builtin(builtin)
-# else
-#  define GRNXX_CLANG_HAS_BUILTIN(builtin) false
-# endif  // __has_builtin
-# ifdef __has_feature
-#  define GRNXX_CLANG_HAS_FEATURE(feature) __has_feature(feature)
-# else
-#  define GRNXX_CLANG_HAS_FEATURE(feature) false
-# endif  // __has_feature
-# ifdef __has_extension
-#  define GRNXX_CLANG_HAS_EXTENSION(extension) __has_extension(extension)
-# else
-#  define GRNXX_CLANG_HAS_EXTENSION(extension) false
-# endif  // __has_extension
-# define GRNXX_CLANG_HAS(thing) (GRNXX_CLANG_HAS_BUILTIN(thing) |\
-    GRNXX_CLANG_HAS_FEATURE(thing) | GRNXX_CLANG_HAS_EXTENSION(thing))
-#endif  // GRNXX_CLANG
-
-#ifdef GRNXX_CLANG
-# if GRNXX_CLANG_HAS(__builtin_bswap16)
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP16
-# endif  // GRNXX_CLANG_HAS(__builtin_bswap16)
-# if GRNXX_CLANG_HAS(__builtin_bswap32)
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP32
-# endif  // GRNXX_CLANG_HAS(__builtin_bswap32)
-# if GRNXX_CLANG_HAS(__builtin_bswap64)
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP64
-# endif  // GRNXX_CLANG_HAS(__builtin_bswap64)
-# if GRNXX_CLANG_HAS(__builtin_clz)
-#  define GRNXX_HAS_GNUC_BUILTIN_CLZ
-# endif  // GRNXX_CLANG_HAS(__builtin_clz)
-# if GRNXX_CLANG_HAS(__sync_bool_compare_and_swap)
-#  define GRNXX_HAS_GNUC_BUILTIN_SYNC
-# endif  // GRNXX_CLANG_HAS(__sync_bool_compare_and_swap)
-# if GRNXX_CLANG_HAS(__atomic_compare_exchange_n)
-#  define GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-# endif  // GRNXX_CLANG_HAS(__atomic_compare_exchange_n)
-# if GRNXX_CLANG_HAS(c_atomic)
-#  define GRNXX_HAS_CLANG_BUILTIN_ATOMIC
-# endif  // GRNXX_CLANG_HAS(c_atomic)
-#elif defined(GRNXX_GNUC)
-# define GRNXX_HAS_GNUC_BUILTIN_CLZ
-# if GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 2, 0)
-#  define GRNXX_HAS_GNUC_BUILTIN_SYNC
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP32
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP64
-# endif  // GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 2, 0)
-# if GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 7, 0)
-#  define GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-# endif  // GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 7, 0)
-# if GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 8, 0)
-#  define GRNXX_HAS_GNUC_BUILTIN_BSWAP16
-# endif  // GRNXX_GNUC_VERSION >= GRNXX_GNUC_MAKE_VERSION(4, 8, 0)
-#endif  // defined(GRNXX_GNUC)
-
-// Source features.
-
-#ifdef _GNU_SOURCE
-# define GRNXX_GNU_SOURCE _GNU_SOURCE
-#else  // _GNU_SOURCE
-# define GRNXX_GNU_SOURCE 0
-#endif  // _GNU_SOURCE
-
-#ifdef _POSIX_C_SOURCE
-# define GRNXX_POSIX_C_SOURCE _POSIX_C_SOURCE
-#else  // _POSIX_C_SOURCE
-# define GRNXX_POSIX_C_SOURCE 0
-#endif  // _POSIX_C_SOURCE
-
-#ifdef _XOPEN_SOURCE
-# define GRNXX_XOPEN_SOURCE _XOPEN_SOURCE
-#else  // _XOPEN_SOURCE
-# define GRNXX_XOPEN_SOURCE 0
-#endif  // _XOPEN_SOURCE
-
-#ifdef _XOPEN_SOURCE_EXTENDED
-# define GRNXX_XOPEN_SOURCE_EXTENDED _XOPEN_SOURCE_EXTENDED
-#else  // _XOPEN_SOURCE_EXTENDED
-# define GRNXX_XOPEN_SOURCE_EXTENDED 0
-#endif  // _XOPEN_SOURCE_EXTENDED
-
-#ifdef _BSD_SOURCE
-# define GRNXX_BSD_SOURCE _BSD_SOURCE
-#else  // _BSD_SOURCE
-# define GRNXX_BSD_SOURCE 0
-#endif  // _BSD_SOURCE
-
-#ifdef _SVID_SOURCE
-# define GRNXX_SVID_SOURCE _SVID_SOURCE
-#else  // _SVID_SOURCE
-# define GRNXX_SVID_SOURCE 0
-#endif  // _SVID_SOURCE
-
-#ifdef _POSIX_SOURCE
-# define GRNXX_POSIX_SOURCE _POSIX_SOURCE
-#else  // _POSIX_SOURCE
-# define GRNXX_POSIX_SOURCE 0
-#endif  // _POSIX_SOURCE
-
-// Available functions.
-
-#if ((GRNXX_POSIX_C_SOURCE >= 20112L) || (GRNXX_XOPEN_SOURCE >= 600)) &&\
-    !GRNXX_GNU_SOURCE
-# define GRNXX_HAS_XSI_STRERROR
-#else  // ((GRNXX_POSIX_C_SOURCE >= 20112L) || ...
-# define GRNXX_HAS_GNU_STRERROR
-#endif  // ((GRNXX_POSIX_C_SOURCE >= 20112L) || ...
-
-#if GRNXX_POSIX_C_SOURCE >= 199309L
-# define GRNXX_HAS_NANOSLEEP
-#endif  // GRNXX_POSIX_C_SOURCE >= 199309L
-
-#if (GRNXX_POSIX_C_SOURCE >= 1) || GRNXX_XOPEN_SOURCE || GRNXX_BSD_SOURCE ||\
-    GRNXX_SVID_SOURCE || GRNXX_POSIX_SOURCE
-# define GRNXX_HAS_GMTIME_R
-# define GRNXX_HAS_LOCALTIME_R
-#endif  // (GRNXX_POSIX_C_SOURCE >= 1) || ...
-
-#if (GRNXX_XOPEN_SOURCE >= 500) || (GRNXX_POSIX_C_SOURCE >= 200809L)
-# define GRNXX_HAS_PREAD
-# define GRNXX_HAS_PWRITE
-#endif  // (GRNXX_XOPEN_SOURCE >= 500) || (GRNXX_POSIX_C_SOURCE >= 200809L)
-
-#ifndef GRNXX_WINDOWS
-# include <unistd.h>
-# ifdef _POSIX_TIMERS
-#  if _POSIX_TIMERS > 0
-#   define GRNXX_HAS_POSIX_TIMER
-#   define GRNXX_HAS_CLOCK_GETTIME
-#  endif  // _POSIX_TIMERS > 0
-# endif  // _POSIX_TIMERS
-# ifdef _POSIX_PRIORITY_SCHEDULING
-#  define GRNXX_HAS_SCHED_YIELD
-# endif  // _POSIX_PRIORITY_SCHEDULING
-#endif  // GRNXX_WINDOWS
-
-// DLL features.
-
-#ifdef GRNXX_WINDOWS
-# ifdef DLL_EXPORT
-#  define GRNXX_EXPORT __declspec(dllexport)
-# else  // DLL_EXPORT
-#  define GRNXX_EXPORT __declspec(dllimport)
-# endif  // DLL_EXPORT
-#else  // GRNXX_WINDOWS
-# define GRNXX_EXPORT
-#endif  // GRNXX_WINDOWS
-
-#endif  // GRNXX_FEATURES_HPP

  Deleted: lib/grnxx/flags_impl.hpp (+0 -84) 100644
===================================================================
--- lib/grnxx/flags_impl.hpp    2013-08-23 10:46:34 +0900 (c5fe933)
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_FLAGS_IMPL_HPP
-#define GRNXX_FLAGS_IMPL_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-template <typename T, typename U = uint32_t>
-class FlagsImpl {
- public:
-  using Identifier = T;
-  using Type = U;
-
-  FlagsImpl() = default;
-
-  constexpr explicit operator bool() const {
-    return flags_ != 0;
-  }
-
-  constexpr FlagsImpl operator&(FlagsImpl rhs) const {
-    return FlagsImpl(flags_ & rhs.flags_);
-  }
-  constexpr FlagsImpl operator|(FlagsImpl rhs) const {
-    return FlagsImpl(flags_ | rhs.flags_);
-  }
-  constexpr FlagsImpl operator^(FlagsImpl rhs) const {
-    return FlagsImpl(flags_ ^ rhs.flags_);
-  }
-  constexpr FlagsImpl operator~() const {
-    return FlagsImpl(~flags_);
-  }
-
-  constexpr bool operator==(FlagsImpl rhs) const {
-    return flags_ == rhs.flags_;
-  }
-  constexpr bool operator!=(FlagsImpl rhs) const {
-    return flags_ == rhs.flags_;
-  }
-
-  FlagsImpl &operator&=(FlagsImpl rhs) {
-    flags_ &= rhs.flags_;
-    return *this;
-  }
-  FlagsImpl &operator|=(FlagsImpl rhs) {
-    flags_ |= rhs.flags_;
-    return *this;
-  }
-  FlagsImpl &operator^=(FlagsImpl rhs) {
-    flags_ ^= rhs.flags_;
-    return *this;
-  }
-
-  static constexpr FlagsImpl define(Type flags) {
-    return FlagsImpl(flags);
-  }
-
- private:
-  Type flags_;
-
-  explicit constexpr FlagsImpl(Type flags) : flags_(flags) {}
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_FLAGS_IMPL_HPP

  Deleted: lib/grnxx/geo_point.cpp (+0 -46) 100644
===================================================================
--- lib/grnxx/geo_point.cpp    2013-08-23 10:46:34 +0900 (4735281)
+++ /dev/null
@@ -1,46 +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 "grnxx/geo_point.hpp"
-
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-
-uint64_t GeoPoint::interleave() const {
-  const Point point = reinterpret_cast<const Point &>(value_);
-  uint64_t latitude = static_cast<uint32_t>(point.latitude);
-  uint64_t longitude = static_cast<uint32_t>(point.longitude);
-  latitude = (latitude | (latitude << 16)) & 0x0000FFFF0000FFFFULL;
-  latitude = (latitude | (latitude <<  8)) & 0x00FF00FF00FF00FFULL;
-  latitude = (latitude | (latitude <<  4)) & 0x0F0F0F0F0F0F0F0FULL;
-  latitude = (latitude | (latitude <<  2)) & 0x3333333333333333ULL;
-  latitude = (latitude | (latitude <<  1)) & 0x5555555555555555ULL;
-  longitude = (longitude | (longitude << 16)) & 0x0000FFFF0000FFFFULL;
-  longitude = (longitude | (longitude <<  8)) & 0x00FF00FF00FF00FFULL;
-  longitude = (longitude | (longitude <<  4)) & 0x0F0F0F0F0F0F0F0FULL;
-  longitude = (longitude | (longitude <<  2)) & 0x3333333333333333ULL;
-  longitude = (longitude | (longitude <<  1)) & 0x5555555555555555ULL;
-  return (latitude << 1) | longitude;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const GeoPoint &point) {
-  return builder << "{ latitude = " << point.latitude()
-                 << ", longitude = " << point.longitude() << " }";
-}
-
-}  // namespace

  Deleted: lib/grnxx/geo_point.hpp (+0 -93) 100644
===================================================================
--- lib/grnxx/geo_point.hpp    2013-08-23 10:46:34 +0900 (098939d)
+++ /dev/null
@@ -1,93 +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_GEO_POINT_HPP
-#define GRNXX_GEO_POINT_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-// Latitude and longitude (lat/long).
-class GeoPoint {
- private:
-  struct Point {
-    int32_t latitude;
-    int32_t longitude;
-  };
-
- public:
-  // Trivial default constructor.
-  GeoPoint() = default;
-  // Copy the lat/long as uint64_t.
-  explicit GeoPoint(uint64_t x) : value_(x) {}
-  // Copy the lat/long.
-  GeoPoint(int32_t latitude, int32_t longitude) : value_() {
-    Point point{ latitude, longitude };
-    value_ = reinterpret_cast<const uint64_t &>(point);
-  }
-
-  // Interleave the lat/long.
-  uint64_t interleave() const;
-
-  // Return the latitude.
-  int32_t latitude() const {
-    return reinterpret_cast<const Point &>(value_).latitude;
-  }
-  // Return the longitude.
-  int32_t longitude() const {
-    return reinterpret_cast<const Point &>(value_).longitude;
-  }
-  // Return the lat/long as uint64_t.
-  uint64_t value() const {
-    return value_;
-  }
-
-  // Set the latitude.
-  void set_latitude(int32_t x) {
-    reinterpret_cast<Point &>(value_).latitude = x;
-  }
-  // Set the longitude.
-  void set_longitude(int32_t x) {
-    reinterpret_cast<Point &>(value_).longitude = x;
-  }
-  // Set the lat/long as uint64_t.
-  void set_value(uint64_t x) {
-    value_ = x;
-  }
-
- private:
-  // Force 8-byte alignment and atomic copy/assignment.
-  uint64_t value_;
-};
-
-inline bool operator==(const GeoPoint &lhs, const GeoPoint &rhs) {
-  return lhs.value() == rhs.value();
-}
-inline bool operator!=(const GeoPoint &lhs, const GeoPoint &rhs) {
-  return lhs.value() != rhs.value();
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const GeoPoint &point);
-
-}  // namespace
-
-#endif  // GRNXX_GEO_POINT_HPP

  Deleted: lib/grnxx/grnxx.cpp (+0 -37) 100644
===================================================================
--- lib/grnxx/grnxx.cpp    2013-08-23 10:46:34 +0900 (e984a31)
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "grnxx/grnxx.hpp"
-
-#include "../config.h"
-#include "grnxx/version.h"
-
-namespace grnxx {
-
-const char *Grnxx::bugreport() {
-  return PACKAGE_BUGREPORT;
-}
-
-const char *Grnxx::version() {
-#ifdef GRNXX_VERSION
-  return GRNXX_VERSION;
-#else  // GRNXX_VERSION
-  return PACKAGE_VERSION;
-#endif  // GRNXX_VERSION
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/grnxx.hpp (+0 -36) 100644
===================================================================
--- lib/grnxx/grnxx.hpp    2013-08-23 10:46:34 +0900 (f66b0d3)
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_GRNXX_HPP
-#define GRNXX_GRNXX_HPP
-
-#include "grnxx/features.hpp"
-
-namespace grnxx {
-
-class GRNXX_EXPORT Grnxx {
- public:
-  // The e-mail address for bug reports.
-  static const char *bugreport();
-
-  // The version.
-  static const char *version();
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_GRNXX_HPP

  Deleted: lib/grnxx/intrinsic.hpp (+0 -847) 100644
===================================================================
--- lib/grnxx/intrinsic.hpp    2013-08-23 10:46:34 +0900 (3ce60ee)
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_INTRINSIC_HPP
-#define GRNXX_INTRINSIC_HPP
-
-#include "grnxx/features.hpp"
-
-#ifdef GRNXX_MSC
-# include <intrin.h>
-# pragma intrinsic(_BitScanReverse)
-# pragma intrinsic(_BitScanForward)
-# pragma intrinsic(_InterlockedCompareExchange)
-# pragma intrinsic(_InterlockedCompareExchange64)
-# pragma intrinsic(_InterlockedExchangeAdd)
-# pragma intrinsic(_InterlockedOr)
-# pragma intrinsic(_InterlockedAnd)
-# pragma intrinsic(_InterlockedXor)
-# ifdef GRNXX_MSC64
-#  pragma intrinsic(_BitScanReverse64)
-#  pragma intrinsic(_BitScanForward64)
-#  pragma intrinsic(_InterlockedExchangeAdd64)
-#  pragma intrinsic(_InterlockedOr64)
-#  pragma intrinsic(_InterlockedAnd64)
-#  pragma intrinsic(_InterlockedXor64)
-# endif  // GRNXX_MSC64
-#endif  // GRNXX_MSC
-
-#include <type_traits>
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-// bit_scan_reverse() returns the position of the most significant 1 bit.
-// For example, if value == 0x1010, bit_scan_reverse() returns 12.
-// Note that if value == 0, the result is undefined.
-template <typename Value>
-inline uint8_t bit_scan_reverse(Value value);
-
-// bit_scan_forward() returns the position of the most insignificant 1 bit.
-// For example, if value == 0x1010, bit_scan_forward() returns 4.
-// Note that if value == 0, the result is undefined.
-template <typename Value>
-inline uint8_t bit_scan_forward(Value value);
-
-// byte_swap() returns the byte-swapped value.
-// For example, byte_swap(0x12345678U) returns 0x78564312U.
-inline uint8_t byte_swap(uint8_t value);
-inline uint16_t byte_swap(uint16_t value);
-inline uint32_t byte_swap(uint32_t value);
-inline uint64_t byte_swap(uint64_t value);
-
-// atomic_compare_and_swap() atomically performs the following.
-//  if (*value == expected) {
-//    *value = desired;
-//    return true;
-//  } else {
-//    return false;
-//  }
-template <typename Value>
-inline bool atomic_compare_and_swap(Value expected, Value desired,
-                                    volatile Value *value);
-
-// atomic_fetch_and_add() atomically performs the following:
-//  temp = *value;
-//  *value += plus;
-//  return temp;
-template <typename Plus, typename Value>
-inline Value atomic_fetch_and_add(Plus plus, volatile Value *value);
-
-// atomic_fetch_or() atomically performs the following:
-//  temp = *value;
-//  *value |= plus;
-//  return temp;
-template <typename Value>
-inline Value atomic_fetch_and_or(Value mask, volatile Value *value);
-
-// atomic_fetch_and() atomically performs the following:
-//  temp = *value;
-//  *value &= plus;
-//  return temp;
-template <typename Value>
-inline Value atomic_fetch_and_and(Value mask, volatile Value *value);
-
-// atomic_fetch_xor() atomically performs the following:
-//  temp = *value;
-//  *value ^= plus;
-//  return temp;
-template <typename Value>
-inline Value atomic_fetch_and_xor(Value mask, volatile Value *value);
-
-// Implementation of bit_scan_reverse.
-
-#if defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-
-template <size_t ValueSize>
-class BitScanReverse {
- public:
-  template <typename Value>
-  uint8_t operator()(Value value) const {
-# ifdef GRNXX_MSC
-    unsigned long index;
-    ::_BitScanReverse(&index, static_cast<unsigned long>(value));
-    return static_cast<uint8_t>(index);
-# else  // GRNXX_MSC
-    return static_cast<uint8_t>(
-        31 - ::__builtin_clz(static_cast<unsigned int>(value)));
-# endif  // GRNXX_MSC
-  }
-};
-
-template <>
-class BitScanReverse<8> {
- public:
-  template <typename Value>
-  uint8_t operator()(Value value) const {
-# ifdef GRNXX_MSC
-#  ifdef GRNXX_MSC64
-    unsigned long index;
-    ::_BitScanReverse64(&index, static_cast<unsigned __int64>(value));
-    return static_cast<uint8_t>(index);
-#  else  // GRNXX_MSC64
-    if ((value >> 32) != 0) {
-      return static_cast<uint8_t>(BitScanReverse<4>(value >> 32) + 32);
-    }
-    return BitScanReverse<4>(value);
-#  endif  // GRNXX_MSC64
-# else  // GRNXX_MSC
-    return static_cast<uint8_t>(
-        63 - ::__builtin_clzll(static_cast<unsigned long long>(value)));
-# endif  // GRNXX_MSC
-  }
-};
-
-#endif  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-
-template <typename Value>
-inline uint8_t bit_scan_reverse(Value value) {
-  static_assert(std::is_integral<Value>::value,
-                "bit_scan_reverse accepts only integer types");
-  using UValue = typename std::make_unsigned<Value>::type;
-
-#if defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-  return BitScanReverse<sizeof(Value)>()(static_cast<UValue>(value));
-#else  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-  uint8_t result = 0;
-  for (uint8_t shift = static_cast<uint8_t>(sizeof(Value) * 4);
-       shift != 0; shift /= 2) {
-    if ((static_cast<UValue>(value) >> shift) != 0) {
-      value = static_cast<UValue>(value) >> shift;
-      result += shift;
-    }
-  }
-  return result;
-#endif  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-}
-
-// Implementation of bit_scan_forward.
-
-#if defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-
-template <size_t ValueSize>
-class BitScanForward {
- public:
-  template <typename Value>
-  uint8_t operator()(Value value) const {
-# ifdef GRNXX_MSC
-    unsigned long index;
-    ::_BitScanForward(&index, static_cast<unsigned long>(value));
-    return static_cast<uint8_t>(index);
-# else  // GRNXX_MSC
-    return static_cast<uint8_t>(
-        ::__builtin_ctz(static_cast<unsigned int>(value)));
-# endif  // GRNXX_MSC
-  }
-};
-
-template <>
-class BitScanForward<8> {
- public:
-  template <typename Value>
-  uint8_t operator()(Value value) const {
-# ifdef GRNXX_MSC
-#  ifdef GRNXX_MSC64
-    unsigned long index;
-    ::_BitScanForward64(&index, static_cast<unsigned __int64>(value));
-    return static_cast<uint8_t>(index);
-#  else  // GRNXX_MSC64
-    if ((value & 0xFFFFFFFFU) == 0) {
-      return static_cast<uint8_t>(BitScanForward<4>(value >> 32) + 32);
-    }
-    return BitScanForward<4>(value);
-#  endif  // GRNXX_MSC64
-# else  // GRNXX_MSC
-    return static_cast<uint8_t>(
-        ::__builtin_ctzll(static_cast<unsigned long long>(value)));
-# endif  // GRNXX_MSC
-  }
-};
-
-#endif  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-
-template <typename Value>
-inline uint8_t bit_scan_forward(Value value) {
-  static_assert(std::is_integral<Value>::value,
-                "bit_scan_forward accepts only integer types");
-  using UValue = typename std::make_unsigned<Value>::type;
-
-#if defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-  return BitScanForward<sizeof(Value)>()(static_cast<UValue>(value));
-#else  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-  uint8_t result = static_cast<uint8_t>(sizeof(Value) * 8) - 1;
-  for (uint8_t shift = static_cast<uint8_t>(sizeof(Value) * 4);
-       shift != 0; shift /= 2) {
-    if (static_cast<Value>(value << shift) != 0) {
-      value <<= shift;
-      result -= shift;
-    }
-  }
-  return result;
-#endif  // defined(GRNXX_MSC) || defined(GRNXX_HAS_GNUC_BUILTIN_CLZ)
-}
-
-// Helper classes.
-
-template <size_t ValueSize> class IntrinsicType;
-
-#ifdef GRNXX_MSC
-template <> class IntrinsicType<1> { public: typedef char Value; };
-template <> class IntrinsicType<2> { public: typedef short Value; };
-template <> class IntrinsicType<4> { public: typedef long Value; };
-template <> class IntrinsicType<8> { public: typedef __int64 Value; };
-#else  // GRNXX_MSC
-template <> class IntrinsicType<1> { public: typedef uint8_t Value; };
-template <> class IntrinsicType<2> { public: typedef uint16_t Value; };
-template <> class IntrinsicType<4> { public: typedef uint32_t Value; };
-template <> class IntrinsicType<8> { public: typedef uint64_t Value; };
-#endif  // GRNXX_MSC
-
-template <typename Value>
-class Intrinsic {
- public:
-  typedef typename IntrinsicType<sizeof(Value)>::Value InternalValue;
-  typedef volatile InternalValue *InternalPointer;
-};
-
-// Implementation of byte_swap.
-
-inline uint8_t byte_swap(uint8_t value) {
-  return value;
-}
-
-inline uint16_t byte_swap(uint16_t value) {
-#ifdef GRNXX_MSC
-  return ::_byteswap_ushort(value);
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP16)
-  return ::__builtin_bswap16(value);
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP16)
-  return (value << 8) | (value >> 8);
-#endif  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP16)
-}
-
-inline uint32_t byte_swap(uint32_t value) {
-#ifdef GRNXX_MSC
-  return ::_byteswap_ulong(value);
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP32)
-  return ::__builtin_bswap32(value);
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP32)
-  return (value << 24) |
-         ((value & (0xFF <<  8)) << 8) |
-         ((value & (0xFF << 16)) >> 8) |
-         (value >> 24);
-#endif  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP32)
-}
-
-inline uint64_t byte_swap(uint64_t value) {
-#ifdef GRNXX_MSC
-  return ::_byteswap_uint64(value);
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP64)
-  return ::__builtin_bswap64(value);
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP64)
-  return (value << 56) |
-         ((value & (0xFFULL <<  8)) << 40) |
-         ((value & (0xFFULL << 16)) << 24) |
-         ((value & (0xFFULL << 24)) <<  8) |
-         ((value & (0xFFULL << 32)) >>  8) |
-         ((value & (0xFFULL << 40)) >> 24) |
-         ((value & (0xFFULL << 48)) >> 40) |
-         (value >> 56);
-#endif  // defined(GRNXX_HAS_GNUC_BUILTIN_BSWAP64)
-}
-
-// Implementation of atomic_compare_and_swap.
-
-#ifdef GRNXX_MSC
-
-template <typename Value>
-class AtomicCompareAndSwap;
-
-template <>
-class AtomicCompareAndSwap<long> {
- public:
-  bool operator()(long expected, long desired,
-                  volatile long *value) const {
-    return ::_InterlockedCompareExchange(value, desired, expected) == expected;
-  }
-};
-
-template <>
-class AtomicCompareAndSwap<__int64> {
- public:
-  bool operator()(__int64 expected, __int64 desired,
-                  volatile __int64 *value) const {
-    return ::_InterlockedCompareExchange64(value, desired, expected) == expected;
-  }
-};
-
-template <typename Value>
-class AtomicCompareAndSwap {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  bool operator()(Value expected, Value desired, volatile Value *value) const {
-    return AtomicCompareAndSwap<InternalValue>()(
-        reinterpret_cast<const InternalValue &>(expected),
-        reinterpret_cast<const InternalValue &>(desired),
-        reinterpret_cast<InternalPointer>(value));
-  }
-};
-
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) ||\
-      defined(GRNXX_HAS_GNUC_BUILTIN_SYNC)
-
-// GNUC builtin functions for atomic operations accept integer types and
-// pointer types. Other types require type casting.
-template <typename Value, bool RequiresCast>
-class InternalAtomicCompareAndSwap;
-
-template <typename Value>
-class InternalAtomicCompareAndSwap<Value, false> {
- public:
-  bool operator()(Value expected, Value desired,
-                  volatile Value *value) const {
-#ifdef GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__atomic_compare_exchange_n(
-        value, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
-#else  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__sync_bool_compare_and_swap(value, expected, desired);
-#endif  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-  }
-};
-
-template <typename Value>
-class InternalAtomicCompareAndSwap<Value, true> {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  bool operator()(Value expected, Value desired, volatile Value *value) const {
-    return InternalAtomicCompareAndSwap<InternalValue, false>()(
-        reinterpret_cast<const InternalValue &>(expected),
-        reinterpret_cast<const InternalValue &>(desired),
-        reinterpret_cast<InternalPointer>(value));
-  }
-};
-
-template <typename Value>
-class AtomicCompareAndSwap {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  bool operator()(Value expected, Value desired, volatile Value *value) const {
-    return InternalAtomicCompareAndSwap<Value,
-        !std::is_integral<Value>::value && !std::is_pointer<Value>::value>()(
-            expected, desired, value);
-  }
-};
-
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-class AtomicCompareAndSwap {
- public:
-  bool operator()(Value expected, Value desired, volatile Value *value) const {
-    // Non-atomic implementation.
-    if (*value == expected) {
-      *value = desired;
-      return true;
-    } else {
-      return false;
-    }
-  }
-};
-
-#endif  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-inline bool atomic_compare_and_swap(Value expected, Value desired,
-                                    volatile Value *value) {
-  static_assert((sizeof(Value) == 4) || (sizeof(Value) == 8),
-      "atomic_compare_and_swap is supported only for 4/8 bytes values.");
-
-  return AtomicCompareAndSwap<Value>()(expected, desired, value);
-}
-
-// Implementation of atomic_fetch_and_add.
-
-#ifdef GRNXX_MSC
-
-template <typename Value>
-class InternalAtomicFetchAndAdd;
-
-template <>
-class InternalAtomicFetchAndAdd<long> {
- public:
-  long operator()(long plus, volatile long *value) const {
-    return ::_InterlockedExchangeAdd(plus, value);
-  }
-};
-
-template <>
-class InternalAtomicFetchAndAdd<__int64> {
- public:
-  __int64 operator()(__int64 plus, volatile __int64 *value) const {
-#ifdef GRNXX_MSC64
-    return ::_InterlockedExchangeAdd64(plus, value);
-#else  // GRNXX_MSC64
-    for ( ; ; ) {
-      const __int64 expected = *value;
-      const __int64 desired = expected + plus;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-#endif  // GRNXX_MSC64
-  }
-};
-
-template <typename Value>
-class InternalAtomicFetchAndAdd {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  Value operator()(Value plus, volatile Value *value) const {
-    return static_cast<Value>(InternalAtomicFetchAndAdd<InternalValue>()(
-        static_cast<InternalValue>(plus),
-        reinterpret_cast<InternalPointer>(value)));
-  }
-};
-
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) ||\
-      defined(GRNXX_HAS_GNUC_BUILTIN_SYNC)
-
-template <typename Value>
-class InternalAtomicFetchAndAdd {
- public:
-  Value operator()(Value plus, volatile Value *value) const {
-#ifdef GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__atomic_fetch_add(value, plus, __ATOMIC_SEQ_CST);
-#else  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__sync_fetch_and_add(value, plus);
-#endif  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-  }
-};
-
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-class InternalAtomicFetchAndAdd {
- public:
-  Value operator()(Value plus, volatile Value *value) const {
-    for ( ; ; ) {
-      const Value expected = *value;
-      const Value desired = expected + plus;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-  }
-};
-
-#endif
-
-template <typename Plus, typename Value, bool PlusAndValueAreIntegers>
-class AtomicFetchAndAdd;
-
-template <typename Plus, typename Value>
-class AtomicFetchAndAdd<Plus, Value, true> {
- public:
-  Value operator()(Plus plus, volatile Value *value) const {
-    return InternalAtomicFetchAndAdd<Value>()(static_cast<Value>(plus), value);
-  }
-};
-
-template <typename Plus, typename Value>
-class AtomicFetchAndAdd<Plus, Value, false> {
- public:
-  Value operator()(Plus plus, volatile Value *value) const {
-    for ( ; ; ) {
-      const Value expected = *value;
-      const Value desired = expected + plus;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-  }
-};
-
-template <typename Plus, typename Value>
-inline Value atomic_fetch_and_add(Plus plus, volatile Value *value) {
-  static_assert((sizeof(Value) == 4) || (sizeof(Value) == 8),
-      "atomic_fetch_and_add is supported only for 4/8 bytes values.");
-
-  return AtomicFetchAndAdd<Plus, Value, std::is_integral<Plus>::value &&
-                           std::is_integral<Value>::value>()(plus, value);
-}
-
-// Implementation of atomic_fetch_and_or.
-
-#ifdef GRNXX_MSC
-
-template <typename Value>
-class AtomicFetchAndOr;
-
-template <>
-class AtomicFetchAndOr<char> {
- public:
-  char operator()(char mask, volatile char *value) const {
-    return ::_InterlockedOr8(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndOr<short> {
- public:
-  short operator()(short mask, volatile short *value) const {
-    return ::_InterlockedOr16(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndOr<long> {
- public:
-  long operator()(long mask, volatile long *value) const {
-    return ::_InterlockedOr(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndOr<__int64> {
- public:
-  __int64 operator()(__int64 mask, volatile __int64 *value) const {
-#ifdef GRNXX_MSC64
-    return ::_InterlockedOr64(mask, value);
-#else  // GRNXX_MSC64
-    for ( ; ; ) {
-      const __int64 expected = *value;
-      const __int64 desired = expected | mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-#endif  // GRNXX_MSC64
-  }
-};
-
-template <typename Value>
-class AtomicFetchAndOr {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  Value operator()(Value plus, volatile Value *value) const {
-    return static_cast<Value>(AtomicFetchAndOr<InternalValue>()(
-        static_cast<InternalValue>(mask),
-        reinterpret_cast<InternalPointer>(value)));
-  }
-};
-
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) ||\
-      defined(GRNXX_HAS_GNUC_BUILTIN_SYNC)
-
-template <typename Value>
-class AtomicFetchAndOr {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-#ifdef GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST);
-#else  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__sync_fetch_and_or(value, mask);
-#endif  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-  }
-};
-
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-class AtomicFetchAndOr {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-    for ( ; ; ) {
-      const Value expected = *value;
-      const Value desired = expected | mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-  }
-};
-
-#endif
-
-template <typename Value>
-inline Value atomic_fetch_and_or(Value mask, volatile Value *value) {
-  static_assert(std::is_integral<Value>::value,
-                "atomic_fetch_and_or accepts only integer types.");
-
-  return AtomicFetchAndOr<Value>()(mask, value);
-}
-
-// Implementation of atomic_fetch_and_and.
-
-#ifdef GRNXX_MSC
-
-template <typename Value>
-class AtomicFetchAndAnd;
-
-template <>
-class AtomicFetchAndAnd<char> {
- public:
-  char operator()(char mask, volatile char *value) const {
-    return ::_InterlockedAnd8(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndAnd<short> {
- public:
-  short operator()(short mask, volatile short *value) const {
-    return ::_InterlockedAnd16(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndAnd<long> {
- public:
-  long operator()(long mask, volatile long *value) const {
-    return ::_InterlockedAnd(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndAnd<__int64> {
- public:
-  __int64 operator()(__int64 mask, volatile __int64 *value) const {
-#ifdef GRNXX_MSC64
-    return ::_InterlockedAnd64(mask, value);
-#else  // GRNXX_MSC64
-    for ( ; ; ) {
-      const __int64 expected = *value;
-      const __int64 desired = expected & mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-#endif  // GRNXX_MSC64
-  }
-};
-
-template <typename Value>
-class AtomicFetchAndAnd {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  Value operator()(Value plus, volatile Value *value) const {
-    return static_cast<Value>(AtomicFetchAndAnd<InternalValue>()(
-        static_cast<InternalValue>(mask),
-        reinterpret_cast<InternalPointer>(value)));
-  }
-};
-
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) ||\
-      defined(GRNXX_HAS_GNUC_BUILTIN_SYNC)
-
-template <typename Value>
-class AtomicFetchAndAnd {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-#ifdef GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST);
-#else  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__sync_fetch_and_and(value, mask);
-#endif  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-  }
-};
-
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-class AtomicFetchAndAnd {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-    for ( ; ; ) {
-      const Value expected = *value;
-      const Value desired = expected & mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-  }
-};
-
-#endif
-
-template <typename Value>
-inline Value atomic_fetch_and_and(Value mask, volatile Value *value) {
-  static_assert(std::is_integral<Value>::value,
-                "atomic_fetch_and_and accepts only integer types.");
-
-  return AtomicFetchAndAnd<Value>()(mask, value);
-}
-
-// Implementation of atomic_fetch_and_xor.
-
-#ifdef GRNXX_MSC
-
-template <typename Value>
-class AtomicFetchAndXor;
-
-template <>
-class AtomicFetchAndXor<char> {
- public:
-  char operator()(char mask, volatile char *value) const {
-    return ::_InterlockedXor8(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndXor<short> {
- public:
-  short operator()(short mask, volatile short *value) const {
-    return ::_InterlockedXor16(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndXor<long> {
- public:
-  long operator()(long mask, volatile long *value) const {
-    return ::_InterlockedXor(mask, value);
-  }
-};
-
-template <>
-class AtomicFetchAndXor<__int64> {
- public:
-  __int64 operator()(__int64 mask, volatile __int64 *value) const {
-#ifdef GRNXX_MSC64
-    return ::_InterlockedXor64(mask, value);
-#else  // GRNXX_MSC64
-    for ( ; ; ) {
-      const __int64 expected = *value;
-      const __int64 desired = expected ^ mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-#endif  // GRNXX_MSC64
-  }
-};
-
-template <typename Value>
-class AtomicFetchAndXor {
- public:
-  typedef typename Intrinsic<Value>::InternalValue InternalValue;
-  typedef typename Intrinsic<Value>::InternalPointer InternalPointer;
-
-  Value operator()(Value plus, volatile Value *value) const {
-    return static_cast<Value>(AtomicFetchAndXor<InternalValue>()(
-        static_cast<InternalValue>(mask),
-        reinterpret_cast<InternalPointer>(value)));
-  }
-};
-
-#elif defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) ||\
-      defined(GRNXX_HAS_GNUC_BUILTIN_SYNC)
-
-template <typename Value>
-class AtomicFetchAndXor {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-#ifdef GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__atomic_fetch_xor(value, mask, __ATOMIC_SEQ_CST);
-#else  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-    return ::__sync_fetch_and_xor(value, mask);
-#endif  // GRNXX_HAS_GNUC_BUILTIN_ATOMIC
-  }
-};
-
-#else  // defined(GRNXX_HAS_GNUC_BUILTIN_ATOMIC) || ...
-
-template <typename Value>
-class AtomicFetchAndXor {
- public:
-  Value operator()(Value mask, volatile Value *value) const {
-    for ( ; ; ) {
-      const Value expected = *value;
-      const Value desired = expected ^ mask;
-      if (atomic_compare_and_swap(expected, desired, value)) {
-        return expected;
-      }
-    }
-  }
-};
-
-#endif
-
-template <typename Value>
-inline Value atomic_fetch_and_xor(Value mask, volatile Value *value) {
-  static_assert(std::is_integral<Value>::value,
-                "atomic_fetch_and_xor accepts only integer types.");
-
-  return AtomicFetchAndXor<Value>()(mask, value);
-}
-
-}  // namespace grnxx
-
-#endif  // INTRINSIC_HPP

  Added: lib/grnxx/library.cpp (+11 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/library.cpp    2014-02-24 15:43:11 +0900 (e4cdaad)
@@ -0,0 +1,11 @@
+#include "grnxx/library.hpp"
+
+#include "grnxx/version.h"
+
+namespace grnxx {
+
+const char *Library::version() {
+  return GRNXX_VERSION;
+}
+
+}  // namespace grnxx

  Added: lib/grnxx/library.hpp (+13 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/library.hpp    2014-02-24 15:43:11 +0900 (3e8c877)
@@ -0,0 +1,13 @@
+#ifndef GRNXX_LIBRARY_HPP
+#define GRNXX_LIBRARY_HPP
+
+namespace grnxx {
+
+class Library {
+ public:
+  static const char *version();
+};
+
+}  // namespace grnxx
+
+#endif  // GRNXX_LIBRARY_HPP

  Deleted: lib/grnxx/lock.hpp (+0 -53) 100644
===================================================================
--- lib/grnxx/lock.hpp    2013-08-23 10:46:34 +0900 (9c36c5c)
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_LOCK_HPP
-#define GRNXX_LOCK_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/duration.hpp"
-#include "grnxx/mutex.hpp"
-
-namespace grnxx {
-
-class Lock {
- public:
-  Lock() = delete;
-  explicit Lock(Mutex *mutex) : mutex_((mutex->lock(), mutex)) {}
-  Lock(Mutex *mutex, Duration timeout)
-      : mutex_(mutex->lock(timeout) ? mutex : nullptr) {}
-  ~Lock() {
-    if (mutex_) {
-      mutex_->unlock();
-    }
-  }
-
-  Lock(const Lock &) = delete;
-  Lock &operator=(const Lock &) = delete;
-
-  explicit operator bool() const {
-    return mutex_ != nullptr;
-  }
-
- private:
-  Mutex *mutex_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_LOCK_HPP

  Deleted: lib/grnxx/logger.cpp (+0 -244) 100644
===================================================================
--- lib/grnxx/logger.cpp    2013-08-23 10:46:34 +0900 (66e68e7)
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-  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/logger.hpp"
-
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <new>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "grnxx/backtrace.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/system_clock.hpp"
-
-namespace grnxx {
-
-class LoggerSingleton {
- public:
-  static bool write(const StringBuilder &builder);
-
-  static bool open(const char *path);
-  static void close();
-
- private:
-  std::unique_ptr<char[]> path_;
-  std::unique_ptr<std::ofstream> file_;
-
-  // These variables may be used even after the instance termination.
-  static volatile bool initialized_;
-  static LoggerSingleton * volatile instance_;
-  static Mutex mutex_;
-
-  LoggerSingleton() : path_(), file_() {}
-  ~LoggerSingleton() {
-    Lock lock(&mutex_);
-    instance_ = nullptr;
-  }
-
-  static void initialize_once() {
-    if (!initialized_) {
-      // C++11 guarantees that a static local variable is initialized once.
-      // However, some compilers don't provide the guarantee.
-      static Mutex mutex;
-      Lock lock(&mutex);
-      if (!initialized_) {
-        initialize();
-      }
-    }
-  }
-  static void initialize() {
-    static LoggerSingleton instance;
-    instance_ = &instance;
-    initialized_ = true;
-  }
-
-  LoggerSingleton(const LoggerSingleton &) = delete;
-  LoggerSingleton &operator=(const LoggerSingleton &) = delete;
-};
-
-volatile bool LoggerSingleton::initialized_           = false;
-LoggerSingleton * volatile LoggerSingleton::instance_ = nullptr;
-Mutex LoggerSingleton::mutex_;
-
-bool LoggerSingleton::write(const StringBuilder &builder) {
-  initialize_once();
-  Lock lock(&mutex_);
-  if (!instance_) {
-    return false;
-  }
-  static constexpr LoggerFlags OUTPUT_FLAGS =
-      LOGGER_ENABLE_COUT | LOGGER_ENABLE_CERR | LOGGER_ENABLE_CLOG;
-  const LoggerFlags flags = Logger::flags();
-  if (!(flags & OUTPUT_FLAGS)) {
-    if (!instance_->file_ || !*instance_->file_) {
-      return false;
-    }
-  }
-  if (instance_->file_ && *instance_->file_) {
-    instance_->file_->write(builder.c_str(), builder.length()) << std::endl;
-  }
-  if (flags & LOGGER_ENABLE_COUT) {
-    std::cout.write(builder.c_str(), builder.length()) << '\n';
-  }
-  if (flags & LOGGER_ENABLE_CERR) {
-    std::cerr.write(builder.c_str(), builder.length()) << '\n';
-  }
-  if (flags & LOGGER_ENABLE_CLOG) {
-    std::clog.write(builder.c_str(), builder.length()) << '\n';
-  }
-  return true;
-}
-
-bool LoggerSingleton::open(const char *path) {
-  if (!path) {
-    return false;
-  }
-  initialize_once();
-  Lock lock(&mutex_);
-  if (!instance_) {
-    return false;
-  }
-  try {
-    const size_t buf_size = std::strlen(path) + 1;
-    std::unique_ptr<char[]> path_clone(new (std::nothrow) char[buf_size]);
-    if (!path_clone) {
-      return false;
-    }
-    std::memcpy(path_clone.get(), path, buf_size);
-    std::unique_ptr<std::ofstream> new_file(
-        new (std::nothrow) std::ofstream(path_clone.get(),
-            std::ios::out | std::ios::app | std::ios::binary));
-    if (!new_file || !*new_file) {
-      return false;
-    }
-    instance_->path_ = std::move(path_clone);
-    instance_->file_.swap(new_file);
-    return true;
-  } catch (...) {
-    return false;
-  }
-}
-
-void LoggerSingleton::close() {
-  initialize_once();
-  Lock lock(&mutex_);
-  if (instance_) {
-    instance_->file_.reset();
-    instance_->path_.reset();
-  }
-}
-
-LoggerFlags Logger::flags_   = LOGGER_DEFAULT;
-int Logger::max_level_       = NOTICE_LOGGER;
-int Logger::backtrace_level_ = ERROR_LOGGER;
-
-Logger::Logger(const char *file, int line, const char *func, int level)
-    : buf_(),
-      builder_(buf_, string_builder_flags()),
-      file_(file),
-      line_(line),
-      func_(func),
-      level_(level) {
-  append_line_header();
-}
-
-Logger::~Logger() {
-  if (level_ <= backtrace_level()) {
-    builder_ << backtrace();
-  }
-  LoggerSingleton::write(builder_);
-}
-
-bool Logger::open(const char *path) {
-  return LoggerSingleton::open(path);
-}
-
-void Logger::close() {
-  return LoggerSingleton::close();
-}
-
-void Logger::append_line_header() {
-  if (!builder_) {
-    return;
-  }
-  const LoggerFlags flags = Logger::flags();
-  if (flags & LOGGER_WITH_DATE_TIME) {
-    builder_ << SystemClock::now().local_time() << ": ";
-  }
-  if (flags & LOGGER_WITH_LOCATION) {
-    builder_ << file_ << ':' << line_ << ": In " << func_ << "(): ";
-  }
-  if (flags & LOGGER_WITH_LEVEL) {
-    switch (level_) {
-      case ERROR_LOGGER: {
-        builder_ << "error: ";
-        break;
-      }
-      case WARNING_LOGGER: {
-        builder_ << "warning: ";
-        break;
-      }
-      case NOTICE_LOGGER: {
-        builder_ << "notice: ";
-        break;
-      }
-      default: {
-        builder_ << "n/a (" << level_ << "): ";
-        break;
-      }
-    }
-  }
-}
-
-StringBuilderFlags Logger::string_builder_flags() {
-  StringBuilderFlags flags = STRING_BUILDER_NOEXCEPT;
-  if (Logger::flags() & LOGGER_ENABLE_AUTO_RESIZE) {
-    flags |= STRING_BUILDER_AUTO_RESIZE;
-  }
-  return flags;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const Logger::NewLine &) {
-  if (!builder) {
-    return builder;
-  }
-  builder << '\n';
-  Logger * const logger = reinterpret_cast<Logger *>(
-      (reinterpret_cast<char *>(&builder) - LOGGER_BUF_SIZE));
-  logger->append_line_header();
-  return builder;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const Logger::Backtrace &) {
-  if (!builder) {
-    return builder;
-  }
-  std::vector<std::string> backtrace;
-  if (Backtrace::pretty_backtrace(1, &backtrace)) {
-    for (size_t i = 0; i < backtrace.size(); ++i) {
-      builder << Logger::new_line() << backtrace[i].c_str();
-    }
-  }
-  return builder;
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/logger.hpp (+0 -148) 100644
===================================================================
--- lib/grnxx/logger.hpp    2013-08-23 10:46:34 +0900 (e34f772)
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_LOGGER_HPP
-#define GRNXX_LOGGER_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/string_builder.hpp"
-#include "grnxx/types.hpp"
-
-#define GRNXX_ERROR()   GRNXX_LOGGER(grnxx::ERROR_LOGGER)
-#define GRNXX_WARNING() GRNXX_LOGGER(grnxx::WARNING_LOGGER)
-#define GRNXX_NOTICE()  GRNXX_LOGGER(grnxx::NOTICE_LOGGER)
-
-#define GRNXX_LOGGER(level)\
-  ((level) > grnxx::Logger::max_level()) ? (void)0 :\
-  grnxx::Logger::Voidify() &\
-  grnxx::Logger(__FILE__, __LINE__, __func__, (level)).builder()
-
-namespace grnxx {
-
-constexpr size_t LOGGER_BUF_SIZE = 4096;
-
-enum LoggerLevel {
-  ERROR_LOGGER   = 0,
-  WARNING_LOGGER = 1,
-  NOTICE_LOGGER  = 2
-};
-
-class Logger;
-typedef FlagsImpl<Logger> LoggerFlags;
-
-// Use the default settings.
-constexpr LoggerFlags LOGGER_DEFAULT        = LoggerFlags::define(0x0000);
-
-// Logging with data and time.
-constexpr LoggerFlags LOGGER_WITH_DATE_TIME = LoggerFlags::define(0x0001);
-// Logging with __FILE__, __LINE__, and __func__.
-constexpr LoggerFlags LOGGER_WITH_LOCATION  = LoggerFlags::define(0x0002);
-// Logging with LoggerLevel.
-constexpr LoggerFlags LOGGER_WITH_LEVEL     = LoggerFlags::define(0x0004);
-// Enable all the LOGGER_WITH_* flags.
-constexpr LoggerFlags LOGGER_WITH_ALL       = LoggerFlags::define(0x0007);
-
-// Logging to the standard output.
-constexpr LoggerFlags LOGGER_ENABLE_COUT    = LoggerFlags::define(0x0100);
-// Logging to the standard error.
-constexpr LoggerFlags LOGGER_ENABLE_CERR    = LoggerFlags::define(0x0200);
-// Logging to the standard log.
-constexpr LoggerFlags LOGGER_ENABLE_CLOG    = LoggerFlags::define(0x0400);
-
-// Dynamically allocate memory when LOGGER_BUF_SIZE is not enough to store a
-// logging message.
-constexpr LoggerFlags LOGGER_ENABLE_AUTO_RESIZE = LoggerFlags::define(0x1000);
-
-class Logger {
- public:
-  Logger(const char *file, int line, const char *func, int level);
-  ~Logger();
-
-  // Open or create a file to which logs are written.
-  static bool open(const char *path);
-  // Close a file opened with open().
-  static void close();
-
-  static LoggerFlags flags() {
-    return flags_;
-  }
-  static int max_level() {
-    return max_level_;
-  }
-  static int backtrace_level() {
-    return backtrace_level_;
-  }
-
-  static void set_flags(LoggerFlags value) {
-    flags_ = value;
-  }
-  static void set_max_level(int value) {
-    max_level_ = value;
-  }
-  static void set_backtrace_level(int value) {
-    backtrace_level_ = value;
-  }
-
-  struct NewLine {};
-  struct Backtrace {};
-
-  static NewLine new_line() {
-    return NewLine();
-  }
-  static Backtrace backtrace() {
-    return Backtrace();
-  }
-
-  // Use an operator&() to voidify StringBuilder.
-  // The operators & and << are both left-to-right and << is prior to &.
-  struct Voidify {
-    void operator&(StringBuilder &) const {}
-  };
-
-  StringBuilder &builder() {
-    return builder_;
-  }
-
-  void append_line_header();
-
- private:
-  char buf_[LOGGER_BUF_SIZE];
-  StringBuilder builder_;
-  const char * const file_;
-  const int line_;
-  const char * const func_;
-  const int level_;
-
-  static LoggerFlags flags_;
-  static int max_level_;
-  static int backtrace_level_;
-
-  static StringBuilderFlags string_builder_flags();
-
-  Logger(const Logger &) = delete;
-  Logger &operator=(const Logger &) = delete;
-};
-
-// These operators must not be called with a regular (non-logger) builder.
-StringBuilder &operator<<(StringBuilder &builder, const Logger::NewLine &);
-StringBuilder &operator<<(StringBuilder &builder, const Logger::Backtrace &);
-
-}  // namespace grnxx
-
-#endif  // GRNXX_LOGGER_HPP

  Deleted: lib/grnxx/map.cpp (+0 -306) 100644
===================================================================
--- lib/grnxx/map.cpp    2013-08-23 10:46:34 +0900 (8a2f65f)
+++ /dev/null
@@ -1,306 +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 "grnxx/map.hpp"
-
-#include <limits>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage.hpp"
-#include "grnxx/string_builder.hpp"
-#include "grnxx/map/array_map.hpp"
-#include "grnxx/map/common_header.hpp"
-#include "grnxx/map/cursor_impl.hpp"
-#include "grnxx/map/double_array.hpp"
-#include "grnxx/map/hash_table.hpp"
-#include "grnxx/map/helper.hpp"
-#include "grnxx/map/patricia.hpp"
-#include "grnxx/map/scanner_impl.hpp"
-
-namespace grnxx {
-
-StringBuilder &operator<<(StringBuilder &builder, MapType type) {
-  switch (type) {
-    case MAP_ARRAY: {
-      return builder << "MAP_ARRAY";
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return builder << "MAP_DOUBLE_ARRAY";
-    }
-    case MAP_PATRICIA: {
-      return builder << "MAP_PATRICIA";
-    }
-    case MAP_HASH_TABLE: {
-      return builder << "MAP_HASH_TABLE";
-    }
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-MapOptions::MapOptions() {}
-
-template <typename T>
-Map<T>::Map() {}
-
-template <typename T>
-Map<T>::~Map() {}
-
-template <typename T>
-Map<T> *Map<T>::create(Storage *storage, uint32_t storage_node_id,
-                       MapType type, const MapOptions &options) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  switch (type) {
-    case MAP_ARRAY: {
-      return map::ArrayMap<T>::create(storage, storage_node_id, options);
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return map::DoubleArray<T>::create(storage, storage_node_id, options);
-    }
-    case MAP_PATRICIA: {
-      return map::Patricia<T>::create(storage, storage_node_id, options);
-    }
-    case MAP_HASH_TABLE: {
-      return map::HashTable<T>::create(storage, storage_node_id, options);
-    }
-    default: {
-      GRNXX_ERROR() << "invalid argument: type = " << type;
-      throw LogicError();
-    }
-  }
-}
-
-template <typename T>
-Map<T> *Map<T>::open(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  const map::CommonHeader * const common_header =
-      static_cast<const map::CommonHeader *>(storage_node.body());
-  if (!*common_header) {
-    GRNXX_ERROR() << "wrong header: format = " << common_header->format();
-    throw LogicError();
-  }
-  switch (common_header->type()) {
-    case MAP_ARRAY: {
-      return map::ArrayMap<T>::open(storage, storage_node_id);
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return map::DoubleArray<T>::open(storage, storage_node_id);
-    }
-    case MAP_PATRICIA: {
-      return map::Patricia<T>::open(storage, storage_node_id);
-    }
-    case MAP_HASH_TABLE: {
-      return map::HashTable<T>::open(storage, storage_node_id);
-    }
-    default: {
-      GRNXX_ERROR() << "invalid format: type = " << common_header->type();
-      throw LogicError();
-    }
-  }
-}
-
-template <typename T>
-void Map<T>::unlink(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<Map<T>> map(open(storage, storage_node_id));
-  storage->unlink_node(storage_node_id);
-}
-
-template <typename T>
-bool Map<T>::get(int64_t, Key *) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-bool Map<T>::get_next(int64_t key_id, int64_t *next_key_id, Key *next_key) {
-  // Naive implementation.
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > MAP_MAX_KEY_ID)) {
-    key_id = MAP_MIN_KEY_ID - 1;
-  }
-  for (++key_id; key_id <= max_key_id(); ++key_id) {
-    if (get(key_id, next_key)) {
-      if (next_key_id) {
-        *next_key_id = key_id;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool Map<T>::unset(int64_t key_id) {
-  // Naive implementation.
-  Key key;
-  if (!get(key_id, &key)) {
-    return false;
-  }
-  return remove(key);
-}
-
-template <typename T>
-bool Map<T>::reset(int64_t key_id, KeyArg dest_key) {
-  // Naive implementation.
-  Key src_key;
-  if (!get(key_id, &src_key)) {
-    return false;
-  }
-  return replace(src_key, dest_key);
-}
-
-template <typename T>
-bool Map<T>::find(KeyArg key, int64_t *key_id) {
-  // Naive implementation.
-  const Key normalized_key = map::Helper<T>::normalize(key);
-  int64_t next_key_id = MAP_INVALID_KEY_ID;
-  Key next_key;
-  while (get_next(next_key_id, &next_key_id, &next_key)) {
-    if (map::Helper<T>::equal_to(normalized_key, next_key)) {
-      if (key_id) {
-        *key_id = next_key_id;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool Map<T>::add(KeyArg, int64_t *) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-bool Map<T>::remove(KeyArg) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-bool Map<T>::replace(KeyArg, KeyArg, int64_t *) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-bool Map<T>::find_longest_prefix_match(KeyArg, int64_t *, Key *) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <>
-bool Map<Bytes>::find_longest_prefix_match(KeyArg query, int64_t *key_id,
-                                           Key *key) {
-  // Naive implementation.
-  int64_t next_key_id = MAP_INVALID_KEY_ID;
-  int64_t longest_prefix_key_id = MAP_INVALID_KEY_ID;
-  Key next_key;
-  Key longest_prefix_key = nullptr;
-  while (get_next(next_key_id, &next_key_id, &next_key)) {
-    if (query.starts_with(next_key)) {
-      if (next_key.size() >= longest_prefix_key.size()) {
-        longest_prefix_key_id = next_key_id;
-        longest_prefix_key = next_key;
-      }
-    }
-  }
-  if (longest_prefix_key_id != MAP_INVALID_KEY_ID) {
-    if (key_id) {
-      *key_id = longest_prefix_key_id;
-    }
-    if (key) {
-      *key = longest_prefix_key;
-    }
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-void Map<T>::defrag() {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-void Map<T>::truncate() {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::create_cursor(MapCursorAllKeys<T>,
-                                    const MapCursorOptions &options) {
-  return map::AllKeysCursor<T>::create(this, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::create_cursor(const MapCursorKeyIDRange<T> &query,
-                                    const MapCursorOptions &options) {
-  return map::KeyIDRangeCursor<T>::create(this, query, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::create_cursor(const MapCursorKeyRange<T> &query,
-                                    const MapCursorOptions &options) {
-  return map::KeyRangeCursor<T>::create(this, query, options);
-}
-
-template <>
-MapCursor<GeoPoint> *Map<GeoPoint>::create_cursor(
-    const MapCursorKeyRange<GeoPoint> &, const MapCursorOptions &) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <typename T>
-MapScanner<T> *Map<T>::create_scanner(KeyArg, const Charset *) {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template <>
-MapScanner<Bytes> *Map<Bytes>::create_scanner(KeyArg query,
-                                              const Charset *charset) {
-  return map::ScannerImpl<Bytes>::create(this, query, charset);
-}
-
-template class Map<int8_t>;
-template class Map<uint8_t>;
-template class Map<int16_t>;
-template class Map<uint16_t>;
-template class Map<int32_t>;
-template class Map<uint32_t>;
-template class Map<int64_t>;
-template class Map<uint64_t>;
-template class Map<double>;
-template class Map<GeoPoint>;
-template class Map<Bytes>;
-
-}  // namespace grnxx

  Deleted: lib/grnxx/map.hpp (+0 -163) 100644
===================================================================
--- lib/grnxx/map.hpp    2013-08-23 10:46:34 +0900 (36e6fa9)
+++ /dev/null
@@ -1,163 +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_MAP_HPP
-#define GRNXX_MAP_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/map_cursor.hpp"
-#include "grnxx/map_cursor_query.hpp"
-#include "grnxx/map_scanner.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Charset;
-class Storage;
-class StringBuilder;
-
-constexpr int64_t MAP_MIN_KEY_ID     = 0;
-constexpr int64_t MAP_MAX_KEY_ID     = (1LL << 40) - 2;
-constexpr int64_t MAP_INVALID_KEY_ID = MAP_MAX_KEY_ID + 1;
-
-enum MapType : uint32_t {
-  MAP_ARRAY        = 0,  // Array-based implementation.
-  MAP_HASH_TABLE   = 1,  // HashTable-based implementation.
-  MAP_PATRICIA     = 2,  // Patricia-based implementation.
-  MAP_DOUBLE_ARRAY = 3   // DoubleArray-based implementation.
-};
-
-StringBuilder &operator<<(StringBuilder &builder, MapType type);
-
-struct MapOptions {
-  // Initialize the members.
-  MapOptions();
-};
-
-template <typename T>
-class Map {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-  using Cursor = MapCursor<T>;
-  using Scanner = MapScanner<T>;
-
-  Map();
-  virtual ~Map();
-
-  // Create a map.
-  static Map *create(Storage *storage, uint32_t storage_node_id,
-                     MapType type, const MapOptions &options = MapOptions());
-  // Open a map.
-  static Map *open(Storage *storage, uint32_t storage_node_id);
-
-  // Unlink a map.
-  static void unlink(Storage *storage, uint32_t storage_node_id);
-
-  // Return the storage node ID.
-  virtual uint32_t storage_node_id() const = 0;
-  // Return the implementation type.
-  virtual MapType type() const = 0;
-
-  // Return the minimum key ID.
-  constexpr int64_t min_key_id() const {
-    return MAP_MIN_KEY_ID;
-  }
-  // Return the maximum key ID ever used.
-  // The return value can be a negative value iff the map is empty.
-  virtual int64_t max_key_id() = 0;
-  // Return the number of keys.
-  virtual uint64_t num_keys() = 0;
-
-  // Get a key associated with "key_id" and return true on success.
-  // Assign the found key to "*key" iff "key" != nullptr.
-  virtual bool get(int64_t key_id, Key *key = nullptr);
-  // Find the next key and return true on success. The next key means the key
-  // associated with the smallest valid ID that is greater than "key_id".
-  // If "key_id" > MAP_MAX_KEY_ID, this finds the first key.
-  // Assign the ID to "*next_key_id" iff "next_key_id" != nullptr.
-  // Assign the key to "*next_key" iff "next_key" != nullptr.
-  virtual bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                        Key *next_key = nullptr);
-  // Remove a key associated with "key_id" and return true on success.
-  virtual bool unset(int64_t key_id);
-  // Replace a key associated with "key_id" with "dest_key" and return true
-  // on success.
-  virtual bool reset(int64_t key_id, KeyArg dest_key);
-
-  // Find "key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool find(KeyArg key, int64_t *key_id = nullptr);
-  // Add "key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool add(KeyArg key, int64_t *key_id = nullptr);
-  // Remove "key" and return true on success.
-  virtual bool remove(KeyArg key);
-  // Replace "src_key" with "dest_key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool replace(KeyArg src_key, KeyArg dest_key,
-                      int64_t *key_id = nullptr);
-
-  // Perform longest prefix matching and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  // Assign the key to "*key" iff "key" != nullptr.
-  virtual bool find_longest_prefix_match(KeyArg query,
-                                         int64_t *key_id = nullptr,
-                                         Key *key = nullptr);
-
-  // Defrag components.
-  virtual void defrag();
-
-  // Remove all the keys in "*this" and return true on success.
-  virtual void truncate();
-
-  // Return a reference to create a cursor query.
-  MapCursorAllKeys<T> all_keys() const {
-    return MapCursorAllKeys<T>();
-  }
-  // Return a reference to create a cursor query.
-  MapCursorKeyID<T> key_id() const {
-    return MapCursorKeyID<T>();
-  }
-  // Return a reference to create a cursor query.
-  MapCursorKey<T> key() const {
-    return MapCursorKey<T>();
-  }
-
-  // Create a cursor for accessing all the keys.
-  virtual Cursor *create_cursor(
-      MapCursorAllKeys<T> query,
-      const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys that satisfy "query".
-  virtual Cursor *create_cursor(
-      const MapCursorKeyIDRange<T> &query,
-      const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys that satisfy "query".
-  virtual Cursor *create_cursor(
-      const MapCursorKeyRange<T> &query,
-      const MapCursorOptions &options = MapCursorOptions());
-
-  // Create a MapScanner object to find keys in "query".
-  virtual Scanner *create_scanner(KeyArg query,
-                                  const Charset *charset = nullptr);
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HPP

  Deleted: lib/grnxx/map/Makefile.am (+0 -31) 100644
===================================================================
--- lib/grnxx/map/Makefile.am    2013-08-23 10:46:34 +0900 (a841299)
+++ /dev/null
@@ -1,31 +0,0 @@
-noinst_LTLIBRARIES = libgrnxx_map.la
-
-libgrnxx_map_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_map_la_SOURCES =				\
-	array_map.cpp					\
-	bytes_pool.cpp					\
-	common_header.cpp				\
-	cursor_impl.cpp					\
-	double_array.cpp				\
-	hash_table.cpp					\
-	key_pool.cpp					\
-	patricia.cpp					\
-	pool.cpp					\
-	scanner_impl.cpp
-
-libgrnxx_map_includedir = ${includedir}/grnxx/map
-libgrnxx_map_include_HEADERS =				\
-	array_map.hpp					\
-	bytes_pool.hpp					\
-	common_header.hpp				\
-	cursor_impl.hpp					\
-	double_array.hpp				\
-	hash.hpp					\
-	hash_table.hpp					\
-	header.hpp					\
-	helper.hpp					\
-	key_pool.hpp					\
-	patricia.hpp					\
-	pool.hpp					\
-	scanner_impl.hpp

  Deleted: lib/grnxx/map/array_map.cpp (+0 -376) 100644
===================================================================
--- lib/grnxx/map/array_map.cpp    2013-08-23 10:46:34 +0900 (568daa6)
+++ /dev/null
@@ -1,376 +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 "grnxx/map/array_map.hpp"
-
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map/common_header.hpp"
-#include "grnxx/map/helper.hpp"
-#include "grnxx/map/pool.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::ArrayMap";
-
-}  // namespace
-
-struct ArrayMapHeader {
-  CommonHeader common_header;
-  uint32_t pool_storage_node_id;
-  uint64_t pool_id;
-  Mutex mutex;
-
-  // Initialize the member variables.
-  ArrayMapHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-ArrayMapHeader::ArrayMapHeader()
-    : common_header(FORMAT_STRING, MAP_ARRAY),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      pool_id(0) {}
-
-ArrayMapHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-template <typename T>
-ArrayMap<T>::ArrayMap()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pool_(),
-      queue_(),
-      pool_id_(0),
-      clock_() {}
-
-template <typename T>
-ArrayMap<T>::~ArrayMap() {}
-
-template <typename T>
-ArrayMap<T> *ArrayMap<T>::create(Storage *storage, uint32_t storage_node_id,
-                                 const MapOptions &options) {
-  std::unique_ptr<ArrayMap> map(new (std::nothrow) ArrayMap);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::ArrayMap failed";
-    throw MemoryError();
-  }
-  map->create_map(storage, storage_node_id, options);
-  return map.release();
-}
-
-template <typename T>
-ArrayMap<T> *ArrayMap<T>::open(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<ArrayMap> map(new (std::nothrow) ArrayMap);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::ArrayMap failed";
-    throw MemoryError();
-  }
-  map->open_map(storage, storage_node_id);
-  return map.release();
-}
-
-template <typename T>
-uint32_t ArrayMap<T>::storage_node_id() const {
-  return storage_node_id_;
-}
-
-template <typename T>
-MapType ArrayMap<T>::type() const {
-  return MAP_ARRAY;
-}
-
-template <typename T>
-int64_t ArrayMap<T>::max_key_id() {
-  refresh_if_possible();
-  return pool_->max_key_id();
-}
-
-template <typename T>
-uint64_t ArrayMap<T>::num_keys() {
-  refresh_if_possible();
-  return pool_->num_keys();
-}
-
-template <typename T>
-bool ArrayMap<T>::get(int64_t key_id, Key *key) {
-  refresh_if_possible();
-  Pool * const pool = pool_.get();
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > pool->max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  if (key) {
-    return pool->get(key_id, key);
-  }
-  return pool->get_bit(key_id);
-}
-
-template <typename T>
-bool ArrayMap<T>::unset(int64_t key_id) {
-  refresh_if_possible();
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > pool_->max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  if (!pool_->get_bit(key_id)) {
-    // Not found.
-    return false;
-  }
-  pool_->unset(key_id);
-  return true;
-}
-
-template <typename T>
-bool ArrayMap<T>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_if_possible();
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > pool_->max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  if (!pool_->get_bit(key_id)) {
-    // Not found.
-    return false;
-  }
-  if (find(dest_key)) {
-    // Found.
-    return false;
-  }
-  pool_->reset(key_id, Helper<T>::normalize(dest_key));
-  return true;
-}
-
-template <typename T>
-bool ArrayMap<T>::find(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  Pool * const pool = pool_.get();
-  const Key normalized_key = map::Helper<T>::normalize(key);
-  const int64_t max_key_id = pool->max_key_id();
-  for (int64_t i = MAP_MIN_KEY_ID; i <= max_key_id; ++i) {
-    Key stored_key;
-    if (pool->get(i, &stored_key)) {
-      if (Helper<T>::equal_to(normalized_key, stored_key)) {
-        // Found.
-        if (key_id) {
-          *key_id = i;
-        }
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool ArrayMap<T>::add(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  const Key normalized_key = Helper<T>::normalize(key);
-  const int64_t max_key_id = pool_->max_key_id();
-  for (int64_t i = MAP_MIN_KEY_ID; i <= max_key_id; ++i) {
-    Key stored_key;
-    if (pool_->get(i, &stored_key)) {
-      if (Helper<T>::equal_to(normalized_key, stored_key)) {
-        // Found.
-        if (key_id) {
-          *key_id = i;
-        }
-        return false;
-      }
-    }
-  }
-  if (key_id) {
-    *key_id = pool_->add(normalized_key);
-  } else {
-    pool_->add(normalized_key);
-  }
-  return true;
-}
-
-template <typename T>
-bool ArrayMap<T>::remove(KeyArg key) {
-  refresh_if_possible();
-  int64_t key_id;
-  if (!find(key, &key_id)) {
-    // Not found.
-    return false;
-  }
-  pool_->unset(key_id);
-  return true;
-}
-
-template <typename T>
-bool ArrayMap<T>::replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id) {
-  refresh_if_possible();
-  const Key normalized_src_key = Helper<T>::normalize(src_key);
-  const Key normalized_dest_key = Helper<T>::normalize(dest_key);
-  int64_t src_key_id = MAP_INVALID_KEY_ID;
-  const int64_t max_key_id = pool_->max_key_id();
-  for (int64_t i = MAP_MIN_KEY_ID; i <= max_key_id; ++i) {
-    Key stored_key;
-    if (pool_->get(i, &stored_key)) {
-      if (Helper<T>::equal_to(normalized_src_key, stored_key)) {
-        // Source key found.
-        src_key_id = i;
-      }
-      if (Helper<T>::equal_to(normalized_dest_key, stored_key)) {
-        // Destination key found.
-        return false;
-      }
-    }
-  }
-  if (src_key_id == MAP_INVALID_KEY_ID) {
-    // Not found.
-    return false;
-  }
-  pool_->reset(src_key_id, normalized_dest_key);
-  if (key_id) {
-    *key_id = src_key_id;
-  }
-  return true;
-}
-
-template <typename T>
-void ArrayMap<T>::defrag() {
-  refresh_if_possible();
-  pool_->defrag();
-}
-
-template <typename T>
-void ArrayMap<T>::sweep(Duration lifetime) {
-  refresh_if_possible();
-  const Time threshold = clock_.now() - lifetime;
-  while (!queue_.empty()) {
-    QueueEntry &queue_entry = queue_.front();
-    if (queue_entry.time <= threshold) {
-      queue_.pop();
-    }
-  }
-  pool_->sweep(lifetime);
-}
-
-template <typename T>
-void ArrayMap<T>::truncate() {
-  refresh_if_possible();
-  if (pool_->max_key_id() == 0) {
-    // Nothing to do.
-    return;
-  }
-  std::unique_ptr<Pool> new_pool(Pool::create(storage_, storage_node_id_));
-  const uint32_t old_pool_storage_node_id = pool_->storage_node_id();
-  {
-    // Validate a new pool.
-    Lock lock(&header_->mutex);
-    header_->pool_storage_node_id = new_pool->storage_node_id();
-    ++header_->pool_id;
-    pool_.swap(new_pool);
-    pool_id_ = header_->pool_id;
-  }
-  Pool::unlink(storage_, old_pool_storage_node_id);
-  try {
-    queue_.push(QueueEntry{ std::move(new_pool), clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-template <typename T>
-void ArrayMap<T>::create_map(Storage *storage, uint32_t storage_node_id,
-                             const MapOptions &) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    pool_.reset(Pool::create(storage, storage_node_id_));
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    pool_id_ = ++header_->pool_id;
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void ArrayMap<T>::open_map(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << storage_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node_id;
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-}
-
-template <typename T>
-void ArrayMap<T>::refresh_if_possible() {
-  if (pool_id_ != header_->pool_id) {
-    refresh();
-  }
-}
-
-template <typename T>
-void ArrayMap<T>::refresh() {
-  Lock lock(&header_->mutex);
-  if (pool_id_ != header_->pool_id) {
-    std::unique_ptr<Pool> new_pool(
-        Pool::open(storage_, header_->pool_storage_node_id));
-    pool_.swap(new_pool);
-    pool_id_ = header_->pool_id;
-    try {
-      queue_.push(QueueEntry{ std::move(new_pool), clock_.now() });
-    } catch (const std::exception &exception) {
-      GRNXX_ERROR() << "std::queue::push() failed";
-      throw StandardError(exception);
-    }
-  }
-}
-
-template class ArrayMap<int8_t>;
-template class ArrayMap<uint8_t>;
-template class ArrayMap<int16_t>;
-template class ArrayMap<uint16_t>;
-template class ArrayMap<int32_t>;
-template class ArrayMap<uint32_t>;
-template class ArrayMap<int64_t>;
-template class ArrayMap<uint64_t>;
-template class ArrayMap<double>;
-template class ArrayMap<GeoPoint>;
-template class ArrayMap<Bytes>;
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/array_map.hpp (+0 -105) 100644
===================================================================
--- lib/grnxx/map/array_map.hpp    2013-08-23 10:46:34 +0900 (b331877)
+++ /dev/null
@@ -1,105 +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_MAP_ARRAY_MAP_HPP
-#define GRNXX_MAP_ARRAY_MAP_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-#include <queue>
-
-#include "grnxx/duration.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-template <typename T> class Pool;
-
-struct ArrayMapHeader;
-
-template <typename T>
-class ArrayMap : public Map<T> {
-  using Header     = ArrayMapHeader;
-  using Pool       = map::Pool<T>;
-
-  struct QueueEntry {
-    std::unique_ptr<Pool> pool;
-    Time time;
-  };
-
- public:
-  using Key    = typename Map<T>::Key;
-  using KeyArg = typename Map<T>::KeyArg;
-  using Cursor = typename Map<T>::Cursor;
-
-  ArrayMap();
-  ~ArrayMap();
-
-  static ArrayMap *create(Storage *storage, uint32_t storage_node_id,
-                          const MapOptions &options = MapOptions());
-  static ArrayMap *open(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const;
-  MapType type() const;
-
-  int64_t max_key_id();
-  uint64_t num_keys();
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  void defrag();
-  void sweep(Duration lifetime);
-
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<Pool> pool_;
-  std::queue<QueueEntry> queue_;
-  uint64_t pool_id_;
-  PeriodicClock clock_;
-
-  void create_map(Storage *storage, uint32_t storage_node_id,
-                  const MapOptions &options);
-  void open_map(Storage *storage, uint32_t storage_node_id);
-
-  inline void refresh_if_possible();
-  void refresh();
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_ARRAY_MAP_HPP

  Deleted: lib/grnxx/map/bytes_pool.cpp (+0 -366) 100644
===================================================================
--- lib/grnxx/map/bytes_pool.cpp    2013-08-23 10:46:34 +0900 (0402fd1)
+++ /dev/null
@@ -1,366 +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 "grnxx/map/bytes_pool.hpp"
-
-#include <cstring>
-#include <new>
-
-#include "grnxx/common_header.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::BytesPool";
-
-constexpr uint64_t POOL_SIZE              = 1ULL << 48;
-constexpr uint64_t PAGE_HEADER_ARRAY_SIZE = POOL_SIZE / BytesPool::page_size();
-
-constexpr uint32_t MAX_PAGE_ID     = PAGE_HEADER_ARRAY_SIZE - 1;
-constexpr uint32_t INVALID_PAGE_ID = MAX_PAGE_ID + 1;
-
-}  // namespace
-
-struct BytesPoolHeader {
-  grnxx::CommonHeader common_header;
-  uint64_t next_offset;
-  uint32_t max_page_id;
-  uint32_t latest_empty_page_id;
-  uint32_t latest_idle_page_id;
-  uint32_t pool_storage_node_id;
-  uint32_t page_headers_storage_node_id;
-  uint32_t reserved;
-
-  // Initialize the member variables.
-  BytesPoolHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-BytesPoolHeader::BytesPoolHeader()
-    : common_header(FORMAT_STRING),
-      next_offset(0),
-      max_page_id(0),
-      latest_empty_page_id(INVALID_PAGE_ID),
-      latest_idle_page_id(INVALID_PAGE_ID),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      page_headers_storage_node_id(STORAGE_INVALID_NODE_ID),
-      reserved(0) {}
-
-BytesPoolHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, BytesPoolPageStatus status) {
-  switch (status) {
-    case BYTES_POOL_PAGE_ACTIVE: {
-      return builder << "BYTES_POOL_PAGE_ACTIVE";
-    }
-    case BYTES_POOL_PAGE_IN_USE: {
-      return builder << "BYTES_POOL_PAGE_IN_USE";
-    }
-    case BYTES_POOL_PAGE_EMPTY: {
-      return builder << "BYTES_POOL_PAGE_EMPTY";
-    }
-    case BYTES_POOL_PAGE_IDLE: {
-      return builder << "BYTES_POOL_PAGE_IDLE";
-    }
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-BytesPoolPageHeader::BytesPoolPageHeader()
-    : status(BYTES_POOL_PAGE_ACTIVE),
-      size_in_use(0),
-      modified_time(0) {}
-
-BytesPool::BytesPool()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pool_(),
-      page_headers_() {}
-
-BytesPool *BytesPool::create(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<BytesPool> pool(new (std::nothrow) BytesPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::BytesPool failed";
-    throw MemoryError();
-  }
-  pool->create_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-BytesPool *BytesPool::open(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<BytesPool> pool(new (std::nothrow) BytesPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::BytesPool failed";
-    throw MemoryError();
-  }
-  pool->open_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-void BytesPool::unlink(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<BytesPool> pool(BytesPool::open(storage, storage_node_id));
-  storage->unlink_node(storage_node_id);
-}
-
-void BytesPool::unset(uint64_t value_id) {
-  const uint64_t offset = get_offset(value_id);
-  const uint32_t size = get_size(value_id);
-  const uint32_t page_id = get_page_id(offset);
-  if ((size > MAX_VALUE_SIZE) || (page_id > header_->max_page_id)) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size
-                  << ", page_id = " << page_id
-                  << ", max_size = " << MAX_VALUE_SIZE
-                  << ", max_page_id = " << header_->max_page_id;
-    throw LogicError();
-  }
-  PageHeader * const page_header = &page_headers_->get_value(page_id);
-  if ((page_header->status != BYTES_POOL_PAGE_ACTIVE) &&
-      (page_header->status != BYTES_POOL_PAGE_IN_USE)) {
-    GRNXX_ERROR() << "wrong page: page_id = " << page_id
-                  << ", status = " << page_header->status;
-    throw LogicError();
-  }
-  if (size > page_header->size_in_use) {
-    GRNXX_ERROR() << "wrong page: size = " << size
-                  << ", size_in_use = " << page_header->size_in_use;
-    throw LogicError();
-  }
-  if ((page_header->status == BYTES_POOL_PAGE_ACTIVE) ||
-      (size < page_header->size_in_use)) {
-    // This operation does not change the page status.
-    page_header->size_in_use -= size;
-  } else {
-    // This operation makes the page EMPTY.
-    make_page_empty(page_id, page_header);
-  }
-}
-
-uint64_t BytesPool::add(ValueArg value) {
-  if (value.size() > MAX_VALUE_SIZE) {
-    GRNXX_ERROR() << "invalid argument: size = " << value.size()
-                  << ", max_size = " << MAX_VALUE_SIZE;
-    throw LogicError();
-  }
-  uint64_t offset = header_->next_offset;
-  uint32_t size = static_cast<uint32_t>(value.size());
-  uint32_t page_id = get_page_id(offset);
-  PageHeader *page_header = &page_headers_->get_value(page_id);
-  uint32_t offset_in_page = get_offset_in_page(offset);
-  const uint32_t size_left = POOL_PAGE_SIZE - offset_in_page;
-  if (size >= size_left) {
-    uint32_t next_page_id;
-    PageHeader *next_page_header = reserve_active_page(&next_page_id);
-    if (size > size_left) {
-      // Skip the remaining space of the previous ACTIVE page.
-      if (page_header->size_in_use == 0) {
-        // Change the page status from ACTIVE to EMPTY.
-        make_page_empty(page_id, page_header);
-      } else {
-        // Change the page status from ACTIVE to IN_USE.
-        page_header->status = BYTES_POOL_PAGE_IN_USE;
-        page_header->modified_time = clock_.now();
-      }
-      // Use the new ACTIVE page.
-      header_->next_offset = next_page_id * POOL_PAGE_SIZE;
-      offset = header_->next_offset;
-      page_id = next_page_id;
-      page_header = next_page_header;
-    } else {
-      // Use the previous ACTIVE page.
-      page_header->status = BYTES_POOL_PAGE_IN_USE;
-      page_header->modified_time = clock_.now();
-      header_->next_offset = next_page_id * POOL_PAGE_SIZE;
-    }
-  }
-  uint8_t * const value_buf = &pool_->get_value(offset);
-  std::memcpy(value_buf, value.data(), size);
-  page_header->size_in_use += size;
-  if (offset == header_->next_offset) {
-    header_->next_offset += size;
-  }
-  return get_value_id(offset, size);
-}
-
-void BytesPool::truncate() {
-  for (uint64_t page_id = 0; page_id < header_->max_page_id; ++page_id) {
-    PageHeader *page_header = &page_headers_->get_value(page_id);
-    if (page_header->status == BYTES_POOL_PAGE_IN_USE) {
-      make_page_empty(page_id, page_header);
-    }
-  }
-}
-
-void BytesPool::sweep(Duration lifetime) {
-  if (header_->latest_empty_page_id == INVALID_PAGE_ID) {
-    // Nothing to do.
-    return;
-  }
-  PageHeader * const latest_empty_page_header =
-      &page_headers_->get_value(header_->latest_empty_page_id);
-  const Time threshold = clock_.now() - lifetime;
-  do {
-    const uint32_t oldest_empty_page_id =
-        latest_empty_page_header->next_page_id;
-    PageHeader * const oldest_empty_page_header =
-        &page_headers_->get_value(oldest_empty_page_id);
-    if (oldest_empty_page_header->status != BYTES_POOL_PAGE_EMPTY) {
-      GRNXX_ERROR() << "status conflict: status = "
-                    << oldest_empty_page_header->status;
-      throw LogicError();
-    }
-    if (oldest_empty_page_header->modified_time > threshold) {
-      // The remaining empty pages are not ready.
-      break;
-    }
-    const uint32_t next_oldest_empty_page_id =
-        oldest_empty_page_header->next_page_id;
-    make_page_idle(oldest_empty_page_id, oldest_empty_page_header);
-    if (oldest_empty_page_header != latest_empty_page_header) {
-      latest_empty_page_header->next_page_id = next_oldest_empty_page_id;
-    } else {
-      header_->latest_empty_page_id = INVALID_PAGE_ID;
-    }
-  } while (header_->latest_empty_page_id != INVALID_PAGE_ID);
-}
-
-BytesPool::~BytesPool() {}
-
-void BytesPool::create_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    pool_.reset(Pool::create(storage, storage_node_id_, POOL_SIZE));
-    page_headers_.reset(PageHeaderArray::create(storage, storage_node_id,
-                                                PAGE_HEADER_ARRAY_SIZE));
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->page_headers_storage_node_id = page_headers_->storage_node_id();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void BytesPool::open_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  pool_.reset(Pool::open(storage, header_->pool_storage_node_id));
-  page_headers_.reset(
-      PageHeaderArray::open(storage, header_->page_headers_storage_node_id));
-}
-
-BytesPoolPageHeader *BytesPool::reserve_active_page(uint32_t *page_id) {
-  PageHeader *latest_idle_page_header = nullptr;
-  uint32_t next_page_id;
-  if (header_->latest_idle_page_id != INVALID_PAGE_ID) {
-    // Use the oldest IDLE page.
-    latest_idle_page_header =
-        &page_headers_->get_value(header_->latest_idle_page_id);
-    next_page_id = latest_idle_page_header->next_page_id;
-  } else {
-    // Create a new page.
-    next_page_id = header_->max_page_id + 1;
-    if (next_page_id > MAX_PAGE_ID) {
-      GRNXX_ERROR() << "too many pages: next_page_id = " << next_page_id
-                    << ", max_page_id = " << MAX_PAGE_ID;
-      throw LogicError();
-    }
-  }
-  PageHeader * const next_page_header =
-      &page_headers_->get_value(next_page_id);
-  if (latest_idle_page_header) {
-    if (next_page_id != header_->latest_idle_page_id) {
-      latest_idle_page_header->next_page_id = next_page_header->next_page_id;
-    } else {
-      header_->latest_idle_page_id = INVALID_PAGE_ID;
-    }
-  } else {
-    ++header_->max_page_id;
-  }
-  *next_page_header = PageHeader();
-  next_page_header->modified_time = clock_.now();
-  *page_id = next_page_id;
-  return next_page_header;
-}
-
-void BytesPool::make_page_empty(uint32_t page_id, PageHeader *page_header) {
-  PageHeader *latest_empty_page_header = nullptr;
-  if (header_->latest_empty_page_id != INVALID_PAGE_ID) {
-    latest_empty_page_header =
-        &page_headers_->get_value(header_->latest_empty_page_id);
-  }
-  page_header->status = BYTES_POOL_PAGE_EMPTY;
-  if (latest_empty_page_header) {
-    page_header->next_page_id = latest_empty_page_header->next_page_id;
-    latest_empty_page_header->next_page_id = page_id;
-  } else {
-    page_header->next_page_id = page_id;
-  }
-  page_header->modified_time = clock_.now();
-  header_->latest_empty_page_id = page_id;
-}
-
-void BytesPool::make_page_idle(uint32_t page_id, PageHeader *page_header) {
-  PageHeader *latest_idle_page_header = nullptr;
-  if (header_->latest_idle_page_id != INVALID_PAGE_ID) {
-    latest_idle_page_header =
-        &page_headers_->get_value(header_->latest_idle_page_id);
-  }
-  page_header->status = BYTES_POOL_PAGE_IDLE;
-  if (latest_idle_page_header) {
-    page_header->next_page_id = latest_idle_page_header->next_page_id;
-    latest_idle_page_header->next_page_id = page_id;
-  } else {
-    page_header->next_page_id = page_id;
-  }
-  page_header->modified_time = clock_.now();
-  header_->latest_idle_page_id = page_id;
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/bytes_pool.hpp (+0 -180) 100644
===================================================================
--- lib/grnxx/map/bytes_pool.hpp    2013-08-23 10:46:34 +0900 (b6c82bc)
+++ /dev/null
@@ -1,180 +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_MAP_BYTES_POOL_HPP
-#define GRNXX_MAP_BYTES_POOL_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/array.hpp"
-#include "grnxx/bytes.hpp"
-#include "grnxx/duration.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-constexpr uint64_t BYTES_POOL_VALUE_ID_MASK = (1ULL << 61) - 1;
-constexpr uint64_t BYTES_POOL_MAX_VALUE_ID  = BYTES_POOL_VALUE_ID_MASK;
-
-struct BytesPoolHeader;
-
-enum BytesPoolPageStatus : uint32_t {
-  // The next byte sequence will be added to this page.
-  BYTES_POOL_PAGE_ACTIVE = 0,
-  // This page is in use.
-  BYTES_POOL_PAGE_IN_USE = 1,
-  // This page is empty but not ready-to-use.
-  BYTES_POOL_PAGE_EMPTY  = 2,
-  // This page is empty and ready-to-use.
-  BYTES_POOL_PAGE_IDLE   = 3
-};
-
-struct BytesPoolPageHeader {
-  // ACTIVE, IN_USE, EMPTY, and IDLE.
-  BytesPoolPageStatus status;
-  union {
-    // ACTIVE and IN_USE.
-    uint32_t size_in_use;
-    // EMPTY and IDLE.
-    uint32_t next_page_id;
-  };
-  // ACTIVE, IN_USE, EMPTY, and IDLE.
-  Time modified_time;
-
-  // Initialize member variables.
-  BytesPoolPageHeader();
-};
-
-class BytesPool {
-  using Header     = BytesPoolHeader;
-  using PageHeader = BytesPoolPageHeader;
-
-  static constexpr uint32_t POOL_PAGE_SIZE     = 1U << 20;
-  static constexpr uint32_t POOL_TABLE_SIZE    = 1U << 14;
-
-  static constexpr uint32_t MAX_VALUE_SIZE     = 4096;
-
-  // The number of bits allocated for representing a value size.
-  static constexpr uint8_t  VALUE_ID_SIZE_BITS = 13;
-  static constexpr uint64_t VALUE_ID_SIZE_MASK =
-      (1ULL << VALUE_ID_SIZE_BITS) - 1;
-
-  using Pool            = Array<uint8_t, POOL_PAGE_SIZE, POOL_TABLE_SIZE>;
-  using PageHeaderArray = Array<PageHeader, POOL_TABLE_SIZE>;
-
- public:
-  using Value    = typename Traits<Bytes>::Type;
-  using ValueArg = typename Traits<Bytes>::ArgumentType;
-
-  ~BytesPool();
-
-  // Create a pool.
-  static BytesPool *create(Storage *storage, uint32_t storage_node_id);
-  // Opena pool.
-  static BytesPool *open(Storage *storage, uint32_t storage_node_id);
-
-  // Unlink a pool.
-  static void unlink(Storage *storage, uint32_t storage_node_id);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  // Return the page size.
-  static constexpr uint64_t page_size() {
-    return POOL_PAGE_SIZE;
-  }
-
-  // Get a byte sequence.
-  Value get(uint64_t value_id) {
-    const uint64_t offset = get_offset(value_id);
-    const uint32_t size = get_size(value_id);
-    return Value(&pool_->get_value(offset), size);
-  }
-  // Remove a byte sequence.
-  void unset(uint64_t value_id);
-  // Add a byte sequence and return its ID.
-  uint64_t add(ValueArg value);
-
-  // Return the actually used size of a page in use.
-  // If a page is not in use, return the page size.
-  uint64_t get_page_size_in_use(uint64_t page_id) {
-    const PageHeader &page_header = page_headers_->get_value(page_id);
-    if (page_header.status == BYTES_POOL_PAGE_IN_USE) {
-      return page_header.size_in_use;
-    } else {
-      return page_size();
-    }
-  }
-
-  // Remove all the byte sequences.
-  void truncate();
-
-  // Sweep empty pages whose modified time <= (now - lifetime).
-  void sweep(Duration lifetime);
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  BytesPoolHeader *header_;
-  std::unique_ptr<Pool> pool_;
-  std::unique_ptr<PageHeaderArray> page_headers_;
-  PeriodicClock clock_;
-
-  BytesPool();
-
-  void create_pool(Storage *storage, uint32_t storage_node_id);
-  void open_pool(Storage *storage, uint32_t storage_node_id);
-
-  // Reserve a page.
-  PageHeader *reserve_active_page(uint32_t *page_id);
-  // Make a page empty.
-  void make_page_empty(uint32_t page_id, PageHeader *page_header);
-  // Make a page idle.
-  void make_page_idle(uint32_t page_id, PageHeader *page_header);
-
-  static uint64_t get_value_id(uint64_t offset, uint32_t size) {
-    return (offset * (VALUE_ID_SIZE_MASK + 1)) | size;
-  }
-  static uint64_t get_offset(uint64_t value_id) {
-    return value_id / (VALUE_ID_SIZE_MASK + 1);
-  }
-  static uint32_t get_size(uint64_t value_id) {
-    return static_cast<uint32_t>(value_id & VALUE_ID_SIZE_MASK);
-  }
-  static uint32_t get_page_id(uint64_t offset) {
-    return static_cast<uint32_t>(offset / POOL_PAGE_SIZE);
-  }
-  static uint32_t get_offset_in_page(uint64_t offset) {
-    return static_cast<uint32_t>(offset % POOL_PAGE_SIZE);
-  }
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_BYTES_POOL_HPP

  Deleted: lib/grnxx/map/common_header.cpp (+0 -38) 100644
===================================================================
--- lib/grnxx/map/common_header.cpp    2013-08-23 10:46:34 +0900 (a5cb0a6)
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  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/map/common_header.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-// Implementations are defined in a namespace "grnxx::map".
-constexpr char FORMAT_PREFIX[] = "grnxx::map::";
-
-}  // namespace
-
-CommonHeader::CommonHeader(const char *format, MapType type)
-    : common_header_(format),
-      type_(type) {}
-
-CommonHeader::operator bool() const {
-  return common_header_.format().starts_with(FORMAT_PREFIX);
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/common_header.hpp (+0 -57) 100644
===================================================================
--- lib/grnxx/map/common_header.hpp    2013-08-23 10:46:34 +0900 (aef4a60)
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_HEADER_HPP
-#define GRNXX_MAP_HEADER_HPP
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/common_header.hpp"
-#include "grnxx/map.hpp"
-
-namespace grnxx {
-namespace map {
-
-class CommonHeader {
- public:
-  // Create a common header with "format", the current version, and "type".
-  CommonHeader(const char *format, MapType type);
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-
-  // Return the format string.
-  Bytes format() const {
-    return common_header_.format();
-  }
-  // Return the version string.
-  Bytes version() const {
-    return common_header_.version();
-  }
-  // Return the implementation type.
-  MapType type() const {
-    return type_;
-  }
-
- private:
-  grnxx::CommonHeader common_header_;
-  MapType type_;
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HEADER_HPP

  Deleted: lib/grnxx/map/cursor_impl.cpp (+0 -351) 100644
===================================================================
--- lib/grnxx/map/cursor_impl.cpp    2013-08-23 10:46:34 +0900 (98ae596)
+++ /dev/null
@@ -1,351 +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 "grnxx/map/cursor_impl.hpp"
-
-#include <memory>
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map.hpp"
-
-namespace grnxx {
-namespace map {
-
-template <typename T>
-AllKeysCursor<T>::AllKeysCursor()
-    : MapCursor<T>(), map_(), cur_(), end_(), step_(), count_(0), options_() {}
-
-template <typename T>
-AllKeysCursor<T>::~AllKeysCursor() {}
-
-template <typename T>
-AllKeysCursor<T> *AllKeysCursor<T>::create(
-    Map<T> *map, const MapCursorOptions &options) {
-  std::unique_ptr<AllKeysCursor<T>> cursor(
-      new (std::nothrow) AllKeysCursor<T>);
-  if (!cursor) {
-    GRNXX_ERROR() << "new grnxx::map::AllKeysCursor<T> failed";
-    throw MemoryError();
-  }
-  cursor->init(map, options);
-  return cursor.release();
-}
-
-template <typename T>
-bool AllKeysCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  while (cur_ != end_) {
-    cur_ += step_;
-    if (map_->get(cur_, &this->key_)) {
-      this->key_id_ = cur_;
-      ++count_;
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool AllKeysCursor<T>::remove() {
-  return map_->unset(this->key_id_);
-}
-
-template <typename T>
-void AllKeysCursor<T>::init(Map<T> *map, const MapCursorOptions &options) {
-  map_ = map;
-  options_ = options;
-  options_.flags = MAP_CURSOR_ORDER_BY_ID;
-  if (options.flags & MAP_CURSOR_REVERSE_ORDER) {
-    options_.flags |= MAP_CURSOR_REVERSE_ORDER;
-  }
-
-  const int64_t min = map->min_key_id();
-  const int64_t max = map->max_key_id();
-  if (min > max) {
-    // There are no keys in the range [min, max].
-    cur_ = end_ = 0;
-    return;
-  }
-
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = max + 1;
-    end_ = min;
-    step_ = -1;
-  } else {
-    cur_ = min - 1;
-    end_ = max;
-    step_ = 1;
-  }
-
-  // Skip the first "options_.offset" keys in range.
-  for (uint64_t count = 0; (count < options_.offset) && (cur_ != end_); ) {
-    cur_ += step_;
-    if (map_->get(cur_)) {
-      ++count;
-    }
-  }
-}
-
-template <typename T>
-KeyIDRangeCursor<T>::KeyIDRangeCursor()
-    : MapCursor<T>(), map_(), cur_(), end_(), step_(), count_(0),
-      query_(), options_() {}
-
-template <typename T>
-KeyIDRangeCursor<T>::~KeyIDRangeCursor() {}
-
-template <typename T>
-KeyIDRangeCursor<T> *KeyIDRangeCursor<T>::create(
-    Map<T> *map,
-    const MapCursorKeyIDRange<T> &query,
-    const MapCursorOptions &options) {
-  std::unique_ptr<KeyIDRangeCursor<T>> cursor(
-      new (std::nothrow) KeyIDRangeCursor<T>);
-  if (!cursor) {
-    GRNXX_ERROR() << "new grnxx::map::KeyIDRangeCursor<T> failed";
-    throw MemoryError();
-  }
-  cursor->init(map, query, options);
-  return cursor.release();
-}
-
-template <typename T>
-bool KeyIDRangeCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  while (cur_ != end_) {
-    cur_ += step_;
-    if (map_->get(cur_, &this->key_)) {
-      this->key_id_ = cur_;
-      ++count_;
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool KeyIDRangeCursor<T>::remove() {
-  return map_->unset(this->key_id_);
-}
-
-template <typename T>
-void KeyIDRangeCursor<T>::init(Map<T> *map,
-                               const MapCursorKeyIDRange<T> &query,
-                               const MapCursorOptions &options) {
-  map_ = map;
-  query_ = query;
-  options_ = options;
-  options_.flags = MAP_CURSOR_ORDER_BY_ID;
-  if (options.flags & MAP_CURSOR_REVERSE_ORDER) {
-    options_.flags |= MAP_CURSOR_REVERSE_ORDER;
-  }
-
-  int64_t min;
-  if (query.flags & MAP_CURSOR_KEY_ID_GREATER) {
-    min = query_.min + 1;
-  } else if (query.flags & MAP_CURSOR_KEY_ID_GREATER_EQUAL) {
-    min = query_.min;
-  } else {
-    min = map->min_key_id();
-  }
-
-  int64_t max;
-  if (query.flags & MAP_CURSOR_KEY_ID_LESS) {
-    max = query_.max + 1;
-  } else if (query.flags & MAP_CURSOR_KEY_ID_LESS_EQUAL) {
-    max = query_.max;
-  } else {
-    max = map->max_key_id();
-  }
-
-  if (min > max) {
-    // There are no keys in the range [min, max].
-    cur_ = end_ = 0;
-    return;
-  }
-
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = max + 1;
-    end_ = min;
-    step_ = -1;
-  } else {
-    cur_ = min - 1;
-    end_ = max;
-    step_ = 1;
-  }
-
-  // Skip the first "options_.offset" keys in range.
-  for (uint64_t count = 0; (count < options_.offset) && (cur_ != end_); ) {
-    cur_ += step_;
-    if (map_->get(cur_)) {
-      ++count;
-    }
-  }
-}
-
-template <typename T>
-KeyFilterCursor<T>::KeyFilterCursor()
-    : MapCursor<T>(), map_(), cur_(), end_(), step_(), count_(0), options_() {}
-
-template <typename T>
-KeyFilterCursor<T>::~KeyFilterCursor() {}
-
-template <typename T>
-bool KeyFilterCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  while (cur_ != end_) {
-    cur_ += step_;
-    if (map_->get(cur_, &this->key_)) {
-      if (filter(this->key_)) {
-        this->key_id_ = cur_;
-        ++count_;
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool KeyFilterCursor<T>::remove() {
-  return map_->unset(this->key_id_);
-}
-
-template <typename T>
-void KeyFilterCursor<T>::init(Map<T> *map, const MapCursorOptions &options) {
-  map_ = map;
-  options_ = options;
-  options_.flags = MAP_CURSOR_ORDER_BY_ID;
-  if (options.flags & MAP_CURSOR_REVERSE_ORDER) {
-    options_.flags |= MAP_CURSOR_REVERSE_ORDER;
-  }
-
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = map_->max_key_id() + 1;
-    end_ = 0;
-    step_ = -1;
-  } else {
-    cur_ = -1;
-    end_ = map_->max_key_id();
-    step_ = 1;
-  }
-
-  // Skip the first "options_.offset" keys in range.
-  for (uint64_t count = 0; (count < options_.offset) && (cur_ != end_); ) {
-    cur_ += step_;
-    if (map_->get(cur_, &this->key_)) {
-      if (filter(this->key_)) {
-        ++count;
-      }
-    }
-  }
-}
-
-template <typename T>
-KeyRangeCursor<T>::KeyRangeCursor() : KeyFilterCursor<T>(), query_() {}
-
-template <typename T>
-KeyRangeCursor<T>::~KeyRangeCursor() {}
-
-template <typename T>
-KeyRangeCursor<T> *KeyRangeCursor<T>::create(
-    Map<T> *map,
-    const MapCursorKeyRange<T> &query,
-    const MapCursorOptions &options) {
-  std::unique_ptr<KeyRangeCursor<T>> cursor(
-      new (std::nothrow) KeyRangeCursor<T>);
-  if (!cursor) {
-    GRNXX_ERROR() << "new grnxx::map::KeyRangeCursor<T> failed";
-    throw MemoryError();
-  }
-  cursor->query_ = query;
-  cursor->init(map, options);
-  return cursor.release();
-}
-
-template <typename T>
-bool KeyRangeCursor<T>::filter(KeyArg key) const {
-  if (query_.flags & MAP_CURSOR_KEY_LESS) {
-    if (key >= query_.min) {
-      return false;
-    }
-  } else if (query_.flags & MAP_CURSOR_KEY_LESS_EQUAL) {
-    if (key > query_.min) {
-      return false;
-    }
-  }
-  if (query_.flags & MAP_CURSOR_KEY_GREATER) {
-    if (key <= query_.min) {
-      return false;
-    }
-  } else if (query_.flags & MAP_CURSOR_KEY_GREATER_EQUAL) {
-    if (key < query_.min) {
-      return false;
-    }
-  }
-  return true;
-}
-
-template class AllKeysCursor<int8_t>;
-template class AllKeysCursor<int16_t>;
-template class AllKeysCursor<int32_t>;
-template class AllKeysCursor<int64_t>;
-template class AllKeysCursor<uint8_t>;
-template class AllKeysCursor<uint16_t>;
-template class AllKeysCursor<uint32_t>;
-template class AllKeysCursor<uint64_t>;
-template class AllKeysCursor<double>;
-template class AllKeysCursor<GeoPoint>;
-template class AllKeysCursor<Bytes>;
-
-template class KeyIDRangeCursor<int8_t>;
-template class KeyIDRangeCursor<int16_t>;
-template class KeyIDRangeCursor<int32_t>;
-template class KeyIDRangeCursor<int64_t>;
-template class KeyIDRangeCursor<uint8_t>;
-template class KeyIDRangeCursor<uint16_t>;
-template class KeyIDRangeCursor<uint32_t>;
-template class KeyIDRangeCursor<uint64_t>;
-template class KeyIDRangeCursor<double>;
-template class KeyIDRangeCursor<GeoPoint>;
-template class KeyIDRangeCursor<Bytes>;
-
-template class KeyRangeCursor<int8_t>;
-template class KeyRangeCursor<int16_t>;
-template class KeyRangeCursor<int32_t>;
-template class KeyRangeCursor<int64_t>;
-template class KeyRangeCursor<uint8_t>;
-template class KeyRangeCursor<uint16_t>;
-template class KeyRangeCursor<uint32_t>;
-template class KeyRangeCursor<uint64_t>;
-template class KeyRangeCursor<double>;
-// GeoPoint does not support comparison operators (<, <=, >, >=).
-//template class KeyRangeCursor<GeoPoint>;
-template class KeyRangeCursor<Bytes>;
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/cursor_impl.hpp (+0 -134) 100644
===================================================================
--- lib/grnxx/map/cursor_impl.hpp    2013-08-23 10:46:34 +0900 (21a3116)
+++ /dev/null
@@ -1,134 +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_MAP_CURSOR_IMPL_HPP
-#define GRNXX_MAP_CURSOR_IMPL_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/map_cursor.hpp"
-#include "grnxx/map_cursor_query.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace map {
-
-template <typename T>
-class AllKeysCursor : public MapCursor<T> {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  AllKeysCursor();
-  ~AllKeysCursor();
-
-  static AllKeysCursor *create(Map<T> *map, const MapCursorOptions &options);
-
-  bool next();
-  bool remove();
-
- private:
-  Map<T> *map_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-
-  void init(Map<T> *map, const MapCursorOptions &options);
-};
-
-template <typename T>
-class KeyIDRangeCursor : public MapCursor<T> {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  KeyIDRangeCursor();
-  ~KeyIDRangeCursor();
-
-  static KeyIDRangeCursor *create(Map<T> *map,
-                                  const MapCursorKeyIDRange<T> &query,
-                                  const MapCursorOptions &options);
-
-  bool next();
-  bool remove();
-
- private:
-  Map<T> *map_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorKeyIDRange<T> query_;
-  MapCursorOptions options_;
-
-  void init(Map<T> *map,
-            const MapCursorKeyIDRange<T> &query,
-            const MapCursorOptions &options);
-};
-
-template <typename T>
-class KeyFilterCursor : public MapCursor<T> {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  KeyFilterCursor();
-  virtual ~KeyFilterCursor();
-
-  bool next();
-  bool remove();
-
- protected:
-  Map<T> *map_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-
-  void init(Map<T> *map, const MapCursorOptions &options);
-
-  // Return true if "key" satisfies the query.
-  virtual bool filter(KeyArg key) const = 0;
-};
-
-template <typename T>
-class KeyRangeCursor : public KeyFilterCursor<T> {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  KeyRangeCursor();
-  ~KeyRangeCursor();
-
-  static KeyRangeCursor *create(Map<T> *map,
-                                const MapCursorKeyRange<T> &query,
-                                const MapCursorOptions &options);
-
- private:
-  MapCursorKeyRange<T> query_;
-
-  bool filter(KeyArg key) const;
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_CURSOR_IMPL_HPP

  Deleted: lib/grnxx/map/double_array.cpp (+0 -1507) 100644
===================================================================
--- lib/grnxx/map/double_array.cpp    2013-08-23 10:46:34 +0900 (48da750)
+++ /dev/null
@@ -1,1507 +0,0 @@
-/*
-  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/map/double_array.hpp"
-
-#include <new>
-
-#include "grnxx/array.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map/common_header.hpp"
-#include "grnxx/map/helper.hpp"
-#include "grnxx/map/pool.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::DoubleArray";
-
-constexpr uint64_t BLOCK_MAX_FAILURE_COUNT = 4;
-constexpr uint64_t BLOCK_MAX_LEVEL         = 5;
-constexpr uint64_t BLOCK_INVALID_ID        = (1ULL << 40) - 1;
-constexpr uint64_t BLOCK_SIZE              = 1ULL << 9;
-constexpr uint64_t BLOCK_MAX_COUNT         = 16;
-
-constexpr uint64_t TERMINAL_LABEL = 0x100;
-constexpr uint64_t MAX_LABEL      = TERMINAL_LABEL;
-constexpr uint64_t INVALID_LABEL  = MAX_LABEL + 1;
-constexpr uint64_t INVALID_OFFSET = 0;
-
-constexpr uint64_t ROOT_NODE_ID = 0;
-
-struct ImplHeader {
-  uint32_t nodes_storage_node_id;
-  uint32_t siblings_storage_node_id;
-  uint32_t blocks_storage_node_id;
-  uint64_t num_blocks;
-  uint64_t num_phantoms;
-  uint64_t num_zombies;
-  uint64_t latest_blocks[BLOCK_MAX_LEVEL + 1];
-
-  ImplHeader();
-};
-
-ImplHeader::ImplHeader()
-    : nodes_storage_node_id(STORAGE_INVALID_NODE_ID),
-      siblings_storage_node_id(STORAGE_INVALID_NODE_ID),
-      blocks_storage_node_id(STORAGE_INVALID_NODE_ID),
-      num_blocks(0),
-      num_phantoms(0),
-      num_zombies(0),
-      latest_blocks() {
-  for (uint64_t i = 0; i <= BLOCK_MAX_LEVEL; ++i) {
-    latest_blocks[i] = BLOCK_INVALID_ID;
-  }
-}
-
-// The internal structure of Block is as follows:
-// - values_[0]
-//    0-15 (16): first_phantom
-//   16-23 ( 8): level
-//   24-63 (40): next
-// - values_[1]
-//    0-15 (16): num_phantoms
-//   16-23 ( 8): failure_count
-//   24-63 (40): prev
-// where 0 is the LSB and 63 is the MSB.
-class Block {
-  // For values_[0].
-  static constexpr uint64_t FIRST_PHANTOM_MASK  = (1ULL << 16) - 1;
-  static constexpr uint8_t  FIRST_PHANTOM_SHIFT = 0;
-  static constexpr uint64_t LEVEL_MASK          = (1ULL << 8) - 1;
-  static constexpr uint8_t  LEVEL_SHIFT         = 16;
-  static constexpr uint64_t NEXT_MASK           = (1ULL << 40) - 1;
-  static constexpr uint8_t  NEXT_SHIFT          = 24;
-
-  // For values_[1].
-  static constexpr uint64_t NUM_PHANTOMS_MASK   = (1ULL << 16) - 1;
-  static constexpr uint8_t  NUM_PHANTOMS_SHIFT  = 0;
-  static constexpr uint64_t FAILURE_COUNT_MASK  = (1ULL << 8) - 1;
-  static constexpr uint8_t  FAILURE_COUNT_SHIFT = 16;
-  static constexpr uint64_t PREV_MASK           = (1ULL << 40) - 1;
-  static constexpr uint8_t  PREV_SHIFT          = 24;
-
- public:
-  static Block empty_block() {
-    return Block(0, BLOCK_SIZE << NUM_PHANTOMS_SHIFT);
-  }
-
-  // Return the first phantom node.
-  uint64_t first_phantom() const {
-    return (values_[0] >> FIRST_PHANTOM_SHIFT) & FIRST_PHANTOM_MASK;
-  }
-  // Return the level.
-  uint64_t level() const {
-    return (values_[0] >> LEVEL_SHIFT) & LEVEL_MASK;
-  }
-  // Return the next block ID of the same level.
-  uint64_t next() const {
-    return (values_[0] >> NEXT_SHIFT) & NEXT_MASK;
-  }
-
-  // Return the number of phantom nodes.
-  uint64_t num_phantoms() const {
-    return (values_[1] >> NUM_PHANTOMS_SHIFT) & NUM_PHANTOMS_MASK;
-  }
-  // Return the failure count.
-  uint64_t failure_count() const {
-    return (values_[1] >> FAILURE_COUNT_SHIFT) & FAILURE_COUNT_MASK;
-  }
-  // Return the previous block ID of the same level.
-  uint64_t prev() const {
-    return (values_[1] >> PREV_SHIFT) & PREV_MASK;
-  }
-
-  void set_first_phantom(uint64_t first_phantom) {
-    values_[0] = (values_[0] & ~(FIRST_PHANTOM_MASK << FIRST_PHANTOM_SHIFT)) |
-                 ((first_phantom & FIRST_PHANTOM_MASK) << FIRST_PHANTOM_SHIFT);
-  }
-  void set_level(uint64_t level) {
-    values_[0] = (values_[0] & ~(LEVEL_MASK << LEVEL_SHIFT)) |
-                 ((level & LEVEL_MASK) << LEVEL_SHIFT);
-  }
-  void set_next(uint64_t next) {
-    values_[0] = (values_[0] & ~(NEXT_MASK << NEXT_SHIFT)) |
-                 ((next & NEXT_MASK) << NEXT_SHIFT);
-  }
-
-  void set_num_phantoms(uint64_t num_phantoms) {
-    values_[1] = (values_[1] & ~(NUM_PHANTOMS_MASK << NUM_PHANTOMS_SHIFT)) |
-                 ((num_phantoms & NUM_PHANTOMS_MASK) << NUM_PHANTOMS_SHIFT);
-  }
-  void set_failure_count(uint64_t failure_count) {
-    values_[1] = (values_[1] & ~(FAILURE_COUNT_MASK << FAILURE_COUNT_SHIFT)) |
-                 ((failure_count & FAILURE_COUNT_MASK) << FAILURE_COUNT_SHIFT);
-  }
-  void set_prev(uint64_t prev) {
-    values_[1] = (values_[1] & ~(PREV_MASK << PREV_SHIFT)) |
-                 ((prev & PREV_MASK) << PREV_SHIFT);
-  }
-
- private:
-  uint64_t values_[2];
-
-  Block(uint64_t value_0, uint64_t value_1) : values_{ value_0, value_1 } {}
-};
-
-// The internal structure of DoubleArray is as follows:
-// - Common
-//      62 ( 1): is_phantom
-//      63 ( 1): is_origin
-// - Phantom: is_phantom
-//    0- 8 ( 9): next
-//    9-17 ( 9): prev
-//   18-61 (44): reserved
-// - NonPhantom: !is_phantom
-//    0- 8 ( 9): label
-//      60 ( 1): has_sibling
-//      61 ( 1): is_leaf
-// - Leaf: !is_phantom && is_leaf
-//    9-48 (40): key_id
-//   49-59 (11): reserved
-// - NonLeaf: !is_phantom && !is_leaf
-//    9-17 ( 9): child
-//   18-59 (42): offset
-// where 0 is the LSB and 63 is the MSB.
-class Node {
-  static constexpr uint64_t IS_PHANTOM_FLAG  = 1ULL << 62;
-  static constexpr uint64_t IS_ORIGIN_FLAG   = 1ULL << 63;
-
-  static constexpr uint64_t NEXT_MASK        = (1ULL << 9) - 1;
-  static constexpr uint8_t  NEXT_SHIFT       = 0;
-  static constexpr uint64_t PREV_MASK        = (1ULL << 9) - 1;
-  static constexpr uint8_t  PREV_SHIFT       = 9;
-
-  static constexpr uint64_t LABEL_MASK       = (1ULL << 9) - 1;
-  static constexpr uint8_t  LABEL_SHIFT      = 0;
-  static constexpr uint64_t HAS_SIBLING_FLAG = 1ULL << 60;
-  static constexpr uint64_t IS_LEAF_FLAG     = 1ULL << 61;
-
-  static constexpr uint64_t KEY_ID_MASK      = (1ULL << 40) - 1;
-  static constexpr uint8_t  KEY_ID_SHIFT     = 9;
-
-  static constexpr uint64_t CHILD_MASK       = (1ULL << 9) - 1;
-  static constexpr uint8_t  CHILD_SHIFT      = 9;
-  static constexpr uint64_t OFFSET_MASK      = (1ULL << 42) - 1;
-  static constexpr uint8_t  OFFSET_SHIFT     = 18;
-
- public:
-  // Create a phantom node.
-  static Node phantom_node(uint64_t next, uint64_t prev) {
-    return Node(IS_PHANTOM_FLAG | ((next & NEXT_MASK) << NEXT_SHIFT) |
-                                  ((prev & PREV_MASK) << PREV_SHIFT));
-  }
-
-  // Return true iff this node is a phantom node.
-  bool is_phantom() const {
-    return value_ & IS_PHANTOM_FLAG;
-  }
-  // Return true iff the ID of this node is used as an offset.
-  bool is_origin() const {
-    return value_ & IS_ORIGIN_FLAG;
-  }
-
-  // Return the ID of the next phantom node in the same block.
-  uint64_t next() const {
-    return (value_ >> NEXT_SHIFT) & NEXT_MASK;
-  }
-  // Return the ID of the prev phantom node in the same block.
-  uint64_t prev() const {
-    return (value_ >> PREV_SHIFT) & PREV_MASK;
-  }
-
-  // Return the label.
-  // Note that a phantom node returns an invalid label.
-  uint64_t label() const {
-    return (value_ >> LABEL_SHIFT) &
-           ((IS_PHANTOM_FLAG >> LABEL_SHIFT) | LABEL_MASK);
-  }
-  // Return true iff this node has a sibling with a greater label.
-  bool has_sibling() const {
-    return value_ & HAS_SIBLING_FLAG;
-  }
-  // Return true iff this node is a leaf node.
-  bool is_leaf() const {
-    return value_ & IS_LEAF_FLAG;
-  }
-
-  // Return the associated key ID.
-  uint64_t key_id() const {
-    return (value_ >> KEY_ID_SHIFT) & KEY_ID_MASK;
-  }
-
-  // Return the ID of the child node with the least label.
-  uint64_t child() const {
-    return (value_ >> CHILD_SHIFT) & CHILD_MASK;
-  }
-  // Return the offset to child nodes.
-  uint64_t offset() const {
-    return (value_ >> OFFSET_SHIFT) & OFFSET_MASK;
-  }
-
-  void unset_is_phantom() {
-    value_ = (value_ & IS_ORIGIN_FLAG) |
-             (INVALID_LABEL << LABEL_SHIFT) |
-             (INVALID_LABEL << CHILD_SHIFT) |
-             (INVALID_OFFSET << OFFSET_SHIFT);
-  }
-  void set_is_origin(bool is_origin) {
-    if (is_origin) {
-      value_ |= IS_ORIGIN_FLAG;
-    } else {
-      value_ &= ~IS_ORIGIN_FLAG;
-    }
-  }
-
-  void set_next(uint64_t next) {
-    value_ = (value_ & ~(NEXT_MASK << NEXT_SHIFT)) |
-             ((next & NEXT_MASK) << NEXT_SHIFT);
-  }
-  void set_prev(uint64_t prev) {
-    value_ = (value_ & ~(PREV_MASK << PREV_SHIFT)) |
-             ((prev & PREV_MASK) << PREV_SHIFT);
-  }
-  void set_next_and_prev(uint64_t next, uint64_t prev) {
-    constexpr uint64_t NEXT_AND_PREV_MASK =
-        (NEXT_MASK << NEXT_SHIFT) | (PREV_MASK << PREV_SHIFT);
-    value_ = (value_ & ~NEXT_AND_PREV_MASK) |
-             ((next & NEXT_MASK) << NEXT_SHIFT) |
-             ((prev & PREV_MASK) << PREV_SHIFT);
-  }
-
-  void set_label(uint64_t label) {
-    value_ = (value_ & ~(LABEL_MASK << LABEL_SHIFT)) |
-             ((label & LABEL_MASK) << LABEL_SHIFT);
-  }
-  void set_has_sibling() {
-    value_ |= HAS_SIBLING_FLAG;
-  }
-  // set_is_leaf() is not provided because set_key_id() sets IS_LEAF_FLAG.
-
-  void set_key_id(uint64_t key_id) {
-    value_ = (value_ & ~(KEY_ID_MASK << KEY_ID_SHIFT)) | IS_LEAF_FLAG |
-             ((key_id & KEY_ID_MASK) << KEY_ID_SHIFT);
-  }
-
-  void set_child(uint64_t child) {
-    value_ = (value_ & ~(CHILD_MASK << CHILD_SHIFT)) |
-             ((child & CHILD_MASK) << CHILD_SHIFT);
-  }
-  void set_offset(uint64_t offset) {
-    if (value_ & IS_LEAF_FLAG) {
-      value_ = (value_ & ~(IS_LEAF_FLAG | (OFFSET_MASK << OFFSET_SHIFT) |
-                           (CHILD_MASK << CHILD_SHIFT))) |
-               (offset << OFFSET_SHIFT) |
-               (INVALID_LABEL << CHILD_SHIFT);
-    } else {
-      value_ = (value_ & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (offset << OFFSET_SHIFT);
-    }
-  }
-
- private:
-  uint64_t value_;
-
-  explicit Node(uint64_t value) : value_(value) {}
-};
-
-}  // namespace
-
-class DoubleArrayImpl {
-  using Header       = ImplHeader;
-  using NodeArray    = Array<Node,     65536, 8192>;  // 42-bit
-  using SiblingArray = Array<uint8_t, 262144, 4096>;  // 42-bit
-  using BlockArray   = Array<Block,     8192, 1024>;  // 33-bit
-  using Pool         = map::Pool<Bytes>;
-
-  static constexpr uint64_t NODE_ARRAY_SIZE    = 1ULL << 42;
-  static constexpr uint64_t SIBLING_ARRAY_SIZE = 1ULL << 42;
-  static constexpr uint64_t BLOCK_ARRAY_SIZE   = 1ULL << 33;
-
- public:
-  using Key = typename Map<Bytes>::Key;
-  using KeyArg = typename Map<Bytes>::KeyArg;
-  using Cursor = typename Map<Bytes>::Cursor;
-
-  DoubleArrayImpl();
-  ~DoubleArrayImpl();
-
-  static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id,
-                                 Pool *pool);
-  static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id,
-                                 DoubleArrayImpl *src_impl);
-  static DoubleArrayImpl *open(Storage *storage, uint32_t storage_node_id,
-                               Pool *pool);
-
-  static void unlink(Storage *storage, uint32_t storage_node_id) {
-    storage->unlink_node(storage_node_id);
-  }
-
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  int64_t max_key_id() {
-    return pool_->max_key_id();
-  }
-  uint64_t num_keys() {
-    return pool_->num_keys();
-  }
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  bool find_longest_prefix_match(KeyArg query,
-                                 int64_t *key_id = nullptr,
-                                 Key *key = nullptr);
-
-//  Cursor *create_cursor(
-//      MapCursorAllKeys<Bytes> query,
-//      const MapCursorOptions &options = MapCursorOptions());
-//  Cursor *create_cursor(
-//      const MapCursorKeyIDRange<Bytes> &query,
-//      const MapCursorOptions &options = MapCursorOptions());
-//  Cursor *create_cursor(
-//      const MapCursorKeyRange<Bytes> &query,
-//      const MapCursorOptions &options = MapCursorOptions());
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<NodeArray> nodes_;
-  std::unique_ptr<SiblingArray> siblings_;
-  std::unique_ptr<BlockArray> blocks_;
-  Pool *pool_;
-
-  void create_impl(Storage *storage, uint32_t storage_node_id, Pool *pool);
-  void create_impl(Storage *storage, uint32_t storage_node_id,
-                   DoubleArrayImpl *src_impl);
-  void open_impl(Storage *storage, uint32_t storage_node_id, Pool *pool);
-
-  void defrag(DoubleArrayImpl *src_impl, uint64_t src, uint64_t dest);
-
-  bool replace_key(int64_t key_id, KeyArg src_key, KeyArg dest_key);
-
-  bool find_leaf(KeyArg key, Node **leaf_node, uint64_t *leaf_key_pos);
-  bool insert_leaf(KeyArg key, Node *node, uint64_t key_pos, Node **leaf_node);
-
-  Node *insert_node(Node *node, uint64_t label);
-  Node *separate(Node *node, uint64_t labels[2]);
-
-  void resolve(Node *node, uint64_t label);
-  void migrate_nodes(Node *node, uint64_t dest_offset,
-                     const uint64_t *labels, uint64_t num_labels);
-
-  uint64_t find_offset(const uint64_t *labels, uint64_t num_labels);
-
-  Node *reserve_node(uint64_t node_id);
-  Block *reserve_block(uint64_t block_id);
-
-  void update_block_level(uint64_t block_id, Block *block, uint64_t level);
-  void set_block_level(uint64_t block_id, Block *block, uint64_t level);
-  void unset_block_level(uint64_t block_id, Block *block);
-};
-
-DoubleArrayImpl::DoubleArrayImpl()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      nodes_(),
-      siblings_(),
-      blocks_(),
-      pool_(nullptr) {}
-
-DoubleArrayImpl::~DoubleArrayImpl() {}
-
-DoubleArrayImpl *DoubleArrayImpl::create(Storage *storage,
-                                         uint32_t storage_node_id,
-                                         Pool *pool) {
-  std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::map::DoubleArrayImpl failed";
-    throw MemoryError();
-  }
-  impl->create_impl(storage, storage_node_id, pool);
-  return impl.release();
-}
-
-DoubleArrayImpl *DoubleArrayImpl::create(Storage *storage,
-                                         uint32_t storage_node_id,
-                                         DoubleArrayImpl *src_impl) {
-  std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::map::DoubleArrayImpl failed";
-    throw MemoryError();
-  }
-  impl->create_impl(storage, storage_node_id, src_impl);
-  return impl.release();
-}
-
-DoubleArrayImpl *DoubleArrayImpl::open(Storage *storage,
-                                       uint32_t storage_node_id,
-                                       Pool *pool) {
-  std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::map::DoubleArrayImpl failed";
-    throw MemoryError();
-  }
-  impl->open_impl(storage, storage_node_id, pool);
-  return impl.release();
-}
-
-bool DoubleArrayImpl::get(int64_t key_id, Key *key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  if (key) {
-    return pool_->get(key_id, key);
-  }
-  return pool_->get_bit(key_id);
-}
-
-bool DoubleArrayImpl::unset(int64_t key_id) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  Key key;
-  if (!pool_->get(key_id, &key)) {
-    // Not found.
-    return false;
-  }
-  return remove(key);
-}
-
-bool DoubleArrayImpl::reset(int64_t key_id, KeyArg dest_key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  Key src_key;
-  if (!pool_->get(key_id, &src_key)) {
-    // Not found.
-    return false;
-  }
-  return replace(src_key, dest_key);
-}
-
-bool DoubleArrayImpl::find(KeyArg key, int64_t *key_id) {
-  uint64_t node_id = ROOT_NODE_ID;
-  Node node = nodes_->get(node_id);
-  uint64_t key_pos;
-  for (key_pos = 0; key_pos < key.size(); ++key_pos) {
-    if (node.is_leaf()) {
-      // Found.
-      break;
-    }
-    node_id = node.offset() ^ key[key_pos];
-    node = nodes_->get(node_id);
-    if (node.label() != key[key_pos]) {
-      // Not found.
-      return false;
-    }
-  }
-  if (!node.is_leaf()) {
-    if (node.child() != TERMINAL_LABEL) {
-      // Not found.
-      return false;
-    }
-    node_id = node.offset() ^ TERMINAL_LABEL;
-    node = nodes_->get(node_id);
-    if (!node.is_leaf()) {
-      // Not found.
-      return false;
-    }
-  }
-  Key stored_key;
-  if (!pool_->get(node.key_id(), &stored_key)) {
-    // Not found.
-    return false;
-  }
-  if (key.except_prefix(key_pos) != stored_key.except_prefix(key_pos)) {
-    // Not found.
-    return false;
-  }
-  if (key_id) {
-    *key_id = node.key_id();
-  }
-  return true;
-}
-
-bool DoubleArrayImpl::add(KeyArg key, int64_t *key_id) {
-  Node *node;
-  uint64_t key_pos;
-  find_leaf(key, &node, &key_pos);
-  if (!insert_leaf(key, node, key_pos, &node)) {
-    if (key_id) {
-      *key_id = node->key_id();
-    }
-    return false;
-  }
-  const int64_t next_key_id = pool_->add(key);
-  node->set_key_id(next_key_id);
-  if (key_id) {
-    *key_id = next_key_id;
-  }
-  return true;
-}
-
-bool DoubleArrayImpl::remove(KeyArg key) {
-  Node *node;
-  uint64_t key_pos;
-  if (!find_leaf(key, &node, &key_pos)) {
-    // Not found.
-    return false;
-  }
-  Key stored_key;
-  if (!pool_->get(node->key_id(), &stored_key)) {
-    // Not found.
-    return false;
-  }
-  if (key.except_prefix(key_pos) != stored_key.except_prefix(key_pos)) {
-    // Not found.
-    return false;
-  }
-  pool_->unset(node->key_id());
-  node->set_offset(INVALID_OFFSET);
-  return true;
-}
-
-bool DoubleArrayImpl::replace(KeyArg src_key, KeyArg dest_key,
-                              int64_t *key_id) {
-  int64_t src_key_id;
-  if (!find(src_key, &src_key_id)) {
-    // Not found.
-    return false;
-  }
-  if (!replace_key(src_key_id, src_key, dest_key)) {
-    // Found.
-    return false;
-  }
-  if (key_id) {
-    *key_id = src_key_id;
-  }
-  return true;
-}
-
-bool DoubleArrayImpl::find_longest_prefix_match(KeyArg query,
-                                                int64_t *key_id, Key *key) {
-  bool found = false;
-  uint64_t node_id = ROOT_NODE_ID;
-  Node node = nodes_->get(node_id);
-  uint64_t query_pos;
-  for (query_pos = 0; query_pos < query.size(); ++query_pos) {
-    if (node.is_leaf()) {
-      Key stored_key;
-      if (pool_->get(node.key_id(), &stored_key)) {
-        if ((stored_key.size() <= query.size()) &&
-            (stored_key.except_prefix(query_pos) ==
-             query.prefix(stored_key.size()).except_prefix(query_pos))) {
-          if (key_id) {
-            *key_id = node.key_id();
-          }
-          if (key) {
-            *key = stored_key;
-          }
-          found = true;
-        }
-      }
-      return found;
-    }
-
-    if (node.child() == TERMINAL_LABEL) {
-      Node leaf_node = nodes_->get(node.offset() ^ TERMINAL_LABEL);
-      if (leaf_node.is_leaf()) {
-        if (pool_->get(leaf_node.key_id(), key)) {
-          if (key_id) {
-            *key_id = leaf_node.key_id();
-          }
-          found = true;
-        }
-      }
-    }
-
-    node_id = node.offset() ^ query[query_pos];
-    node = nodes_->get(node_id);
-    if (node.label() != query[query_pos]) {
-      return found;
-    }
-  }
-
-  if (node.is_leaf()) {
-    Key stored_key;
-    if (pool_->get(node.key_id(), &stored_key)) {
-      if (stored_key.size() <= query.size()) {
-        if (key_id) {
-          *key_id = node.key_id();
-        }
-        if (key) {
-          *key = stored_key;
-        }
-        found = true;
-      }
-    }
-  } else if (node.child() == TERMINAL_LABEL) {
-    node = nodes_->get(node.offset() ^ TERMINAL_LABEL);
-    if (pool_->get(node.key_id(), key)) {
-      if (key_id) {
-        *key_id = node.key_id();
-      }
-      found = true;
-    }
-  }
-  return found;
-}
-
-void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id,
-                                  Pool *pool) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    pool_ = pool;
-    nodes_.reset(NodeArray::create(storage, storage_node_id_,
-                                   NODE_ARRAY_SIZE));
-    siblings_.reset(SiblingArray::create(storage, storage_node_id_,
-                                         SIBLING_ARRAY_SIZE));
-    blocks_.reset(BlockArray::create(storage, storage_node_id_,
-                                     BLOCK_ARRAY_SIZE));
-    header_->nodes_storage_node_id = nodes_->storage_node_id();
-    header_->siblings_storage_node_id = siblings_->storage_node_id();
-    header_->blocks_storage_node_id = blocks_->storage_node_id();
-    Node * const root_node = reserve_node(ROOT_NODE_ID);
-    root_node[INVALID_OFFSET - ROOT_NODE_ID].set_is_origin(true);
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id,
-                                  DoubleArrayImpl *src_impl) {
-  create_impl(storage, storage_node_id, src_impl->pool_);
-  try {
-    // Build a double-array from "src_impl".
-    defrag(src_impl, ROOT_NODE_ID, ROOT_NODE_ID);
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void DoubleArrayImpl::open_impl(Storage *storage, uint32_t storage_node_id,
-                                Pool *pool) {
-  storage_ = storage;
-  storage_node_id_ = storage_node_id;
-  StorageNode storage_node = storage->open_node(storage_node_id_);
-  if (storage_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << storage_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  header_ = static_cast<Header *>(storage_node.body());
-  pool_ = pool;
-  nodes_.reset(NodeArray::open(storage, header_->nodes_storage_node_id));
-  siblings_.reset(
-      SiblingArray::open(storage, header_->siblings_storage_node_id));
-  blocks_.reset(BlockArray::open(storage, header_->blocks_storage_node_id));
-}
-
-bool DoubleArrayImpl::replace_key(int64_t key_id, KeyArg src_key,
-                                  KeyArg dest_key) {
-  Node *dest_node;
-  uint64_t key_pos;
-  find_leaf(dest_key, &dest_node, &key_pos);
-  if (!insert_leaf(dest_key, dest_node, key_pos, &dest_node)) {
-    return false;
-  }
-  Node *src_node;
-  if (!find_leaf(src_key, &src_node, &key_pos)) {
-    // Critical error.
-    GRNXX_ERROR() << "not found: src_key = " << src_key;
-    throw LogicError();
-  }
-  pool_->reset(key_id, dest_key);
-  dest_node->set_key_id(key_id);
-  src_node->set_offset(INVALID_OFFSET);
-  return true;
-}
-
-void DoubleArrayImpl::defrag(DoubleArrayImpl *src_impl, uint64_t src_node_id,
-                             uint64_t dest_node_id) {
-  const Node src_node = src_impl->nodes_->get(src_node_id);
-  Node &dest_node = nodes_->get_value(dest_node_id);
-  if (src_node.is_leaf()) {
-    dest_node.set_key_id(src_node.key_id());
-    return;
-  }
-
-  const uint64_t src_offset = src_node.offset();
-  uint64_t dest_offset;
-  {
-    uint64_t labels[MAX_LABEL + 1];
-    uint64_t num_labels = 0;
-    uint64_t label = src_node.child();
-    while (label != INVALID_LABEL) {
-      const uint64_t child_node_id = src_offset ^ label;
-      const Node child_node = src_impl->nodes_->get(child_node_id);
-      if (child_node.is_leaf() || (child_node.child() != INVALID_LABEL)) {
-        labels[num_labels++] = label;
-      }
-      if (child_node.has_sibling()) {
-        label = src_impl->siblings_->get(child_node_id);
-      } else {
-        label = INVALID_LABEL;
-      }
-    }
-    if (num_labels == 0) {
-      return;
-    }
-
-    dest_offset = find_offset(labels, num_labels);
-    for (uint64_t i = 0; i < num_labels; ++i) {
-      const uint64_t child_node_id = dest_offset ^ labels[i];
-      reserve_node(child_node_id);
-      Node &child_node = nodes_->get_value(child_node_id);
-      child_node.set_label(labels[i]);
-      if ((i + 1) < num_labels) {
-        child_node.set_has_sibling();
-        siblings_->set(child_node_id, labels[i + 1]);
-      }
-    }
-
-    nodes_->get_value(dest_offset).set_is_origin(true);
-    dest_node.set_offset(dest_offset);
-    dest_node.set_child(labels[0]);
-  }
-
-  uint16_t label = dest_node.child();
-  while (label != INVALID_LABEL) {
-    const uint64_t next_src_node_id = src_offset ^ label;
-    const uint64_t next_dest_node_id = dest_offset ^ label;
-    defrag(src_impl, next_src_node_id, next_dest_node_id);
-    label = nodes_->get_value(next_dest_node_id).has_sibling() ?
-        siblings_->get(next_dest_node_id) : INVALID_LABEL;
-  }
-}
-
-bool DoubleArrayImpl::find_leaf(KeyArg key, Node **leaf_node,
-                                uint64_t *leaf_key_pos) {
-  Node *node = &nodes_->get_value(ROOT_NODE_ID);
-  uint64_t key_pos;
-  for (key_pos = 0; key_pos < key.size(); ++key_pos) {
-    if (node->is_leaf()) {
-      // Found.
-      *leaf_node = node;
-      *leaf_key_pos = key_pos;
-      return true;
-    }
-    const uint64_t child_node_id = node->offset() ^ key[key_pos];
-    Node * const child_node = &nodes_->get_value(child_node_id);
-    if (child_node->label() != key[key_pos]) {
-      // Not found.
-      *leaf_node = node;
-      *leaf_key_pos = key_pos;
-      return false;
-    }
-    node = child_node;
-  }
-  *leaf_node = node;
-  *leaf_key_pos = key_pos;
-  if (node->is_leaf()) {
-    // Found.
-    return true;
-  }
-  if (node->child() != TERMINAL_LABEL) {
-    // Not found.
-    return false;
-  }
-  const uint64_t node_id = node->offset() ^ TERMINAL_LABEL;
-  node = &nodes_->get_value(node_id);
-  *leaf_node = node;
-  return node->is_leaf();
-}
-
-bool DoubleArrayImpl::insert_leaf(KeyArg key, Node *node,
-                                  uint64_t key_pos, Node **leaf_node) {
-  if (node->is_leaf()) {
-    Key stored_key;
-    if (!pool_->get(node->key_id(), &stored_key)) {
-      GRNXX_ERROR() << "not found: key = " << key << ", key_pos = " << key_pos;
-      throw LogicError();
-    }
-    uint64_t i = key_pos;
-    while ((i < key.size()) && (i < stored_key.size())) {
-      if (key[i] != stored_key[i]) {
-        break;
-      }
-      ++i;
-    }
-    if ((i == key.size()) && (i == stored_key.size())) {
-      return false;
-    }
-    while (key_pos < i) {
-      node = insert_node(node, key[key_pos]);
-      ++key_pos;
-    }
-    uint64_t labels[2];
-    labels[0] = (key_pos < stored_key.size()) ?
-        stored_key[key_pos] : TERMINAL_LABEL;
-    labels[1] = (key_pos < key.size()) ? key[key_pos] : TERMINAL_LABEL;
-    *leaf_node = separate(node, labels);
-    return true;
-  } else if (node->label() == TERMINAL_LABEL) {
-    *leaf_node = node;
-    return true;
-  } else {
-    const uint64_t label = (key_pos < key.size()) ?
-        key[key_pos] : TERMINAL_LABEL;
-    resolve(node, label);
-    *leaf_node = insert_node(node, label);
-    return true;
-  }
-}
-
-Node *DoubleArrayImpl::insert_node(Node *node, uint64_t label) {
-  uint64_t offset = node->offset();
-  if (node->is_leaf() || (offset == INVALID_OFFSET)) {
-    offset = find_offset(&label, 1);
-  }
-  const uint64_t next_node_id = offset ^ label;
-  uint8_t *next_sibling = &siblings_->get_value(next_node_id);
-  Node * const next_node = reserve_node(next_node_id);
-  next_node->set_label(label);
-  if (node->is_leaf()) {
-    next_node[offset - next_node_id].set_is_origin(true);
-    next_node->set_key_id(node->key_id());
-  } else if (node->offset() == INVALID_OFFSET) {
-    next_node[offset - next_node_id].set_is_origin(true);
-  }
-  node->set_offset(offset);
-  const uint64_t child_label = node->child();
-  if (child_label == INVALID_LABEL) {
-    node->set_child(label);
-  } else if ((label == TERMINAL_LABEL) ||
-             ((child_label != TERMINAL_LABEL) && (label < child_label))) {
-    // The child node becomes the first child.
-    *next_sibling = child_label;
-    next_node->set_has_sibling();
-    node->set_child(label);
-  } else {
-    uint64_t prev_node_id = offset ^ child_label;
-    Node *prev_node = &next_node[prev_node_id - next_node_id];
-    uint8_t *prev_sibling = &next_sibling[prev_node_id - next_node_id];
-    uint64_t sibling_label = prev_node->has_sibling() ?
-        *prev_sibling : INVALID_LABEL;
-    while (label > sibling_label) {
-      prev_node_id = offset ^ sibling_label;
-      prev_node = &next_node[prev_node_id - next_node_id];
-      prev_sibling = &next_sibling[prev_node_id - next_node_id];
-      sibling_label = prev_node->has_sibling() ?
-          *prev_sibling : INVALID_LABEL;
-    }
-    *next_sibling = *prev_sibling;
-    *prev_sibling = label;
-    if (prev_node->has_sibling()) {
-      next_node->set_has_sibling();
-    }
-    prev_node->set_has_sibling();
-  }
-  return next_node;
-}
-
-Node *DoubleArrayImpl::separate(Node *node, uint64_t labels[2]) {
-  const uint64_t offset = find_offset(labels, 2);
-  uint64_t node_ids[2] = { offset ^ labels[0], offset ^ labels[1] };
-  Node *nodes[2];
-  nodes[0] = reserve_node(node_ids[0]);
-  nodes[1] = reserve_node(node_ids[1]);
-  uint8_t * const sibling_block =
-      &siblings_->get_value(offset & ~(BLOCK_SIZE - 1));
-  nodes[0]->set_label(labels[0]);
-  nodes[0]->set_key_id(node->key_id());
-  nodes[1]->set_label(labels[1]);
-  nodes[0][offset - node_ids[0]].set_is_origin(true);
-  node->set_offset(offset);
-  if ((labels[0] == TERMINAL_LABEL) ||
-      ((labels[1] != TERMINAL_LABEL) && (labels[0] < labels[1]))) {
-    sibling_block[node_ids[0] % BLOCK_SIZE] = static_cast<uint8_t>(labels[1]);
-    nodes[0]->set_has_sibling();
-    node->set_child(labels[0]);
-  } else {
-    sibling_block[node_ids[1] % BLOCK_SIZE] = static_cast<uint8_t>(labels[0]);
-    nodes[1]->set_has_sibling();
-    node->set_child(labels[1]);
-  }
-  return nodes[1];
-}
-
-void DoubleArrayImpl::resolve(Node *node, uint64_t label) {
-  uint64_t offset = node->offset();
-  if (offset == INVALID_OFFSET) {
-    return;
-  }
-  uint64_t dest_node_id = offset ^ label;
-  Node * const dest_node = &nodes_->get_value(dest_node_id);
-  if (dest_node->is_phantom()) {
-    return;
-  }
-  Node * const node_block = dest_node - (dest_node_id % BLOCK_SIZE);
-  uint8_t * const sibling_block =
-      &siblings_->get_value(dest_node_id & ~(BLOCK_SIZE - 1));
-  uint64_t labels[MAX_LABEL + 1];
-  uint64_t num_labels = 0;
-  uint64_t child_label = node->child();
-  while (child_label != INVALID_LABEL) {
-    labels[num_labels++] = child_label;
-    const uint64_t child_node_id = offset ^ child_label;
-    if (node_block[child_node_id % BLOCK_SIZE].has_sibling()) {
-      child_label = sibling_block[child_node_id % BLOCK_SIZE];
-    } else {
-      child_label = INVALID_LABEL;
-    }
-  }
-  labels[num_labels] = label;
-  offset = find_offset(labels, num_labels + 1);
-  migrate_nodes(node, offset, labels, num_labels);
-}
-
-void DoubleArrayImpl::migrate_nodes(Node *node, uint64_t dest_offset,
-                                    const uint64_t *labels,
-                                    uint64_t num_labels) {
-  const uint64_t src_offset = node->offset();
-  Node * const src_node_block =
-      &nodes_->get_value(src_offset & ~(BLOCK_SIZE - 1));
-  uint8_t * const src_sibling_block =
-      &siblings_->get_value(src_offset & ~(BLOCK_SIZE - 1));
-  Node * const dest_node_block =
-      &nodes_->get_value(dest_offset & ~(BLOCK_SIZE - 1));
-  uint8_t * const dest_sibling_block =
-      &siblings_->get_value(dest_offset & ~(BLOCK_SIZE - 1));
-  for (uint64_t i = 0; i < num_labels; ++i) {
-    const uint64_t src_node_id = src_offset ^ labels[i];
-    Node * const src_node = &src_node_block[src_node_id % BLOCK_SIZE];
-    uint8_t * const src_sibling = &src_sibling_block[src_node_id % BLOCK_SIZE];
-    const uint64_t dest_node_id = dest_offset ^ labels[i];
-    Node * const dest_node = reserve_node(dest_node_id);
-    uint8_t * const dest_sibling =
-        &dest_sibling_block[dest_node_id % BLOCK_SIZE];
-    Node dummy_node = *src_node;
-    dummy_node.set_is_origin(dest_node->is_origin());
-    *dest_node = dummy_node;
-    *dest_sibling = *src_sibling;
-  }
-  header_->num_zombies += num_labels;
-  dest_node_block[dest_offset % BLOCK_SIZE].set_is_origin(true);
-  node->set_offset(dest_offset);
-}
-
-uint64_t DoubleArrayImpl::find_offset(const uint64_t *labels,
-                                      uint64_t num_labels) {
-  // Blocks are tested in descending order of level.
-  // Generally, a lower level contains more phantom nodes.
-  uint64_t level = bit_scan_reverse(num_labels) + 1;
-  level = (level < BLOCK_MAX_LEVEL) ? (BLOCK_MAX_LEVEL - level) : 0;
-  uint64_t block_count = 0;
-  do {
-    uint64_t latest_block_id = header_->latest_blocks[level];
-    if (latest_block_id == BLOCK_INVALID_ID) {
-      // This level group is skipped because it is empty.
-      continue;
-    }
-    uint64_t block_id = latest_block_id;
-    do {
-      Block * const block = &blocks_->get_value(block_id);
-      Node * const node_block = &nodes_->get_value(block_id * BLOCK_SIZE);
-      const uint64_t first_phantom_node_id = block->first_phantom();
-      uint64_t node_id = first_phantom_node_id;
-      do {
-        const uint64_t offset = node_id ^ labels[0];
-        if (!node_block[offset].is_origin()) {
-          uint64_t i;
-          for (i = 1; i < num_labels; ++i) {
-            if (!node_block[offset ^ labels[i]].is_phantom()) {
-              break;
-            }
-          }
-          if (i >= num_labels) {
-            // Found.
-            return (block_id * BLOCK_SIZE) | offset;
-          }
-        }
-        node_id = node_block[node_id].next();
-      } while (node_id != first_phantom_node_id);
-
-      Block * const prev_block = block;
-      const uint64_t prev_block_id = block_id;
-      const uint64_t next_block_id = block->next();
-      block_id = next_block_id;
-
-      // A block level is updated if this function fails many times.
-      prev_block->set_failure_count(prev_block->failure_count() + 1);
-      if (prev_block->failure_count() >= BLOCK_MAX_FAILURE_COUNT) {
-        update_block_level(prev_block_id, prev_block, level + 1);
-        if (next_block_id == latest_block_id) {
-          // All the blocks are tested.
-          break;
-        } else {
-          latest_block_id = header_->latest_blocks[level];
-          continue;
-        }
-      }
-    } while ((++block_count < BLOCK_MAX_COUNT) &&
-             (block_id != latest_block_id));
-  } while ((block_count < BLOCK_MAX_COUNT) && (level-- != 0));
-  // Use a new block.
-  return (header_->num_blocks * BLOCK_SIZE) ^ labels[0];
-}
-
-Node *DoubleArrayImpl::reserve_node(uint64_t node_id) {
-  const uint64_t block_id = node_id / BLOCK_SIZE;
-  Block *block;
-  if (node_id >= (header_->num_blocks * BLOCK_SIZE)) {
-    block = reserve_block(block_id);
-  } else {
-    block = &blocks_->get_value(block_id);
-  }
-  Node * const node = &nodes_->get_value(node_id);
-  Node * const node_block = node - (node_id % BLOCK_SIZE);
-  Node * const next_node = &node_block[node->next()];
-  Node * const prev_node = &node_block[node->prev()];
-  if ((node_id % BLOCK_SIZE) == block->first_phantom()) {
-    block->set_first_phantom(node->next());
-  }
-  prev_node->set_next(node->next());
-  next_node->set_prev(node->prev());
-  if (block->level() != BLOCK_MAX_LEVEL) {
-    const uint64_t threshold =
-        1ULL << ((BLOCK_MAX_LEVEL - block->level() - 1) * 2);
-    if (block->num_phantoms() == threshold) {
-      update_block_level(block_id, block, block->level() + 1);
-    }
-  }
-  block->set_num_phantoms(block->num_phantoms() - 1);
-  node->unset_is_phantom();
-  --header_->num_phantoms;
-  return node;
-}
-
-Block *DoubleArrayImpl::reserve_block(uint64_t block_id) {
-  if (block_id >= blocks_->size()) {
-    GRNXX_ERROR() << "too many blocks: block_id = " << block_id
-                  << ", max_block_id = " << (blocks_->size() - 1);
-    throw LogicError();
-  }
-  Block * const block = &blocks_->get_value(block_id);
-  Node * const node = &nodes_->get_value(block_id * BLOCK_SIZE);
-  *block = Block::empty_block();
-  for (uint64_t i = 0; i < BLOCK_SIZE; ++i) {
-    node[i] = Node::phantom_node(i + 1, i - 1);
-  }
-  // The level of a new block is 0.
-  set_block_level(block_id, block, 0);
-  header_->num_blocks = block_id + 1;
-  header_->num_phantoms += BLOCK_SIZE;
-  return block;
-}
-
-void DoubleArrayImpl::update_block_level(uint64_t block_id, Block *block,
-                                         uint64_t level) {
-  // FIXME: If set_block_level() fails, the block gets lost.
-  unset_block_level(block_id, block);
-  set_block_level(block_id, block, level);
-}
-
-void DoubleArrayImpl::set_block_level(uint64_t block_id, Block *block,
-                                      uint64_t level) {
-  if (header_->latest_blocks[level] == BLOCK_INVALID_ID) {
-    // The block becomes the only one member of the level group.
-    block->set_next(block_id);
-    block->set_prev(block_id);
-    header_->latest_blocks[level] = block_id;
-  } else {
-    // The block is appended to the level group.
-    const uint64_t next_block_id = header_->latest_blocks[level];
-    Block * const next_block = &blocks_->get_value(next_block_id);
-    const uint64_t prev_block_id = next_block->prev();
-    Block * const prev_block = &blocks_->get_value(prev_block_id);
-    block->set_next(next_block_id);
-    block->set_prev(prev_block_id);
-    prev_block->set_next(block_id);
-    next_block->set_prev(block_id);
-  }
-  block->set_level(level);
-  block->set_failure_count(0);
-}
-
-void DoubleArrayImpl::unset_block_level(uint64_t block_id, Block *block) {
-  const uint64_t level = block->level();
-  const uint64_t next_block_id = block->next();
-  const uint64_t prev_block_id = block->prev();
-  if (next_block_id == prev_block_id) {
-    // The level group becomes empty.
-    header_->latest_blocks[level] = BLOCK_INVALID_ID;
-  } else {
-    Block * const next_block = &blocks_->get_value(next_block_id);
-    Block * const prev_block = &blocks_->get_value(prev_block_id);
-    prev_block->set_next(next_block_id);
-    next_block->set_prev(prev_block_id);
-    if (block_id == header_->latest_blocks[level]) {
-      // The next block becomes the latest block of the level group.
-      header_->latest_blocks[level] = next_block_id;
-    }
-  }
-}
-
-struct DoubleArrayHeader {
-  CommonHeader common_header;
-  uint64_t pool_id;
-  uint64_t impl_id;
-  uint32_t pool_storage_node_id;
-  uint32_t impl_storage_node_id;
-  Mutex mutex;
-
-  // Initialize the member variables.
-  DoubleArrayHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-DoubleArrayHeader::DoubleArrayHeader()
-    : common_header(FORMAT_STRING, MAP_DOUBLE_ARRAY),
-      pool_id(0),
-      impl_id(0),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      impl_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-DoubleArrayHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-template <typename T>
-Map<T> *DoubleArray<T>::create(Storage *, uint32_t, const MapOptions &) {
-  GRNXX_ERROR() << "unsupported type";
-  throw LogicError();
-}
-
-template <typename T>
-Map<T> *DoubleArray<T>::open(Storage *, uint32_t) {
-  GRNXX_ERROR() << "unsupported type";
-  throw LogicError();
-}
-
-template class DoubleArray<int8_t>;
-template class DoubleArray<uint8_t>;
-template class DoubleArray<int16_t>;
-template class DoubleArray<uint16_t>;
-template class DoubleArray<int32_t>;
-template class DoubleArray<uint32_t>;
-template class DoubleArray<int64_t>;
-template class DoubleArray<uint64_t>;
-template class DoubleArray<double>;
-template class DoubleArray<GeoPoint>;
-
-DoubleArray<Bytes>::DoubleArray()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pool_(),
-      impl_(),
-      queue_(),
-      pool_id_(0),
-      impl_id_(0),
-      clock_() {}
-
-DoubleArray<Bytes>::~DoubleArray() {}
-
-DoubleArray<Bytes> *DoubleArray<Bytes>::create(Storage *storage,
-                                               uint32_t storage_node_id,
-                                               const MapOptions &options) {
-  std::unique_ptr<DoubleArray> map(new (std::nothrow) DoubleArray);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::DoubleArray failed";
-    throw MemoryError();
-  }
-  map->create_map(storage, storage_node_id, options);
-  return map.release();
-}
-
-DoubleArray<Bytes> *DoubleArray<Bytes>::open(Storage *storage,
-                                             uint32_t storage_node_id) {
-  std::unique_ptr<DoubleArray> map(new (std::nothrow) DoubleArray);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::DoubleArray failed";
-    throw MemoryError();
-  }
-  map->open_map(storage, storage_node_id);
-  return map.release();
-}
-
-uint32_t DoubleArray<Bytes>::storage_node_id() const {
-  return storage_node_id_;
-}
-
-MapType DoubleArray<Bytes>::type() const {
-  return MAP_DOUBLE_ARRAY;
-}
-
-int64_t DoubleArray<Bytes>::max_key_id() {
-  refresh_if_possible();
-  return impl_->max_key_id();
-}
-
-uint64_t DoubleArray<Bytes>::num_keys() {
-  refresh_if_possible();
-  return impl_->num_keys();
-}
-
-bool DoubleArray<Bytes>::get(int64_t key_id, Key *key) {
-  refresh_if_possible();
-  return impl_->get(key_id, key);
-}
-
-bool DoubleArray<Bytes>::unset(int64_t key_id) {
-  refresh_if_possible();
-  return impl_->unset(key_id);
-}
-
-bool DoubleArray<Bytes>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_if_possible();
-  return impl_->reset(key_id, dest_key);
-}
-
-bool DoubleArray<Bytes>::find(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  return impl_->find(key, key_id);
-}
-
-bool DoubleArray<Bytes>::add(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  return impl_->add(key, key_id);
-}
-
-bool DoubleArray<Bytes>::remove(KeyArg key) {
-  refresh_if_possible();
-  return impl_->remove(key);
-}
-
-bool DoubleArray<Bytes>::replace(KeyArg src_key, KeyArg dest_key,
-                                 int64_t *key_id) {
-  refresh_if_possible();
-  return impl_->replace(src_key, dest_key, key_id);
-}
-
-void DoubleArray<Bytes>::defrag() {
-  refresh_if_possible();
-  if (max_key_id() < MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  pool_->defrag();
-  std::unique_ptr<Impl> new_impl(
-      Impl::create(storage_, storage_node_id_, impl_.get()));
-  {
-    // Validate a new impl.
-    Lock lock(&header_->mutex);
-    header_->impl_storage_node_id = new_impl->storage_node_id();
-    ++header_->impl_id;
-    impl_.swap(new_impl);
-    impl_id_ = header_->impl_id;
-  }
-  Impl::unlink(storage_, new_impl->storage_node_id());
-  try {
-    queue_.push(QueueEntry{ nullptr, std::move(new_impl), clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-void DoubleArray<Bytes>::sweep(Duration lifetime) {
-  const Time threshold = clock_.now() - lifetime;
-  while (!queue_.empty()) {
-    QueueEntry &queue_entry = queue_.front();
-    if (queue_entry.time <= threshold) {
-      queue_.pop();
-    }
-  }
-}
-
-void DoubleArray<Bytes>::truncate() {
-  refresh_if_possible();
-  if (max_key_id() < MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  std::unique_ptr<Pool> new_pool(Pool::create(storage_, storage_node_id_));
-  std::unique_ptr<Impl> new_impl;
-  try {
-    new_impl.reset(Impl::create(storage_, storage_node_id_, new_pool.get()));
-  } catch (...) {
-    Pool::unlink(storage_, new_pool->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new impl and a new pool.
-    Lock lock(&header_->mutex);
-    header_->pool_storage_node_id = new_pool->storage_node_id();
-    header_->impl_storage_node_id = new_impl->storage_node_id();
-    ++header_->pool_id;
-    ++header_->impl_id;
-    pool_.swap(new_pool);
-    impl_.swap(new_impl);
-    pool_id_ = header_->pool_id;
-    impl_id_ = header_->impl_id;
-  }
-  Pool::unlink(storage_, new_pool->storage_node_id());
-  Impl::unlink(storage_, new_impl->storage_node_id());
-  try {
-    queue_.push(QueueEntry{ std::move(new_pool), std::move(new_impl),
-                            clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-bool DoubleArray<Bytes>::find_longest_prefix_match(KeyArg query,
-                                                   int64_t *key_id,
-                                                   Key *key) {
-  refresh_if_possible();
-  return impl_->find_longest_prefix_match(query, key_id, key);
-}
-
-//MapCursor<Bytes> *DoubleArray<Bytes>::create_cursor(
-//    MapCursorAllKeys<Bytes> query, const MapCursorOptions &options) {
-//  // TODO
-//  return nullptr;
-//}
-
-//MapCursor<Bytes> *DoubleArray<Bytes>::create_cursor(
-//    const MapCursorKeyIDRange<Bytes> &query, const MapCursorOptions &options) {
-//  // TODO
-//  return nullptr;
-//}
-
-//MapCursor<Bytes> *DoubleArray<Bytes>::create_cursor(
-//    const MapCursorKeyRange<Bytes> &query, const MapCursorOptions &options) {
-//  // TODO
-//  return nullptr;
-//}
-
-void DoubleArray<Bytes>::create_map(Storage *storage, uint32_t storage_node_id,
-                                    const MapOptions &) {
-  storage_ = storage;
-  StorageNode header_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<Header *>(header_node.body());
-    *header_ = Header();
-    pool_.reset(Pool::create(storage, storage_node_id_));
-    impl_.reset(Impl::create(storage, storage_node_id_, pool_.get()));
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->impl_storage_node_id = impl_->storage_node_id();
-    pool_id_ = ++header_->pool_id;
-    impl_id_ = ++header_->impl_id;
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void DoubleArray<Bytes>::open_map(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  storage_node_id_ = storage_node_id;
-  StorageNode header_node = storage->open_node(storage_node_id_);
-  if (header_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << header_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  header_ = static_cast<Header *>(header_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-}
-
-void DoubleArray<Bytes>::refresh_if_possible() {
-  if (impl_id_ != header_->impl_id) {
-    refresh();
-  }
-}
-
-void DoubleArray<Bytes>::refresh() {
-  Lock lock(&header_->mutex);
-  if (pool_id_ != header_->pool_id) {
-    refresh_pool();
-  }
-  if (impl_id_ != header_->impl_id) {
-    refresh_impl();
-  }
-}
-
-void DoubleArray<Bytes>::refresh_pool() {
-  std::unique_ptr<Pool> new_pool(
-      Pool::open(storage_, header_->pool_storage_node_id));
-  pool_.swap(new_pool);
-  pool_id_ = header_->pool_id;
-  try {
-    queue_.push(QueueEntry{ std::move(new_pool), nullptr, clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-void DoubleArray<Bytes>::refresh_impl() {
-  std::unique_ptr<Impl> new_impl(
-      Impl::open(storage_, header_->impl_storage_node_id, pool_.get()));
-  impl_.swap(new_impl);
-  impl_id_ = header_->impl_id;
-  try {
-    queue_.push(QueueEntry{ nullptr, std::move(new_impl), clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/double_array.hpp (+0 -137) 100644
===================================================================
--- lib/grnxx/map/double_array.hpp    2013-08-23 10:46:34 +0900 (3fb028e)
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_DOUBLE_ARRAY_HPP
-#define GRNXX_MAP_DOUBLE_ARRAY_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-#include <queue>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/duration.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/map_cursor.hpp"
-#include "grnxx/map_cursor_query.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-template <typename T> class Pool;
-
-class DoubleArrayImpl;
-
-struct DoubleArrayHeader;
-
-template <typename T>
-class DoubleArray {
- public:
-  static Map<T> *create(Storage *storage, uint32_t storage_node_id,
-                        const MapOptions &options = MapOptions());
-  static Map<T> *open(Storage *storage, uint32_t storage_node_id);
-};
-
-template <>
-class DoubleArray<Bytes> : public Map<Bytes> {
-  using Header = DoubleArrayHeader;
-  using Impl   = DoubleArrayImpl;
-  using Pool   = map::Pool<Bytes>;
-
-  struct QueueEntry {
-    std::unique_ptr<Pool> pool;
-    std::unique_ptr<Impl> impl;
-    Time time;
-  };
-
- public:
-  using Key    = typename Map<Bytes>::Key;
-  using KeyArg = typename Map<Bytes>::KeyArg;
-  using Cursor = typename Map<Bytes>::Cursor;
-
-  DoubleArray();
-  ~DoubleArray();
-
-  static DoubleArray *create(Storage *storage, uint32_t storage_node_id,
-                             const MapOptions &options = MapOptions());
-  static DoubleArray *open(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const;
-  MapType type() const;
-
-  int64_t max_key_id();
-  uint64_t num_keys();
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  void defrag();
-  void sweep(Duration lifetime);
-
-  void truncate();
-
-  bool find_longest_prefix_match(KeyArg query,
-                                 int64_t *key_id = nullptr,
-                                 Key *key = nullptr);
-
-//  Cursor *create_cursor(
-//      MapCursorAllKeys<Bytes> query,
-//      const MapCursorOptions &options = MapCursorOptions());
-//  Cursor *create_cursor(
-//      const MapCursorKeyIDRange<Bytes> &query,
-//      const MapCursorOptions &options = MapCursorOptions());
-//  Cursor *create_cursor(
-//      const MapCursorKeyRange<Bytes> &query,
-//      const MapCursorOptions &options = MapCursorOptions());
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<Pool> pool_;
-  std::unique_ptr<Impl> impl_;
-  std::queue<QueueEntry> queue_;
-  uint64_t pool_id_;
-  uint64_t impl_id_;
-  PeriodicClock clock_;
-
-  void create_map(Storage *storage, uint32_t storage_node_id,
-                  const MapOptions &options);
-  void open_map(Storage *storage, uint32_t storage_node_id);
-
-  inline void refresh_if_possible();
-  void refresh();
-  void refresh_pool();
-  void refresh_impl();
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_DOUBLE_ARRAY_HPP

  Deleted: lib/grnxx/map/hash.hpp (+0 -133) 100644
===================================================================
--- lib/grnxx/map/hash.hpp    2013-08-23 10:46:34 +0900 (23475ff)
+++ /dev/null
@@ -1,133 +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_MAP_HASH_HPP
-#define GRNXX_MAP_HASH_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace map {
-
-// Calculate a hash value.
-template <typename T>
-struct Hash;
-
-// Use Murmur3's 64-bit finalizer for integers.
-template <>
-struct Hash<uint64_t> {
-  uint64_t operator()(uint64_t key) const {
-    uint64_t hash = key;
-    hash ^= hash >> 33;
-    hash *= 0xFF51AFD7ED558CCDULL;
-    hash ^= hash >> 33;
-    hash *= 0xC4CEB9FE1A85EC53ULL;
-    hash ^= hash >> 33;
-    return hash;
-  }
-};
-
-template <>
-struct Hash<int64_t> {
-  uint64_t operator()(int64_t key) const {
-    return Hash<uint64_t>()(key);
-  }
-};
-
-template <>
-struct Hash<uint32_t> {
-  uint64_t operator()(uint32_t key) const {
-    return Hash<uint64_t>()(key);
-  }
-};
-
-template <>
-struct Hash<int32_t> {
-  uint64_t operator()(int32_t key) const {
-    return Hash<uint32_t>()(key);
-  }
-};
-
-template <>
-struct Hash<uint16_t> {
-  uint64_t operator()(uint16_t key) const {
-    return Hash<uint64_t>()(key);
-  }
-};
-
-template <>
-struct Hash<int16_t> {
-  uint64_t operator()(int16_t key) const {
-    return Hash<uint16_t>()(key);
-  }
-};
-
-template <>
-struct Hash<uint8_t> {
-  uint64_t operator()(uint8_t key) const {
-    return Hash<uint64_t>()(key);
-  }
-};
-
-template <>
-struct Hash<int8_t> {
-  uint64_t operator()(int8_t key) const {
-    return Hash<uint8_t>()(key);
-  }
-};
-
-// Murmur3's 64-bit finalizer.
-template <>
-struct Hash<double> {
-  using KeyArg = typename Traits<double>::ArgumentType;
-  uint64_t operator()(KeyArg key) const {
-    return Hash<uint64_t>()(reinterpret_cast<const uint64_t &>(key));
-  }
-};
-
-// Murmur3's 64-bit finalizer.
-template <>
-struct Hash<GeoPoint> {
-  using KeyArg = typename Traits<GeoPoint>::ArgumentType;
-  uint64_t operator()(KeyArg key) const {
-    return Hash<uint64_t>()(key.value());
-  }
-};
-
-// 64-bit FNV-1a.
-template <>
-struct Hash<Bytes> {
-  using KeyArg = typename Traits<Bytes>::ArgumentType;
-  uint64_t operator()(KeyArg key) const {
-    uint64_t hash = 0xCBF29CE484222325ULL;
-    for (uint64_t i = 0; i < key.size(); ++i) {
-      hash ^= key[i];
-      hash *= 0x100000001B3ULL;
-    }
-    return hash;
-  }
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HASH_HPP

  Deleted: lib/grnxx/map/hash_table.cpp (+0 -847) 100644
===================================================================
--- lib/grnxx/map/hash_table.cpp    2013-08-23 10:46:34 +0900 (7d236e7)
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
-  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/map/hash_table.hpp"
-
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map/common_header.hpp"
-#include "grnxx/map/hash.hpp"
-#include "grnxx/map/helper.hpp"
-#include "grnxx/map/pool.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::HashTable";
-
-constexpr uint64_t MIN_TABLE_SIZE = 64;
-constexpr uint64_t MAX_TABLE_SIZE = 1ULL << 41;
-
-struct ImplHeader {
-  uint64_t num_entries;
-  uint64_t table_size;
-  uint32_t table_storage_node_id;
-
-  ImplHeader();
-};
-
-ImplHeader::ImplHeader()
-    : num_entries(0),
-      table_size(0),
-      table_storage_node_id(STORAGE_INVALID_NODE_ID) {}
-
-class TableEntry {
-  static constexpr uint64_t IS_UNUSED_FLAG  = 1ULL << 40;
-  static constexpr uint64_t IS_REMOVED_FLAG = 1ULL << 41;
-  static constexpr uint8_t  MEMO_SHIFT      = 42;
-  static constexpr uint64_t KEY_ID_MASK     = (1ULL << 40) - 1;
-
- public:
-  // Create an unused entry.
-  static TableEntry unused_entry() {
-    return TableEntry(IS_UNUSED_FLAG);
-  }
-
-  // Return true iff this entry is not used.
-  bool is_unused() const {
-    return value_ & IS_UNUSED_FLAG;
-  }
-  // Return true iff this entry is removed.
-  bool is_removed() const {
-    return value_ & IS_REMOVED_FLAG;
-  }
-  // Return true iff this entry and "hash_value" have the same memo.
-  bool test_hash_value(uint64_t hash_value) const {
-    return ((value_ ^ hash_value) >> MEMO_SHIFT) == 0;
-  }
-  // Return a stored key ID.
-  int64_t key_id() const {
-    return value_ & KEY_ID_MASK;
-  }
-
-  // Set a key ID and a memo, which is extracted from "hash_value".
-  void set(int64_t key_id, uint64_t hash_value) {
-    value_ = key_id | (hash_value & (~0ULL << MEMO_SHIFT));
-  }
-  // Remove this entry.
-  void remove() {
-    value_ |= IS_REMOVED_FLAG;
-  }
-
- private:
-  uint64_t value_;
-
-  explicit TableEntry(uint64_t value) : value_(value) {}
-};
-
-struct TableSizeError {};
-
-}  // namespace
-
-template <typename T>
-class HashTableImpl {
-  using Header = ImplHeader;
-  using Pool   = map::Pool<T>;
-
- public:
-  using Key    = typename Map<T>::Key;
-  using KeyArg = typename Map<T>::KeyArg;
-  using Cursor = typename Map<T>::Cursor;
-
-  HashTableImpl();
-  ~HashTableImpl();
-
-  static HashTableImpl *create(Storage *storage, uint32_t storage_node_id,
-                               Pool *pool);
-  static HashTableImpl *open(Storage *storage, uint32_t storage_node_id,
-                             Pool *pool);
-
-  static void unlink(Storage *storage, uint32_t storage_node_id) {
-    storage->unlink_node(storage_node_id);
-  }
-
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  int64_t max_key_id() {
-    return pool_->max_key_id();
-  }
-  uint64_t num_keys() {
-    return pool_->num_keys();
-  }
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  void defrag();
-
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  Pool *pool_;
-  TableEntry *table_;
-  uint64_t id_mask_;
-
-  void create_impl(Storage *storage, uint32_t storage_node_id, Pool *pool);
-  void open_impl(Storage *storage, uint32_t storage_node_id, Pool *pool);
-
-  // Search a hash table for a key ID.
-  // On success, return a pointer to a matched entry.
-  // On failure, return nullptr.
-  TableEntry *find_key_id(int64_t key_id);
-  // Search a hash table for a key.
-  // On success, assign a pointer to a matched entry to "*entry" and return
-  // true.
-  // On failure, assign a pointer to the first unused or removed entry to
-  // "*entry" and return false.
-  bool find_key(KeyArg key, uint64_t hash_value, TableEntry **entry);
-
-  // Build a hash table.
-  void build_table();
-
-  // Move to the next entry.
-  uint64_t rehash(uint64_t hash) const {
-    return hash + 1;
-  }
-
-  // Return the table size threshold.
-  uint64_t table_size_threshold() const {
-    return ((header_->table_size + (header_->table_size / 4)) / 2);
-  }
-};
-
-template <typename T>
-HashTableImpl<T>::HashTableImpl()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pool_(nullptr),
-      table_(nullptr),
-      id_mask_(0) {}
-
-template <typename T>
-HashTableImpl<T>::~HashTableImpl() {}
-
-template <typename T>
-HashTableImpl<T> *HashTableImpl<T>::create(Storage *storage,
-                                           uint32_t storage_node_id,
-                                           Pool *pool) {
-  std::unique_ptr<HashTableImpl> map(new (std::nothrow) HashTableImpl);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::HashTable failed";
-    throw MemoryError();
-  }
-  map->create_impl(storage, storage_node_id, pool);
-  return map.release();
-}
-
-template <typename T>
-HashTableImpl<T> *HashTableImpl<T>::open(Storage *storage,
-                                         uint32_t storage_node_id,
-                                         Pool *pool) {
-  std::unique_ptr<HashTableImpl> map(new (std::nothrow) HashTableImpl);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::HashTable failed";
-    throw MemoryError();
-  }
-  map->open_impl(storage, storage_node_id, pool);
-  return map.release();
-}
-
-template <typename T>
-bool HashTableImpl<T>::get(int64_t key_id, Key *key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  if (key) {
-    return pool_->get(key_id, key);
-  }
-  return pool_->get_bit(key_id);
-}
-
-template <typename T>
-bool HashTableImpl<T>::unset(int64_t key_id) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  TableEntry * const entry = find_key_id(key_id);
-  if (!entry) {
-    // Not found.
-    return false;
-  }
-  pool_->unset(key_id);
-  entry->remove();
-  return true;
-}
-
-template <typename T>
-bool HashTableImpl<T>::reset(int64_t key_id, KeyArg dest_key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  TableEntry * const src_entry = find_key_id(key_id);
-  if (!src_entry) {
-    // Not found.
-    return false;
-  }
-  const Key dest_normalized_key = Helper<T>::normalize(dest_key);
-  const uint64_t dest_hash_value = Hash<T>()(dest_normalized_key);
-  TableEntry *dest_entry;
-  if (find_key(dest_normalized_key, dest_hash_value, &dest_entry)) {
-    // Found.
-    return false;
-  }
-  // Throw an exception if the filling rate of the current table is greater
-  // than 62.5%.
-  if (header_->num_entries > table_size_threshold()) {
-    throw TableSizeError();
-  }
-  pool_->reset(key_id, dest_normalized_key);
-  if (dest_entry->is_unused()) {
-    ++header_->num_entries;
-  }
-  dest_entry->set(key_id, dest_hash_value);
-  src_entry->remove();
-  return true;
-}
-
-template <typename T>
-bool HashTableImpl<T>::find(KeyArg key, int64_t *key_id) {
-  const Key normalized_key = Helper<T>::normalize(key);
-  const uint64_t hash_value = Hash<T>()(normalized_key);
-  for (uint64_t id = hash_value; ; ) {
-    const TableEntry entry = table_[id & id_mask_];
-    if (entry.is_unused()) {
-      // Not found.
-      return false;
-    } else if (!entry.is_removed()) {
-      if (entry.test_hash_value(hash_value)) {
-        Key stored_key = pool_->get_key(entry.key_id());
-        if (Helper<T>::equal_to(stored_key, normalized_key)) {
-          // Found.
-          if (key_id) {
-            *key_id = entry.key_id();
-          }
-          return true;
-        }
-      }
-    }
-    id = rehash(id);
-    if (((id ^ hash_value) & id_mask_) == 0) {
-      // Critical error.
-      GRNXX_ERROR() << "endless loop";
-      throw LogicError();
-    }
-  }
-}
-
-template <typename T>
-bool HashTableImpl<T>::add(KeyArg key, int64_t *key_id) {
-  // Throw an exception if the filling rate of the current table is greater
-  // than 62.5%.
-  if (header_->num_entries > table_size_threshold()) {
-    throw TableSizeError();
-  }
-  const Key normalized_key = Helper<T>::normalize(key);
-  const uint64_t hash_value = Hash<T>()(normalized_key);
-  TableEntry *entry;
-  if (find_key(normalized_key, hash_value, &entry)) {
-    // Found.
-    if (key_id) {
-      *key_id = entry->key_id();
-    }
-    return false;
-  }
-  int64_t next_key_id = pool_->add(normalized_key);
-  if (entry->is_unused()) {
-    ++header_->num_entries;
-  }
-  entry->set(next_key_id, hash_value);
-  if (key_id) {
-    *key_id = next_key_id;
-  }
-  return true;
-}
-
-template <typename T>
-bool HashTableImpl<T>::remove(KeyArg key) {
-  const Key normalized_key = Helper<T>::normalize(key);
-  const uint64_t hash_value = Hash<T>()(normalized_key);
-  TableEntry *entry;
-  if (!find_key(normalized_key, hash_value, &entry)) {
-    // Not found.
-    return false;
-  }
-  pool_->unset(entry->key_id());
-  entry->remove();
-  return true;
-}
-
-template <typename T>
-bool HashTableImpl<T>::replace(KeyArg src_key, KeyArg dest_key,
-                               int64_t *key_id) {
-  const Key src_normalized_key = Helper<T>::normalize(src_key);
-  const uint64_t src_hash_value = Hash<T>()(src_normalized_key);
-  TableEntry *src_entry;
-  if (!find_key(src_normalized_key, src_hash_value, &src_entry)) {
-    // Not found.
-    return false;
-  }
-  const Key dest_normalized_key = Helper<T>::normalize(dest_key);
-  const uint64_t dest_hash_value = Hash<T>()(dest_normalized_key);
-  TableEntry *dest_entry;
-  if (find_key(dest_normalized_key, dest_hash_value, &dest_entry)) {
-    // Found.
-    return false;
-  }
-  // Throw an exception if the filling rate of the current table is greater
-  // than 62.5%.
-  if (header_->num_entries > table_size_threshold()) {
-    throw TableSizeError();
-  }
-  pool_->reset(src_entry->key_id(), dest_normalized_key);
-  if (dest_entry->is_unused()) {
-    ++header_->num_entries;
-  }
-  dest_entry->set(src_entry->key_id(), dest_hash_value);
-  src_entry->remove();
-  if (key_id) {
-    *key_id = dest_entry->key_id();
-  }
-  return true;
-}
-
-template <typename T>
-void HashTableImpl<T>::create_impl(Storage *storage, uint32_t storage_node_id,
-                                   Pool *pool) {
-  storage_ = storage;
-  StorageNode header_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<Header *>(header_node.body());
-    *header_ = Header();
-    pool_ = pool;
-    build_table();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void HashTableImpl<T>::open_impl(Storage *storage, uint32_t storage_node_id,
-                                 Pool *pool) {
-  storage_ = storage;
-  StorageNode header_node = storage->open_node(storage_node_id);
-  if (header_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << header_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node_id;
-  header_ = static_cast<Header *>(header_node.body());
-  pool_ = pool;
-  StorageNode table_node = storage->open_node(header_->table_storage_node_id);
-  table_ = static_cast<TableEntry *>(table_node.body());
-  id_mask_ = header_->table_size - 1;
-}
-
-template <typename T>
-TableEntry *HashTableImpl<T>::find_key_id(int64_t key_id) {
-  Key stored_key;
-  if (!pool_->get(key_id, &stored_key)) {
-    // Not found.
-    return nullptr;
-  }
-  const uint64_t hash_value = Hash<T>()(stored_key);
-  for (uint64_t id = hash_value; ; ) {
-    TableEntry &entry = table_[id & id_mask_];
-    if (entry.key_id() == key_id) {
-      // Found.
-      return &entry;
-    }
-    id = rehash(id);
-    if (((id ^ hash_value) & id_mask_) == 0) {
-      // Critical error.
-      GRNXX_ERROR() << "endless loop";
-      throw LogicError();
-    }
-  }
-}
-
-template <typename T>
-bool HashTableImpl<T>::find_key(KeyArg key, uint64_t hash_value,
-                                TableEntry **entry) {
-  *entry = nullptr;
-  for (uint64_t id = hash_value; ; ) {
-    TableEntry &this_entry = table_[id & id_mask_];
-    if (this_entry.is_unused()) {
-      // Not found.
-      if (!*entry) {
-        *entry = &this_entry;
-      }
-      return false;
-    } else if (this_entry.is_removed()) {
-      // Save the first removed entry.
-      if (!*entry) {
-        *entry = &this_entry;
-      }
-    } else if (this_entry.test_hash_value(hash_value)) {
-      Key stored_key = pool_->get_key(this_entry.key_id());
-      if (Helper<T>::equal_to(stored_key, key)) {
-        // Found.
-        *entry = &this_entry;
-        return true;
-      }
-    }
-    id = rehash(id);
-    if (((id ^ hash_value) & id_mask_) == 0) {
-      // Critical error.
-      GRNXX_ERROR() << "endless loop";
-      throw LogicError();
-    }
-  }
-}
-
-template <typename T>
-void HashTableImpl<T>::build_table() {
-  // Create a new table.
-  uint64_t new_size = pool_->num_keys() * 2;
-  if (new_size < MIN_TABLE_SIZE) {
-    new_size = MIN_TABLE_SIZE;
-  } else if (new_size > MAX_TABLE_SIZE) {
-    new_size = MAX_TABLE_SIZE;
-  }
-  new_size = 2ULL << bit_scan_reverse(new_size - 1);
-  StorageNode table_node =
-      storage_->create_node(storage_node_id_, sizeof(TableEntry) * new_size);
-  table_ = static_cast<TableEntry *>(table_node.body());
-  id_mask_ = new_size - 1;
-  for (uint64_t i = 0; i < new_size; ++i) {
-    table_[i] = TableEntry::unused_entry();
-  }
-  // Add entries associated with keys in a pool.
-  const uint64_t new_id_mask = new_size - 1;
-  const int64_t max_key_id = pool_->max_key_id();
-  for (int64_t key_id = MAP_MIN_KEY_ID; key_id <= max_key_id; ++key_id) {
-    Key stored_key;
-    if (!pool_->get(key_id, &stored_key)) {
-      continue;
-    }
-    const uint64_t hash_value = Hash<T>()(stored_key);
-    for (uint64_t id = hash_value; ; id = rehash(id)) {
-      TableEntry &entry = table_[id & new_id_mask];
-      if (entry.is_unused()) {
-        entry.set(key_id, hash_value);
-        break;
-      }
-    }
-    ++header_->num_entries;
-  }
-  header_->table_size = new_size;
-  header_->table_storage_node_id = table_node.id();
-}
-
-struct HashTableHeader {
-  CommonHeader common_header;
-  uint64_t pool_id;
-  uint64_t impl_id;
-  uint32_t pool_storage_node_id;
-  uint32_t impl_storage_node_id;
-  Mutex mutex;
-
-  // Initialize the member variables.
-  HashTableHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-HashTableHeader::HashTableHeader()
-    : common_header(FORMAT_STRING, MAP_HASH_TABLE),
-      pool_id(0),
-      impl_id(0),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      impl_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-HashTableHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-template <typename T>
-HashTable<T>::HashTable()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pool_(),
-      impl_(),
-      queue_(),
-      pool_id_(0),
-      impl_id_(0),
-      clock_() {}
-
-template <typename T>
-HashTable<T>::~HashTable() {}
-
-template <typename T>
-HashTable<T> *HashTable<T>::create(Storage *storage, uint32_t storage_node_id,
-                                   const MapOptions &options) {
-  std::unique_ptr<HashTable> map(new (std::nothrow) HashTable);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::HashTable failed";
-    throw MemoryError();
-  }
-  map->create_map(storage, storage_node_id, options);
-  return map.release();
-}
-
-template <typename T>
-HashTable<T> *HashTable<T>::open(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<HashTable> map(new (std::nothrow) HashTable);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::HashTable failed";
-    throw MemoryError();
-  }
-  map->open_map(storage, storage_node_id);
-  return map.release();
-}
-
-template <typename T>
-uint32_t HashTable<T>::storage_node_id() const {
-  return storage_node_id_;
-}
-
-template <typename T>
-MapType HashTable<T>::type() const {
-  return MAP_HASH_TABLE;
-}
-
-template <typename T>
-int64_t HashTable<T>::max_key_id() {
-  refresh_if_possible();
-  return impl_->max_key_id();
-}
-
-template <typename T>
-uint64_t HashTable<T>::num_keys() {
-  refresh_if_possible();
-  return impl_->num_keys();
-}
-
-template <typename T>
-bool HashTable<T>::get(int64_t key_id, Key *key) {
-  refresh_if_possible();
-  return impl_->get(key_id, key);
-}
-
-template <typename T>
-bool HashTable<T>::unset(int64_t key_id) {
-  refresh_if_possible();
-  return impl_->unset(key_id);
-}
-
-template <typename T>
-bool HashTable<T>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_if_possible();
-  try {
-    return impl_->reset(key_id, dest_key);
-  } catch (TableSizeError) {
-    rebuild_table();
-    return impl_->reset(key_id, dest_key);
-  }
-}
-
-template <typename T>
-bool HashTable<T>::find(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  return impl_->find(key, key_id);
-}
-
-template <typename T>
-bool HashTable<T>::add(KeyArg key, int64_t *key_id) {
-  refresh_if_possible();
-  try {
-    return impl_->add(key, key_id);
-  } catch (TableSizeError) {
-    rebuild_table();
-    return impl_->add(key, key_id);
-  }
-}
-
-template <typename T>
-bool HashTable<T>::remove(KeyArg key) {
-  refresh_if_possible();
-  return impl_->remove(key);
-}
-
-template <typename T>
-bool HashTable<T>::replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id) {
-  refresh_if_possible();
-  try {
-    return impl_->replace(src_key, dest_key, key_id);
-  } catch (TableSizeError) {
-    rebuild_table();
-    return impl_->replace(src_key, dest_key, key_id);
-  }
-}
-
-template <typename T>
-void HashTable<T>::rebuild_table() {
-  std::unique_ptr<Impl> new_impl(
-      Impl::create(storage_, storage_node_id_, pool_.get()));
-  {
-    // Validate a new impl.
-    Lock lock(&header_->mutex);
-    header_->impl_storage_node_id = new_impl->storage_node_id();
-    ++header_->impl_id;
-    impl_.swap(new_impl);
-    impl_id_ = header_->impl_id;
-  }
-  Impl::unlink(storage_, new_impl->storage_node_id());
-  try {
-    queue_.push(QueueEntry{ nullptr, std::move(new_impl), clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-template <typename T>
-void HashTable<T>::defrag() {
-  refresh_if_possible();
-  if (max_key_id() < MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  pool_->defrag();
-  rebuild_table();
-}
-
-template <typename T>
-void HashTable<T>::sweep(Duration lifetime) {
-  const Time threshold = clock_.now() - lifetime;
-  while (!queue_.empty()) {
-    QueueEntry &queue_entry = queue_.front();
-    if (queue_entry.time <= threshold) {
-      queue_.pop();
-    }
-  }
-}
-
-template <typename T>
-void HashTable<T>::truncate() {
-  refresh_if_possible();
-  if (max_key_id() < MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  std::unique_ptr<Pool> new_pool(Pool::create(storage_, storage_node_id_));
-  std::unique_ptr<Impl> new_impl;
-  try {
-    new_impl.reset(Impl::create(storage_, storage_node_id_, new_pool.get()));
-  } catch (...) {
-    Pool::unlink(storage_, new_pool->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new impl and a new pool.
-    Lock lock(&header_->mutex);
-    header_->pool_storage_node_id = new_pool->storage_node_id();
-    header_->impl_storage_node_id = new_impl->storage_node_id();
-    ++header_->pool_id;
-    ++header_->impl_id;
-    pool_.swap(new_pool);
-    impl_.swap(new_impl);
-    pool_id_ = header_->pool_id;
-    impl_id_ = header_->impl_id;
-  }
-  Pool::unlink(storage_, new_pool->storage_node_id());
-  Impl::unlink(storage_, new_impl->storage_node_id());
-  try {
-    queue_.push(QueueEntry{ std::move(new_pool), std::move(new_impl),
-                            clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-template <typename T>
-void HashTable<T>::create_map(Storage *storage, uint32_t storage_node_id,
-                              const MapOptions &) {
-  storage_ = storage;
-  StorageNode header_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<Header *>(header_node.body());
-    *header_ = Header();
-    pool_.reset(Pool::create(storage, storage_node_id_));
-    impl_.reset(Impl::create(storage, storage_node_id_, pool_.get()));
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->impl_storage_node_id = impl_->storage_node_id();
-    pool_id_ = ++header_->pool_id;
-    impl_id_ = ++header_->impl_id;
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void HashTable<T>::open_map(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode header_node = storage->open_node(storage_node_id);
-  if (header_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << header_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node_id;
-  header_ = static_cast<Header *>(header_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-}
-
-template <typename T>
-void HashTable<T>::refresh_if_possible() {
-  if (impl_id_ != header_->impl_id) {
-    refresh();
-  }
-}
-
-template <typename T>
-void HashTable<T>::refresh() {
-  Lock lock(&header_->mutex);
-  if (pool_id_ != header_->pool_id) {
-    refresh_pool();
-  }
-  if (impl_id_ != header_->impl_id) {
-    refresh_impl();
-  }
-}
-
-template <typename T>
-void HashTable<T>::refresh_pool() {
-  std::unique_ptr<Pool> new_pool(
-      Pool::open(storage_, header_->pool_storage_node_id));
-  pool_.swap(new_pool);
-  pool_id_ = header_->pool_id;
-  try {
-    queue_.push(QueueEntry{ std::move(new_pool), nullptr, clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-template <typename T>
-void HashTable<T>::refresh_impl() {
-  std::unique_ptr<Impl> new_impl(
-      Impl::open(storage_, header_->impl_storage_node_id, pool_.get()));
-  impl_.swap(new_impl);
-  impl_id_ = header_->impl_id;
-  try {
-    queue_.push(QueueEntry{ nullptr, std::move(new_impl), clock_.now() });
-  } catch (const std::exception &exception) {
-    GRNXX_ERROR() << "std::queue::push() failed";
-    throw StandardError(exception);
-  }
-}
-
-template class HashTable<int8_t>;
-template class HashTable<uint8_t>;
-template class HashTable<int16_t>;
-template class HashTable<uint16_t>;
-template class HashTable<int32_t>;
-template class HashTable<uint32_t>;
-template class HashTable<int64_t>;
-template class HashTable<uint64_t>;
-template class HashTable<double>;
-template class HashTable<GeoPoint>;
-template class HashTable<Bytes>;
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/hash_table.hpp (+0 -114) 100644
===================================================================
--- lib/grnxx/map/hash_table.hpp    2013-08-23 10:46:34 +0900 (fe51f69)
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_HASH_TABLE_HPP
-#define GRNXX_MAP_HASH_TABLE_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-#include <queue>
-
-#include "grnxx/duration.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-template <typename T> class Pool;
-
-template <typename T> class HashTableImpl;
-
-struct HashTableHeader;
-
-template <typename T>
-class HashTable : public Map<T> {
-  using Header     = HashTableHeader;
-  using Pool       = map::Pool<T>;
-  using Impl       = HashTableImpl<T>;
-
-  struct QueueEntry {
-    std::unique_ptr<Pool> pool;
-    std::unique_ptr<Impl> impl;
-    Time time;
-  };
-
- public:
-  using Key    = typename Map<T>::Key;
-  using KeyArg = typename Map<T>::KeyArg;
-  using Cursor = typename Map<T>::Cursor;
-
-  HashTable();
-  ~HashTable();
-
-  static HashTable *create(Storage *storage, uint32_t storage_node_id,
-                           const MapOptions &options = MapOptions());
-  static HashTable *open(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const;
-  MapType type() const;
-
-  int64_t max_key_id();
-  uint64_t num_keys();
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  void defrag();
-  void sweep(Duration lifetime);
-
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<Pool> pool_;
-  std::unique_ptr<Impl> impl_;
-  std::queue<QueueEntry> queue_;
-  uint64_t pool_id_;
-  uint64_t impl_id_;
-  PeriodicClock clock_;
-
-  void create_map(Storage *storage, uint32_t storage_node_id,
-                  const MapOptions &options);
-  void open_map(Storage *storage, uint32_t storage_node_id);
-
-  void rebuild_table();
-
-  inline void refresh_if_possible();
-  void refresh();
-  void refresh_pool();
-  void refresh_impl();
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HASH_TABLE_HPP

  Deleted: lib/grnxx/map/header.hpp (+0 -33) 100644
===================================================================
--- lib/grnxx/map/header.hpp    2013-08-23 10:46:34 +0900 (375fd05)
+++ /dev/null
@@ -1,33 +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_MAP_HEADER_HPP
-#define GRNXX_MAP_HEADER_HPP
-
-#include "grnxx/map.hpp"
-
-namespace grnxx {
-namespace map {
-
-struct Header {
-  MapType type;
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HEADER_HPP

  Deleted: lib/grnxx/map/helper.hpp (+0 -106) 100644
===================================================================
--- lib/grnxx/map/helper.hpp    2013-08-23 10:46:34 +0900 (8144d4c)
+++ /dev/null
@@ -1,106 +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_MAP_HELPER_HPP
-#define GRNXX_MAP_HELPER_HPP
-
-#include "grnxx/features.hpp"
-
-#include <cmath>
-#include <cstring>
-#include <limits>
-#include <type_traits>
-
-#include "grnxx/array.hpp"
-#include "grnxx/bytes.hpp"
-#include "grnxx/traits.hpp"
-
-namespace grnxx {
-namespace map {
-
-// Normalize a key.
-template <typename T,
-          bool IS_FLOATING_POINT = std::is_floating_point<T>::value>
-struct NormalizeHelper;
-// Do nothing if "T" is not a floating point type.
-template <typename T>
-struct NormalizeHelper<T, false> {
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  // Return "key" as is.
-  static Key normalize(KeyArg key) {
-    return key;
-  }
-};
-// Normalize a floating point number.
-template <typename T>
-struct NormalizeHelper<T, true> {
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  // Return the normalized NaN iff "key" is a NaN.
-  // Return +0.0 iff "key" is +/-0.0.
-  // Return "key" as is otherwise.
-  static Key normalize(KeyArg key) {
-    return std::isnan(key) ? std::numeric_limits<Key>::quiet_NaN() :
-        (key != 0.0 ? key : 0.0);
-  }
-};
-
-// Compare keys.
-template <typename T,
-          bool IS_FLOATING_POINT = std::is_floating_point<T>::value>
-struct EqualToHelper;
-// Compare keys with operator==() if "T" is not a floating point type.
-template <typename T>
-struct EqualToHelper<T, false> {
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  static bool equal_to(KeyArg lhs, KeyArg rhs) {
-    return lhs == rhs;
-  }
-};
-// Compare keys as sequences of bytes.
-template <typename T>
-struct EqualToHelper<T, true> {
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  static bool equal_to(KeyArg lhs, KeyArg rhs) {
-    return std::memcmp(&lhs, &rhs, sizeof(Key)) == 0;
-  }
-};
-
-template <typename T>
-struct Helper {
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  static Key normalize(KeyArg key) {
-    return NormalizeHelper<T>::normalize(key);
-  }
-  static bool equal_to(KeyArg lhs, KeyArg rhs) {
-    return EqualToHelper<T>::equal_to(lhs, rhs);
-  }
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_HELPER_HPP

  Deleted: lib/grnxx/map/key_pool.cpp (+0 -428) 100644
===================================================================
--- lib/grnxx/map/key_pool.cpp    2013-08-23 10:46:34 +0900 (54624ca)
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
-  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/map/key_pool.hpp"
-
-#include "grnxx/common_header.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::KeyPool";
-
-constexpr int64_t MIN_KEY_ID = MAP_MIN_KEY_ID;
-constexpr int64_t MAX_KEY_ID = MAP_MAX_KEY_ID;
-
-constexpr uint64_t INVALID_UNIT_ID  = ~0ULL;
-constexpr uint64_t INVALID_ENTRY_ID = (1ULL << 63) - 1;
-
-}  // namespace
-
-struct KeyPoolHeader {
-  grnxx::CommonHeader common_header;
-  int64_t max_key_id;
-  uint64_t num_keys;
-  // For other than Bytes.
-  uint64_t latest_available_unit_id;
-  uint32_t keys_storage_node_id;
-  uint32_t bits_storage_node_id;
-  uint32_t links_storage_node_id;
-  // For Bytes.
-  uint64_t latest_free_entry_id;
-  uint32_t pool_storage_node_id;
-  uint32_t entries_storage_node_id;
-
-  // Initialize the member variables.
-  KeyPoolHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-KeyPoolHeader::KeyPoolHeader()
-    : common_header(FORMAT_STRING),
-      max_key_id(MIN_KEY_ID - 1),
-      num_keys(0),
-      latest_available_unit_id(INVALID_UNIT_ID),
-      keys_storage_node_id(STORAGE_INVALID_NODE_ID),
-      bits_storage_node_id(STORAGE_INVALID_NODE_ID),
-      links_storage_node_id(STORAGE_INVALID_NODE_ID),
-      latest_free_entry_id(INVALID_ENTRY_ID),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      entries_storage_node_id(STORAGE_INVALID_NODE_ID) {}
-
-KeyPoolHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-template <typename T>
-KeyPool<T>::KeyPool()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      max_key_id_(nullptr),
-      num_keys_(nullptr),
-      keys_(),
-      bits_(),
-      links_() {}
-
-template <typename T>
-KeyPool<T>::~KeyPool() {}
-
-template <typename T>
-KeyPool<T> *KeyPool<T>::create(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<KeyPool> pool(new (std::nothrow) KeyPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::KeyPool failed";
-    throw MemoryError();
-  }
-  pool->create_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-template <typename T>
-KeyPool<T> *KeyPool<T>::open(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<KeyPool> pool(new (std::nothrow) KeyPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::KeyPool failed";
-    throw MemoryError();
-  }
-  pool->open_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-template <typename T>
-void KeyPool<T>::unset(int64_t key_id) {
-  // Prepare to update "bits_" and "links_".
-  const uint64_t unit_id = key_id / UNIT_SIZE;
-  const uint64_t unit_bit = 1ULL << (key_id % UNIT_SIZE);
-  BitArrayUnit * const unit = &bits_->get_unit(unit_id);
-  if ((*unit & unit_bit) == 0) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  // Set "link" if this operation creates the first 0 bit in the unit.
-  Link *link = nullptr;
-  if (*unit == ~BitArrayUnit(0)) {
-    link = &links_->get_value(unit_id);
-  }
-  *unit &= ~unit_bit;
-  if (link) {
-    if (header_->latest_available_unit_id != INVALID_UNIT_ID) {
-      // "*link" points to the next unit.
-      *link = static_cast<Link>(header_->latest_available_unit_id);
-    } else {
-      // "*link" points to itself because there are no more units.
-      *link = static_cast<Link>(unit_id);
-    }
-    header_->latest_available_unit_id = *link;
-  }
-  --header_->num_keys;
-}
-
-template <typename T>
-void KeyPool<T>::reset(int64_t key_id, KeyArg dest_key) {
-  if (!get_bit(key_id)) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  keys_->set(key_id, dest_key);
-}
-
-template <typename T>
-int64_t KeyPool<T>::add(KeyArg key) {
-  // Find an unused key ID.
-  const bool is_new_unit = header_->latest_available_unit_id == INVALID_UNIT_ID;
-  uint64_t unit_id;
-  if (is_new_unit) {
-    if (header_->max_key_id == MAX_KEY_ID) {
-      GRNXX_ERROR() << "too many keys: key_id = " << (header_->max_key_id + 1)
-                    << ", max_key_id = " << MAX_KEY_ID;
-      throw LogicError();
-    }
-    unit_id = (header_->max_key_id + 1) / UNIT_SIZE;
-  } else {
-    unit_id = header_->latest_available_unit_id;
-  }
-  BitArrayUnit * const unit = &bits_->get_unit(unit_id);
-  uint8_t unit_bit_id;
-  uint64_t unit_bit;
-  const Link *link = nullptr;
-  if (is_new_unit) {
-    // "links_[unit_id]" points to itself because there are no more units.
-    links_->set(unit_id, unit_id);
-    *unit = 0;
-    unit_bit_id = 0;
-    unit_bit = 1;
-    header_->latest_available_unit_id = unit_id;
-  } else {
-    unit_bit_id = bit_scan_forward(~*unit);
-    unit_bit = 1ULL << unit_bit_id;
-    if ((*unit | unit_bit) == ~BitArrayUnit(0)) {
-      // The unit must be removed from "links_" because it becomes full.
-      link = &links_->get_value(header_->latest_available_unit_id);
-    }
-  }
-  const int64_t next_key_id = (unit_id * UNIT_SIZE) + unit_bit_id;
-  keys_->set(next_key_id, key);
-  if (link) {
-    if (*link != unit_id) {
-      // Move to the next unit.
-      header_->latest_available_unit_id = *link;
-    } else {
-      // There are no more units.
-      header_->latest_available_unit_id = INVALID_UNIT_ID;
-    }
-  }
-  *unit |= unit_bit;
-  if (next_key_id > header_->max_key_id) {
-    header_->max_key_id = next_key_id;
-  }
-  ++header_->num_keys;
-  return next_key_id;
-}
-
-template <typename T>
-void KeyPool<T>::defrag(double) {
-  // Nothing to do.
-}
-
-template <typename T>
-void KeyPool<T>::truncate() {
-  header_->max_key_id = MIN_KEY_ID - 1;
-  header_->num_keys = 0;
-  header_->latest_available_unit_id = INVALID_UNIT_ID;
-}
-
-template <typename T>
-void KeyPool<T>::create_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    max_key_id_ = &header_->max_key_id;
-    num_keys_ = &header_->num_keys;
-    keys_.reset(KeyArray::create(storage, storage_node_id_,
-                                 KeyPoolHelper<T>::KEY_ARRAY_SIZE));
-    bits_.reset(BitArray::create(storage, storage_node_id_,
-                                 KeyPoolHelper<T>::BIT_ARRAY_SIZE));
-    links_.reset(LinkArray::create(storage, storage_node_id_,
-                                   KeyPoolHelper<T>::LINK_ARRAY_SIZE));
-    header_->keys_storage_node_id = keys_->storage_node_id();
-    header_->bits_storage_node_id = bits_->storage_node_id();
-    header_->links_storage_node_id = links_->storage_node_id();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void KeyPool<T>::open_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  max_key_id_ = &header_->max_key_id;
-  num_keys_ = &header_->num_keys;
-  keys_.reset(KeyArray::open(storage, header_->keys_storage_node_id));
-  bits_.reset(BitArray::open(storage, header_->bits_storage_node_id));
-  links_.reset(LinkArray::open(storage, header_->links_storage_node_id));
-}
-
-template class KeyPool<int8_t>;
-template class KeyPool<uint8_t>;
-template class KeyPool<int16_t>;
-template class KeyPool<uint16_t>;
-template class KeyPool<int32_t>;
-template class KeyPool<uint32_t>;
-template class KeyPool<int64_t>;
-template class KeyPool<uint64_t>;
-template class KeyPool<double>;
-template class KeyPool<GeoPoint>;
-
-KeyPool<Bytes>::KeyPool()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      max_key_id_(nullptr),
-      num_keys_(nullptr),
-      pool_(),
-      entries_() {}
-
-KeyPool<Bytes>::~KeyPool() {}
-
-KeyPool<Bytes> *KeyPool<Bytes>::create(Storage *storage,
-                                       uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<KeyPool> pool(new (std::nothrow) KeyPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::KeyPool failed";
-    throw MemoryError();
-  }
-  pool->create_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-KeyPool<Bytes> *KeyPool<Bytes>::open(Storage *storage,
-                                     uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<KeyPool> pool(new (std::nothrow) KeyPool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::KeyPool failed";
-    throw MemoryError();
-  }
-  pool->open_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-void KeyPool<Bytes>::unset(int64_t key_id) {
-  Entry &entry = entries_->get_value(key_id);
-  if (!entry) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  pool_->unset(entry.bytes_id());
-  entry.set_next_free_entry_id(header_->latest_free_entry_id);
-  header_->latest_free_entry_id = key_id;
-  --header_->num_keys;
-}
-
-void KeyPool<Bytes>::reset(int64_t key_id, KeyArg dest_key) {
-  Entry &entry = entries_->get_value(key_id);
-  if (!entry) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  const uint64_t src_bytes_id = entry.bytes_id();
-  entry.set_bytes_id(pool_->add(dest_key));
-  pool_->unset(src_bytes_id);
-}
-
-int64_t KeyPool<Bytes>::add(KeyArg key) {
-  uint64_t entry_id;
-  if (header_->latest_free_entry_id != INVALID_ENTRY_ID) {
-    entry_id = header_->latest_free_entry_id;
-  } else {
-    entry_id = header_->max_key_id + 1;
-  }
-  Entry &entry = entries_->get_value(entry_id);
-  const uint64_t bytes_id = pool_->add(key);
-  if (header_->latest_free_entry_id != INVALID_ENTRY_ID) {
-    header_->latest_free_entry_id = entry.next_free_entry_id();
-  }
-  entry.set_bytes_id(bytes_id);
-  if (static_cast<int64_t>(entry_id) > header_->max_key_id) {
-    header_->max_key_id = entry_id;
-  }
-  ++header_->num_keys;
-  return entry_id;
-}
-
-void KeyPool<Bytes>::defrag(double usage_rate_threshold) {
-  const uint64_t page_size_in_use_threshold =
-      uint64_t(pool_->page_size() * usage_rate_threshold);
-  for (int64_t key_id = MIN_KEY_ID; key_id <= header_->max_key_id; ++key_id) {
-    Entry &entry = entries_->get_value(key_id);
-    if (entry) {
-      // Reallocate a key if it belongs to a page whose usage rate is less than
-      // "usage_rate_threshold".
-      const uint64_t bytes_id = entry.bytes_id();
-      const uint64_t page_id = bytes_id / pool_->page_size();
-      if (pool_->get_page_size_in_use(page_id) < page_size_in_use_threshold) {
-        entry.set_bytes_id(pool_->add(pool_->get(bytes_id)));
-        pool_->unset(bytes_id);
-      }
-    }
-  }
-}
-
-void KeyPool<Bytes>::truncate() {
-  header_->max_key_id = MIN_KEY_ID - 1;
-  header_->num_keys = 0;
-  header_->latest_free_entry_id = INVALID_ENTRY_ID;
-  pool_->truncate();
-}
-
-void KeyPool<Bytes>::create_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    max_key_id_ = &header_->max_key_id;
-    num_keys_ = &header_->num_keys;
-    pool_.reset(BytesPool::create(storage, storage_node_id_));
-    entries_.reset(EntryArray::create(storage, storage_node_id_,
-                                      ENTRY_ARRAY_SIZE));
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->entries_storage_node_id = entries_->storage_node_id();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void KeyPool<Bytes>::open_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  max_key_id_ = &header_->max_key_id;
-  num_keys_ = &header_->num_keys;
-  pool_.reset(BytesPool::open(storage, header_->pool_storage_node_id));
-  entries_.reset(EntryArray::open(storage, header_->entries_storage_node_id));
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/key_pool.hpp (+0 -307) 100644
===================================================================
--- lib/grnxx/map/key_pool.hpp    2013-08-23 10:46:34 +0900 (9a62887)
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_KEY_POOL_HPP
-#define GRNXX_MAP_KEY_POOL_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/array.hpp"
-#include "grnxx/bytes.hpp"
-#include "grnxx/map/bytes_pool.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-class BytesPool;
-
-struct KeyPoolHeader;
-
-// Change the size of arrays based on "T".
-// Note that the size of link array is N/64 where N is the size of KeyArray.
-template <typename T, size_t T_SIZE = sizeof(T)>
-struct KeyPoolHelper;
-
-// Map<T> has at most 2^40 different keys.
-template <typename T, size_t T_SIZE>
-struct KeyPoolHelper {
-  using KeyArray = Array<T, (1 << 16), (1 << 12)>;
-  using BitArray = Array<bool, (1 << 18), (1 << 11)>;
-  using Link = uint64_t;
-  using LinkArray = Array<Link, (1 << 14), (1 << 10)>;
-
-  static constexpr uint64_t KEY_ARRAY_SIZE  = 1ULL << 40;
-  static constexpr uint64_t BIT_ARRAY_SIZE  = 1ULL << 40;
-  static constexpr uint64_t LINK_ARRAY_SIZE = 1ULL << 34;
-};
-
-// Map<T> has at most 2^8 different keys.
-template <typename T>
-struct KeyPoolHelper<T, 1> {
-  using KeyArray = Array<T>;
-  using BitArray = Array<bool>;
-  using Link = uint8_t;
-  using LinkArray = Array<Link>;
-
-  static constexpr uint64_t KEY_ARRAY_SIZE  = 1ULL << 8;
-  static constexpr uint64_t BIT_ARRAY_SIZE  = 1ULL << 8;
-  static constexpr uint64_t LINK_ARRAY_SIZE = 1ULL << 2;
-};
-
-// Map<T> has at most 2^16 different keys.
-template <typename T>
-struct KeyPoolHelper<T, 2> {
-  using KeyArray = Array<T>;
-  using BitArray = Array<bool>;
-  using Link = uint16_t;
-  using LinkArray = Array<Link>;
-
-  static constexpr uint64_t KEY_ARRAY_SIZE  = 1ULL << 16;
-  static constexpr uint64_t BIT_ARRAY_SIZE  = 1ULL << 16;
-  static constexpr uint64_t LINK_ARRAY_SIZE = 1ULL << 10;
-};
-
-// Map<T> has at most 2^32 different keys.
-template <typename T>
-struct KeyPoolHelper<T, 4> {
-  using KeyArray = Array<T, (1 << 18)>;
-  using BitArray = Array<bool, (1 << 20)>;
-  using Link = uint32_t;
-  using LinkArray = Array<Link, (1 << 15)>;
-
-  static constexpr uint64_t KEY_ARRAY_SIZE  = 1ULL << 32;
-  static constexpr uint64_t BIT_ARRAY_SIZE  = 1ULL << 32;
-  static constexpr uint64_t LINK_ARRAY_SIZE = 1ULL << 26;
-};
-
-template <typename T>
-class KeyPool {
-  using Header = KeyPoolHeader;
-  using KeyArray = typename KeyPoolHelper<T>::KeyArray;
-  using BitArray = typename KeyPoolHelper<T>::BitArray;
-  using BitArrayUnit = typename BitArray::Unit;
-  using Link = typename KeyPoolHelper<T>::Link;
-  using LinkArray = typename KeyPoolHelper<T>::LinkArray;
-
-  static constexpr uint64_t UNIT_SIZE = sizeof(BitArrayUnit) * 8;
-
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  KeyPool();
-  ~KeyPool();
-
-  // Create a pool.
-  static KeyPool *create(Storage *storage, uint32_t storage_node_id);
-  // Open a pool.
-  static KeyPool *open(Storage *storage, uint32_t storage_node_id);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  // Return the maximum key ID ever used.
-  // The return value can be a negative value iff the map is empty.
-  int64_t max_key_id() const {
-    return *max_key_id_;
-  }
-  // Return the number of keys.
-  uint64_t num_keys() const {
-    return *num_keys_;
-  }
-
-  // Get a key associated with "key_id" and return true iff it exists.
-  // Assign the found key to "*key" iff "key" != nullptr.
-  bool get(int64_t key_id, Key *key) {
-    if (!get_bit(key_id)) {
-      return false;
-    }
-    if (key) {
-      *key = get_key(key_id);
-    }
-    return true;
-  }
-  // Get a key associated with "key_id" without check.
-  Key get_key(int64_t key_id) {
-    return keys_->get(key_id);
-  }
-  // Return true iff "key_id" is valid.
-  bool get_bit(int64_t key_id) {
-    return bits_->get(key_id);
-  }
-  // Remove a key associated with "key_id".
-  void unset(int64_t key_id);
-  // Replace a key associated with "key_id" with "dest_key".
-  void reset(int64_t key_id, KeyArg dest_key);
-
-  // Add "key" and return its ID.
-  int64_t add(KeyArg key);
-
-  // Defrag a pool.
-  void defrag(double usage_rate_threshold);
-
-  // Remove all the keys.
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  const int64_t *max_key_id_;
-  const uint64_t *num_keys_;
-  std::unique_ptr<KeyArray> keys_;
-  std::unique_ptr<BitArray> bits_;
-  std::unique_ptr<LinkArray> links_;
-
-  // Create a pool.
-  void create_pool(Storage *storage, uint32_t storage_node_id);
-  // Open a pool.
-  void open_pool(Storage *storage, uint32_t storage_node_id);
-};
-
-class KeyPoolEntry {
-  static constexpr uint64_t IS_VALID_FLAG = 1ULL << 63;
-
- public:
-  KeyPoolEntry() = default;
-
-  // Return true iff the entry is valid.
-  explicit operator bool() const {
-    return value_ & IS_VALID_FLAG;
-  }
-
-  // Return the ID of the associated byte sequence.
-  uint64_t bytes_id() const {
-    return value_ & ~IS_VALID_FLAG;
-  }
-  // Return the ID of the next invalid entry.
-  uint64_t next_free_entry_id() const {
-    return value_;
-  }
-
-  // Set the ID of the associated byte sequence.
-  void set_bytes_id(uint64_t bytes_id) {
-    value_ = IS_VALID_FLAG | bytes_id;
-  }
-  // Set the ID of the next free entry.
-  void set_next_free_entry_id(uint64_t next_free_entry_id) {
-    value_ = next_free_entry_id;
-  }
-
- private:
-  uint64_t value_;
-
-  explicit KeyPoolEntry(uint64_t value) : value_(value) {}
-};
-
-template <>
-class KeyPool<Bytes> {
-  using Header = KeyPoolHeader;
-  using Entry = KeyPoolEntry;
-  using EntryArray = Array<Entry, (1 << 16), (1 << 12)>;
-
-  static constexpr uint64_t ENTRY_ARRAY_SIZE = 1ULL << 40;
-
- public:
-  using Key = typename Traits<Bytes>::Type;
-  using KeyArg = typename Traits<Bytes>::ArgumentType;
-
-  KeyPool();
-  ~KeyPool();
-
-  // Create a pool.
-  static KeyPool *create(Storage *storage, uint32_t storage_node_id);
-  // Open a pool.
-  static KeyPool *open(Storage *storage, uint32_t storage_node_id);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  // Return the maximum key ID ever used.
-  // The return value can be a negative value iff the map is empty.
-  int64_t max_key_id() const {
-    return *max_key_id_;
-  }
-  // Return the number of keys.
-  uint64_t num_keys() const {
-    return *num_keys_;
-  }
-
-  // Get a key associated with "key_id" and return true iff it exists.
-  // Assign the found key to "*key" iff "key" != nullptr.
-  bool get(int64_t key_id, Key *key) {
-    const Entry entry = entries_->get(key_id);
-    if (!entry) {
-      return false;
-    }
-    if (key) {
-      *key = pool_->get(entry.bytes_id());
-    }
-    return true;
-  }
-  // Get a key associated with "key_id" without check.
-  Key get_key(int64_t key_id) {
-    return pool_->get(entries_->get(key_id).bytes_id());
-  }
-  // Return true iff "key_id" is valid.
-  bool get_bit(int64_t key_id) {
-    return bool(entries_->get(key_id));
-  }
-  // Remove a key associated with "key_id".
-  void unset(int64_t key_id);
-  // Replace a key associated with "key_id" with "dest_key".
-  void reset(int64_t key_id, KeyArg dest_key);
-
-  // Add "key" and return its ID.
-  int64_t add(KeyArg key);
-
-  // Defrag a pool.
-  void defrag(double usage_rate_threshold);
-
-  // Remove all the keys.
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  const int64_t *max_key_id_;
-  const uint64_t *num_keys_;
-  std::unique_ptr<BytesPool> pool_;
-  std::unique_ptr<EntryArray> entries_;
-
-  // Create a pool.
-  void create_pool(Storage *storage, uint32_t storage_node_id);
-  // Open a pool.
-  void open_pool(Storage *storage, uint32_t storage_node_id);
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_KEY_POOL_HPP

  Deleted: lib/grnxx/map/patricia.cpp (+0 -1771) 100644
===================================================================
--- lib/grnxx/map/patricia.cpp    2013-08-23 10:46:34 +0900 (815409c)
+++ /dev/null
@@ -1,1771 +0,0 @@
-/*
-  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/map/patricia.hpp"
-
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map/common_header.hpp"
-#include "grnxx/map/hash.hpp"
-#include "grnxx/map/helper.hpp"
-#include "grnxx/map/key_pool.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::map::Patricia";
-
-constexpr uint64_t ROOT_NODE_ID  = 0;
-constexpr uint64_t DUMMY_NODE_ID = ROOT_NODE_ID + 1;
-
-constexpr uint64_t NODE_ARRAY_SIZE = 1ULL << 41;
-constexpr uint64_t CACHE_SIZE      = 1ULL << 19;
-
-enum NodeStatus : uint64_t {
-  NODE_DEAD     = 0,
-  NODE_LEAF     = 1,
-  NODE_BRANCH   = 2,
-  NODE_TERMINAL = 3
-};
-
-}  // namespace
-
-struct PatriciaHeader {
-  CommonHeader common_header;
-  MapType map_type;
-  uint64_t next_node_id;
-  uint64_t nodes_id;
-  uint32_t nodes_storage_node_id;
-  uint32_t pool_storage_node_id;
-  uint32_t cache_storage_node_id;
-  Mutex mutex;
-
-  // Initialize the member variables.
-  PatriciaHeader();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-};
-
-PatriciaHeader::PatriciaHeader()
-    : common_header(FORMAT_STRING, MAP_PATRICIA),
-      next_node_id(2),
-      nodes_id(0),
-      nodes_storage_node_id(STORAGE_INVALID_NODE_ID),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      cache_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-PatriciaHeader::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-// The internal structure of PatriciaNode is as follows:
-// - Common
-//   62-63 ( 2): status (DEAD, LEAF, BRANCH, TERMINAL)
-// - Leaf: LEAF
-//    0-39 (40): key_id
-//   40-61 (22): reserved
-// - Branch or Terminal: BRANCH || TERMINAL
-//   16-57 (42): offset
-//   58-61 ( 4): reserved
-// - Branch: BRANCH
-//    0-15 (16): bit_pos
-// - Terminal: TERMINAL
-//    0-15 (16): bit_size
-// where 0 is the LSB and 63 is the MSB.
-class PatriciaNode {
-  static constexpr uint64_t STATUS_MASK    = (1ULL << 2) - 1;
-  static constexpr uint8_t  STATUS_SHIFT   = 62;
-
-  static constexpr uint64_t KEY_ID_MASK    = (1ULL << 40) - 1;
-  static constexpr uint8_t  KEY_ID_SHIFT   = 0;
-
-  static constexpr uint64_t OFFSET_MASK    = (1ULL << 42) - 1;
-  static constexpr uint8_t  OFFSET_SHIFT   = 16;
-
-  static constexpr uint64_t BIT_POS_MASK   = (1ULL << 16) - 1;
-  static constexpr uint8_t  BIT_POS_SHIFT  = 0;
-
-  static constexpr uint64_t BIT_SIZE_MASK  = (1ULL << 16) - 1;
-  static constexpr uint8_t  BIT_SIZE_SHIFT = 0;
-
- public:
-  PatriciaNode() = default;
-
-  // Create a node that has neither descendants nor an associated key.
-  static PatriciaNode dead_node() {
-    return PatriciaNode(NODE_DEAD << STATUS_SHIFT);
-  }
-  // Create a node that has an associated key that is identified by "key_id".
-  static PatriciaNode leaf_node(int64_t key_id) {
-    return PatriciaNode((NODE_LEAF << STATUS_SHIFT) |
-                        ((key_id & KEY_ID_MASK) << KEY_ID_SHIFT));
-  }
-  // Create a node that works as a 0/1 branch.
-  // If key["bit_pos"] == 0, the next node ID is "offset".
-  // Otherwise, the next node ID is "offset" + 1.
-  static PatriciaNode branch_node(uint64_t bit_pos, uint64_t offset) {
-    return PatriciaNode((NODE_BRANCH << STATUS_SHIFT) |
-                        ((bit_pos & BIT_POS_MASK) << BIT_POS_SHIFT) |
-                        ((offset & OFFSET_MASK) << OFFSET_SHIFT));
-  }
-  // Create a node that works as a short/long branch.
-  // If key_size <= "bit_size", the next node ID is "offset".
-  // Otherwise, the next node ID is "offset" + 1.
-  static PatriciaNode terminal_node(uint64_t bit_size, uint64_t offset) {
-    return PatriciaNode((NODE_TERMINAL << STATUS_SHIFT) |
-                        ((bit_size & BIT_SIZE_MASK) << BIT_SIZE_SHIFT) |
-                         ((offset & OFFSET_MASK) << OFFSET_SHIFT));
-  }
-
-  // Return the node status.
-  uint64_t status() const {
-    return (value_ >> STATUS_SHIFT) & STATUS_MASK;
-  }
-  // Return the associated key ID.
-  int64_t key_id() const {
-    return (value_ >> KEY_ID_SHIFT) & KEY_ID_MASK;
-  }
-  // Return the offset to the next nodes.
-  uint64_t offset() const {
-    return (value_ >> OFFSET_SHIFT) & OFFSET_MASK;
-  }
-  // Return the position of the branch.
-  uint64_t bit_pos() const {
-    return (value_ >> BIT_POS_SHIFT) & BIT_POS_MASK;
-  }
-  // Return the branch condition.
-  uint64_t bit_size() const {
-    return (value_ >> BIT_SIZE_SHIFT) & BIT_SIZE_MASK;
-  }
-
- private:
-  uint64_t value_;
-
-  explicit PatriciaNode(uint64_t value) : value_(value) {}
-};
-
-class PatriciaCacheEntry {
- public:
-  // Create an unused entry.
-  static PatriciaCacheEntry invalid_entry() {
-    return PatriciaCacheEntry(0);
-  }
-
-  // Return true iff this entry is not empty.
-  explicit operator bool() {
-    return value_ & IS_VALID_FLAG;
-  }
-
-  // Return true iff this entry and "hash_value" have the same memo.
-  bool test_hash_value(uint64_t hash_value) const {
-    return ((value_ ^ hash_value) >> MEMO_SHIFT) == 0;
-  }
-  // Return a stored key ID.
-  int64_t key_id() const {
-    return value_ & KEY_ID_MASK;
-  }
-
-  // Set a key ID and a memo, which is extracted from "hash_value".
-  void set(int64_t key_id, uint64_t hash_value) {
-    value_ = IS_VALID_FLAG | key_id | (hash_value & (~0ULL << MEMO_SHIFT));
-  }
-
- private:
-  uint64_t value_;
-
-  explicit PatriciaCacheEntry(uint64_t value) : value_(value) {}
-
-  static constexpr uint64_t IS_VALID_FLAG = 1ULL << 40;
-  static constexpr uint8_t  MEMO_SHIFT    = 41;
-  static constexpr uint64_t KEY_ID_MASK   = (1ULL << 40) - 1;
-};
-
-template <typename T>
-Patricia<T>::Patricia()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      nodes_(),
-      old_nodes_(),
-      pool_(),
-      cache_(),
-      nodes_id_(0) {}
-
-template <typename T>
-Patricia<T>::~Patricia() {}
-
-template <typename T>
-Patricia<T> *Patricia<T>::create(Storage *storage,
-                                 uint32_t storage_node_id,
-                                 const MapOptions &options) {
-  std::unique_ptr<Patricia> map(new (std::nothrow) Patricia);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::Patricia failed";
-    throw MemoryError();
-  }
-  map->create_map(storage, storage_node_id, options);
-  return map.release();
-}
-
-template <typename T>
-Patricia<T> *Patricia<T>::open(Storage *storage,
-                               uint32_t storage_node_id) {
-  std::unique_ptr<Patricia> map(new (std::nothrow) Patricia);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::Patricia failed";
-    throw MemoryError();
-  }
-  map->open_map(storage, storage_node_id);
-  return map.release();
-}
-
-template <typename T>
-uint32_t Patricia<T>::storage_node_id() const {
-  return storage_node_id_;
-}
-
-template <typename T>
-MapType Patricia<T>::type() const {
-  return MAP_PATRICIA;
-}
-
-template <typename T>
-int64_t Patricia<T>::max_key_id() {
-  return pool_->max_key_id();
-}
-
-template <typename T>
-uint64_t Patricia<T>::num_keys() {
-  return pool_->num_keys();
-}
-
-template <typename T>
-bool Patricia<T>::get(int64_t key_id, Key *key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > pool_->max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  return pool_->get(key_id, key);
-}
-
-template <typename T>
-bool Patricia<T>::unset(int64_t key_id) {
-  refresh_nodes();
-  Key key;
-  if (!get(key_id, &key)) {
-    // Not found.
-    return false;
-  }
-  // The root node must not be dead because the above get() has succeeded.
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *prev_node = nullptr;
-  for ( ; ; ) {
-    Node * const node = &nodes_->get_value(node_id);
-    if (node->status() == NODE_LEAF) {
-      if (node->key_id() != key_id) {
-        // Not found.
-        return false;
-      }
-      pool_->unset(key_id);
-      if (prev_node) {
-        Node * const sibling_node = node + (node_id ^ 1) - node_id;
-        *prev_node = *sibling_node;
-      } else {
-        *node = Node::dead_node();
-      }
-      return true;
-    }
-    prev_node = node;
-    node_id = node->offset() + get_ith_bit(key, node->bit_pos());
-  }
-}
-
-template <typename T>
-bool Patricia<T>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_nodes();
-  // Find the source key.
-  Key src_key;
-  if (!get(key_id, &src_key)) {
-    // Not found.
-    return false;
-  }
-  // The root node must not be dead because the above get() has succeeded.
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *src_node;
-  Node *src_prev_node = nullptr;
-  Node *src_sibling_node = nullptr;
-  for ( ; ; ) {
-    src_node = &nodes_->get_value(node_id);
-    if (src_node->status() == NODE_LEAF) {
-      if (src_node->key_id() != key_id) {
-        // Not found.
-        return false;
-      }
-      if (src_prev_node) {
-        src_sibling_node = src_node + (node_id ^ 1) - node_id;
-      }
-      break;
-    }
-    src_prev_node = src_node;
-    node_id = src_node->offset() + get_ith_bit(src_key, src_node->bit_pos());
-  }
-  // Add the destination key.
-  const Key dest_normalized_key = Helper<T>::normalize(dest_key);
-  node_id = ROOT_NODE_ID;
-  Node *history[(sizeof(Key) * 8) + 1];
-  int depth = -1;
-  for ( ; ; ) {
-    Node * const node = &nodes_->get_value(node_id);
-    history[++depth] = node;
-    if (node->status() == NODE_LEAF) {
-      break;
-    }
-    node_id = node->offset() +
-              get_ith_bit(dest_normalized_key, node->bit_pos());
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(history[depth]->key_id());
-  const uint64_t count =
-      count_common_prefix_bits(dest_normalized_key, stored_key);
-  if (count == (sizeof(Key) * 8)) {
-    // Found.
-    return false;
-  }
-  // Find the branching point in "history".
-  while (depth > 0) {
-    if (history[depth - 1]->bit_pos() < count) {
-      break;
-    }
-    --depth;
-  }
-  Node * const dest_prev_node = history[depth];
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  pool_->reset(key_id, dest_normalized_key);
-  Node *dest_node;
-  Node *dest_sibling_node;
-  if (get_ith_bit(dest_normalized_key, count)) {
-    dest_node = &next_nodes[1];
-    dest_sibling_node = &next_nodes[0];
-  } else {
-    dest_node = &next_nodes[0];
-    dest_sibling_node = &next_nodes[1];
-  }
-  if (dest_prev_node == src_prev_node) {
-    src_prev_node = dest_sibling_node;
-  } else if (dest_prev_node == src_node) {
-    src_sibling_node = dest_node;
-    src_prev_node = dest_prev_node;
-  }
-  *dest_sibling_node = *dest_prev_node;
-  *dest_node = Node::leaf_node(key_id);
-  *dest_prev_node = Node::branch_node(count, header_->next_node_id);
-  *src_prev_node = *src_sibling_node;
-  header_->next_node_id += 2;
-  return true;
-}
-
-template <typename T>
-bool Patricia<T>::find(KeyArg key, int64_t *key_id) {
-  refresh_nodes();
-  const Key normalized_key = Helper<T>::normalize(key);
-  uint64_t node_id = ROOT_NODE_ID;
-  Node node = nodes_->get(node_id);
-  if (node.status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  for ( ; ; ) {
-    if (node.status() == NODE_LEAF) {
-      Key stored_key = pool_->get_key(node.key_id());
-      if (!Helper<T>::equal_to(normalized_key, stored_key)) {
-        // Not found.
-        return false;
-      }
-      if (key_id) {
-        *key_id = node.key_id();
-      }
-      return true;
-    }
-    node_id = node.offset() + get_ith_bit(normalized_key, node.bit_pos());
-    node = nodes_->get(node_id);
-  }
-}
-
-template <typename T>
-bool Patricia<T>::add(KeyArg key, int64_t *key_id) {
-  refresh_nodes();
-  const Key normalized_key = Helper<T>::normalize(key);
-  const uint64_t hash_value = Hash<Key>()(normalized_key);
-  CacheEntry &cache = cache_->get_value(hash_value & (cache_->size() - 1));
-  if (cache && cache.test_hash_value(hash_value)) {
-    Key cached_key;
-    if (pool_->get(cache.key_id(), &cached_key)) {
-      if (key == cached_key) {
-        if (key_id) {
-          *key_id = cache.key_id();
-        }
-        return false;
-      }
-    }
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *node = &nodes_->get_value(node_id);
-  if (node->status() == NODE_DEAD) {
-    // The patricia is empty.
-    int64_t next_key_id = pool_->add(normalized_key);
-    *node = Node::leaf_node(next_key_id);
-    if (key_id) {
-      *key_id = next_key_id;
-    }
-    cache.set(next_key_id, hash_value);
-    return true;
-  }
-  Node *history[(sizeof(Key) * 8) + 1];
-  int depth = 0;
-  history[0] = node;
-  while (node->status() != NODE_LEAF) {
-    node_id = node->offset() + get_ith_bit(normalized_key, node->bit_pos());
-    node = &nodes_->get_value(node_id);
-    history[++depth] = node;
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(node->key_id());
-  const uint64_t count = count_common_prefix_bits(normalized_key, stored_key);
-  if (count == (sizeof(Key) * 8)) {
-    // Found.
-    if (key_id) {
-      *key_id = node->key_id();
-    }
-    cache.set(node->key_id(), hash_value);
-    return false;
-  }
-  // Find the branching point in "history".
-  while (depth > 0) {
-    if (history[depth - 1]->bit_pos() < count) {
-      break;
-    }
-    --depth;
-  }
-  node = history[depth];
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  int64_t next_key_id = pool_->add(normalized_key);
-  if (get_ith_bit(normalized_key, count)) {
-    next_nodes[0] = *node;
-    next_nodes[1] = Node::leaf_node(next_key_id);
-  } else {
-    next_nodes[0] = Node::leaf_node(next_key_id);
-    next_nodes[1] = *node;
-  }
-  *node = Node::branch_node(count, header_->next_node_id);
-  header_->next_node_id += 2;
-  if (key_id) {
-    *key_id = next_key_id;
-  }
-  cache.set(next_key_id, hash_value);
-  return true;
-}
-
-template <typename T>
-bool Patricia<T>::remove(KeyArg key) {
-  refresh_nodes();
-  const Key normalized_key = Helper<T>::normalize(key);
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *node = &nodes_->get_value(node_id);
-  if (node->status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  Node *prev_node = nullptr;
-  for ( ; ; ) {
-    if (node->status() == NODE_LEAF) {
-      Key stored_key = pool_->get_key(node->key_id());
-      if (!Helper<T>::equal_to(normalized_key, stored_key)) {
-        // Not found.
-        return false;
-      }
-      pool_->unset(node->key_id());
-      if (prev_node) {
-        Node * const sibling_node = node + (node_id ^ 1) - node_id;
-        *prev_node = *sibling_node;
-      } else {
-        *node = Node::dead_node();
-      }
-      return true;
-    }
-    prev_node = node;
-    node_id = node->offset() + get_ith_bit(normalized_key, node->bit_pos());
-    node = &nodes_->get_value(node_id);
-  }
-}
-
-template <typename T>
-bool Patricia<T>::replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id) {
-  refresh_nodes();
-  const Key src_normalized_key = Helper<T>::normalize(src_key);
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *src_node = &nodes_->get_value(node_id);
-  if (src_node->status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  int64_t src_key_id;
-  Node *src_prev_node = nullptr;
-  Node *src_sibling_node = nullptr;
-  for ( ; ; ) {
-    if (src_node->status() == NODE_LEAF) {
-      src_key_id = src_node->key_id();
-      Key stored_key = pool_->get_key(src_key_id);
-      if (!Helper<T>::equal_to(src_normalized_key, stored_key)) {
-        // Not found.
-        return false;
-      }
-      if (src_prev_node) {
-        src_sibling_node = src_node + (node_id ^ 1) - node_id;
-      }
-      break;
-    }
-    src_prev_node = src_node;
-    node_id = src_node->offset() +
-              get_ith_bit(src_normalized_key, src_node->bit_pos());
-    src_node = &nodes_->get_value(node_id);
-  }
-  // Add the destination key.
-  const Key dest_normalized_key = Helper<T>::normalize(dest_key);
-  node_id = ROOT_NODE_ID;
-  Node *history[(sizeof(Key) * 8) + 1];
-  int depth = -1;
-  for ( ; ; ) {
-    Node * const node = &nodes_->get_value(node_id);
-    history[++depth] = node;
-    if (node->status() == NODE_LEAF) {
-      break;
-    }
-    node_id = node->offset() +
-              get_ith_bit(dest_normalized_key, node->bit_pos());
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(history[depth]->key_id());
-  const uint64_t count =
-      count_common_prefix_bits(dest_normalized_key, stored_key);
-  if (count == (sizeof(Key) * 8)) {
-    // Found.
-    return false;
-  }
-  // Find the branching point in "history".
-  while (depth > 0) {
-    if (history[depth - 1]->bit_pos() < count) {
-      break;
-    }
-    --depth;
-  }
-  Node * const dest_prev_node = history[depth];
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  pool_->reset(src_key_id, dest_normalized_key);
-  Node *dest_node;
-  Node *dest_sibling_node;
-  if (get_ith_bit(dest_normalized_key, count)) {
-    dest_node = &next_nodes[1];
-    dest_sibling_node = &next_nodes[0];
-  } else {
-    dest_node = &next_nodes[0];
-    dest_sibling_node = &next_nodes[1];
-  }
-  if (dest_prev_node == src_prev_node) {
-    src_prev_node = dest_sibling_node;
-  } else if (dest_prev_node == src_node) {
-    src_sibling_node = dest_node;
-    src_prev_node = dest_prev_node;
-  }
-  *dest_sibling_node = *dest_prev_node;
-  *dest_node = Node::leaf_node(src_key_id);
-  *dest_prev_node = Node::branch_node(count, header_->next_node_id);
-  *src_prev_node = *src_sibling_node;
-  header_->next_node_id += 2;
-  if (key_id) {
-    *key_id = src_key_id;
-  }
-  return true;
-}
-
-template <typename T>
-void Patricia<T>::defrag() {
-  refresh_nodes();
-  if (max_key_id() == MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  defrag_nodes();
-  pool_->defrag(0.5);
-}
-
-template <typename T>
-void Patricia<T>::truncate() {
-  refresh_nodes();
-  if (max_key_id() == MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  std::unique_ptr<NodeArray> new_nodes(
-      NodeArray::create(storage_, storage_node_id_, NODE_ARRAY_SIZE));
-  try {
-    new_nodes->set(ROOT_NODE_ID, Node::dead_node());
-    new_nodes->set(DUMMY_NODE_ID, Node::dead_node());
-    for (uint64_t i = 0; i < CACHE_SIZE; ++i) {
-      cache_->set(i, CacheEntry::invalid_entry());
-    }
-    pool_->truncate();
-  } catch (...) {
-    NodeArray::unlink(storage_, new_nodes->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new nodes.
-    Lock lock(&header_->mutex);
-    header_->nodes_storage_node_id = new_nodes->storage_node_id();
-    header_->next_node_id = 2;
-    ++header_->nodes_id;
-    old_nodes_.swap(new_nodes);
-    nodes_.swap(old_nodes_);
-    nodes_id_ = header_->nodes_id;
-  }
-  NodeArray::unlink(storage_, old_nodes_->storage_node_id());
-}
-
-template <typename T>
-void Patricia<T>::create_map(Storage *storage, uint32_t storage_node_id,
-                             const MapOptions &) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    nodes_.reset(NodeArray::create(storage, storage_node_id_, NODE_ARRAY_SIZE));
-    pool_.reset(KeyPool<T>::create(storage, storage_node_id_));
-    cache_.reset(Cache::create(storage, storage_node_id_,
-                               CACHE_SIZE, CacheEntry::invalid_entry()));
-    header_->nodes_storage_node_id = nodes_->storage_node_id();
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->cache_storage_node_id = cache_->storage_node_id();
-    nodes_->set(ROOT_NODE_ID, Node::dead_node());
-    nodes_->set(DUMMY_NODE_ID, Node::dead_node());
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void Patricia<T>::open_map(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << storage_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node_id;
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  Lock lock(&header_->mutex);
-  nodes_.reset(NodeArray::open(storage, header_->nodes_storage_node_id));
-  pool_.reset(KeyPool<T>::open(storage, header_->pool_storage_node_id));
-  cache_.reset(Cache::open(storage, header_->cache_storage_node_id));
-  nodes_id_ = header_->nodes_id;
-}
-
-template <typename T>
-void Patricia<T>::defrag_nodes() {
-  // Create a new nodes.
-  std::unique_ptr<NodeArray> new_nodes(
-      NodeArray::create(storage_, storage_node_id_, NODE_ARRAY_SIZE));
-  uint64_t next_node_id = 2;
-  try {
-    next_node_id = rearrange_nodes(ROOT_NODE_ID, ROOT_NODE_ID,
-                                   next_node_id, new_nodes.get());
-    next_node_id = rearrange_nodes(DUMMY_NODE_ID, DUMMY_NODE_ID,
-                                   next_node_id, new_nodes.get());
-  } catch (...) {
-    NodeArray::unlink(storage_, new_nodes->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new nodes.
-    Lock lock(&header_->mutex);
-    header_->nodes_storage_node_id = new_nodes->storage_node_id();
-    header_->next_node_id = next_node_id;
-    ++header_->nodes_id;
-    old_nodes_.swap(new_nodes);
-    nodes_.swap(old_nodes_);
-    nodes_id_ = header_->nodes_id;
-  }
-  NodeArray::unlink(storage_, old_nodes_->storage_node_id());
-}
-
-template <typename T>
-uint64_t Patricia<T>::rearrange_nodes(uint64_t src_node_id,
-                                      uint64_t dest_node_id,
-                                      uint64_t next_node_id,
-                                      NodeArray *dest_nodes) {
-  const Node src_node = nodes_->get(src_node_id);
-  Node &dest_node = dest_nodes->get_value(dest_node_id);
-  switch (src_node.status()) {
-    case NODE_DEAD:
-    case NODE_LEAF: {
-      dest_node = src_node;
-      return next_node_id;
-    }
-    case NODE_BRANCH: {
-      dest_node = Node::branch_node(src_node.bit_pos(), next_node_id);
-      break;
-    }
-    case NODE_TERMINAL: {
-      dest_node = Node::terminal_node(src_node.bit_size(), next_node_id);
-      break;
-    }
-  }
-  src_node_id = src_node.offset();
-  dest_node_id = next_node_id;
-  next_node_id += 2;
-  next_node_id = rearrange_nodes(src_node_id, dest_node_id,
-                                 next_node_id, dest_nodes);
-  next_node_id = rearrange_nodes(src_node_id + 1, dest_node_id + 1,
-                                 next_node_id, dest_nodes);
-  return next_node_id;
-}
-
-template <typename T>
-void Patricia<T>::refresh_nodes() {
-  if (nodes_id_ != header_->nodes_id) {
-    Lock lock(&header_->mutex);
-    if (nodes_id_ != header_->nodes_id) {
-      std::unique_ptr<NodeArray> new_nodes(
-          NodeArray::open(storage_, header_->nodes_storage_node_id));
-      old_nodes_.swap(new_nodes);
-      nodes_.swap(old_nodes_);
-      nodes_id_ = header_->nodes_id;
-    }
-  }
-}
-
-template <typename T>
-uint64_t Patricia<T>::get_ith_bit(KeyArg key, uint64_t bit_pos) {
-  return (key >> ((sizeof(Key) * 8) - 1 - bit_pos)) & 1;
-}
-
-template <>
-uint64_t Patricia<double>::get_ith_bit(KeyArg key, uint64_t bit_pos) {
-  constexpr uint64_t MASK[2] = { 1ULL << 63, ~0ULL };
-  uint64_t x = *reinterpret_cast<const uint64_t *>(&key);
-  x ^= MASK[x >> 63];
-  return (x >> ((sizeof(Key) * 8) - 1 - bit_pos)) & 1;
-}
-
-template <>
-uint64_t Patricia<GeoPoint>::get_ith_bit(KeyArg key, uint64_t bit_pos) {
-  const uint32_t x = reinterpret_cast<const uint32_t *>(&key)[bit_pos & 1];
-  return (x >> (31 - (bit_pos >> 1))) & 1;
-}
-
-template <typename T>
-uint64_t Patricia<T>::count_common_prefix_bits(KeyArg lhs, KeyArg rhs) {
-  if (lhs == rhs) {
-    return sizeof(Key) * 8;
-  }
-  return (sizeof(Key) * 8) - 1 - bit_scan_reverse(static_cast<Key>(lhs ^ rhs));
-}
-
-template <>
-uint64_t Patricia<double>::count_common_prefix_bits(KeyArg lhs, KeyArg rhs) {
-  const uint64_t x = *reinterpret_cast<const uint64_t *>(&lhs);
-  const uint64_t y = *reinterpret_cast<const uint64_t *>(&rhs);
-  if (x == y) {
-    return sizeof(Key) * 8;
-  }
-  return (sizeof(Key) * 8) - 1 - bit_scan_reverse(x ^ y);
-}
-
-template <>
-uint64_t Patricia<GeoPoint>::count_common_prefix_bits(KeyArg lhs, KeyArg rhs) {
-  if (lhs == rhs) {
-    return sizeof(GeoPoint) * 8;
-  }
-  const GeoPoint x = GeoPoint(lhs.value() ^ rhs.value());
-  const uint32_t latitude = x.latitude();
-  const uint32_t longitude = x.longitude();
-  const uint8_t y = bit_scan_reverse(latitude | longitude);
-  return ((31 - y) << 1) + 1 - (latitude >> y);
-}
-
-template class Patricia<int8_t>;
-template class Patricia<uint8_t>;
-template class Patricia<int16_t>;
-template class Patricia<uint16_t>;
-template class Patricia<int32_t>;
-template class Patricia<uint32_t>;
-template class Patricia<int64_t>;
-template class Patricia<uint64_t>;
-template class Patricia<double>;
-template class Patricia<GeoPoint>;
-
-Patricia<Bytes>::Patricia()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      nodes_(),
-      old_nodes_(),
-      pool_(),
-      cache_(),
-      nodes_id_(0) {}
-
-Patricia<Bytes>::~Patricia() {}
-
-Patricia<Bytes> *Patricia<Bytes>::create(Storage *storage,
-                                         uint32_t storage_node_id,
-                                         const MapOptions &options) {
-  std::unique_ptr<Patricia> map(new (std::nothrow) Patricia);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::Patricia failed";
-    throw MemoryError();
-  }
-  map->create_map(storage, storage_node_id, options);
-  return map.release();
-}
-
-Patricia<Bytes> *Patricia<Bytes>::open(Storage *storage,
-                                       uint32_t storage_node_id) {
-  std::unique_ptr<Patricia> map(new (std::nothrow) Patricia);
-  if (!map) {
-    GRNXX_ERROR() << "new grnxx::map::Patricia failed";
-    throw MemoryError();
-  }
-  map->open_map(storage, storage_node_id);
-  return map.release();
-}
-
-uint32_t Patricia<Bytes>::storage_node_id() const {
-  return storage_node_id_;
-}
-
-MapType Patricia<Bytes>::type() const {
-  return MAP_PATRICIA;
-}
-
-int64_t Patricia<Bytes>::max_key_id() {
-  return pool_->max_key_id();
-}
-
-uint64_t Patricia<Bytes>::num_keys() {
-  return pool_->num_keys();
-}
-
-bool Patricia<Bytes>::get(int64_t key_id, Key *key) {
-  if ((key_id < MAP_MIN_KEY_ID) || (key_id > pool_->max_key_id())) {
-    // Out of range.
-    return false;
-  }
-  return pool_->get(key_id, key);
-}
-
-bool Patricia<Bytes>::unset(int64_t key_id) {
-  refresh_nodes();
-  Key key;
-  if (!get(key_id, &key)) {
-    // Not found.
-    return false;
-  }
-  const uint64_t bit_size = key.size() * 8;
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *prev_node = nullptr;
-  for ( ; ; ) {
-    Node * const node = &nodes_->get_value(node_id);
-    switch (node->status()) {
-      case NODE_LEAF: {
-        if (node->key_id() != key_id) {
-          // Not found.
-          return false;
-        }
-        pool_->unset(key_id);
-        if (prev_node) {
-          Node * const sibling_node = node + (node_id ^ 1) - node_id;
-          *prev_node = *sibling_node;
-        } else {
-          *node = Node::dead_node();
-        }
-        return true;
-      }
-      case NODE_BRANCH: {
-        if (node->bit_pos() >= bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node->offset() + get_ith_bit(key, node->bit_pos());
-        break;
-      }
-      case NODE_TERMINAL: {
-        if (node->bit_size() > bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node->offset() + (node->bit_size() < bit_size);
-        break;
-      }
-    }
-    prev_node = node;
-  }
-}
-
-bool Patricia<Bytes>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_nodes();
-  // Find the source key.
-  Key src_key;
-  if (!get(key_id, &src_key)) {
-    // Not found.
-    return false;
-  }
-  const uint64_t src_bit_size = src_key.size() * 8;
-  uint64_t src_node_id = ROOT_NODE_ID;
-  Node *src_node;
-  Node *src_prev_node = nullptr;
-  Node *src_sibling_node = nullptr;
-  for ( ; ; ) {
-    src_node = &nodes_->get_value(src_node_id);
-    if (src_node->status() == NODE_LEAF) {
-      if (src_node->key_id() != key_id) {
-        // Not found.
-        return false;
-      }
-      if (src_prev_node) {
-        src_sibling_node = src_node + (src_node_id ^ 1) - src_node_id;
-      }
-      break;
-    } else if (src_node->status() == NODE_BRANCH) {
-      if (src_node->bit_pos() >= src_bit_size) {
-        // Not found.
-        return false;
-      }
-      src_node_id = src_node->offset() +
-                    get_ith_bit(src_key, src_node->bit_pos());
-    } else if (src_node->status() == NODE_TERMINAL) {
-      if (src_node->bit_size() > src_bit_size) {
-        // Not found.
-        return false;
-      }
-      src_node_id = src_node->offset() +
-                    (src_node->bit_size() < src_bit_size);
-    }
-    src_prev_node = src_node;
-  }
-  if (header_->next_node_id >= NODE_ARRAY_SIZE) {
-    defrag_nodes();
-  }
-  // Add the destination key.
-  constexpr std::size_t HISTORY_SIZE = 8;
-  uint64_t dest_node_id = ROOT_NODE_ID;
-  const uint64_t dest_bit_size = dest_key.size() * 8;
-  Node *history[HISTORY_SIZE];
-  int depth = -1;
-  for ( ; ; ) {
-    Node *node = &nodes_->get_value(dest_node_id);
-    history[++depth % HISTORY_SIZE] = node;
-    if (node->status() == NODE_LEAF) {
-      break;
-    } else if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() >= dest_bit_size) {
-        break;
-      }
-      dest_node_id = node->offset() + get_ith_bit(dest_key, node->bit_pos());
-    } else {
-      if (node->bit_size() >= dest_bit_size) {
-        break;
-      }
-      dest_node_id = node->offset() + 1;
-    }
-  }
-  // Find a leaf node.
-  Node *leaf_node = history[depth % HISTORY_SIZE];
-  while (leaf_node->status() != NODE_LEAF) {
-    leaf_node = &nodes_->get_value(leaf_node->offset());
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(leaf_node->key_id());
-  const uint64_t min_size = (dest_key.size() < stored_key.size()) ?
-                            dest_key.size() : stored_key.size();
-  uint64_t count;
-  for (count = 0; count < min_size; ++count) {
-    if (dest_key[count] != stored_key[count]) {
-      break;
-    }
-  }
-  if (count == min_size) {
-    if (dest_key.size() == stored_key.size()) {
-      // Found.
-      return false;
-    }
-    Node * const dest_prev_node = history[depth % HISTORY_SIZE];
-    Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-    pool_->reset(key_id, dest_key);
-    Node *dest_node;
-    Node *dest_sibling_node;
-    if (count == dest_key.size()) {
-      // "dest_key" is a prefix of "stored_key".
-      dest_node = &next_nodes[0];
-      dest_sibling_node = &next_nodes[1];
-    } else {
-      // "stored_key" is a prefix of "dest_key".
-      dest_node = &next_nodes[1];
-      dest_sibling_node = &next_nodes[0];
-    }
-    if (dest_prev_node == src_prev_node) {
-      src_prev_node = dest_sibling_node;
-    } else if (dest_prev_node == src_node) {
-      src_sibling_node = dest_node;
-      src_prev_node = dest_prev_node;
-    }
-    *dest_sibling_node = *dest_prev_node;
-    *dest_node = Node::leaf_node(key_id);
-    *dest_prev_node = Node::terminal_node(count * 8, header_->next_node_id);
-    *src_prev_node = *src_sibling_node;
-    header_->next_node_id += 2;
-    return true;
-  }
-  count = (count * 8) + 7 -
-          bit_scan_reverse(dest_key[count] ^ stored_key[count]);
-  // Find the branching point in "history".
-  int min_depth = (depth < 8) ? 0 : depth - 7;
-  while (--depth >= min_depth) {
-    Node * const node = history[depth % HISTORY_SIZE];
-    if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() < count) {
-        break;
-      }
-    } else if (node->bit_size() < count) {
-      break;
-    }
-  }
-  Node *dest_prev_node;
-  if (depth >= min_depth) {
-    // The branching point exists in "history".
-    dest_prev_node = history[(depth + 1) % HISTORY_SIZE];
-  } else {
-    // Find the branching point with the naive method.
-    dest_node_id = ROOT_NODE_ID;
-    for ( ; ; ) {
-      dest_prev_node = &nodes_->get_value(dest_node_id);
-      if (dest_prev_node->status() == NODE_LEAF) {
-        break;
-      } else if (dest_prev_node->status() == NODE_BRANCH) {
-        if (dest_prev_node->bit_pos() >= count) {
-          break;
-        }
-        dest_node_id = dest_prev_node->offset() +
-                       get_ith_bit(dest_key, dest_prev_node->bit_pos());
-      } else {
-        if (dest_prev_node->bit_size() > count) {
-          break;
-        }
-        dest_node_id = dest_prev_node->offset() + 1;
-      }
-    }
-  }
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  pool_->reset(key_id, dest_key);
-  Node *dest_node;
-  Node *dest_sibling_node;
-  if (get_ith_bit(dest_key, count)) {
-    dest_node = &next_nodes[1];
-    dest_sibling_node = &next_nodes[0];
-  } else {
-    dest_node = &next_nodes[0];
-    dest_sibling_node = &next_nodes[1];
-  }
-  if (dest_prev_node == src_prev_node) {
-    src_prev_node = dest_sibling_node;
-  } else if (dest_prev_node == src_node) {
-    src_sibling_node = dest_node;
-    src_prev_node = dest_prev_node;
-  }
-  *dest_sibling_node = *dest_prev_node;
-  *dest_node = Node::leaf_node(key_id);
-  *dest_prev_node = Node::branch_node(count, header_->next_node_id);
-  *src_prev_node = *src_sibling_node;
-  header_->next_node_id += 2;
-  return true;
-}
-
-bool Patricia<Bytes>::find(KeyArg key, int64_t *key_id) {
-  refresh_nodes();
-  NodeArray * const nodes = nodes_.get();
-  const uint64_t bit_size = key.size() * 8;
-  uint64_t node_id = ROOT_NODE_ID;
-  Node node = nodes->get(node_id);
-  if (node.status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  for ( ; ; ) {
-    switch (node.status()) {
-      case NODE_LEAF: {
-        Key stored_key = pool_->get_key(node.key_id());
-        if (key != stored_key) {
-          // Not found.
-          return false;
-        }
-        if (key_id) {
-          *key_id = node.key_id();
-        }
-        return true;
-      }
-      case NODE_BRANCH: {
-        if (node.bit_pos() >= bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node.offset() + get_ith_bit(key, node.bit_pos());
-        break;
-      }
-      case NODE_TERMINAL: {
-        if (node.bit_size() > bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node.offset() + (node.bit_size() < bit_size);
-        break;
-      }
-    }
-    node = nodes->get(node_id);
-  }
-}
-
-bool Patricia<Bytes>::add(KeyArg key, int64_t *key_id) {
-  refresh_nodes();
-  const uint64_t hash_value = Hash<Key>()(key);
-  CacheEntry &cache = cache_->get_value(hash_value & (cache_->size() - 1));
-  if (cache && cache.test_hash_value(hash_value)) {
-    Key cached_key;
-    if (pool_->get(cache.key_id(), &cached_key)) {
-      if (key == cached_key) {
-        if (key_id) {
-          *key_id = cache.key_id();
-        }
-        return false;
-      }
-    }
-  }
-  if (header_->next_node_id >= NODE_ARRAY_SIZE) {
-    defrag_nodes();
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *node = &nodes_->get_value(node_id);
-  if (node->status() == NODE_DEAD) {
-    // The patricia is empty.
-    int64_t next_key_id = pool_->add(key);
-    *node = Node::leaf_node(next_key_id);
-    if (key_id) {
-      *key_id = next_key_id;
-    }
-    cache.set(next_key_id, hash_value);
-    return true;
-  }
-  const uint64_t bit_size = key.size() * 8;
-  constexpr std::size_t HISTORY_SIZE = 8;
-  Node *history[HISTORY_SIZE];
-  int depth = 0;
-  history[0] = node;
-  while (node->status() != NODE_LEAF) {
-    if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() >= bit_size) {
-        break;
-      }
-      node_id = node->offset() + get_ith_bit(key, node->bit_pos());
-    } else {
-      if (node->bit_size() >= bit_size) {
-        break;
-      }
-      node_id = node->offset() + 1;
-    }
-    node = &nodes_->get_value(node_id);
-    history[++depth % HISTORY_SIZE] = node;
-  }
-  // Find a leaf node.
-  while (node->status() != NODE_LEAF) {
-    node_id = node->offset();
-    node = &nodes_->get_value(node_id);
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(node->key_id());
-  const uint64_t min_size =
-      (key.size() < stored_key.size()) ? key.size() : stored_key.size();
-  uint64_t count;
-  for (count = 0; count < min_size; ++count) {
-    if (key[count] != stored_key[count]) {
-      break;
-    }
-  }
-  if (count == min_size) {
-    if (key.size() == stored_key.size()) {
-      // Found.
-      if (key_id) {
-        *key_id = node->key_id();
-      }
-      cache.set(node->key_id(), hash_value);
-      return false;
-    }
-    node = history[depth % HISTORY_SIZE];
-    Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-    int64_t next_key_id = pool_->add(key);
-    if (count == key.size()) {
-      // "key" is a prefix of "stored_key".
-      next_nodes[0] = Node::leaf_node(next_key_id);
-      next_nodes[1] = *node;
-    } else {
-      // "stored_key" is a prefix of "key".
-      next_nodes[0] = *node;
-      next_nodes[1] = Node::leaf_node(next_key_id);
-    }
-    *node = Node::terminal_node(count * 8, header_->next_node_id);
-    header_->next_node_id += 2;
-    if (key_id) {
-      *key_id = next_key_id;
-    }
-    cache.set(next_key_id, hash_value);
-    return true;
-  }
-  count = (count * 8) + 7 - bit_scan_reverse(key[count] ^ stored_key[count]);
-  // Find the branching point in "history".
-  int min_depth = (depth < 8) ? 0 : depth - 7;
-  while (--depth >= min_depth) {
-    node = history[depth % HISTORY_SIZE];
-    if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() < count) {
-        break;
-      }
-    } else if (node->bit_size() <= count) {
-      break;
-    }
-  }
-  if (depth >= min_depth) {
-    // The branching point exists in "history".
-    node = history[(depth + 1) % HISTORY_SIZE];
-  } else {
-    // Find the branching point with the naive method.
-    node_id = ROOT_NODE_ID;
-    for ( ; ; ) {
-      node = &nodes_->get_value(node_id);
-      if (node->status() == NODE_LEAF) {
-        break;
-      } else if (node->status() == NODE_BRANCH) {
-        if (node->bit_pos() >= count) {
-          break;
-        }
-        node_id = node->offset() + get_ith_bit(key, node->bit_pos());
-      } else {
-        if (node->bit_size() > count) {
-          break;
-        }
-        node_id = node->offset() + 1;
-      }
-    }
-  }
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  int64_t next_key_id = pool_->add(key);
-  if (get_ith_bit(key, count)) {
-    next_nodes[0] = *node;
-    next_nodes[1] = Node::leaf_node(next_key_id);
-  } else {
-    next_nodes[0] = Node::leaf_node(next_key_id);
-    next_nodes[1] = *node;
-  }
-  *node = Node::branch_node(count, header_->next_node_id);
-  header_->next_node_id += 2;
-  if (key_id) {
-    *key_id = next_key_id;
-  }
-  cache.set(next_key_id, hash_value);
-  return true;
-}
-
-bool Patricia<Bytes>::remove(KeyArg key) {
-  refresh_nodes();
-  const uint64_t bit_size = key.size() * 8;
-  uint64_t node_id = ROOT_NODE_ID;
-  Node *node = &nodes_->get_value(node_id);
-  if (node->status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  Node *prev_node = nullptr;
-  for ( ; ; ) {
-    switch (node->status()) {
-      case NODE_LEAF: {
-        Key stored_key = pool_->get_key(node->key_id());
-        if (stored_key != key) {
-          // Not found.
-          return false;
-        }
-        pool_->unset(node->key_id());
-        if (prev_node) {
-          Node * const sibling_node = node + (node_id ^ 1) - node_id;
-          *prev_node = *sibling_node;
-        } else {
-          *node = Node::dead_node();
-        }
-        return true;
-      }
-      case NODE_BRANCH: {
-        if (node->bit_pos() >= bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node->offset() + get_ith_bit(key, node->bit_pos());
-        break;
-      }
-      case NODE_TERMINAL: {
-        if (node->bit_size() > bit_size) {
-          // Not found.
-          return false;
-        }
-        node_id = node->offset() + (node->bit_size() < bit_size);
-        break;
-      }
-    }
-    prev_node = node;
-    node = &nodes_->get_value(node_id);
-  }
-}
-
-bool Patricia<Bytes>::replace(KeyArg src_key, KeyArg dest_key,
-                              int64_t *key_id) {
-  refresh_nodes();
-  // Find the source key.
-  const uint64_t src_bit_size = src_key.size() * 8;
-  int64_t src_key_id;
-  uint64_t src_node_id = ROOT_NODE_ID;
-  Node *src_node = &nodes_->get_value(src_node_id);
-  if (src_node->status() == NODE_DEAD) {
-    // Not found.
-    return false;
-  }
-  Node *src_prev_node = nullptr;
-  Node *src_sibling_node = nullptr;
-  for ( ; ; ) {
-    if (src_node->status() == NODE_LEAF) {
-      src_key_id = src_node->key_id();
-      Key stored_key = pool_->get_key(src_key_id);
-      if (stored_key != src_key) {
-        // Not found.
-        return false;
-      }
-      if (key_id) {
-        *key_id = src_key_id;
-      }
-      if (src_prev_node) {
-        src_sibling_node = src_node + (src_node_id ^ 1) - src_node_id;
-      }
-      break;
-    } else if (src_node->status() == NODE_BRANCH) {
-      if (src_node->bit_pos() >= src_bit_size) {
-        // Not found.
-        return false;
-      }
-      src_node_id = src_node->offset() +
-                    get_ith_bit(src_key, src_node->bit_pos());
-    } else if (src_node->status() == NODE_TERMINAL) {
-      if (src_node->bit_size() > src_bit_size) {
-        // Not found.
-        return false;
-      }
-      src_node_id = src_node->offset() +
-                    (src_node->bit_size() < src_bit_size);
-    }
-    src_prev_node = src_node;
-    src_node = &nodes_->get_value(src_node_id);
-  }
-  if (header_->next_node_id >= NODE_ARRAY_SIZE) {
-    defrag_nodes();
-  }
-  // Add the destination key.
-  constexpr std::size_t HISTORY_SIZE = 8;
-  uint64_t dest_node_id = ROOT_NODE_ID;
-  const uint64_t dest_bit_size = dest_key.size() * 8;
-  Node *history[HISTORY_SIZE];
-  int depth = -1;
-  for ( ; ; ) {
-    Node *node = &nodes_->get_value(dest_node_id);
-    history[++depth % HISTORY_SIZE] = node;
-    if (node->status() == NODE_LEAF) {
-      break;
-    } else if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() >= dest_bit_size) {
-        break;
-      }
-      dest_node_id = node->offset() + get_ith_bit(dest_key, node->bit_pos());
-    } else {
-      if (node->bit_size() >= dest_bit_size) {
-        break;
-      }
-      dest_node_id = node->offset() + 1;
-    }
-  }
-  // Find a leaf node.
-  Node *leaf_node = history[depth % HISTORY_SIZE];
-  while (leaf_node->status() != NODE_LEAF) {
-    leaf_node = &nodes_->get_value(leaf_node->offset());
-  }
-  // Count the number of the common prefix bits.
-  Key stored_key = pool_->get_key(leaf_node->key_id());
-  const uint64_t min_size = (dest_key.size() < stored_key.size()) ?
-                            dest_key.size() : stored_key.size();
-  uint64_t count;
-  for (count = 0; count < min_size; ++count) {
-    if (dest_key[count] != stored_key[count]) {
-      break;
-    }
-  }
-  if (count == min_size) {
-    if (dest_key.size() == stored_key.size()) {
-      // Found.
-      return false;
-    }
-    Node * const dest_prev_node = history[depth % HISTORY_SIZE];
-    Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-    pool_->reset(src_key_id, dest_key);
-    Node *dest_node;
-    Node *dest_sibling_node;
-    if (count == dest_key.size()) {
-      // "dest_key" is a prefix of "stored_key".
-      dest_node = &next_nodes[0];
-      dest_sibling_node = &next_nodes[1];
-    } else {
-      // "stored_key" is a prefix of "dest_key".
-      dest_node = &next_nodes[1];
-      dest_sibling_node = &next_nodes[0];
-    }
-    if (dest_prev_node == src_prev_node) {
-      src_prev_node = dest_sibling_node;
-    } else if (dest_prev_node == src_node) {
-      src_sibling_node = dest_node;
-      src_prev_node = dest_prev_node;
-    }
-    *dest_sibling_node = *dest_prev_node;
-    *dest_node = Node::leaf_node(src_key_id);
-    *dest_prev_node = Node::terminal_node(count * 8, header_->next_node_id);
-    *src_prev_node = *src_sibling_node;
-    header_->next_node_id += 2;
-    return true;
-  }
-  count = (count * 8) + 7 -
-          bit_scan_reverse(dest_key[count] ^ stored_key[count]);
-  // Find the branching point in "history".
-  int min_depth = (depth < 8) ? 0 : depth - 7;
-  while (--depth >= min_depth) {
-    Node * const node = history[depth % HISTORY_SIZE];
-    if (node->status() == NODE_BRANCH) {
-      if (node->bit_pos() < count) {
-        break;
-      }
-    } else if (node->bit_size() < count) {
-      break;
-    }
-  }
-  Node *dest_prev_node;
-  if (depth >= min_depth) {
-    // The branching point exists in "history".
-    dest_prev_node = history[(depth + 1) % HISTORY_SIZE];
-  } else {
-    // Find the branching point with the naive method.
-    dest_node_id = ROOT_NODE_ID;
-    for ( ; ; ) {
-      dest_prev_node = &nodes_->get_value(dest_node_id);
-      if (dest_prev_node->status() == NODE_LEAF) {
-        break;
-      } else if (dest_prev_node->status() == NODE_BRANCH) {
-        if (dest_prev_node->bit_pos() >= count) {
-          break;
-        }
-        dest_node_id = dest_prev_node->offset() +
-                       get_ith_bit(dest_key, dest_prev_node->bit_pos());
-      } else {
-        if (dest_prev_node->bit_size() > count) {
-          break;
-        }
-        dest_node_id = dest_prev_node->offset() + 1;
-      }
-    }
-  }
-  Node * const next_nodes = &nodes_->get_value(header_->next_node_id);
-  pool_->reset(src_key_id, dest_key);
-  Node *dest_node;
-  Node *dest_sibling_node;
-  if (get_ith_bit(dest_key, count)) {
-    dest_node = &next_nodes[1];
-    dest_sibling_node = &next_nodes[0];
-  } else {
-    dest_node = &next_nodes[0];
-    dest_sibling_node = &next_nodes[1];
-  }
-  if (dest_prev_node == src_prev_node) {
-    src_prev_node = dest_sibling_node;
-  } else if (dest_prev_node == src_node) {
-    src_sibling_node = dest_node;
-    src_prev_node = dest_prev_node;
-  }
-  *dest_sibling_node = *dest_prev_node;
-  *dest_node = Node::leaf_node(src_key_id);
-  *dest_prev_node = Node::branch_node(count, header_->next_node_id);
-  *src_prev_node = *src_sibling_node;
-  header_->next_node_id += 2;
-  return true;
-}
-
-bool Patricia<Bytes>::find_longest_prefix_match(KeyArg query, int64_t *key_id,
-                                                Key *key) {
-  refresh_nodes();
-  NodeArray * const nodes = nodes_.get();
-  const uint64_t bit_size = query.size() * 8;
-  bool found = false;
-  uint64_t node_id = ROOT_NODE_ID;
-  for ( ; ; ) {
-    Node node = nodes->get(node_id);
-    switch (node.status()) {
-      case NODE_DEAD: {
-        // Not found.
-        return found;
-      }
-      case NODE_LEAF: {
-        Key stored_key = pool_->get_key(node.key_id());
-        if (query.starts_with(stored_key)) {
-          if (key_id) {
-            *key_id = node.key_id();
-          }
-          if (key) {
-            *key = stored_key;
-          }
-          found = true;
-        }
-        return found;
-      }
-      case NODE_BRANCH: {
-        if (node.bit_pos() >= bit_size) {
-          return found;
-        }
-        node_id = node.offset() + get_ith_bit(query, node.bit_pos());
-        break;
-      }
-      case NODE_TERMINAL: {
-        if (node.bit_size() > bit_size) {
-          return found;
-        } else if (node.bit_size() < bit_size) {
-          Node leaf_node = nodes->get(node.offset());
-          Key stored_key = pool_->get_key(leaf_node.key_id());
-          if (query.starts_with(stored_key)) {
-            if (key_id) {
-              *key_id = leaf_node.key_id();
-            }
-            if (key) {
-              *key = stored_key;
-            }
-            found = true;
-          }
-        }
-        node_id = node.offset() + (node.bit_size() < bit_size);
-        break;
-      }
-    }
-  }
-}
-
-void Patricia<Bytes>::defrag() {
-  refresh_nodes();
-  if (max_key_id() == MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  defrag_nodes();
-  pool_->defrag(0.5);
-}
-
-void Patricia<Bytes>::truncate() {
-  refresh_nodes();
-  if (max_key_id() == MAP_MIN_KEY_ID) {
-    // Nothing to do.
-    return;
-  }
-  std::unique_ptr<NodeArray> new_nodes(
-      NodeArray::create(storage_, storage_node_id_, NODE_ARRAY_SIZE));
-  try {
-    new_nodes->set(ROOT_NODE_ID, Node::dead_node());
-    new_nodes->set(DUMMY_NODE_ID, Node::dead_node());
-    for (uint64_t i = 0; i < CACHE_SIZE; ++i) {
-      cache_->set(i, CacheEntry::invalid_entry());
-    }
-    pool_->truncate();
-  } catch (...) {
-    NodeArray::unlink(storage_, new_nodes->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new nodes.
-    Lock lock(&header_->mutex);
-    header_->nodes_storage_node_id = new_nodes->storage_node_id();
-    header_->next_node_id = 2;
-    ++header_->nodes_id;
-    old_nodes_.swap(new_nodes);
-    nodes_.swap(old_nodes_);
-    nodes_id_ = header_->nodes_id;
-  }
-  NodeArray::unlink(storage_, old_nodes_->storage_node_id());
-}
-
-void Patricia<Bytes>::create_map(Storage *storage, uint32_t storage_node_id,
-                                 const MapOptions &) {
-  storage_ = storage;
-  StorageNode storage_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = storage_node.id();
-  try {
-    header_ = static_cast<Header *>(storage_node.body());
-    *header_ = Header();
-    nodes_.reset(NodeArray::create(storage, storage_node_id_, NODE_ARRAY_SIZE));
-    pool_.reset(KeyPool<Bytes>::create(storage, storage_node_id_));
-    cache_.reset(Cache::create(storage, storage_node_id_,
-                               CACHE_SIZE, CacheEntry::invalid_entry()));
-    header_->nodes_storage_node_id = nodes_->storage_node_id();
-    header_->pool_storage_node_id = pool_->storage_node_id();
-    header_->cache_storage_node_id = cache_->storage_node_id();
-    nodes_->set(ROOT_NODE_ID, Node::dead_node());
-    nodes_->set(DUMMY_NODE_ID, Node::dead_node());
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void Patricia<Bytes>::open_map(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  if (storage_node.size() < sizeof(Header)) {
-    GRNXX_ERROR() << "invalid format: size = " << storage_node.size()
-                  << ", header_size = " << sizeof(Header);
-    throw LogicError();
-  }
-  storage_node_id_ = storage_node_id;
-  header_ = static_cast<Header *>(storage_node.body());
-  if (!*header_) {
-    GRNXX_ERROR() << "wrong format: expected = " << FORMAT_STRING
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  Lock lock(&header_->mutex);
-  nodes_.reset(NodeArray::open(storage, header_->nodes_storage_node_id));
-  pool_.reset(KeyPool<Bytes>::open(storage, header_->pool_storage_node_id));
-  cache_.reset(Cache::open(storage, header_->cache_storage_node_id));
-  nodes_id_ = header_->nodes_id;
-}
-
-void Patricia<Bytes>::defrag_nodes() {
-  // Create a new nodes.
-  std::unique_ptr<NodeArray> new_nodes(
-      NodeArray::create(storage_, storage_node_id_, NODE_ARRAY_SIZE));
-  uint64_t next_node_id = 2;
-  try {
-    next_node_id = rearrange_nodes(ROOT_NODE_ID, ROOT_NODE_ID,
-                                   next_node_id, new_nodes.get());
-    next_node_id = rearrange_nodes(DUMMY_NODE_ID, DUMMY_NODE_ID,
-                                   next_node_id, new_nodes.get());
-  } catch (...) {
-    NodeArray::unlink(storage_, new_nodes->storage_node_id());
-    throw;
-  }
-  {
-    // Validate a new nodes.
-    Lock lock(&header_->mutex);
-    header_->nodes_storage_node_id = new_nodes->storage_node_id();
-    header_->next_node_id = next_node_id;
-    ++header_->nodes_id;
-    old_nodes_.swap(new_nodes);
-    nodes_.swap(old_nodes_);
-    nodes_id_ = header_->nodes_id;
-  }
-  NodeArray::unlink(storage_, old_nodes_->storage_node_id());
-}
-
-uint64_t Patricia<Bytes>::rearrange_nodes(uint64_t src_node_id,
-                                          uint64_t dest_node_id,
-                                          uint64_t next_node_id,
-                                          NodeArray *dest_nodes) {
-  const Node src_node = nodes_->get(src_node_id);
-  Node &dest_node = dest_nodes->get_value(dest_node_id);
-  switch (src_node.status()) {
-    case NODE_DEAD:
-    case NODE_LEAF: {
-      dest_node = src_node;
-      return next_node_id;
-    }
-    case NODE_BRANCH: {
-      dest_node = Node::branch_node(src_node.bit_pos(), next_node_id);
-      break;
-    }
-    case NODE_TERMINAL: {
-      dest_node = Node::terminal_node(src_node.bit_size(), next_node_id);
-      break;
-    }
-  }
-  src_node_id = src_node.offset();
-  dest_node_id = next_node_id;
-  next_node_id += 2;
-  next_node_id = rearrange_nodes(src_node_id, dest_node_id,
-                                 next_node_id, dest_nodes);
-  next_node_id = rearrange_nodes(src_node_id + 1, dest_node_id + 1,
-                                 next_node_id, dest_nodes);
-  return next_node_id;
-}
-
-void Patricia<Bytes>::refresh_nodes() {
-  if (nodes_id_ != header_->nodes_id) {
-    Lock lock(&header_->mutex);
-    if (nodes_id_ != header_->nodes_id) {
-      std::unique_ptr<NodeArray> new_nodes(
-          NodeArray::open(storage_, header_->nodes_storage_node_id));
-      old_nodes_.swap(new_nodes);
-      nodes_.swap(old_nodes_);
-      nodes_id_ = header_->nodes_id;
-    }
-  }
-}
-
-uint64_t Patricia<Bytes>::get_ith_bit(KeyArg key, uint64_t bit_pos) {
-  return (key[bit_pos / 8] >> (7 - (bit_pos % 8))) & 1;
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/patricia.hpp (+0 -179) 100644
===================================================================
--- lib/grnxx/map/patricia.hpp    2013-08-23 10:46:34 +0900 (9e08d5a)
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_PATRICIA_HPP
-#define GRNXX_MAP_PATRICIA_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/array.hpp"
-#include "grnxx/bytes.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-template <typename T> class KeyPool;
-
-struct PatriciaHeader;
-class PatriciaNode;
-class PatriciaCacheEntry;
-
-template <typename T>
-class Patricia : public Map<T> {
-  using Header = PatriciaHeader;
-  using Node = PatriciaNode;
-  using NodeArray = Array<Node, 65536, 8192>;
-  using CacheEntry = PatriciaCacheEntry;
-  using Cache = Array<CacheEntry>;
-
- public:
-  using Key = typename Map<T>::Key;
-  using KeyArg = typename Map<T>::KeyArg;
-  using Cursor = typename Map<T>::Cursor;
-
-  Patricia();
-  ~Patricia();
-
-  static Patricia *create(Storage *storage, uint32_t storage_node_id,
-                          const MapOptions &options = MapOptions());
-  static Patricia *open(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const;
-  MapType type() const;
-
-  int64_t max_key_id();
-  uint64_t num_keys();
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  void defrag();
-
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<NodeArray> nodes_;
-  std::unique_ptr<NodeArray> old_nodes_;
-  std::unique_ptr<KeyPool<T>> pool_;
-  std::unique_ptr<Cache> cache_;
-  uint64_t nodes_id_;
-
-  void create_map(Storage *storage, uint32_t storage_node_id,
-                  const MapOptions &options);
-  void open_map(Storage *storage, uint32_t storage_node_id);
-
-  // Resize "nodes_" and "cache_".
-  void defrag_nodes();
-  // Recursively arrange nodes.
-  uint64_t rearrange_nodes(uint64_t src_node_id, uint64_t dest_node_id,
-                           uint64_t next_node_id, NodeArray *dest_nodes);
-
-  // Refresh "nodes_" and "cache_" if new ones are available.
-  void refresh_nodes();
-
-  static uint64_t get_ith_bit(KeyArg key, uint64_t bit_pos);
-  static uint64_t count_common_prefix_bits(KeyArg lhs, KeyArg rhs);
-};
-
-template <>
-class Patricia<Bytes> : public Map<Bytes> {
-  using Header = PatriciaHeader;
-  using Node = PatriciaNode;
-  using NodeArray = Array<Node, 65536, 8192>;
-  using CacheEntry = PatriciaCacheEntry;
-  using Cache = Array<CacheEntry>;
-
- public:
-  using Key = typename Map<Bytes>::Key;
-  using KeyArg = typename Map<Bytes>::KeyArg;
-  using Cursor = typename Map<Bytes>::Cursor;
-
-  Patricia();
-  ~Patricia();
-
-  static Patricia *create(Storage *storage, uint32_t storage_node_id,
-                          const MapOptions &options = MapOptions());
-  static Patricia *open(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const;
-  MapType type() const;
-
-  int64_t max_key_id();
-  uint64_t num_keys();
-
-  bool get(int64_t key_id, Key *key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, KeyArg dest_key);
-
-  bool find(KeyArg key, int64_t *key_id = nullptr);
-  bool add(KeyArg key, int64_t *key_id = nullptr);
-  bool remove(KeyArg key);
-  bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
-
-  bool find_longest_prefix_match(KeyArg query, int64_t *key_id = nullptr,
-                                 Key *key = nullptr);
-
-  void defrag();
-
-  void truncate();
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<NodeArray> nodes_;
-  std::unique_ptr<NodeArray> old_nodes_;
-  std::unique_ptr<KeyPool<Bytes>> pool_;
-  std::unique_ptr<Cache> cache_;
-  uint64_t nodes_id_;
-
-  void create_map(Storage *storage, uint32_t storage_node_id,
-                  const MapOptions &options);
-  void open_map(Storage *storage, uint32_t storage_node_id);
-
-  // Resize "nodes_" and "cache_".
-  void defrag_nodes();
-  // Recursively arrange nodes.
-  uint64_t rearrange_nodes(uint64_t src_node_id, uint64_t dest_node_id,
-                           uint64_t next_node_id, NodeArray *dest_nodes);
-
-  // Refresh "nodes_" and "cache_" if new ones are available.
-  void refresh_nodes();
-
-  static uint64_t get_ith_bit(KeyArg key, uint64_t bit_pos);
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_PATRICIA_HPP

  Deleted: lib/grnxx/map/pool.cpp (+0 -830) 100644
===================================================================
--- lib/grnxx/map/pool.cpp    2013-08-23 10:46:34 +0900 (fa0ae37)
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
-  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/map/pool.hpp"
-
-#include <cstring>
-#include <exception>
-#include <limits>
-
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace map {
-namespace {
-
-constexpr uint64_t INVALID_UNIT_ID = std::numeric_limits<uint64_t>::max();
-
-}  // namespace
-
-template <typename T>
-PoolHeader<T>::PoolHeader()
-    : max_key_id(-1),
-      num_keys(0),
-      size(0),
-      latest_available_unit_id(INVALID_UNIT_ID),
-      page_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-template <typename T>
-Pool<T>::Pool()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      pages_(),
-      table_(nullptr),
-      size_(0),
-      queue_(),
-      clock_() {}
-
-template <typename T>
-Pool<T>::~Pool() {}
-
-template <typename T>
-Pool<T> *Pool<T>::create(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<Pool> pool(new (std::nothrow) Pool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::Pool failed";
-    throw MemoryError();
-  }
-  pool->create_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-template <typename T>
-Pool<T> *Pool<T>::open(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<Pool> pool(new (std::nothrow) Pool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::Pool failed";
-    throw MemoryError();
-  }
-  pool->open_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-template <typename T>
-void Pool<T>::unlink(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<Pool> pool(Pool::open(storage, storage_node_id));
-  storage->unlink_node(storage_node_id);
-}
-
-template <typename T>
-void Pool<T>::unset(int64_t key_id) {
-  refresh_if_possible();
-  void * const page = get_page(key_id / PAGE_SIZE);
-  const uint64_t local_key_id = key_id % PAGE_SIZE;
-  const uint64_t unit_id = local_key_id / UNIT_SIZE;
-  const uint64_t validity_bit = 1ULL << (local_key_id % UNIT_SIZE);
-  Unit * const unit = static_cast<Unit *>(page) - unit_id - 1;
-  if (~unit->validity_bits & validity_bit) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  if (unit->validity_bits == ~uint64_t(0)) {
-    unit->next_available_unit_id = header_->latest_available_unit_id;
-    header_->latest_available_unit_id = unit_id;
-  }
-  unit->validity_bits &= ~validity_bit;
-  --header_->num_keys;
-}
-
-template <typename T>
-void Pool<T>::reset(int64_t key_id, KeyArg dest_key) {
-  refresh_if_possible();
-  void * const page = get_page(key_id / PAGE_SIZE);
-  const uint64_t local_key_id = key_id % PAGE_SIZE;
-  const Unit * const unit =
-      static_cast<const Unit *>(page) - (local_key_id / UNIT_SIZE) - 1;
-  if (~unit->validity_bits & (1ULL << (local_key_id % UNIT_SIZE))) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  static_cast<T *>(page)[local_key_id] = dest_key;
-}
-
-template <typename T>
-int64_t Pool<T>::add(KeyArg key) {
-  refresh_if_possible();
-  if (header_->latest_available_unit_id == INVALID_UNIT_ID) {
-    // Use a new unit.
-    const int64_t next_key_id = header_->max_key_id + 1;
-    if (next_key_id > MAX_KEY_ID) {
-      GRNXX_ERROR() << "pool is full: next_key_id = " << next_key_id
-                    << ", max_key_id = " << MAX_KEY_ID;
-      throw LogicError();
-    }
-    reserve_key_id(next_key_id);
-    void * const page = get_page(next_key_id / PAGE_SIZE);
-    const uint64_t local_key_id = next_key_id % PAGE_SIZE;
-    Unit * const unit =
-        static_cast<Unit *>(page) - (local_key_id / UNIT_SIZE) - 1;
-    unit->validity_bits = 1;
-    unit->next_available_unit_id = INVALID_UNIT_ID;
-    header_->latest_available_unit_id = next_key_id / UNIT_SIZE;
-    static_cast<T *>(page)[local_key_id] = key;
-    header_->max_key_id = next_key_id;
-    ++header_->num_keys;
-    return next_key_id;
-  } else {
-    // Use an existing unit.
-    const uint64_t unit_id = header_->latest_available_unit_id;
-    void * const page = get_page(unit_id * UNIT_SIZE / PAGE_SIZE);
-    Unit * const unit =
-        static_cast<Unit *>(page) - (unit_id % (PAGE_SIZE / UNIT_SIZE)) - 1;
-    const uint8_t validity_bit_id = bit_scan_forward(~unit->validity_bits);
-    const int64_t next_key_id = (unit_id * UNIT_SIZE) + validity_bit_id;
-    if (next_key_id > MAX_KEY_ID) {
-      GRNXX_ERROR() << "pool is full: next_key_id = " << next_key_id
-                    << ", max_key_id = " << MAX_KEY_ID;
-      throw LogicError();
-    }
-    unit->validity_bits |= 1ULL << validity_bit_id;
-    if (unit->validity_bits == ~uint64_t(0)) {
-      header_->latest_available_unit_id = unit->next_available_unit_id;
-    }
-    static_cast<T *>(page)[next_key_id % PAGE_SIZE] = key;
-    if (next_key_id > header_->max_key_id) {
-      header_->max_key_id = next_key_id;
-    }
-    ++header_->num_keys;
-    return next_key_id;
-  }
-}
-
-template <typename T>
-void Pool<T>::defrag() {
-  refresh_if_possible();
-  // Nothing to do.
-}
-
-template <typename T>
-void Pool<T>::sweep(Duration lifetime) {
-  const Time threshold = clock_.now() - lifetime;
-  while (!queue_.empty()) {
-    QueueEntry &queue_entry = queue_.front();
-    if (queue_entry.time <= threshold) {
-      queue_.pop();
-    }
-  }
-}
-
-template <typename T>
-void Pool<T>::create_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode header_node =
-      storage->create_node(storage_node_id, sizeof(Header));
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<Header *>(header_node.body());
-    *header_ = Header();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-template <typename T>
-void Pool<T>::open_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode header_node = storage->open_node(storage_node_id);
-  storage_node_id_ = header_node.id();
-  header_ = static_cast<Header *>(header_node.body());
-}
-
-template <typename T>
-void *Pool<T>::open_page(uint64_t page_id) {
-  if (page_id >= (header_->size / PAGE_SIZE)) {
-    GRNXX_ERROR() << "invalid argument: page_id = " << page_id
-                  << ", table_size = " << (header_->size / PAGE_SIZE);
-    throw LogicError();
-  }
-  if (!pages_[page_id]) {
-    Lock lock(&header_->mutex);
-    if (!pages_[page_id]) {
-      // Open an existing full-size page.
-      // Note that a small-size page is opened in refresh_page().
-      if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-        GRNXX_ERROR() << "not found: page_id = " << page_id;
-        throw LogicError();
-      }
-      StorageNode page_node = storage_->open_node(table_[page_id]);
-      pages_[page_id] =
-          static_cast<Unit *>(page_node.body()) + (PAGE_SIZE / UNIT_SIZE);
-    }
-  }
-  return pages_[page_id];
-}
-
-template <typename T>
-void Pool<T>::reserve_key_id(int64_t key_id) {
-  if (static_cast<uint64_t>(key_id) >= header_->size) {
-    expand();
-  }
-  const uint64_t page_id = key_id / PAGE_SIZE;
-  if (!pages_[page_id]) {
-    // Note that "pages_[0]" is not nullptr if there is a small-size page
-    // because it is opened in refresh_page().
-    if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-      Lock lock(&header_->mutex);
-      if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-        // Create a full-size page.
-        // Note that a small-size page is created in expand_page().
-        const uint64_t page_node_size =
-            (sizeof(Unit) * (PAGE_SIZE / UNIT_SIZE)) + (sizeof(T) * PAGE_SIZE);
-        StorageNode page_node =
-            storage_->create_node(storage_node_id_, page_node_size);
-        table_[page_id] = page_node.id();
-      }
-    }
-  }
-}
-
-template <typename T>
-void Pool<T>::expand() {
-  Lock lock(&header_->mutex);
-  if (size_ < PAGE_SIZE) {
-    // Create a small-size page or the first full-size page.
-    expand_page();
-    refresh_page();
-  } else {
-    // Create a table.
-    expand_table();
-    refresh_table();
-  }
-}
-
-template <typename T>
-void Pool<T>::expand_page() {
-  const uint64_t new_size = (size_ == 0) ? MIN_PAGE_SIZE : (size_ * 2);
-  const uint64_t page_node_size =
-      (sizeof(Unit) * (new_size / UNIT_SIZE)) + (sizeof(T) * new_size);
-  StorageNode page_node =
-      storage_->create_node(storage_node_id_, page_node_size);
-  if (size_ != 0) {
-    // Copy data from the current page and unlink it.
-    std::memcpy(static_cast<Unit *>(page_node.body()) + (size_ / UNIT_SIZE),
-                static_cast<Unit *>(pages_[0]) - (size_ / UNIT_SIZE),
-                page_node_size / 2);
-    try {
-      storage_->unlink_node(header_->page_storage_node_id);
-    } catch (...) {
-      storage_->unlink_node(page_node.id());
-      throw;
-    }
-  }
-  header_->page_storage_node_id = page_node.id();
-  header_->size = new_size;
-}
-
-template <typename T>
-void Pool<T>::expand_table() {
-  const uint64_t old_table_size =
-      (size_ <= PAGE_SIZE) ? 0 : (size_ / PAGE_SIZE);
-  const uint64_t new_table_size =
-      (old_table_size == 0) ? MIN_TABLE_SIZE : (old_table_size * 2);
-  const uint64_t new_size = new_table_size * PAGE_SIZE;
-  StorageNode table_node = storage_->create_node(
-      storage_node_id_, sizeof(uint32_t) * new_table_size);
-  uint32_t * const new_table = static_cast<uint32_t *>(table_node.body());
-  uint64_t i;
-  if (old_table_size == 0) {
-    new_table[0] = header_->page_storage_node_id;
-    i = 1;
-  } else {
-    for (i = 0; i < old_table_size; ++i) {
-      new_table[i] = table_[i];
-    }
-  }
-  for ( ; i < new_table_size; ++i) {
-    new_table[i] = STORAGE_INVALID_NODE_ID;
-  }
-  header_->table_storage_node_id = table_node.id();
-  header_->size = new_size;
-}
-
-template <typename T>
-void Pool<T>::refresh() {
-  Lock lock(&header_->mutex);
-  if (size_ != header_->size) {
-    if (header_->size <= PAGE_SIZE) {
-      // Reopen a page because it is old.
-      refresh_page();
-    } else {
-      // Reopen a table because it is old.
-      refresh_table();
-    }
-    size_ = header_->size;
-  }
-}
-
-template <typename T>
-void Pool<T>::refresh_page() {
-  StorageNode page_node =
-      storage_->open_node(header_->page_storage_node_id);
-  if (!pages_) {
-    std::unique_ptr<void *[]> new_pages(new (std::nothrow) void *[1]);
-    if (!new_pages) {
-      GRNXX_ERROR() << "new void *[] failed: size = " << 1;
-      throw MemoryError();
-    }
-    new_pages[0] =
-        static_cast<Unit *>(page_node.body()) + (header_->size / UNIT_SIZE);
-    pages_.swap(new_pages);
-  } else {
-    pages_[0] =
-        static_cast<Unit *>(page_node.body()) + (header_->size / UNIT_SIZE);
-  }
-}
-
-template <typename T>
-void Pool<T>::refresh_table() {
-  StorageNode table_node =
-      storage_->open_node(header_->table_storage_node_id);
-  uint32_t * const new_table = static_cast<uint32_t *>(table_node.body());
-  const uint64_t new_table_size = header_->size / PAGE_SIZE;
-  std::unique_ptr<void *[]> new_pages(
-      new (std::nothrow) void *[new_table_size]);
-  if (!new_pages) {
-    GRNXX_ERROR() << "new void *[] failed: size = " << new_table_size;
-    throw MemoryError();
-  }
-  // Initialize a new cache table.
-  const uint64_t old_table_size = size_ / PAGE_SIZE;
-  uint64_t i = 0;
-  for ( ; i < old_table_size; ++i) {
-    new_pages[i] = pages_[i];
-  }
-  for ( ; i < new_table_size; ++i) {
-    new_pages[i] = nullptr;
-  }
-  pages_.swap(new_pages);
-  // Keep an old cache table because another thread may read it.
-  if (new_pages) {
-    try {
-      queue_.push(QueueEntry{ std::move(new_pages), clock_.now() });
-    } catch (const std::exception &exception) {
-      GRNXX_ERROR() << "std::queue::push() failed";
-      throw StandardError(exception);
-    }
-  }
-  table_ = new_table;
-}
-
-template class Pool<int8_t>;
-template class Pool<int16_t>;
-template class Pool<int32_t>;
-template class Pool<int64_t>;
-template class Pool<uint8_t>;
-template class Pool<uint16_t>;
-template class Pool<uint32_t>;
-template class Pool<uint64_t>;
-template class Pool<double>;
-template class Pool<GeoPoint>;
-
-namespace {
-
-constexpr uint32_t MAX_PAGE_ID     = std::numeric_limits<uint32_t>::max() - 1;
-constexpr uint32_t INVALID_PAGE_ID = MAX_PAGE_ID + 1;
-
-}  // namespace
-
-PoolHeader<Bytes>::PoolHeader()
-    : size(0),
-      next_offset(0),
-      page_storage_node_id(STORAGE_INVALID_NODE_ID),
-      index_pool_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-PoolTableEntry::PoolTableEntry()
-    : page_storage_node_id(STORAGE_INVALID_NODE_ID),
-      size_in_use(0) {}
-
-Pool<Bytes>::Pool()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      header_(nullptr),
-      index_pool_(),
-      pages_(),
-      table_(nullptr),
-      size_(0),
-      queue_(),
-      clock_() {}
-
-Pool<Bytes>::~Pool() {}
-
-Pool<Bytes> *Pool<Bytes>::create(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<Pool> pool(new (std::nothrow) Pool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::Pool failed";
-    throw MemoryError();
-  }
-  pool->create_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-Pool<Bytes> *Pool<Bytes>::open(Storage *storage, uint32_t storage_node_id) {
-  if (!storage) {
-    GRNXX_ERROR() << "invalid argument: storage == nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<Pool> pool(new (std::nothrow) Pool);
-  if (!pool) {
-    GRNXX_ERROR() << "new grnxx::map::Pool failed";
-    throw MemoryError();
-  }
-  pool->open_pool(storage, storage_node_id);
-  return pool.release();
-}
-
-void Pool<Bytes>::unlink(Storage *storage, uint32_t storage_node_id) {
-  std::unique_ptr<Pool> pool(Pool::open(storage, storage_node_id));
-  storage->unlink_node(storage_node_id);
-}
-
-void Pool<Bytes>::unset(int64_t key_id) {
-  uint64_t bytes_id;
-  if (!index_pool_->get(key_id, &bytes_id)) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  refresh_if_possible();
-  index_pool_->unset(key_id);
-  unset_bytes(bytes_id);
-}
-
-void Pool<Bytes>::reset(int64_t key_id, KeyArg dest_key) {
-  uint64_t src_bytes_id;
-  if (!index_pool_->get(key_id, &src_bytes_id)) {
-    GRNXX_ERROR() << "not found: key_id = " << key_id;
-    throw LogicError();
-  }
-  refresh_if_possible();
-  const uint64_t dest_bytes_id = add_bytes(dest_key);
-  index_pool_->reset(key_id, dest_bytes_id);
-  unset_bytes(src_bytes_id);
-}
-
-int64_t Pool<Bytes>::add(KeyArg key) {
-  refresh_if_possible();
-  const uint64_t bytes_id = add_bytes(key);
-  try {
-    const int64_t key_id = index_pool_->add(bytes_id);
-    return key_id;
-  } catch (...) {
-    unset_bytes(bytes_id);
-    throw;
-  }
-}
-
-void Pool<Bytes>::defrag() {
-  index_pool_->defrag();
-  refresh_if_possible();
-  if (header_->size <= PAGE_SIZE) {
-    // Nothing to do.
-    return;
-  }
-  // Keys in the active page should not be moved.
-  const uint64_t offset_threshold =
-      header_->next_offset - (header_->next_offset % PAGE_SIZE);
-  // Keys in low-usage-rate pages should be moved.
-  const uint32_t size_in_use_threshold =
-      static_cast<uint32_t>(PAGE_SIZE * USAGE_RATE_THRESHOLD);
-  const int64_t max_key_id = index_pool_->max_key_id();
-  uint32_t prev_page_id = INVALID_PAGE_ID;
-  uint8_t *page = nullptr;
-  for (int64_t key_id = MIN_KEY_ID; key_id <= max_key_id; ++key_id) {
-    // FIXME: "index_pool_->get/reset()" can be the bottleneck.
-    uint64_t bytes_id;
-    if (!index_pool_->get(key_id, &bytes_id)) {
-      continue;
-    }
-    const uint64_t offset = get_offset(bytes_id);
-    if (offset >= offset_threshold) {
-      continue;
-    }
-    const uint32_t page_id = static_cast<uint32_t>(offset / PAGE_SIZE);
-    if (page_id != prev_page_id) {
-      if (table_[page_id].size_in_use >= size_in_use_threshold) {
-        page = nullptr;
-      } else {
-        page = get_page(page_id);
-      }
-      prev_page_id = page_id;
-    }
-    if (!page) {
-      continue;
-    }
-    const uint32_t bytes_size = get_size(bytes_id);
-    const Bytes bytes(page + (offset % PAGE_SIZE), bytes_size);
-    const uint64_t new_bytes_id = add_bytes(bytes);
-    index_pool_->reset(key_id, new_bytes_id);
-    table_[page_id].size_in_use -= bytes_size;
-    if (table_[page_id].size_in_use == 0) {
-      // Unlink a page if this operation makes it empty.
-      storage_->unlink_node(table_[page_id].page_storage_node_id);
-    }
-  }
-}
-
-void Pool<Bytes>::sweep(Duration lifetime) {
-  const Time threshold = clock_.now() - lifetime;
-  while (!queue_.empty()) {
-    QueueEntry &queue_entry = queue_.front();
-    if (queue_entry.time <= threshold) {
-      queue_.pop();
-    }
-  }
-}
-
-void Pool<Bytes>::create_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  const uint64_t header_node_size = sizeof(Header) + sizeof(TableEntry);
-  StorageNode header_node =
-      storage->create_node(storage_node_id, header_node_size);
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<Header *>(header_node.body());
-    *header_ = Header();
-    index_pool_.reset(IndexPool::create(storage_, storage_node_id_));
-    header_->index_pool_storage_node_id = index_pool_->storage_node_id();
-    table_ = reinterpret_cast<TableEntry *>(header_ + 1);
-    *table_ = TableEntry();
-  } catch (...) {
-    storage->unlink_node(storage_node_id_);
-    throw;
-  }
-}
-
-void Pool<Bytes>::open_pool(Storage *storage, uint32_t storage_node_id) {
-  storage_ = storage;
-  StorageNode storage_node = storage->open_node(storage_node_id);
-  storage_node_id_ = storage_node.id();
-  header_ = static_cast<Header *>(storage_node.body());
-  index_pool_.reset(IndexPool::open(storage_,
-                                    header_->index_pool_storage_node_id));
-  table_ = reinterpret_cast<TableEntry *>(header_ + 1);
-}
-
-void Pool<Bytes>::unset_bytes(uint64_t bytes_id) {
-  if (bytes_id == EMPTY_BYTES_ID) {
-    // Nothing to do.
-    return;
-  }
-  const uint64_t bytes_offset = get_offset(bytes_id);
-  const uint32_t bytes_size = get_size(bytes_id);
-  if ((bytes_offset + bytes_size) > header_->next_offset) {
-    GRNXX_ERROR() << "invalid argument: bytes_offset = " << bytes_offset
-                  << ", bytes_size = " << bytes_size
-                  << ", next_offset = " << header_->next_offset;
-    throw LogicError();
-  }
-  const uint32_t page_id = static_cast<uint32_t>(bytes_offset / PAGE_SIZE);
-  TableEntry * const table_entry = &table_[page_id];
-  if (bytes_size > table_entry->size_in_use) {
-    GRNXX_ERROR() << "invalid argument: bytes_size = " << bytes_size
-                  << ", size_in_use = " << table_entry->size_in_use;
-    throw LogicError();
-  }
-  table_entry->size_in_use -= bytes_size;
-  if ((table_entry->size_in_use == 0) &&
-      (page_id != (header_->next_offset / PAGE_SIZE))) {
-    // Unlink a page if this operation makes it empty.
-    storage_->unlink_node(table_entry->page_storage_node_id);
-  }
-}
-
-uint64_t Pool<Bytes>::add_bytes(KeyArg bytes) {
-  const uint32_t bytes_size = static_cast<uint32_t>(bytes.size());
-  if (bytes_size > MAX_KEY_SIZE) {
-    GRNXX_ERROR() << "invalid argument: key_size = " << bytes_size
-                  << ", max_key_size = " << MAX_KEY_SIZE;
-    throw LogicError();
-  }
-  if (bytes_size == 0) {
-    return EMPTY_BYTES_ID;
-  }
-  const uint64_t bytes_offset = reserve_space(bytes_size);
-  const uint32_t page_id = static_cast<uint32_t>(bytes_offset / PAGE_SIZE);
-  uint8_t * const page = get_page(page_id);
-  std::memcpy(page + (bytes_offset % PAGE_SIZE), bytes.data(), bytes_size);
-  TableEntry * const table_entry = &table_[page_id];
-  table_entry->size_in_use += bytes_size;
-  return get_bytes_id(bytes_offset, bytes_size);
-}
-
-uint8_t *Pool<Bytes>::open_page(uint32_t page_id) {
-  if (page_id >= (header_->size / PAGE_SIZE)) {
-    GRNXX_ERROR() << "invalid argument: page_id = " << page_id
-                  << ", table_size = " << (header_->size / PAGE_SIZE);
-    throw LogicError();
-  }
-  if (!pages_[page_id]) {
-    Lock lock(&header_->mutex);
-    if (!pages_[page_id]) {
-      // Open an existing full-size page.
-      // Note that a small-size page is opened in refresh_page().
-      if (table_[page_id].page_storage_node_id == STORAGE_INVALID_NODE_ID) {
-        GRNXX_ERROR() << "not found: page_id = " << page_id;
-        throw LogicError();
-      }
-      StorageNode page_node =
-          storage_->open_node(table_[page_id].page_storage_node_id);
-      pages_[page_id] = static_cast<uint8_t *>(page_node.body());
-    }
-  }
-  return pages_[page_id];
-}
-
-uint64_t Pool<Bytes>::reserve_space(uint32_t size) {
-  uint64_t offset = header_->next_offset;
-  const uint32_t page_size = static_cast<uint32_t>(
-      (header_->size < PAGE_SIZE) ? header_->size : PAGE_SIZE);
-  const uint32_t page_size_left = static_cast<uint32_t>(
-      ((offset % PAGE_SIZE) == 0) ? 0 : (page_size - (offset % PAGE_SIZE)));
-  if (size <= page_size_left) {
-    header_->next_offset += size;
-    return offset;
-  }
-  if ((header_->next_offset + size) > header_->size) {
-    expand(size);
-  }
-  if (page_size == PAGE_SIZE) {
-    offset += page_size_left;
-  }
-  const uint32_t page_id = static_cast<uint32_t>(offset / PAGE_SIZE);
-  if (page_id > 0) {
-    if ((table_[page_id - 1].size_in_use == 0) && (page_size_left != 0)) {
-      // Unlink an empty page if it is fixed.
-      storage_->unlink_node(table_[page_id - 1].page_storage_node_id);
-    }
-  }
-  if (!pages_[page_id]) {
-    // Note that "pages_[0]" is not nullptr if there is a small-size page
-    // because it is opened in refresh_page().
-    if (table_[page_id].page_storage_node_id == STORAGE_INVALID_NODE_ID) {
-      Lock lock(&header_->mutex);
-      if (table_[page_id].page_storage_node_id == STORAGE_INVALID_NODE_ID) {
-        // Create a full-size page.
-        // Note that a small-size page is created in expand_page().
-        StorageNode page_node =
-            storage_->create_node(storage_node_id_, PAGE_SIZE);
-        table_[page_id].page_storage_node_id = page_node.id();
-      }
-    }
-  }
-  header_->next_offset = offset + size;
-  return offset;
-}
-
-void Pool<Bytes>::expand(uint32_t additional_size) {
-  Lock lock(&header_->mutex);
-  if (size_ < PAGE_SIZE) {
-    // Create a small-size page or the first full-size page.
-    expand_page(additional_size);
-    refresh_page();
-  } else {
-    // Create a table.
-    expand_table(additional_size);
-    refresh_table();
-  }
-}
-
-void Pool<Bytes>::expand_page(uint32_t additional_size) {
-  const uint64_t min_size = size_ + additional_size;
-  uint64_t new_size = (size_ == 0) ? MIN_PAGE_SIZE : (size_ * 2);
-  while (new_size < min_size) {
-    new_size *= 2;
-  }
-  StorageNode page_node = storage_->create_node(storage_node_id_, new_size);
-  if (size_ != 0) {
-    // Copy data from the current page and unlink it.
-    std::memcpy(page_node.body(), pages_[0], size_);
-    try {
-      storage_->unlink_node(header_->page_storage_node_id);
-    } catch (...) {
-      storage_->unlink_node(page_node.id());
-      throw;
-    }
-  }
-  table_[0].page_storage_node_id = page_node.id();
-  header_->page_storage_node_id = page_node.id();
-  header_->size = new_size;
-}
-
-void Pool<Bytes>::expand_table(uint32_t) {
-  const uint64_t old_table_size = size_ / PAGE_SIZE;
-  const uint64_t new_table_size = (old_table_size < MIN_TABLE_SIZE) ?
-       MIN_TABLE_SIZE : (old_table_size * 2);
-  const uint64_t new_size = new_table_size * PAGE_SIZE;
-  StorageNode table_node = storage_->create_node(
-      storage_node_id_, sizeof(TableEntry) * new_table_size);
-  TableEntry * const new_table = static_cast<TableEntry *>(table_node.body());
-  uint64_t i = 0;
-  for ( ; i < old_table_size; ++i) {
-    new_table[i] = table_[i];
-  }
-  for ( ; i < new_table_size; ++i) {
-    new_table[i] = TableEntry();
-  }
-  header_->table_storage_node_id = table_node.id();
-  header_->size = new_size;
-}
-
-void Pool<Bytes>::refresh() {
-  if (size_ != header_->size) {
-    Lock lock(&header_->mutex);
-    if (header_->size <= PAGE_SIZE) {
-      // Reopen a page because it is old.
-      refresh_page();
-    } else {
-      // Reopen a table because it is old.
-      refresh_table();
-    }
-    size_ = header_->size;
-  }
-}
-
-void Pool<Bytes>::refresh_page() {
-  StorageNode page_node =
-      storage_->open_node(header_->page_storage_node_id);
-  if (!pages_) {
-    std::unique_ptr<uint8_t *[]> new_pages(new (std::nothrow) uint8_t *[1]);
-    if (!new_pages) {
-      GRNXX_ERROR() << "new uint8_t *[] failed: size = " << 1;
-      throw MemoryError();
-    }
-    new_pages[0] = static_cast<uint8_t *>(page_node.body());
-    pages_.swap(new_pages);
-  } else {
-    pages_[0] = static_cast<uint8_t *>(page_node.body());
-  }
-}
-
-void Pool<Bytes>::refresh_table() {
-  StorageNode table_node =
-      storage_->open_node(header_->table_storage_node_id);
-  TableEntry * const new_table =
-      static_cast<TableEntry *>(table_node.body());
-  const uint64_t new_table_size = header_->size / PAGE_SIZE;
-  std::unique_ptr<uint8_t *[]> new_pages(
-      new (std::nothrow) uint8_t *[new_table_size]);
-  if (!new_pages) {
-    GRNXX_ERROR() << "new uint8_t *[] failed: size = " << new_table_size;
-    throw MemoryError();
-  }
-  // Initialize a new cache table.
-  const uint64_t old_table_size = size_ / PAGE_SIZE;
-  uint64_t i = 0;
-  for ( ; i < old_table_size; ++i) {
-    new_pages[i] = pages_[i];
-  }
-  for ( ; i < new_table_size; ++i) {
-    new_pages[i] = nullptr;
-  }
-  pages_.swap(new_pages);
-  // Keep an old cache table because another thread may read it.
-  if (new_pages) {
-    try {
-      queue_.push(QueueEntry{ std::move(new_pages), clock_.now() });
-    } catch (const std::exception &exception) {
-      GRNXX_ERROR() << "std::queue::push() failed";
-      throw StandardError(exception);
-    }
-  }
-  table_ = new_table;
-}
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/pool.hpp (+0 -344) 100644
===================================================================
--- lib/grnxx/map/pool.hpp    2013-08-23 10:46:34 +0900 (fb06ea5)
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MAP_POOL_HPP
-#define GRNXX_MAP_POOL_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-#include <queue>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/duration.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace map {
-
-// The minimum key ID.
-constexpr int64_t POOL_MIN_KEY_ID = 0;
-// The maximum key ID.
-constexpr int64_t POOL_MAX_KEY_ID = (1LL << 40) - 2;
-
-template <typename T>
-struct PoolHeader {
-  int64_t max_key_id;
-  uint64_t num_keys;
-  uint64_t size;
-  uint64_t latest_available_unit_id;
-  union {
-    uint32_t page_storage_node_id;
-    uint32_t table_storage_node_id;
-  };
-  Mutex mutex;
-
-  PoolHeader();
-};
-
-struct PoolUnit {
-  uint64_t validity_bits;
-  uint64_t next_available_unit_id;
-};
-
-template <typename T>
-struct PoolQueueEntry {
-  std::unique_ptr<void *[]> page;
-  Time time;
-};
-
-template <typename T>
-class Pool {
-  using Header     = PoolHeader<T>;
-  using Unit       = PoolUnit;
-  using QueueEntry = PoolQueueEntry<T>;
-
-  static constexpr int64_t  MIN_KEY_ID     = POOL_MIN_KEY_ID;
-  static constexpr int64_t  MAX_KEY_ID     = POOL_MAX_KEY_ID;
-
-  static constexpr uint64_t UNIT_SIZE      = 64;
-  static constexpr uint64_t PAGE_SIZE      = 1ULL << 16;
-
-  static constexpr uint64_t MIN_PAGE_SIZE  = UNIT_SIZE;
-  static constexpr uint64_t MIN_TABLE_SIZE = 1ULL << 10;
-
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  Pool();
-  ~Pool();
-
-  static Pool *create(Storage *storage, uint32_t storage_node_id);
-  static Pool *open(Storage *storage, uint32_t storage_node_id);
-
-  static void unlink(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  static constexpr int64_t min_key_id() {
-    return MIN_KEY_ID;
-  }
-  int64_t max_key_id() const {
-    return header_->max_key_id;
-  }
-  uint64_t num_keys() const {
-    return header_->num_keys;
-  }
-
-  bool get(int64_t key_id, Key *key) {
-    refresh_if_possible();
-    const void * const page = get_page(key_id / PAGE_SIZE);
-    const uint64_t local_key_id = key_id % PAGE_SIZE;
-    const Unit * const unit =
-        static_cast<const Unit *>(page) - (local_key_id / UNIT_SIZE) - 1;
-    if (~unit->validity_bits & (1ULL << (local_key_id % UNIT_SIZE))) {
-      // Not found.
-      return false;
-    }
-    *key = static_cast<const T *>(page)[local_key_id];
-    return true;
-  }
-
-  Key get_key(int64_t key_id) {
-    refresh_if_possible();
-    const void * const page = get_page(key_id / PAGE_SIZE);
-    return static_cast<const T *>(page)[key_id % PAGE_SIZE];
-  }
-
-  bool get_bit(int64_t key_id) {
-    refresh_if_possible();
-    const void * const page = get_page(key_id / PAGE_SIZE);
-    const uint64_t local_key_id = key_id % PAGE_SIZE;
-    const Unit * const unit =
-        static_cast<const Unit *>(page) - (local_key_id / UNIT_SIZE) - 1;
-    return unit->validity_bits & (1ULL << (local_key_id % UNIT_SIZE));
-  }
-
-  void unset(int64_t key_id);
-  void reset(int64_t key_id, KeyArg dest_key);
-
-  int64_t add(KeyArg key);
-
-  void defrag();
-  void sweep(Duration lifetime);
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<void *[]> pages_;
-  uint32_t *table_;
-  uint64_t size_;
-  std::queue<QueueEntry> queue_;
-  PeriodicClock clock_;
-
-  void create_pool(Storage *storage, uint32_t storage_node_id);
-  void open_pool(Storage *storage, uint32_t storage_node_id);
-
-  void *get_page(uint64_t page_id) {
-    return pages_[page_id] ? pages_[page_id] : open_page(page_id);
-  }
-  void *open_page(uint64_t page_id);
-
-  void reserve_key_id(int64_t key_id);
-
-  void expand();
-  void expand_page();
-  void expand_table();
-
-  void refresh_if_possible() {
-    if (size_ != header_->size) {
-      refresh();
-    }
-  }
-  void refresh();
-  void refresh_page();
-  void refresh_table();
-};
-
-template <>
-struct PoolHeader<Bytes> {
-  uint64_t size;
-  uint64_t next_offset;
-  union {
-    uint32_t page_storage_node_id;
-    uint32_t table_storage_node_id;
-  };
-  uint32_t index_pool_storage_node_id;
-  Mutex mutex;
-
-  PoolHeader();
-};
-
-struct PoolTableEntry {
-  uint32_t page_storage_node_id;
-  uint32_t size_in_use;
-
-  PoolTableEntry();
-};
-
-template <>
-struct PoolQueueEntry<Bytes> {
-  std::unique_ptr<uint8_t *[]> page;
-  Time time;
-};
-
-template <>
-class Pool<Bytes> {
-  using Header     = PoolHeader<Bytes>;
-  using IndexPool  = Pool<uint64_t>;
-  using TableEntry = PoolTableEntry;
-  using QueueEntry = PoolQueueEntry<Bytes>;
-
-  static constexpr int64_t  MIN_KEY_ID     = POOL_MIN_KEY_ID;
-  static constexpr int64_t  MAX_KEY_ID     = POOL_MAX_KEY_ID;
-  static constexpr uint64_t MAX_KEY_SIZE   = 4096;
-
-  static constexpr uint64_t PAGE_SIZE      = 1ULL << 20;
-
-  static constexpr uint64_t MIN_PAGE_SIZE  = 64;
-  static constexpr uint64_t MIN_TABLE_SIZE = 1ULL << 10;
-
-  static constexpr uint64_t BYTES_ID_SIZE_MASK = (1ULL << 13) - 1;
-
-  static constexpr uint64_t EMPTY_BYTES_ID = 0;
-
-  static constexpr double   USAGE_RATE_THRESHOLD = 0.5;
-
- public:
-  using Key = typename Traits<Bytes>::Type;
-  using KeyArg = typename Traits<Bytes>::ArgumentType;
-
-  Pool();
-  ~Pool();
-
-  static Pool *create(Storage *storage, uint32_t storage_node_id);
-  static Pool *open(Storage *storage, uint32_t storage_node_id);
-
-  static void unlink(Storage *storage, uint32_t storage_node_id);
-
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-
-  static constexpr int64_t min_key_id() {
-    return IndexPool::min_key_id();
-  }
-  int64_t max_key_id() const {
-    return index_pool_->max_key_id();
-  }
-  uint64_t num_keys() const {
-    return index_pool_->num_keys();
-  }
-
-  bool get(int64_t key_id, Key *key) {
-    uint64_t bytes_id;
-    if (!index_pool_->get(key_id, &bytes_id)) {
-      // Not found.
-      return false;
-    }
-    *key = get_bytes(bytes_id);
-    return true;
-  }
-
-  Key get_key(int64_t key_id) {
-    return get_bytes(index_pool_->get_key(key_id));
-  }
-
-  bool get_bit(int64_t key_id) {
-    return index_pool_->get_bit(key_id);
-  }
-
-  void unset(int64_t key_id);
-  void reset(int64_t key_id, KeyArg dest_key);
-
-  int64_t add(KeyArg key);
-
-  void defrag();
-  void sweep(Duration lifetime);
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  Header *header_;
-  std::unique_ptr<IndexPool> index_pool_;
-  std::unique_ptr<uint8_t *[]> pages_;
-  TableEntry *table_;
-  uint64_t size_;
-  std::queue<QueueEntry> queue_;
-  PeriodicClock clock_;
-
-  void create_pool(Storage *storage, uint32_t storage_node_id);
-  void open_pool(Storage *storage, uint32_t storage_node_id);
-
-  Key get_bytes(uint64_t bytes_id) {
-    if (bytes_id == EMPTY_BYTES_ID) {
-      return Bytes("", 0);
-    }
-    refresh_if_possible();
-    const uint64_t offset = get_offset(bytes_id);
-    const uint32_t page_id = static_cast<uint32_t>(offset / PAGE_SIZE);
-    return Bytes(get_page(page_id) + (offset % PAGE_SIZE), get_size(bytes_id));
-  }
-  void unset_bytes(uint64_t bytes_id);
-  uint64_t add_bytes(KeyArg bytes);
-
-  uint8_t *get_page(uint32_t page_id) {
-    return pages_[page_id] ? pages_[page_id] : open_page(page_id);
-  }
-  uint8_t *open_page(uint32_t page_id);
-
-  uint64_t reserve_space(uint32_t size);
-
-  static uint64_t get_bytes_id(uint64_t offset, uint32_t size) {
-    return (offset * (BYTES_ID_SIZE_MASK + 1)) | size;
-  }
-  static uint64_t get_offset(uint64_t bytes_id) {
-    return bytes_id / (BYTES_ID_SIZE_MASK + 1);
-  }
-  static uint32_t get_size(uint64_t bytes_id) {
-    return static_cast<uint32_t>(bytes_id & BYTES_ID_SIZE_MASK);
-  }
-
-  void expand(uint32_t additional_size);
-  void expand_page(uint32_t additional_size);
-  void expand_table(uint32_t additional_size);
-
-  void refresh_if_possible() {
-    if (size_ != header_->size) {
-      refresh();
-    }
-  }
-  void refresh();
-  void refresh_page();
-  void refresh_table();
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_POOL_HPP

  Deleted: lib/grnxx/map/scanner_impl.cpp (+0 -75) 100644
===================================================================
--- lib/grnxx/map/scanner_impl.cpp    2013-08-23 10:46:34 +0900 (8c09113)
+++ /dev/null
@@ -1,75 +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 "grnxx/map/scanner_impl.hpp"
-
-#include <memory>
-#include <new>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/charset.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map.hpp"
-
-namespace grnxx {
-namespace map {
-
-template <typename T>
-ScannerImpl<T>::ScannerImpl() : map_(), query_(), charset_() {}
-
-template <typename T>
-ScannerImpl<T>::~ScannerImpl() {}
-
-template <typename T>
-ScannerImpl<T> *ScannerImpl<T>::create(Map<T> *map, KeyArg query,
-                                       const Charset *charset) {
-  std::unique_ptr<ScannerImpl> scanner(new (std::nothrow) ScannerImpl);
-  if (!scanner) {
-    GRNXX_ERROR() << "new grnxx::map::ScannerImpl failed";
-    throw MemoryError();
-  }
-  scanner->map_ = map;
-  scanner->query_ = query;
-  scanner->charset_ = charset;
-  return scanner.release();
-}
-
-template <typename T>
-bool ScannerImpl<T>::next() {
-  this->offset_ += this->size_;
-  while (this->offset_ < query_.size()) {
-    const T rest = query_.except_prefix(this->offset_);
-    if (map_->find_longest_prefix_match(rest, &this->key_id_, &this->key_)) {
-      this->size_ = this->key_.size();
-      return true;
-    }
-    // Move to the next character.
-    if (charset_) {
-      this->offset_ += charset_->get_char_size(rest);
-    } else {
-      ++this->offset_;
-    }
-  }
-  this->size_ = 0;
-  return false;
-}
-
-template class ScannerImpl<Bytes>;
-
-}  // namespace map
-}  // namespace grnxx

  Deleted: lib/grnxx/map/scanner_impl.hpp (+0 -55) 100644
===================================================================
--- lib/grnxx/map/scanner_impl.hpp    2013-08-23 10:46:34 +0900 (3d23ce2)
+++ /dev/null
@@ -1,55 +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_MAP_SCANNER_IMPL_HPP
-#define GRNXX_MAP_SCANNER_IMPL_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/map_scanner.hpp"
-
-namespace grnxx {
-
-class Charset;
-template <typename T> class Map;
-
-namespace map {
-
-template <typename T>
-class ScannerImpl : public MapScanner<T> {
- public:
-  using Key = typename MapScanner<T>::Key;
-  using KeyArg = typename MapScanner<T>::KeyArg;
-
-  ScannerImpl();
-  ~ScannerImpl();
-
-  static ScannerImpl *create(Map<T> *map, KeyArg query,
-                             const Charset *charset);
-
-  bool next();
-
- protected:
-  Map<T> *map_;
-  Key query_;
-  const Charset *charset_;
-};
-
-}  // namespace map
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_SCANNER_IMPL_HPP

  Deleted: lib/grnxx/map_cursor.cpp (+0 -81) 100644
===================================================================
--- lib/grnxx/map_cursor.cpp    2013-08-23 10:46:34 +0900 (9e9e284)
+++ /dev/null
@@ -1,81 +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 "grnxx/map_cursor.hpp"
-
-#include <limits>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/map.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-
-#define GRNXX_FLAGS_WRITE(flag) do { \
-  if (flags & flag) { \
-    if (!is_first) { \
-      builder << " | "; \
-    } \
-    builder << #flag; \
-    is_first = false; \
-  } \
-} while (false)
-
-StringBuilder &operator<<(StringBuilder &builder, MapCursorFlags flags) {
-  bool is_first = true;
-  GRNXX_FLAGS_WRITE(MAP_CURSOR_ORDER_BY_ID);
-  GRNXX_FLAGS_WRITE(MAP_CURSOR_ORDER_BY_KEY);
-  GRNXX_FLAGS_WRITE(MAP_CURSOR_REVERSE_ORDER);
-  if (is_first) {
-    builder << "MAP_CURSOR_DEFAULT";
-  }
-  return builder;
-}
-
-MapCursorOptions::MapCursorOptions()
-    : flags(MAP_CURSOR_DEFAULT),
-      offset(0),
-      limit(std::numeric_limits<uint64_t>::max()) {}
-
-template <typename T>
-MapCursor<T>::MapCursor() : key_id_(MAP_INVALID_KEY_ID), key_() {}
-
-template <typename T>
-MapCursor<T>::~MapCursor() {}
-
-template <typename T>
-bool MapCursor<T>::remove() {
-  GRNXX_ERROR() << "invalid operation";
-  throw LogicError();
-}
-
-template class MapCursor<int8_t>;
-template class MapCursor<uint8_t>;
-template class MapCursor<int16_t>;
-template class MapCursor<uint16_t>;
-template class MapCursor<int32_t>;
-template class MapCursor<uint32_t>;
-template class MapCursor<int64_t>;
-template class MapCursor<uint64_t>;
-template class MapCursor<double>;
-template class MapCursor<GeoPoint>;
-template class MapCursor<Bytes>;
-
-}  // namespace grnxx

  Deleted: lib/grnxx/map_cursor.hpp (+0 -91) 100644
===================================================================
--- lib/grnxx/map_cursor.hpp    2013-08-23 10:46:34 +0900 (9297eba)
+++ /dev/null
@@ -1,91 +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_MAP_CURSOR_HPP
-#define GRNXX_MAP_CURSOR_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-template <typename T> class Map;
-
-// TODO: How to implement NEAR cursor.
-struct MapCursorFlagsIdentifier;
-using MapCursorFlags = FlagsImpl<MapCursorFlagsIdentifier>;
-
-// Use the default settings.
-constexpr MapCursorFlags MAP_CURSOR_DEFAULT       =
-    MapCursorFlags::define(0x00);
-// Sort keys by ID.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_ID   =
-    MapCursorFlags::define(0x01);
-// Sort keys by key.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_KEY  =
-    MapCursorFlags::define(0x02);
-// Access keys in reverse order.
-constexpr MapCursorFlags MAP_CURSOR_REVERSE_ORDER =
-    MapCursorFlags::define(0x10);
-
-StringBuilder &operator<<(StringBuilder &builder, MapCursorFlags flags);
-
-struct MapCursorOptions {
-  MapCursorFlags flags;
-  uint64_t offset;
-  uint64_t limit;
-
-  // Initialize the members.
-  MapCursorOptions();
-};
-
-template <typename T>
-class MapCursor {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  MapCursor();
-  virtual ~MapCursor();
-
-  // Move the cursor to the next key and return true on success.
-  virtual bool next() = 0;
-  // Remove the current key and return true on success.
-  virtual bool remove();
-
-  // Return the ID of the current key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return the current key.
-  const Key &key() const {
-    return key_;
-  }
-
- protected:
-  int64_t key_id_;
-  Key key_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_CURSOR_HPP

  Deleted: lib/grnxx/map_cursor_query.hpp (+0 -326) 100644
===================================================================
--- lib/grnxx/map_cursor_query.hpp    2013-08-23 10:46:34 +0900 (9ebe771)
+++ /dev/null
@@ -1,326 +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_MAP_CURSOR_QUERY_HPP
-#define GRNXX_MAP_CURSOR_QUERY_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-// MapCursorAllKeys.
-
-template <typename T> struct MapCursorAllKeys {};
-
-// MapCursorKeyID
-
-template <typename T> struct MapCursorKeyID {};
-
-struct MapCursorKeyIDFlagsIdentifier;
-using MapCursorKeyIDFlags = FlagsImpl<MapCursorKeyIDFlagsIdentifier>;
-
-constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_LESS          =
-    MapCursorKeyIDFlags::define(0x01);
-constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_LESS_EQUAL    =
-    MapCursorKeyIDFlags::define(0x02);
-constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_GREATER       =
-    MapCursorKeyIDFlags::define(0x04);
-constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_GREATER_EQUAL =
-    MapCursorKeyIDFlags::define(0x08);
-
-template <typename T>
-struct MapCursorKeyIDRange {
-  MapCursorKeyIDFlags flags;
-  int64_t min;
-  int64_t max;
-};
-
-template <typename T>
-struct MapCursorKeyIDLess {
-  int64_t max;
-  constexpr MapCursorKeyIDFlags flags() const {
-    return MAP_CURSOR_KEY_ID_LESS;
-  }
-  operator MapCursorKeyIDRange<T>() const {
-    return MapCursorKeyIDRange<T>{ flags(), 0, max };
-  }
-};
-
-template <typename T>
-struct MapCursorKeyIDLessEqual {
-  int64_t max;
-  constexpr MapCursorKeyIDFlags flags() const {
-    return MAP_CURSOR_KEY_ID_LESS_EQUAL;
-  }
-  operator MapCursorKeyIDRange<T>() const {
-    return MapCursorKeyIDRange<T>{ flags(), 0, max };
-  };
-};
-
-template <typename T>
-struct MapCursorKeyIDGreater {
-  int64_t min;
-  constexpr MapCursorKeyIDFlags flags() const {
-    return MAP_CURSOR_KEY_ID_GREATER;
-  }
-  operator MapCursorKeyIDRange<T>() const {
-    return MapCursorKeyIDRange<T>{ flags(), min, 0 };
-  }
-};
-
-template <typename T>
-struct MapCursorKeyIDGreaterEqual {
-  int64_t min;
-  constexpr MapCursorKeyIDFlags flags() const {
-    return MAP_CURSOR_KEY_ID_GREATER_EQUAL;
-  }
-  operator MapCursorKeyIDRange<T>() const {
-    return MapCursorKeyIDRange<T>{ flags(), min, 0 };
-  }
-};
-
-template <typename T>
-MapCursorKeyIDLess<T> operator<(MapCursorKeyID<T>, int64_t max) {
-  return MapCursorKeyIDLess<T>{ max };
-}
-template <typename T>
-MapCursorKeyIDLessEqual<T> operator<=(MapCursorKeyID<T>, int64_t max) {
-  return MapCursorKeyIDLessEqual<T>{ max };
-}
-template <typename T>
-MapCursorKeyIDGreater<T> operator>(MapCursorKeyID<T>, int64_t min) {
-  return MapCursorKeyIDGreater<T>{ min };
-}
-template <typename T>
-MapCursorKeyIDGreaterEqual<T> operator>=(MapCursorKeyID<T>, int64_t min) {
-  return MapCursorKeyIDGreaterEqual<T>{ min };
-}
-
-template <typename T>
-MapCursorKeyIDGreater<T> operator<(int64_t min, MapCursorKeyID<T>) {
-  return MapCursorKeyIDGreater<T>{ min };
-}
-template <typename T>
-MapCursorKeyIDGreaterEqual<T> operator<=(int64_t min, MapCursorKeyID<T>) {
-  return MapCursorKeyIDGreaterEqual<T>{ min };
-}
-template <typename T>
-MapCursorKeyIDLess<T> operator>(int64_t max, MapCursorKeyID<T>) {
-  return MapCursorKeyIDLess<T>{ max };
-}
-template <typename T>
-MapCursorKeyIDLessEqual<T> operator>=(int64_t max, MapCursorKeyID<T>) {
-  return MapCursorKeyIDLessEqual<T>{ max };
-}
-
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLess<T> less,
-                                  MapCursorKeyIDGreater<T> greater) {
-  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
-                                 greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLess<T> less,
-                                  MapCursorKeyIDGreaterEqual<T> greater) {
-  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
-                                 greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLessEqual<T> less,
-                                  MapCursorKeyIDGreater<T> greater) {
-  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
-                                 greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLessEqual<T> less,
-                                  MapCursorKeyIDGreaterEqual<T> greater) {
-  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
-                                 greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreater<T> greater,
-                                  MapCursorKeyIDLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreater<T> greater,
-                                  MapCursorKeyIDLessEqual<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreaterEqual<T> greater,
-                                  MapCursorKeyIDLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreaterEqual<T> greater,
-                                  MapCursorKeyIDLessEqual<T> less) {
-  return less && greater;
-}
-
-// MapCursorKey
-
-template <typename T> struct MapCursorKey {};
-
-struct MapCursorKeyFlagsIdentifier;
-using MapCursorKeyFlags = FlagsImpl<MapCursorKeyFlagsIdentifier>;
-
-constexpr MapCursorKeyFlags MAP_CURSOR_KEY_LESS          =
-    MapCursorKeyFlags::define(0x01);
-constexpr MapCursorKeyFlags MAP_CURSOR_KEY_LESS_EQUAL    =
-    MapCursorKeyFlags::define(0x02);
-constexpr MapCursorKeyFlags MAP_CURSOR_KEY_GREATER       =
-    MapCursorKeyFlags::define(0x04);
-constexpr MapCursorKeyFlags MAP_CURSOR_KEY_GREATER_EQUAL =
-    MapCursorKeyFlags::define(0x08);
-
-template <typename T>
-struct MapCursorKeyRange {
-  MapCursorKeyFlags flags;
-  T min;
-  T max;
-};
-
-template <typename T>
-struct MapCursorKeyLess {
-  T max;
-  constexpr MapCursorKeyFlags flags() const {
-    return MAP_CURSOR_KEY_LESS;
-  }
-  operator MapCursorKeyRange<T>() const {
-    return MapCursorKeyRange<T>{ flags(), T(), max };
-  }
-};
-
-template <typename T>
-struct MapCursorKeyLessEqual {
-  T max;
-  constexpr MapCursorKeyFlags flags() const {
-    return MAP_CURSOR_KEY_LESS_EQUAL;
-  }
-  operator MapCursorKeyRange<T>() const {
-    return MapCursorKeyRange<T>{ flags(), T(), max };
-  }
-};
-
-template <typename T>
-struct MapCursorKeyGreater {
-  T min;
-  constexpr MapCursorKeyFlags flags() const {
-    return MAP_CURSOR_KEY_GREATER;
-  }
-  operator MapCursorKeyRange<T>() const {
-    return MapCursorKeyRange<T>{ flags(), min, T() };
-  }
-};
-
-template <typename T>
-struct MapCursorKeyGreaterEqual {
-  T min;
-  constexpr MapCursorKeyFlags flags() const {
-    return MAP_CURSOR_KEY_GREATER_EQUAL;
-  }
-  operator MapCursorKeyRange<T>() const {
-    return MapCursorKeyRange<T>{ flags(), min, T() };
-  }
-};
-
-template <typename T>
-MapCursorKeyLess<T> operator<(MapCursorKey<T>, T max) {
-  return MapCursorKeyLess<T>{ max };
-}
-template <typename T>
-MapCursorKeyLessEqual<T> operator<=(MapCursorKey<T>, T max) {
-  return MapCursorKeyLessEqual<T>{ max };
-}
-template <typename T>
-MapCursorKeyGreater<T> operator>(MapCursorKey<T>, T min) {
-  return MapCursorKeyGreater<T>{ min };
-}
-template <typename T>
-MapCursorKeyGreaterEqual<T> operator>=(MapCursorKey<T>, T min) {
-  return MapCursorKeyGreaterEqual<T>{ min };
-}
-
-template <typename T>
-MapCursorKeyGreater<T> operator<(T min, MapCursorKey<T>) {
-  return MapCursorKeyGreater<T>{ min };
-}
-template <typename T>
-MapCursorKeyGreaterEqual<T> operator<=(T min, MapCursorKey<T>) {
-  return MapCursorKeyGreaterEqual<T>{ min };
-}
-template <typename T>
-MapCursorKeyLess<T> operator>(T max, MapCursorKey<T>) {
-  return MapCursorKeyLess<T>{ max };
-}
-template <typename T>
-MapCursorKeyLessEqual<T> operator>=(T max, MapCursorKey<T>) {
-  return MapCursorKeyLessEqual<T>{ max };
-}
-
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyLess<T> less,
-                                MapCursorKeyGreater<T> greater) {
-  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
-                               greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyLess<T> less,
-                                MapCursorKeyGreaterEqual<T> greater) {
-  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
-                               greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyLessEqual<T> less,
-                                MapCursorKeyGreater<T> greater) {
-  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
-                               greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyLessEqual<T> less,
-                                MapCursorKeyGreaterEqual<T> greater) {
-  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
-                               greater.min, less.max };
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyGreater<T> greater,
-                                MapCursorKeyLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyGreater<T> greater,
-                                MapCursorKeyLessEqual<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyGreaterEqual<T> greater,
-                                MapCursorKeyLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapCursorKeyRange<T> operator&&(MapCursorKeyGreaterEqual<T> greater,
-                                MapCursorKeyLessEqual<T> less) {
-  return less && greater;
-}
-
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_CURSOR_QUERY_HPP

  Deleted: lib/grnxx/map_scanner.cpp (+0 -37) 100644
===================================================================
--- lib/grnxx/map_scanner.cpp    2013-08-23 10:46:34 +0900 (8814983)
+++ /dev/null
@@ -1,37 +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 "grnxx/map_scanner.hpp"
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/map.hpp"
-
-namespace grnxx {
-
-template <typename T>
-MapScanner<T>::MapScanner()
-    : offset_(0),
-      size_(0),
-      key_id_(MAP_INVALID_KEY_ID),
-      key_() {}
-
-template <typename T>
-MapScanner<T>::~MapScanner() {}
-
-template class MapScanner<Bytes>;
-
-}  // namespace grnxx

  Deleted: lib/grnxx/map_scanner.hpp (+0 -70) 100644
===================================================================
--- lib/grnxx/map_scanner.hpp    2013-08-23 10:46:34 +0900 (b28af1c)
+++ /dev/null
@@ -1,70 +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_MAP_SCANNER_HPP
-#define GRNXX_MAP_SCANNER_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Charset;
-class Storage;
-
-template <typename T>
-class MapScanner {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  MapScanner();
-  virtual ~MapScanner();
-
-  // Find the next key from the rest of the query and return true on success.
-  virtual bool next() = 0;
-
-  // Return the start position of the found key.
-  uint64_t offset() const {
-    return offset_;
-  }
-  // Return the size of the found key.
-  uint64_t size() const {
-    return size_;
-  }
-  // Return the ID of the found key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return the found key.
-  const Key &key() const {
-    return key_;
-  }
-
- protected:
-  uint64_t offset_;
-  uint64_t size_;
-  int64_t key_id_;
-  Key key_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_MAP_SCANNER_HPP

  Deleted: lib/grnxx/mutex.cpp (+0 -92) 100644
===================================================================
--- lib/grnxx/mutex.cpp    2013-08-23 10:46:34 +0900 (ac8b575)
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-  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/mutex.hpp"
-
-#include "grnxx/string_builder.hpp"
-#include "grnxx/thread.hpp"
-#include "grnxx/stopwatch.hpp"
-
-namespace grnxx {
-namespace {
-
-constexpr int MUTEX_SPIN_COUNT           = 100;
-constexpr int MUTEX_CONTEXT_SWITCH_COUNT = 100;
-constexpr Duration MUTEX_SLEEP_DURATION  = Duration::milliseconds(10);
-
-}  // namespace
-
-void Mutex::lock_without_timeout() {
-  for (int i = 0; i < MUTEX_SPIN_COUNT; ++i) {
-    if (try_lock()) {
-      return;
-    }
-  }
-  for (int i = 0; i < MUTEX_CONTEXT_SWITCH_COUNT; ++i) {
-    if (try_lock()) {
-      return;
-    }
-    Thread::yield();
-  }
-  while (!try_lock()) {
-    Thread::sleep_for(MUTEX_SLEEP_DURATION);
-  }
-}
-
-bool Mutex::lock_with_timeout(Duration timeout) {
-  if (timeout <= Duration(0)) {
-    return false;
-  }
-  for (int i = 0; i < MUTEX_SPIN_COUNT; ++i) {
-    if (try_lock()) {
-      return true;
-    }
-  }
-  Stopwatch stopwatch(true);
-  for (int i = 0; i < MUTEX_CONTEXT_SWITCH_COUNT; ++i) {
-    if (stopwatch.elapsed() >= timeout) {
-      return false;
-    }
-    if (try_lock()) {
-      return true;
-    }
-    Thread::yield();
-  }
-  while (stopwatch.elapsed() < timeout) {
-    if (try_lock()) {
-      return true;
-    }
-    Thread::sleep_for(MUTEX_SLEEP_DURATION);
-  }
-  return false;
-}
-
-StringBuilder &Mutex::write_to(StringBuilder &builder) const {
-  switch (status_) {
-    case MUTEX_UNLOCKED: {
-      return builder << "unlocked";
-    }
-    case MUTEX_LOCKED: {
-      return builder << "locked";
-    }
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/mutex.hpp (+0 -84) 100644
===================================================================
--- lib/grnxx/mutex.hpp    2013-08-23 10:46:34 +0900 (f1d267c)
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_MUTEX_HPP
-#define GRNXX_MUTEX_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/duration.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-enum MutexStatus : uint32_t {
-  MUTEX_UNLOCKED = 0,
-  MUTEX_LOCKED   = 1
-};
-
-class Mutex {
- public:
-  constexpr Mutex() : status_(MUTEX_UNLOCKED) {}
-
-  void lock() {
-    if (!try_lock()) {
-      lock_without_timeout();
-    }
-  }
-  bool lock(Duration timeout) {
-    if (try_lock()) {
-      return true;
-    }
-    return lock_with_timeout(timeout);
-  }
-  bool try_lock() {
-    if (locked()) {
-      return false;
-    }
-    return atomic_compare_and_swap(MUTEX_UNLOCKED, MUTEX_LOCKED, &status_);
-  }
-  bool unlock() {
-    if (!locked()) {
-      return false;
-    }
-    status_ = MUTEX_UNLOCKED;
-    return true;
-  }
-
-  bool locked() const {
-    return status_ != MUTEX_UNLOCKED;
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const;
-
- private:
-  volatile MutexStatus status_;
-
-  void lock_without_timeout();
-  bool lock_with_timeout(Duration timeout);
-};
-
-inline StringBuilder &operator<<(StringBuilder &builder, const Mutex &mutex) {
-  return mutex.write_to(builder);
-}
-
-}  // namespace grnxx
-
-#endif  // GRNXX_MUTEX_HPP

  Deleted: lib/grnxx/os.cpp (+0 -92) 100644
===================================================================
--- lib/grnxx/os.cpp    2013-08-23 10:46:34 +0900 (75db2d2)
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-  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/os.hpp"
-
-#include <cerrno>
-#include <cstdlib>
-#include <cstring>
-#include <memory>
-#include <new>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-
-uint64_t OS::get_page_size() {
-#if defined(GRNXX_WINDOWS) || !defined(_SC_PAGESIZE)
-  static const uint64_t page_size = 4096;
-#else  // defined(GRNXX_WINDOWS) || !defined(_SC_PAGESIZE)
-  static const uint64_t page_size = ::sysconf(_SC_PAGESIZE);
-#endif  // defined(GRNXX_WINDOWS) || !defined(_SC_PAGESIZE)
-  return page_size;
-}
-
-char *OS::get_environment_variable(const char *name) {
-  if (!name) {
-    GRNXX_ERROR() << "invalid argument: name = nullptr";
-    throw LogicError();
-  }
-  static Mutex mutex;
-  Lock lock(&mutex);
-#ifdef GRNXX_MSC
-  char *value;
-  size_t value_size;
-  errno_t error;
-  error = ::_dupenv_s(&value, &value_size, name);
-  if (error != 0) {
-    const Errno error_code(error);
-    GRNXX_ERROR() << "failed to get environment variable: name = " << name
-                  << ": '::_dupenv_s' " << error_code;
-    throw SystemError(error_code);
-  }
-  if (!value) {
-    // No match.
-    return nullptr;
-  }
-  char * const result = new (std::nothrow) char[value_size + 1];
-  if (!result) {
-    GRNXX_ERROR() << "new char[] failed: size = " << (value_size + 1);
-    std::free(value);
-    throw MemoryError();
-  }
-  std::memcpy(result, value, value_size);
-  result[value_size] = '\0';
-  std::free(value);
-  return result;
-#else  // GRNXX_MSC
-  char * const value = std::getenv(name);
-  if (!value) {
-    // No match.
-    return nullptr;
-  }
-  const size_t value_size = std::strlen(value);
-  char * const result = new (std::nothrow) char[value_size + 1];
-  if (!result) {
-    GRNXX_ERROR() << "new char[] failed: size = " << (value_size + 1);
-    throw MemoryError();
-  }
-  std::memcpy(result, value, value_size);
-  result[value_size] = '\0';
-  return result;
-#endif  // GRNXX_MSC
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/os.hpp (+0 -39) 100644
===================================================================
--- lib/grnxx/os.hpp    2013-08-23 10:46:34 +0900 (9d7ecd5)
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_OS_HPP
-#define GRNXX_OS_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class OS {
- public:
-  // Get the page size.
-  static uint64_t get_page_size();
-
-  // Return an environment variable, or nullptr if "name" does not exist.
-  // The returned string must be freed with delete[].
-  static char *get_environment_variable(const char *name);
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_OS_HPP

  Deleted: lib/grnxx/periodic_clock.cpp (+0 -81) 100644
===================================================================
--- lib/grnxx/periodic_clock.cpp    2013-08-23 10:46:34 +0900 (2f10d49)
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-  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/periodic_clock.hpp"
-
-#include <memory>
-
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/thread.hpp"
-
-namespace grnxx {
-namespace {
-
-// Accuracy of the periodic clock. Note that a short sleep may lead to a
-// busy-wait loop, which exhausts CPU resources.
-constexpr Duration UPDATE_INTERVAL = Duration::milliseconds(100);
-
-// The number of PeriodicClock objects.
-volatile uint32_t ref_count = 0;
-// The current thread ID.
-volatile uint32_t thread_id = 0;
-Mutex mutex;
-
-}  // namespace
-
-Time PeriodicClock::now_ = Time::min();
-
-PeriodicClock::PeriodicClock() {
-  Lock lock(&mutex);
-  if (++ref_count == 1) try {
-    // Start an internal thread that updates "now_" periodically.
-    std::unique_ptr<grnxx::Thread> thread(grnxx::Thread::create(routine));
-    thread->detach();
-    // Immediately update "now_".
-    now_ = SystemClock::now();
-  } catch (...) {
-    GRNXX_WARNING() << "failed to create thread for PeriodicClock";
-  }
-}
-
-PeriodicClock::~PeriodicClock() {
-  Lock lock(&mutex);
-  if (--ref_count == 0) {
-    now_ = Time::min();
-    // Increment "thread_id" so that an internal thread will stop.
-    atomic_fetch_and_add(1, &thread_id);
-  }
-}
-
-void PeriodicClock::routine() {
-  // Increment "thread_id" to generate the ID of this thread.
-  const uint64_t this_thread_id = atomic_fetch_and_add(1, &thread_id) + 1;
-  // This thread terminates if there are no PeriodicClock objects or another
-  // thread is running.
-  while ((ref_count != 0) && (this_thread_id == thread_id)) {
-    Thread::sleep_for(UPDATE_INTERVAL);
-    Lock lock(&mutex);
-    if ((ref_count != 0) && (this_thread_id == thread_id)) {
-      now_ = SystemClock::now();
-    }
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/periodic_clock.hpp (+0 -51) 100644
===================================================================
--- lib/grnxx/periodic_clock.hpp    2013-08-23 10:46:34 +0900 (074fdf1)
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_PERIODIC_CLOCK_HPP
-#define GRNXX_PERIODIC_CLOCK_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/system_clock.hpp"
-#include "grnxx/time.hpp"
-
-namespace grnxx {
-
-class PeriodicClock {
- public:
-  // Increment an internal reference count.
-  // Start a thread for updating "now_" when the reference count becomes 1.
-  PeriodicClock();
-  // Decrement an internal reference count.
-  // Stop a thread for updating "now_" when the reference count becomes 0.
-  ~PeriodicClock();
-
-  // Return the current time.
-  static Time now() {
-    return (now_ == Time::min()) ? SystemClock::now() : now_;
-  }
-
- private:
-  static Time now_;
-
-  // Update "now_" periodically.
-  static void routine();
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_PERIODIC_CLOCK_HPP

  Deleted: lib/grnxx/stopwatch.cpp (+0 -66) 100644
===================================================================
--- lib/grnxx/stopwatch.cpp    2013-08-23 10:46:34 +0900 (db8927a)
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-  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/stopwatch.hpp"
-
-#include <chrono>
-
-namespace grnxx {
-namespace {
-
-int64_t now() {
-  return std::chrono::duration_cast<std::chrono::microseconds>(
-      std::chrono::steady_clock::now().time_since_epoch()).count();
-}
-
-}  // namespace
-
-Stopwatch::Stopwatch(bool is_running)
-    : elapsed_(0),
-      start_count_(is_running ? now() : 0),
-      is_running_(is_running) {}
-
-void Stopwatch::start() {
-  if (!is_running_) {
-    start_count_ = now();
-    is_running_ = true;
-  }
-}
-
-void Stopwatch::stop() {
-  if (is_running_) {
-    elapsed_ += Duration(now() - start_count_);
-    is_running_ = false;
-  }
-}
-
-void Stopwatch::reset() {
-  if (is_running_) {
-    start_count_ = now();
-  }
-  elapsed_ = Duration(0);
-}
-
-Duration Stopwatch::elapsed() const {
-  if (is_running_) {
-    return elapsed_ + Duration(now() - start_count_);
-  } else {
-    return elapsed_;
-  }
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/stopwatch.hpp (+0 -57) 100644
===================================================================
--- lib/grnxx/stopwatch.hpp    2013-08-23 10:46:34 +0900 (5933bee)
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STOPWATCH_HPP
-#define GRNXX_STOPWATCH_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/duration.hpp"
-
-namespace grnxx {
-
-// To measure the amount of time elapsed.
-class Stopwatch {
- public:
-  // Initialize a stopwatch, which is started if "is_running" == true.
-  explicit Stopwatch(bool is_running = false);
-
-  // Return true iff the stopwatch is running.
-  bool is_running() const {
-    return is_running_;
-  }
-
-  // Start measurement.
-  void start();
-  // Stop measurement.
-  void stop();
-
-  // Clear the elapsed time.
-  void reset();
-
-  // Get the current elapsed time.
-  Duration elapsed() const;
-
- private:
-  Duration elapsed_;
-  int64_t start_count_;
-  bool is_running_;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_STOPWATCH_HPP

  Deleted: lib/grnxx/storage.cpp (+0 -165) 100644
===================================================================
--- lib/grnxx/storage.cpp    2013-08-23 10:46:34 +0900 (07daccf)
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-  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/storage.hpp"
-
-#include "grnxx/storage/node_header.hpp"
-#include "grnxx/storage/storage_impl.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace {
-
-// 1GB-8EB (default: 1TB).
-constexpr uint64_t MAX_FILE_SIZE_LOWER_LIMIT = 1ULL << 30;
-constexpr uint64_t MAX_FILE_SIZE_UPPER_LIMIT = 1ULL << 63;
-constexpr uint64_t MAX_FILE_SIZE_DEFAULT     = 1ULL << 40;
-// 1-1000 (default: 1000).
-constexpr uint16_t MAX_NUM_FILES_LOWER_LIMIT = 1;
-constexpr uint16_t MAX_NUM_FILES_UPPER_LIMIT = 1000;
-constexpr uint16_t MAX_NUM_FILES_DEFAULT     = MAX_NUM_FILES_UPPER_LIMIT;
-// 0-max_file_size bytes (default: 4KB).
-constexpr uint64_t ROOT_SIZE_DEFAULT         = 1ULL << 12;
-
-}  // namespace
-
-#define GRNXX_FLAGS_WRITE(flag) do { \
-  if (flags & flag) { \
-    if (!is_first) { \
-      builder << " | "; \
-    } \
-    builder << #flag; \
-    is_first = false; \
-  } \
-} while (false)
-
-StringBuilder &operator<<(StringBuilder &builder, StorageFlags flags) {
-  bool is_first = true;
-  GRNXX_FLAGS_WRITE(STORAGE_ANONYMOUS);
-  GRNXX_FLAGS_WRITE(STORAGE_HUGE_TLB);
-  GRNXX_FLAGS_WRITE(STORAGE_READ_ONLY);
-  GRNXX_FLAGS_WRITE(STORAGE_TEMPORARY);
-  if (is_first) {
-    builder << "STORAGE_DEFAULT";
-  }
-  return builder;
-}
-
-#define GRNXX_STATUS_CASE(status) \
-  case status: { \
-    return builder << #status; \
-  }
-
-StringBuilder &operator<<(StringBuilder &builder, StorageNodeStatus status) {
-  switch (status) {
-    GRNXX_STATUS_CASE(STORAGE_NODE_PHANTOM)
-    GRNXX_STATUS_CASE(STORAGE_NODE_ACTIVE)
-    GRNXX_STATUS_CASE(STORAGE_NODE_UNLINKED)
-    GRNXX_STATUS_CASE(STORAGE_NODE_IDLE)
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-StorageOptions::StorageOptions()
-    : max_file_size(MAX_FILE_SIZE_DEFAULT),
-      max_num_files(MAX_NUM_FILES_DEFAULT),
-      root_size(ROOT_SIZE_DEFAULT) {}
-
-StorageOptions::operator bool() const {
-  if ((max_file_size < MAX_FILE_SIZE_LOWER_LIMIT) ||
-      (max_file_size > MAX_FILE_SIZE_UPPER_LIMIT)) {
-    return false;
-  }
-  if ((max_num_files < MAX_NUM_FILES_LOWER_LIMIT) ||
-      (max_num_files > MAX_NUM_FILES_UPPER_LIMIT)) {
-    return false;
-  }
-  if (root_size > max_file_size) {
-    return false;
-  }
-  return true;
-}
-
-StringBuilder &operator<<(StringBuilder &builder,
-                          const StorageOptions &options) {
-  if (!builder) {
-    return builder;
-  }
-  return builder << "{ max_num_files = " << options.max_num_files
-                 << ", max_file_size = " << options.max_file_size
-                 << ", root_size = " << options.root_size << " }";
-}
-
-uint32_t StorageNode::id() const {
-  return header_->id;
-}
-
-StorageNodeStatus StorageNode::status() const {
-  return header_->status;
-}
-
-uint16_t StorageNode::chunk_id() const {
-  return header_->chunk_id;
-}
-
-uint64_t StorageNode::offset() const {
-  return header_->offset;
-}
-
-uint64_t StorageNode::size() const {
-  return header_->size;
-}
-
-Time StorageNode::modified_time() const {
-  return header_->modified_time;
-}
-
-void *StorageNode::user_data() const {
-  return header_->user_data;
-}
-
-Storage::Storage() {}
-Storage::~Storage() {}
-
-Storage *Storage::create(const char *path,
-                         StorageFlags flags,
-                         const StorageOptions &options) {
-  return storage::StorageImpl::create(path, flags, options);
-}
-
-Storage *Storage::open(const char *path,
-                       StorageFlags flags) {
-  return storage::StorageImpl::open(path, flags);
-}
-
-Storage *Storage::open_or_create(const char *path,
-                                 StorageFlags flags,
-                                 const StorageOptions &options) {
-  return storage::StorageImpl::open_or_create(path, flags, options);
-}
-
-bool Storage::exists(const char *path) {
-  return storage::StorageImpl::exists(path);
-}
-
-void Storage::unlink(const char *path) {
-  storage::StorageImpl::unlink(path);
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/storage.hpp (+0 -191) 100644
===================================================================
--- lib/grnxx/storage.hpp    2013-08-23 10:46:34 +0900 (1efdca9)
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_HPP
-#define GRNXX_STORAGE_HPP
-
-#include "grnxx/features.hpp"
-
-#include <limits>
-
-#include "grnxx/duration.hpp"
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace storage {
-
-struct NodeHeader;
-
-}  // namespace storage
-
-class Storage;
-using StorageFlags = FlagsImpl<Storage>;
-
-// Use the default settings.
-constexpr StorageFlags STORAGE_DEFAULT   = StorageFlags::define(0x00);
-// Create an anonymous storage.
-// This flag is implicitly enabled if "path" == nullptr and "flags" does not
-// contain STORAGE_TEMPORARY.
-constexpr StorageFlags STORAGE_ANONYMOUS = StorageFlags::define(0x01);
-// Use huge pages if available, or use regular pages.
-constexpr StorageFlags STORAGE_HUGE_TLB  = StorageFlags::define(0x02);
-// Open a storage in read-only mode.
-// If not specified, a storage is opened in read-write mode.
-constexpr StorageFlags STORAGE_READ_ONLY = StorageFlags::define(0x04);
-// Create a file-backed temporary storage.
-constexpr StorageFlags STORAGE_TEMPORARY = StorageFlags::define(0x08);
-
-StringBuilder &operator<<(StringBuilder &builder, StorageFlags flags);
-
-enum StorageNodeStatus : uint8_t {
-  // A node without body.
-  STORAGE_NODE_PHANTOM  = 0,
-  // An active node.
-  STORAGE_NODE_ACTIVE   = 1,
-  // An unlinked node.
-  STORAGE_NODE_UNLINKED = 2,
-  // An unused node.
-  STORAGE_NODE_IDLE     = 3
-};
-
-StringBuilder &operator<<(StringBuilder &builder, StorageNodeStatus status);
-
-constexpr uint32_t STORAGE_ROOT_NODE_ID    = 0;
-constexpr uint32_t STORAGE_INVALID_NODE_ID =
-    std::numeric_limits<uint32_t>::max();
-
-struct StorageOptions {
-  // The maximum size of each file.
-  uint64_t max_file_size;
-  // The maximum number of files.
-  uint16_t max_num_files;
-  // The size of the root node.
-  uint64_t root_size;
-
-  // Initialize the members with the default parameters.
-  StorageOptions();
-
-  // Return true iff the options are valid.
-  explicit operator bool() const;
-};
-
-StringBuilder &operator<<(StringBuilder &builder,
-                          const StorageOptions &options);
-
-class StorageNode {
- public:
-  StorageNode() : header_(nullptr), body_(nullptr) {}
-  StorageNode(storage::NodeHeader *header, void *body)
-      : header_(header),
-        body_(body) {}
-
-  // Return true iff the node is valid.
-  explicit operator bool() const {
-    return header_ != nullptr;
-  }
-
-  // Return the ID.
-  uint32_t id() const;
-  // Return the status.
-  StorageNodeStatus status() const;
-  // Return the ID of the chunk to which the node belongs.
-  uint16_t chunk_id() const;
-  // Return the offset in chunk.
-  uint64_t offset() const;
-  // Return the body size.
-  uint64_t size() const;
-  // Return the last modified time.
-  Time modified_time() const;
-  // Return the address to the user data (8 bytes) in the header.
-  void *user_data() const;
-  // Return the address to the body.
-  void *body() const {
-    return body_;
-  }
-
- private:
-  // The address to the node header.
-  storage::NodeHeader *header_;
-  // The address to the node body.
-  void *body_;
-};
-
-class Storage {
- public:
-  Storage();
-  virtual ~Storage();
-
-  // Create a storage.
-  // STORAGE_ANONYMOUS is implicitly enabled if "path" == nullptr and "flags"
-  // does not contain STORAGE_TEMPORARY.
-  // Available flags are STORAGE_HUGE_TLB and STORAGE_TEMPORARY.
-  static Storage *create(const char *path,
-                         StorageFlags flags = STORAGE_DEFAULT,
-                         const StorageOptions &options = StorageOptions());
-  // Open a storage.
-  // Available flags are STORAGE_HUGE_TLB and STORAGE_READ_ONLY.
-  static Storage *open(const char *path,
-                       StorageFlags flags = STORAGE_DEFAULT);
-  // Open or create a storage.
-  // The available flags is STORAGE_HUGE_TLB.
-  static Storage *open_or_create(
-      const char *path, StorageFlags flags = STORAGE_DEFAULT,
-      const StorageOptions &options = StorageOptions());
-
-  // Return true iff "path" refers to a valid storage.
-  static bool exists(const char *path);
-  // Remove a storage.
-  static void unlink(const char *path);
-
-  // Create a node of at least "size" bytes under the specified parent node.
-  virtual StorageNode create_node(uint32_t parent_node_id, uint64_t size) = 0;
-  // Open a node.
-  virtual StorageNode open_node(uint32_t node_id) = 0;
-
-  // Unlink a node and return true on success.
-  // The unlinked node and its descendants will be removed by sweep().
-  virtual void unlink_node(uint32_t node_id) = 0;
-
-  // Sweep unlinked nodes whose modified time < (now - lifetime).
-  virtual void sweep(Duration lifetime) = 0;
-
-  // Return the storage path.
-  // Note that an anonymous or temporary storage may return nullptr.
-  virtual const char *path() const = 0;
-  // Return the activated flags.
-  virtual StorageFlags flags() const = 0;
-  // Return the maximum size of each file.
-  virtual uint64_t max_file_size() const = 0;
-  // Return the maximum number of files.
-  virtual uint16_t max_num_files() const = 0;
-  // Return the number of active or unlinked nodes.
-  virtual uint32_t num_nodes() const = 0;
-  // Return the number of chunks for node body.
-  virtual uint16_t num_chunks() const = 0;
-  // Return the total usage of body chunks (including unlinked nodes).
-  virtual uint64_t body_usage() const = 0;
-  // Return the total size of body chunks.
-  virtual uint64_t body_size() const = 0;
-  // Return the total size.
-  virtual uint64_t total_size() const = 0;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_HPP

  Deleted: lib/grnxx/storage/Makefile.am (+0 -30) 100644
===================================================================
--- lib/grnxx/storage/Makefile.am    2013-08-23 10:46:34 +0900 (937f1a9)
+++ /dev/null
@@ -1,30 +0,0 @@
-noinst_LTLIBRARIES = libgrnxx_storage.la
-
-libgrnxx_storage_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_storage_la_SOURCES =		\
-	chunk.cpp			\
-	chunk-posix.cpp			\
-	chunk-windows.cpp		\
-	chunk_index.cpp			\
-	file.cpp			\
-	file-posix.cpp			\
-	file-windows.cpp		\
-	header.cpp			\
-	node_header.cpp			\
-	path.cpp			\
-	storage_impl.cpp
-
-libgrnxx_storage_includedir = ${includedir}/grnxx/storage
-libgrnxx_storage_include_HEADERS =	\
-	chunk.hpp			\
-	chunk-posix.hpp			\
-	chunk-windows.hpp		\
-	chunk_index.hpp			\
-	file.hpp			\
-	file-posix.hpp			\
-	file-windows.hpp		\
-	header.hpp			\
-	node_header.hpp			\
-	path.hpp			\
-	storage_impl.hpp

  Deleted: lib/grnxx/storage/chunk-posix.cpp (+0 -188) 100644
===================================================================
--- lib/grnxx/storage/chunk-posix.cpp    2013-08-23 10:46:34 +0900 (b54c83b)
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-  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/storage/chunk-posix.hpp"
-
-#ifndef GRNXX_WINDOWS
-
-#include <sys/mman.h>
-
-#include <cerrno>
-#include <limits>
-#include <memory>
-#include <new>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage/file.hpp"
-
-#ifndef MAP_ANONYMOUS
-# ifdef MAP_ANON
-#  define MAP_ANONYMOUS MAP_ANON
-# endif  // MAP_ANON
-#endif  // MAP_ANONYMOUS
-
-namespace grnxx {
-namespace storage {
-
-ChunkImpl::ChunkImpl()
-    : flags_(CHUNK_DEFAULT),
-      address_(MAP_FAILED),
-      size_(0) {}
-
-ChunkImpl::~ChunkImpl() {
-  if (address_ != MAP_FAILED) {
-    if (::munmap(address_, static_cast<size_t>(size_)) != 0) {
-      Errno errno_copy(errno);
-      GRNXX_WARNING() << "failed to unmap chunk: "
-                      << "call = ::munmap, errno = " << errno_copy;
-    }
-  }
-}
-
-ChunkImpl *ChunkImpl::create(File *file, uint64_t offset, uint64_t size,
-                             ChunkFlags flags) {
-  std::unique_ptr<ChunkImpl> chunk(new (std::nothrow) ChunkImpl);
-  if (!chunk) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  if (file) {
-    chunk->create_file_backed_chunk(file, offset, size, flags);
-  } else {
-    chunk->create_anonymous_chunk(size, flags);
-  }
-  return chunk.release();
-}
-
-void ChunkImpl::sync(uint64_t offset, uint64_t size) {
-  if ((flags_ & CHUNK_ANONYMOUS) || (flags_ & CHUNK_READ_ONLY)) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  if ((offset > size_) || (size > size_) || (size > (size_ - offset))) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size << ", chunk_size = " << size_;
-    throw LogicError();
-  }
-  if (size == 0) {
-    size = size_ - offset;
-  }
-  if (size > std::numeric_limits<size_t>::max()) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  if (size > 0) {
-    if (::msync(static_cast<char *>(address_) + offset, size, MS_SYNC) != 0) {
-      Errno errno_copy(errno);
-      GRNXX_ERROR() << "failed to sync chunk: offset = " << offset
-                    << ", size = " << size
-                    << ", call = ::msync, errno = " << errno_copy;
-      throw SystemError(errno_copy);
-    }
-  }
-}
-
-ChunkFlags ChunkImpl::flags() const {
-  return flags_;
-}
-
-void *ChunkImpl::address() const {
-  return address_;
-}
-
-uint64_t ChunkImpl::size() const {
-  return size_;
-}
-
-void ChunkImpl::create_file_backed_chunk(File *file, uint64_t offset,
-                                         uint64_t size, ChunkFlags flags) {
-  const uint64_t file_size = file->get_size();
-  if ((offset >= file_size) || (size > file_size) ||
-      (size > (file_size - offset))) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size << ", file_size = " << file_size;
-    throw LogicError();
-  }
-  if (size == 0) {
-    size = file_size - offset;
-  }
-  if ((offset > static_cast<uint64_t>(std::numeric_limits<off_t>::max())) ||
-      (size > std::numeric_limits<size_t>::max())) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size;
-    throw LogicError();
-  }
-  if (file->flags() & FILE_READ_ONLY) {
-    flags_ |= CHUNK_READ_ONLY;
-  }
-  size_ = size;
-  int protection_flags = PROT_READ | PROT_WRITE;
-  if (flags_ & CHUNK_READ_ONLY) {
-    flags_ |= CHUNK_READ_ONLY;
-    protection_flags = PROT_READ;
-  }
-  const int mmap_flags = MAP_SHARED;
-  address_ = ::mmap(nullptr, size, protection_flags, mmap_flags,
-                    *static_cast<const int *>(file->handle()), offset);
-  if (address_ == MAP_FAILED) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to map file-backed chunk: "
-                  << "file_path = " << file->path()
-                  << ", file_size = " << file_size
-                  << ", offset = " << offset << ", size = " << size
-                  << ", flags = " << flags
-                  << ", call = ::mmap, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void ChunkImpl::create_anonymous_chunk(uint64_t size, ChunkFlags flags) {
-  if ((size == 0) || (size > std::numeric_limits<size_t>::max())) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  flags_ = CHUNK_ANONYMOUS;
-  size_ = size;
-  const int protection_flags = PROT_READ | PROT_WRITE;
-  const int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
-#ifdef MAP_HUGETLB
-  if (flags & CHUNK_HUGE_TLB) {
-    address_ = ::mmap(nullptr, size, protection_flags,
-                      mmap_flags | MAP_HUGETLB, -1, 0);
-    if (address_ != MAP_FAILED) {
-      flags_ |= CHUNK_HUGE_TLB;
-    }
-  }
-#endif  // MAP_HUGETLB
-  if (address_ == MAP_FAILED) {
-    address_ = ::mmap(nullptr, size, protection_flags, mmap_flags, -1, 0);
-    if (address_ == MAP_FAILED) {
-      Errno errno_copy(errno);
-      GRNXX_ERROR() << "failed to map anonymous chunk: size = " << size
-                    << ", flags = " << flags
-                    << ", call = ::mmap, errno = " << errno_copy;
-      throw SystemError(errno_copy);
-    }
-  }
-}
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS

  Deleted: lib/grnxx/storage/chunk-posix.hpp (+0 -59) 100644
===================================================================
--- lib/grnxx/storage/chunk-posix.hpp    2013-08-23 10:46:34 +0900 (659bc7a)
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_CHUNK_POSIX_HPP
-#define GRNXX_STORAGE_CHUNK_POSIX_HPP
-
-#include "grnxx/features.hpp"
-
-#ifndef GRNXX_WINDOWS
-
-#include "grnxx/storage/chunk.hpp"
-
-namespace grnxx {
-namespace storage {
-
-class ChunkImpl : public Chunk {
- public:
-  ChunkImpl();
-  ~ChunkImpl();
-
-  static ChunkImpl *create(File *file, uint64_t offset, uint64_t size,
-                           ChunkFlags flags);
-
-  void sync(uint64_t offset, uint64_t size);
-
-  ChunkFlags flags() const;
-  void *address() const;
-  uint64_t size() const;
-
- private:
-  ChunkFlags flags_;
-  void *address_;
-  uint64_t size_;
-
-  void create_file_backed_chunk(File *file, uint64_t offset, uint64_t size,
-                                ChunkFlags flags);
-  void create_anonymous_chunk(uint64_t size, ChunkFlags flags);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS
-
-#endif  // GRNXX_STORAGE_CHUNK_POSIX_HPP

  Deleted: lib/grnxx/storage/chunk-windows.cpp (+0 -181) 100644
===================================================================
--- lib/grnxx/storage/chunk-windows.cpp    2013-08-23 10:46:34 +0900 (8e912f9)
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-  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/storage/chunk-windows.hpp"
-
-#ifdef GRNXX_WINDOWS
-
-#include <limits>
-#include <memory>
-#include <new>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage/file.hpp"
-
-namespace grnxx {
-namespace storage {
-
-ChunkImpl::ChunkImpl()
-    : flags_(CHUNK_DEFAULT),
-      handle_(nullptr),
-      address_(nullptr),
-      size_(0) {}
-
-ChunkImpl::~ChunkImpl() {
-  if (address_) {
-    if (!::UnmapViewOfFile(address_)) {
-      Errno errno_copy(::GetLastError());
-      GRNXX_ERROR() << "failed to unmap chunk: "
-                    << "call = ::UnmapViewOfFile, errno = " << errno_copy;
-    }
-  }
-  if (handle_) {
-    if (!::CloseHandle(handle_)) {
-      Errno errno_copy(::GetLastError());
-      GRNXX_ERROR() << "failed to close file mapping: "
-                    << "call = ::CloseHandle, errno = " << errno_copy;
-    }
-  }
-}
-
-ChunkImpl *ChunkImpl::create(File *file, uint64_t offset, uint64_t size,
-                             ChunkFlags flags) {
-  std::unique_ptr<ChunkImpl> chunk(new (std::nothrow) ChunkImpl);
-  if (!chunk) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  if (file) {
-    chunk->create_file_backed_chunk(file, offset, size, flags);
-  } else {
-    chunk->create_anonymous_chunk(size, flags);
-  }
-  return chunk.release();
-}
-
-void ChunkImpl::sync(uint64_t offset, uint64_t size) {
-  if ((flags_ & CHUNK_ANONYMOUS) || (flags_ & CHUNK_READ_ONLY)) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  if ((offset > size_) || (size > size_) || (size > (size_ - offset))) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size << ", chunk_size = " << size_;
-    throw LogicError();
-  }
-  if (size > std::numeric_limits<SIZE_T>::max()) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  if (!::FlushViewOfFile(static_cast<char *>(address_) + offset, size)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to sync chunk: offset = " << offset
-                  << ", size = " << size
-                  << ", call = FlushViewOfFile;, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void ChunkImpl::create_file_backed_chunk(File *file, uint64_t offset,
-                                         uint64_t size, ChunkFlags flags) {
-  uint64_t file_size = file->get_size();
-  if ((offset >= file_size) || (size > file_size) ||
-      (size > (file_size - offset))) {
-    GRNXX_ERROR() << "invalid argument: offset = " << offset
-                  << ", size = " << size << ", file_size = " << file_size;
-    throw LogicError();
-  }
-  if (size == 0) {
-    size = file_size - offset;
-  }
-  if (size > std::numeric_limits<SIZE_T>::max()) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  if (file->flags() & FILE_READ_ONLY) {
-    flags_ |= CHUNK_READ_ONLY;
-  }
-  size_ = size;
-  int protection_mode = PAGE_READWRITE;
-  DWORD desired_access = FILE_MAP_WRITE;
-  if (flags_ & CHUNK_READ_ONLY) {
-    protection_mode = PAGE_READONLY;
-    desired_access = FILE_MAP_READ;
-  }
-  const DWORD size_high = static_cast<DWORD>((offset + size) >> 32);
-  const DWORD size_low = static_cast<DWORD>(offset + size);
-  handle_ = ::CreateFileMapping(*static_cast<const HANDLE *>(file->handle()),
-                                nullptr, protection_mode, size_high, size_low,
-                                nullptr);
-  if (!handle_) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to create file mapping: "
-                  << "file_path = " << file->path()
-                  << ", file_size = " << file_size << ", offset = " << offset
-                  << ", size = " << size << ", flags = " << flags
-                  << ", call = ::CreateFileMapping, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  const DWORD offset_high = static_cast<DWORD>(offset >> 32);
-  const DWORD offset_low = static_cast<DWORD>(offset);
-  address_ = ::MapViewOfFile(handle_, desired_access, offset_high, offset_low,
-                             static_cast<SIZE_T>(size));
-  if (!address_) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to map chunk: "
-                  << "file_path = " << file->path()
-                  << ", file_size = " << file_size << ", offset = " << offset
-                  << ", size = " << size << ", flags = " << flags
-                  << ", call = ::MapViewOfFile, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void ChunkImpl::create_anonymous_chunk(uint64_t size, ChunkFlags flags) {
-  if (size == 0) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  flags_ = CHUNK_ANONYMOUS;
-  size_ = size;
-  const DWORD size_high = static_cast<DWORD>(size >> 32);
-  const DWORD size_low = static_cast<DWORD>(size);
-  handle_ = ::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
-                                size_high, size_low, nullptr);
-  if (!handle_) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to create anonymous file mapping: "
-                  << "size = " << size << ", flags = " << flags
-                  << ", call = ::CreateFileMapping, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  address_ = ::MapViewOfFile(handle_, FILE_MAP_WRITE, 0, 0, 0);
-  if (!address_) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to map anonymous chunk: "
-                  << "size = " << size << ", flags = " << flags
-                  << ", call = ::MapViewOfFile, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS

  Deleted: lib/grnxx/storage/chunk-windows.hpp (+0 -67) 100644
===================================================================
--- lib/grnxx/storage/chunk-windows.hpp    2013-08-23 10:46:34 +0900 (a6460ba)
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_CHUNK_WINDOWS_HPP
-#define GRNXX_STORAGE_CHUNK_WINDOWS_HPP
-
-#include "grnxx/features.hpp"
-
-#ifdef GRNXX_WINDOWS
-
-#include <windows.h>
-
-#include "grnxx/storage/chunk.hpp"
-
-// FILE_READ_ONLY is defined as a macro in windows.h.
-#ifdef FILE_READ_ONLY
-# undef FILE_READ_ONLY
-#endif  // FILE_READ_ONLY
-
-namespace grnxx {
-namespace storage {
-
-class ChunkImpl : public Chunk {
- public:
-  ChunkImpl();
-  ~ChunkImpl();
-
-  static ChunkImpl *create(File *file, uint64_t offset, uint64_t size,
-                           ChunkFlags flags);
-
-  void sync(uint64_t offset, uint64_t size);
-
-  ChunkFlags flags() const;
-  void *address() const;
-  uint64_t size() const;
-
- private:
-  ChunkFlags flags_;
-  HANDLE handle_;
-  void *address_;
-  uint64_t size_;
-
-  void create_file_backed_chunk(File *file, uint64_t offset, uint64_t size,
-                                ChunkFlags flags);
-  void create_anonymous_chunk(uint64_t size, ChunkFlags flags);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS
-
-#endif  // GRNXX_STORAGE_CHUNK_WINDOWS_HPP

  Deleted: lib/grnxx/storage/chunk.cpp (+0 -57) 100644
===================================================================
--- lib/grnxx/storage/chunk.cpp    2013-08-23 10:46:34 +0900 (40c3331)
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-  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/storage/chunk.hpp"
-
-#include "grnxx/storage/chunk-posix.hpp"
-#include "grnxx/storage/chunk-windows.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace storage {
-
-#define GRNXX_FLAGS_WRITE(flag) do { \
-  if (flags & flag) { \
-    if (!is_first) { \
-      builder << " | "; \
-    } \
-    builder << #flag; \
-    is_first = false; \
-  } \
-} while (false)
-
-StringBuilder &operator<<(StringBuilder &builder, ChunkFlags flags) {
-  bool is_first = true;
-  GRNXX_FLAGS_WRITE(CHUNK_ANONYMOUS);
-  GRNXX_FLAGS_WRITE(CHUNK_HUGE_TLB);
-  GRNXX_FLAGS_WRITE(CHUNK_READ_ONLY);
-  if (is_first) {
-    builder << "CHUNK_DEFAULT";
-  }
-  return builder;
-}
-
-Chunk::Chunk() {}
-Chunk::~Chunk() {}
-
-Chunk *Chunk::create(File *file, uint64_t offset, uint64_t size,
-                     ChunkFlags flags) {
-  return ChunkImpl::create(file, offset, size, flags);
-}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/chunk.hpp (+0 -75) 100644
===================================================================
--- lib/grnxx/storage/chunk.hpp    2013-08-23 10:46:34 +0900 (c852ed0)
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_CHUNK_HPP
-#define GRNXX_STORAGE_CHUNK_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-namespace storage {
-
-class File;
-
-class Chunk;
-using ChunkFlags = FlagsImpl<Chunk>;
-
-// Use the default settings.
-constexpr ChunkFlags CHUNK_DEFAULT   = ChunkFlags::define(0x00);
-// Create an anonymous memory mapping.
-// This flag is implicitly enabled if "file" == nullptr.
-constexpr ChunkFlags CHUNK_ANONYMOUS = ChunkFlags::define(0x01);
-// Use huge pages if available, or use regular pages.
-constexpr ChunkFlags CHUNK_HUGE_TLB  = ChunkFlags::define(0x02);
-// Create a read-only memory mapping.
-// This flag is implicitly enabled if "file" is read-only.
-constexpr ChunkFlags CHUNK_READ_ONLY = ChunkFlags::define(0x04);
-
-StringBuilder &operator<<(StringBuilder &builder, ChunkFlags flags);
-
-class Chunk {
- public:
-  Chunk();
-  virtual ~Chunk();
-
-  // Create a file-backed memory mapping on "file" if "file" != nullptr, or
-  // create an anonymous memory mapping.
-  // The available flag is CHUNK_HUGE_TLB.
-  static Chunk *create(File *file, uint64_t offset = 0, uint64_t size = 0,
-                       ChunkFlags flags = CHUNK_DEFAULT);
-
-  // Flush modified pages.
-  virtual void sync(uint64_t offset = 0, uint64_t size = 0) = 0;
-
-  // Return the enabled flags.
-  virtual ChunkFlags flags() const = 0;
-  // Return the starting address.
-  virtual void *address() const = 0;
-  // Return the size.
-  virtual uint64_t size() const = 0;
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_CHUNK_HPP

  Deleted: lib/grnxx/storage/chunk_index.cpp (+0 -34) 100644
===================================================================
--- lib/grnxx/storage/chunk_index.cpp    2013-08-23 10:46:34 +0900 (e7c4369)
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-  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/storage/chunk_index.hpp"
-
-namespace grnxx {
-namespace storage {
-
-ChunkIndex::ChunkIndex(uint16_t id, ChunkIndexType type)
-    : id(id),
-      type(type),
-      reserved_0(0),
-      file_id(0),
-      reserved_1(0),
-      offset(0),
-      size(0),
-      reserved_2(0) {}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/chunk_index.hpp (+0 -60) 100644
===================================================================
--- lib/grnxx/storage/chunk_index.hpp    2013-08-23 10:46:34 +0900 (744496d)
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_CHUNK_INDEX_HPP
-#define GRNXX_STORAGE_CHUNK_INDEX_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace storage {
-
-constexpr size_t CHUNK_INDEX_SIZE = 32;
-
-enum ChunkIndexType : uint8_t {
-  HEADER_CHUNK       = 0,
-  REGULAR_BODY_CHUNK = 1,
-  SMALL_BODY_CHUNK   = 2
-};
-
-struct ChunkIndex {
-  // The chunk ID.
-  uint16_t id;
-  // The chunk type.
-  ChunkIndexType type;
-  uint8_t reserved_0;
-  // The ID of the file to which the chunk belongs.
-  uint16_t file_id;
-  uint16_t reserved_1;
-  // The offset in file.
-  uint64_t offset;
-  // The chunk size.
-  uint64_t size;
-  uint64_t reserved_2;
-
-  ChunkIndex(uint16_t id, ChunkIndexType type);
-};
-
-static_assert(sizeof(ChunkIndex) == CHUNK_INDEX_SIZE,
-              "sizeof(ChunkIndex) != CHUNK_INDEX_SIZE");
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_CHUNK_INDEX_HPP

  Deleted: lib/grnxx/storage/file-posix.cpp (+0 -310) 100644
===================================================================
--- lib/grnxx/storage/file-posix.cpp    2013-08-23 10:46:34 +0900 (db3fb5e)
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
-  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/storage/file-posix.hpp"
-
-#ifndef GRNXX_WINDOWS
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cerrno>
-#include <limits>
-#include <new>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage/path.hpp"
-
-namespace grnxx {
-namespace storage {
-namespace {
-
-constexpr int UNIQUE_PATH_GENERATION_TRIAL_COUNT = 10;
-
-}  // namespace
-
-FileImpl::FileImpl()
-    : File(),
-      path_(),
-      flags_(FILE_DEFAULT),
-      fd_(-1),
-      locked_(false) {}
-
-FileImpl::~FileImpl() {
-  if (fd_ != -1) {
-    if (locked_) {
-      unlock();
-    }
-    if (::close(fd_) != 0) {
-      Errno errno_copy(errno);
-      GRNXX_WARNING() << "failed to close file: path = " << path_.get()
-                      << ", call = ::close, errno = " << errno_copy;
-    }
-  }
-}
-
-FileImpl *FileImpl::create(const char *path, FileFlags flags) {
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  if (path && (~flags & FILE_TEMPORARY)) {
-    file->create_persistent_file(path, flags);
-  } else {
-    file->create_temporary_file(path, flags);
-  }
-  return file.release();
-}
-
-FileImpl *FileImpl::open(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  file->open_file(path, flags);
-  return file.release();
-}
-
-FileImpl *FileImpl::open_or_create(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  file->open_or_create_file(path, flags);
-  return file.release();
-}
-
-bool FileImpl::exists(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  struct stat stat;
-  if (::stat(path, &stat) != 0) {
-    if (errno != ENOENT) {
-      Errno errno_copy(errno);
-      GRNXX_WARNING() << "failed to get file information: "
-                      << "call = ::stat, errno = " << errno_copy;
-    }
-    return false;
-  }
-  return S_ISREG(stat.st_mode);
-}
-
-void FileImpl::unlink(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  if (::unlink(path) != 0) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to unlink file: path = " << path
-                  << ", call = ::unlink, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-bool FileImpl::lock(FileLockFlags lock_flags) {
-  if (locked_) {
-    GRNXX_ERROR() << "already locked: path = " << path_.get();
-    throw LogicError();
-  }
-  FileLockFlags lock_type =
-      lock_flags & (FILE_LOCK_SHARED | FILE_LOCK_EXCLUSIVE);
-  if (!lock_type || (lock_type == (FILE_LOCK_SHARED | FILE_LOCK_EXCLUSIVE))) {
-    GRNXX_ERROR() << "invalid argument: lock_flags == " << lock_flags;
-    throw LogicError();
-  }
-  int operation = 0;
-  if (lock_flags & FILE_LOCK_SHARED) {
-    operation |= LOCK_SH;
-  }
-  if (lock_flags & FILE_LOCK_EXCLUSIVE) {
-    operation |= LOCK_EX;
-  }
-  if (lock_flags & FILE_LOCK_NONBLOCKING) {
-    operation |= LOCK_NB;
-  }
-  if (::flock(fd_, operation) != 0) {
-    if (errno == EWOULDBLOCK) {
-      return false;
-    }
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to lock file: path = " << path_.get()
-                  << ", lock_flags = " << lock_flags
-                  << ", call = ::flock, errno = " << Errno(errno_copy);
-    throw SystemError(errno_copy);
-  }
-  locked_ = true;
-  return true;
-}
-
-void FileImpl::unlock() {
-  if (!locked_) {
-    GRNXX_WARNING() << "unlocked: path = " << path_.get();
-    throw LogicError();
-  }
-  if (::flock(fd_, LOCK_UN) != 0) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to unlock file: path = " << path_.get()
-                  << ", call = ::flock, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  locked_ = false;
-}
-
-void FileImpl::sync() {
-  if (::fsync(fd_) != 0) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to sync file: path = " << path_.get()
-                  << ", call = ::fsync, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::resize(uint64_t size) {
-  if (flags_ & FILE_READ_ONLY) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  if (size > static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  if (::ftruncate(fd_, size) != 0) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to resize file: path = " << path_.get()
-                  << ", size = " << size
-                  << ", call = ::ftruncate, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-uint64_t FileImpl::get_size() {
-  struct stat stat;
-  if (::fstat(fd_, &stat) != 0) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to stat file: path = " << path_.get()
-                  << ", call = ::fstat, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  return stat.st_size;
-}
-
-const char *FileImpl::path() const {
-  return path_.get();
-}
-
-FileFlags FileImpl::flags() const {
-  return flags_;
-}
-
-const void *FileImpl::handle() const {
-  return &fd_;
-}
-
-void FileImpl::create_persistent_file(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  path_.reset(Path::clone_path(path));
-  fd_ = ::open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
-  if (fd_ == -1) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to create file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::open, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::create_temporary_file(const char *path, FileFlags flags) {
-  flags_ = FILE_TEMPORARY;
-  int posix_flags = O_RDWR | O_CREAT | O_EXCL | O_NOCTTY;
-#ifdef O_NOATIME
-  posix_flags |= O_NOATIME;
-#endif  // O_NOATIME
-#ifdef O_NOFOLLOW
-  posix_flags |= O_NOFOLLOW;
-#endif  // O_NOFOLLOW
-  Errno errno_copy;
-  for (int i = 0; i < UNIQUE_PATH_GENERATION_TRIAL_COUNT; ++i) {
-    path_.reset(Path::unique_path(path));
-    fd_ = ::open(path_.get(), posix_flags, 0600);
-    if (fd_ != -1) {
-      unlink(path_.get());
-      return;
-    }
-    errno_copy = Errno(errno);
-    GRNXX_WARNING() << "failed to create file: path = " << path_.get()
-                    << ", call = ::open, errno = " << errno_copy;
-  }
-  GRNXX_ERROR() << "failed to create temporary file: "
-                << "path = " << path << ", flags = " << flags;
-  throw SystemError(errno_copy);
-}
-
-void FileImpl::open_file(const char *path, FileFlags flags) {
-  path_.reset(Path::clone_path(path));
-  int posix_flags = O_RDWR;
-  if (flags & FILE_READ_ONLY) {
-    posix_flags = O_RDONLY;
-    flags_ |= FILE_READ_ONLY;
-  }
-  fd_ = ::open(path, posix_flags);
-  if (fd_ == -1) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to open file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::open, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::open_or_create_file(const char *path, FileFlags flags) {
-  path_.reset(Path::clone_path(path));
-  fd_ = ::open(path, O_RDWR | O_CREAT, 0644);
-  if (fd_ == -1) {
-    Errno errno_copy(errno);
-    GRNXX_ERROR() << "failed to open file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::open, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS

  Deleted: lib/grnxx/storage/file-posix.hpp (+0 -73) 100644
===================================================================
--- lib/grnxx/storage/file-posix.hpp    2013-08-23 10:46:34 +0900 (72740e1)
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_FILE_POSIX_HPP
-#define GRNXX_STORAGE_FILE_POSIX_HPP
-
-#include "grnxx/features.hpp"
-
-#ifndef GRNXX_WINDOWS
-
-#include <memory>
-
-#include "grnxx/storage/file.hpp"
-
-namespace grnxx {
-namespace storage {
-
-class FileImpl : public File {
- public:
-  FileImpl();
-  ~FileImpl();
-
-  static FileImpl *create(const char *path, FileFlags flags);
-  static FileImpl *open(const char *path, FileFlags flags);
-  static FileImpl *open_or_create(const char *path, FileFlags flags);
-
-  static bool exists(const char *path);
-  static void unlink(const char *path);
-
-  bool lock(FileLockFlags lock_flags);
-  void unlock();
-
-  void sync();
-
-  void resize(uint64_t size);
-  uint64_t get_size();
-
-  const char *path() const;
-  FileFlags flags() const;
-  const void *handle() const;
-
- private:
-  std::unique_ptr<char[]> path_;
-  FileFlags flags_;
-  int fd_;
-  bool locked_;
-
-  void create_persistent_file(const char *path, FileFlags flags);
-  void create_temporary_file(const char *path_prefix, FileFlags flags);
-  void open_file(const char *path, FileFlags flags);
-  void open_or_create_file(const char *path, FileFlags flags);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS
-
-#endif  // GRNXX_STORAGE_FILE_POSIX_HPP

  Deleted: lib/grnxx/storage/file-windows.cpp (+0 -343) 100644
===================================================================
--- lib/grnxx/storage/file-windows.cpp    2013-08-23 10:46:34 +0900 (1ba3f77)
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
-  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/storage/file-windows.hpp"
-
-#ifdef GRNXX_WINDOWS
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <io.h>
-
-#include <cerrno>
-#include <limits>
-#include <new>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage/path.hpp"
-
-namespace grnxx {
-namespace storage {
-namespace {
-
-constexpr int UNIQUE_PATH_GENERATION_TRIAL_COUNT = 10;
-
-}  // namespace
-
-FileImpl::FileImpl()
-    : File(),
-      path_(),
-      flags_(FILE_DEFAULT),
-      handle_(INVALID_HANDLE_VALUE),
-      locked_(false) {}
-
-FileImpl::~FileImpl() {
-  if (handle_ != INVALID_HANDLE_VALUE) {
-    if (locked_) {
-      unlock();
-    }
-    if (!::CloseHandle(handle_)) {
-      Errno errno_copy(::GetLastError());
-      GRNXX_WARNING() << "failed to close file: file = " << *this
-                      << ", call = ::CloseHandle, errno = " << errno_copy;
-    }
-  }
-}
-
-
-FileImpl *FileImpl::create(const char *path, FileFlags flags) {
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  if (path && (~flags & FILE_TEMPORARY)) {
-    file->create_persistent_file(path, flags);
-  } else {
-    file->create_temporary_file(path, flags);
-  }
-  return file.release();
-}
-
-FileImpl *FileImpl::open(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  file->open_file(path, flags);
-  return file.release();
-}
-
-FileImpl *FileImpl::open_or_create(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<FileImpl> file(new (std::nothrow) FileImpl);
-  if (!file) {
-    GRNXX_ERROR() << "new grnxx::storage::FileImpl failed";
-    throw MemoryError();
-  }
-  file->open_or_create_file(path, flags);
-  return file.release();
-}
-
-bool FileImpl::exists(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  struct _stat stat;
-  if (::_stat(path, &stat) != 0) {
-    if (errno != ENOENT) {
-      Errno errno_copy(errno);
-      GRNXX_WARNING() << "failed to get file information: "
-                      << "call = ::_stat, errno = " << errno_copy;
-    }
-    return false;
-  }
-  return stat.st_mode & _S_IFREG;
-}
-
-void FileImpl::unlink(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  if (!::DeleteFile(path)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to unlink file: path = " << path
-                  << ", call = ::DeleteFile, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-bool FileImpl::lock(FileLockMode mode) {
-  if (locked_) {
-    GRNXX_ERROR() << "already locked: path = " << path_.get();
-    throw LogicError();
-  }
-  FileLockFlags lock_type =
-      lock_flags & (FILE_LOCK_SHARED | FILE_LOCK_EXCLUSIVE);
-  if (!lock_type || (lock_type == (FILE_LOCK_SHARED | FILE_LOCK_EXCLUSIVE))) {
-    GRNXX_ERROR() << "invalid argument: lock_flags == " << lock_flags;
-    throw LogicError();
-  }
-  DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
-  if (lock_flags & FILE_LOCK_SHARED) {
-    // Nothing to do.
-  }
-  if (lock_flags & FILE_LOCK_EXCLUSIVE) {
-    flags |= LOCKFILE_EXCLUSIVE_LOCK;
-  }
-  if (lock_flags & FILE_LOCK_NONBLOCKING) {
-    flags |= LOCKFILE_FAIL_IMMEDIATELY;
-  }
-
-  OVERLAPPED overlapped;
-  overlapped.Offset = 0;
-  overlapped.OffsetHigh = 0x80000000U;
-  if (!::LockFileEx(handle_, flags, 0, 0, 0x80000000U, &overlapped)) {
-    const DWORD last_error = ::GetLastError();
-    if (last_error == ERROR_LOCK_FAILED) {
-      // The file is locked by others.
-      return false;
-    }
-    Errno errno_copy(last_error);
-    GRNXX_ERROR() << "failed to lock file: path = " << path_.get()
-                  << ", mode = " << mode
-                  << ", call = ::LockFileEx, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  locked_ = true;
-  return true;
-}
-
-void FileImpl::unlock() {
-  if (!locked_) {
-    GRNXX_WARNING() << "unlocked: path = " << path_.get();
-    throw LogicError();
-  }
-  OVERLAPPED overlapped;
-  overlapped.Offset = 0;
-  overlapped.OffsetHigh = 0x80000000U;
-  if (!::UnlockFileEx(handle_, 0, 0, 0x80000000U, &overlapped)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to unlock file: path = " << path_.get()
-                  << ", call = ::UnlockFileEx, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  locked_ = false;
-}
-
-void FileImpl::sync() {
-  if (!::FlushFileBuffers(handle_)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to sync file: path = " << path_.get()
-                  << ", call = ::FlushFileBuffers, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::resize(uint64_t size) {
-  if (flags_ & FILE_READ_ONLY) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  if (size > static_cast<uint64_t>(std::numeric_limits<LONGLONG>::max())) {
-    GRNXX_ERROR() << "invalid argument: size = " << size;
-    throw LogicError();
-  }
-  LARGE_INTEGER request;
-  request.QuadPart = size;
-  if (!::SetFilePointerEx(handle_, request, nullptr, FILE_BEGIN)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to seek file: path = " << path_.get()
-                  << ", offset = " << offset << ", whence = " << whence
-                  << ", call = ::SetFilePointerEx, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-  if (!::SetEndOfFile(handle_)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to resize file: path = " << path_.get()
-                  << ", size = " << size
-                  << ", call = ::SetEndOfFile, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-uint64_t FileImpl::get_size() {
-  LARGE_INTEGER file_size;
-  if (!::GetFileSizeEx(handle_, &file_size)) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to get file size: path = " << path_.get()
-                  << ": '::GetFileSizeEx' " << Errno(::GetLastError());
-    throw SystemError(errno_copy);
-  }
-  return file_size.QuadPart;
-}
-
-const char *FileImpl::path() const {
-  return path_.get();
-}
-
-FileFlags FileImpl::flags() const {
-  return flags_;
-}
-
-const void *FileImpl::handle() const {
-  return &handle_;
-}
-
-void FileImpl::create_persistent_file(const char *path, FileFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  path_.reset(Path::clone_path(path));
-  const DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
-  const DWORD share_mode =
-      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-  const DWORD creation_disposition = CREATE_NEW;
-  const DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
-  handle_ = ::CreateFileA(path, desired_access, share_mode, nullptr,
-                          creation_disposition, flags_and_attributes, nullptr);
-  if (handle_ == INVALID_HANDLE_VALUE) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to open file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::CreateFileA, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::create_temporary_file(const char *path, FileFlags flags) {
-  flags_ = FILE_TEMPORARY;
-  const DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
-  const DWORD share_mode = FILE_SHARE_DELETE;
-  const DWORD creation_disposition = CREATE_NEW;
-  const DWORD flags_and_attributes = FILE_ATTRIBUTE_TEMPORARY |
-                                     FILE_FLAG_DELETE_ON_CLOSE;
-  Errno errno_copy;
-  for (int i = 0; i < UNIQUE_PATH_GENERATION_TRIAL_COUNT; ++i) {
-    path_.reset(Path::unique_path(path));
-    handle_ = ::CreateFileA(path_.get(), desired_access,
-                            share_mode, nullptr, creation_disposition,
-                            flags_and_attributes, nullptr);
-    if (handle_ != INVALID_HANDLE_VALUE) {
-      return;
-    }
-    errno_copy = Errno(::GetLastError());
-    GRNXX_WARNING() << "failed to create file: path = " << path_.get()
-                    << ", call = ::CreateFileA, errno = " << errno_copy;
-  }
-  GRNXX_ERROR() << "failed to create temporary file: "
-                << "path = " << path << ", flags = " << flags;
-  throw SystemError(errno_copy);
-}
-
-void FileImpl::open_file(const char *path, FileFlags flags) {
-  path_.reset(Path::clone_path(path));
-  DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
-  if (flags_ & FILE_READ_ONLY) {
-    flags_ |= FILE_READ_ONLY;
-    desired_access = GENERIC_READ;
-  }
-  const DWORD share_mode =
-      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-  const DWORD creation_disposition = OPEN_EXISTING;
-  const DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
-  handle_ = ::CreateFileA(path, desired_access, share_mode, nullptr,
-                          creation_disposition, flags_and_attributes, nullptr);
-  if (handle_ == INVALID_HANDLE_VALUE) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to open file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::CreateFileA, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-void FileImpl::open_or_create_file(const char *path, FileFlags flags) {
-  path_.reset(Path::clone_path(path));
-  const DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
-  const DWORD share_mode =
-      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-  const DWORD creation_disposition = OPEN_ALWAYS;
-  const DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
-  handle_ = ::CreateFileA(path, desired_access, share_mode, nullptr,
-                          creation_disposition, flags_and_attributes, nullptr);
-  if (handle_ == INVALID_HANDLE_VALUE) {
-    Errno errno_copy(::GetLastError());
-    GRNXX_ERROR() << "failed to open file: path = " << path
-                  << ", flags = " << flags
-                  << ", call = ::CreateFileA, errno = " << errno_copy;
-    throw SystemError(errno_copy);
-  }
-}
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS

  Deleted: lib/grnxx/storage/file-windows.hpp (+0 -81) 100644
===================================================================
--- lib/grnxx/storage/file-windows.hpp    2013-08-23 10:46:34 +0900 (9dc527e)
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_FILE_WINDOWS_HPP
-#define GRNXX_STORAGE_FILE_WINDOWS_HPP
-
-#include "grnxx/features.hpp"
-
-#ifdef GRNXX_WINDOWS
-
-#include <windows.h>
-
-#include <memory>
-
-#include "grnxx/storage/file.hpp"
-
-// FILE_READ_ONLY is defined as a macro in windows.h.
-#ifdef FILE_READ_ONLY
-# undef FILE_READ_ONLY
-#endif  // FILE_READ_ONLY
-
-namespace grnxx {
-namespace storage {
-
-class FileImpl : public File {
- public:
-  FileImpl();
-  ~FileImpl();
-
-  static FileImpl *create(const char *path, FileFlags flags);
-  static FileImpl *open(const char *path, FileFlags flags);
-  static FileImpl *open_or_create(const char *path, FileFlags flags);
-
-  static bool exists(const char *path);
-  static void unlink(const char *path);
-
-  bool lock(FileLockFlags lock_flags);
-  void unlock();
-
-  void sync();
-
-  void resize(uint64_t size);
-  uint64_t get_size();
-
-  const char *path() const;
-  FileFlags flags() const;
-  const void *handle() const;
-
- private:
-  std::unique_ptr<char[]> path_;
-  FileFlags flags_;
-  HANDLE handle_;
-  int fd_;
-  bool locked_;
-
-  void create_persistent_file(const char *path, FileFlags flags);
-  void create_temporary_file(const char *path_prefix, FileFlags flags);
-  void open_file(const char *path, FileFlags flags);
-  void open_or_create_file(const char *path, FileFlags flags);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_WINDOWS
-
-#endif  // GRNXX_STORAGE_FILE_WINDOWS_HPP

  Deleted: lib/grnxx/storage/file.cpp (+0 -82) 100644
===================================================================
--- lib/grnxx/storage/file.cpp    2013-08-23 10:46:34 +0900 (8bb3370)
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-  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/storage/file.hpp"
-
-#include "grnxx/storage/file-posix.hpp"
-#include "grnxx/storage/file-windows.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace storage {
-
-#define GRNXX_FLAGS_WRITE(flag) do { \
-  if (flags & flag) { \
-    if (!is_first) { \
-      builder << " | "; \
-    } \
-    builder << #flag; \
-    is_first = false; \
-  } \
-} while (false)
-
-StringBuilder &operator<<(StringBuilder &builder, FileFlags flags) {
-  bool is_first = true;
-  GRNXX_FLAGS_WRITE(FILE_READ_ONLY);
-  GRNXX_FLAGS_WRITE(FILE_TEMPORARY);
-  if (is_first) {
-    builder << "FILE_DEFAULT";
-  }
-  return builder;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, FileLockFlags flags) {
-  bool is_first = true;
-  GRNXX_FLAGS_WRITE(FILE_LOCK_SHARED);
-  GRNXX_FLAGS_WRITE(FILE_LOCK_EXCLUSIVE);
-  GRNXX_FLAGS_WRITE(FILE_LOCK_NONBLOCKING);
-  if (is_first) {
-    builder << "0";
-  }
-  return builder;
-}
-
-File::File() {}
-File::~File() {}
-
-File *File::create(const char *path, FileFlags flags) {
-  return FileImpl::create(path, flags);
-}
-
-File *File::open(const char *path, FileFlags flags) {
-  return FileImpl::open(path, flags);
-}
-
-File *File::open_or_create(const char *path, FileFlags flags) {
-  return FileImpl::open_or_create(path, flags);
-}
-
-bool File::exists(const char *path) {
-  return FileImpl::exists(path);
-}
-
-void File::unlink(const char *path) {
-  FileImpl::unlink(path);
-}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/file.hpp (+0 -107) 100644
===================================================================
--- lib/grnxx/storage/file.hpp    2013-08-23 10:46:34 +0900 (5cabce4)
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_FILE_HPP
-#define GRNXX_STORAGE_FILE_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-namespace storage {
-
-class File;
-using FileFlags = FlagsImpl<File>;
-
-// Use the default settings.
-constexpr FileFlags FILE_DEFAULT   = FileFlags::define(0x00);
-// Open a file in read-only mode.
-constexpr FileFlags FILE_READ_ONLY = FileFlags::define(0x01);
-// Create a temporary file.
-// This flag is implicitly enabled if "path" == nullptr.
-constexpr FileFlags FILE_TEMPORARY = FileFlags::define(0x02);
-
-StringBuilder &operator<<(StringBuilder &builder, FileFlags flags);
-
-class FileLock;
-using FileLockFlags = FlagsImpl<FileLock>;
-
-// Apply an exclusive advisory lock.
-constexpr FileLockFlags FILE_LOCK_SHARED      = FileLockFlags::define(0x01);
-// Apply a shared advisory lock.
-constexpr FileLockFlags FILE_LOCK_EXCLUSIVE   = FileLockFlags::define(0x02);
-// Immediately return the result when the file is locked.
-constexpr FileLockFlags FILE_LOCK_NONBLOCKING = FileLockFlags::define(0x04);
-
-StringBuilder &operator<<(StringBuilder &builder, FileLockFlags flags);
-
-class File {
- public:
-  File();
-  virtual ~File();
-
-  // Create a file.
-  // FILE_TEMPORARY is implicitly enabled if "path" == nullptr.
-  // The available flag is FILE_TEMPORARY.
-  static File *create(const char *path,
-                      FileFlags flags = FILE_DEFAULT);
-  // Open a file.
-  // The available flag is FILE_READ_ONLY.
-  static File *open(const char *path,
-                    FileFlags flags = FILE_DEFAULT);
-  // Open or create a file.
-  // There are no available flags.
-  static File *open_or_create(const char *path,
-                              FileFlags flags = FILE_DEFAULT);
-
-  // Return true iff "path" refers to a regular file.
-  static bool exists(const char *path);
-  // Unlink a file.
-  static void unlink(const char *path);
-
-  // Try to lock a file and return true on success.
-  // Note that the file is accessible even if it is locked (advisory).
-  virtual bool lock(FileLockFlags lock_flags) = 0;
-  // Unlock a file.
-  virtual void unlock() = 0;
-
-  // Flush modified pages.
-  virtual void sync() = 0;
-
-  // Extend or truncate a file to "size" bytes.
-  // Note that the contents of the extended part are undefined.
-  virtual void resize(uint64_t size) = 0;
-  // Return the file size.
-  virtual uint64_t get_size() = 0;
-
-  // Return the file path.
-  virtual const char *path() const = 0;
-  // Return the activated flags.
-  virtual FileFlags flags() const = 0;
-  // Return a pointer to the file handle 
-  virtual const void *handle() const = 0;
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_FILE_HPP

  Deleted: lib/grnxx/storage/header.cpp (+0 -67) 100644
===================================================================
--- lib/grnxx/storage/header.cpp    2013-08-23 10:46:34 +0900 (44011f0)
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-  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/storage/header.hpp"
-
-#include <cstring>
-
-#include "grnxx/grnxx.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace storage {
-namespace {
-
-constexpr char FORMAT_STRING[] = "grnxx::Storage";
-
-}  // namespace
-
-Header::Header()
-    : common_header(),
-      max_file_size(0),
-      max_num_files(0),
-      num_body_chunks(0),
-      num_small_body_chunks(0),
-      reserved_0(0),
-      num_nodes(0),
-      num_active_or_unlinked_nodes(0),
-      max_num_nodes(0),
-      reserved_1(0),
-      body_usage(0),
-      body_size(0),
-      total_size(0),
-      latest_phantom_node_id(STORAGE_INVALID_NODE_ID),
-      latest_unlinked_node_id(STORAGE_INVALID_NODE_ID),
-      oldest_idle_node_ids(),
-      data_mutex(),
-      file_mutex(),
-      reserved_2{} {
-  for (size_t i = 0; i < NUM_IDLE_NODE_LISTS; ++i) {
-    oldest_idle_node_ids[i] = STORAGE_INVALID_NODE_ID;
-  }
-}
-
-Header::operator bool() const {
-  return common_header.format() == FORMAT_STRING;
-}
-
-void Header::validate() {
-  common_header = CommonHeader(FORMAT_STRING);
-}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/header.hpp (+0 -92) 100644
===================================================================
--- lib/grnxx/storage/header.hpp    2013-08-23 10:46:34 +0900 (087a1aa)
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_HEADER_HPP
-#define GRNXX_STORAGE_HEADER_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/common_header.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace storage {
-
-// The number of bytes allocated to a header.
-// sizeof(Header) must not be greater than this value.
-constexpr size_t HEADER_SIZE         = 512;
-
-constexpr size_t NUM_IDLE_NODE_LISTS = 64;
-
-struct Header {
-  // The file format and the grnxx version.
-  CommonHeader common_header;
-  // The maximum size of each file.
-  uint64_t max_file_size;
-  // The maximum number of files.
-  uint16_t max_num_files;
-  // The number of body chunks.
-  uint16_t num_body_chunks;
-  // The number of small body chunks.
-  uint16_t num_small_body_chunks;
-  uint16_t reserved_0;
-  // The number of nodes.
-  uint32_t num_nodes;
-  // The number of active or unlinked nodes.
-  uint32_t num_active_or_unlinked_nodes;
-  // The upper limit of the number of nodes.
-  // This value is extended when a node header chunk is added.
-  uint32_t max_num_nodes;
-  uint32_t reserved_1;
-  // The total usage of body chunks.
-  uint64_t body_usage;
-  // The total size of body chunks.
-  uint64_t body_size;
-  // The total size including headers.
-  uint64_t total_size;
-  // The ID of the latest phantom node.
-  // STORAGE_INVALID_NODE_ID indicates that there are no phantom nodes.
-  uint32_t latest_phantom_node_id;
-  // The ID of the latest unlinked node.
-  // STORAGE_INVALID_NODE_ID indicates that there are no unlinked nodes.
-  uint32_t latest_unlinked_node_id;
-  // The IDs of the oldest idle nodes.
-  // STORAGE_INVALID_NODE_ID indicates that the idle node list is empty.
-  uint32_t oldest_idle_node_ids[NUM_IDLE_NODE_LISTS];
-  // A mutex object for exclusively updating data.
-  Mutex data_mutex;
-  // A mutex object for exclusively update files.
-  Mutex file_mutex;
-  uint8_t reserved_2[88];
-
-  // Initialize the members except "common_header".
-  Header();
-
-  // Return true iff the header seems to be correct.
-  explicit operator bool() const;
-
-  // Initialize "common_header".
-  void validate();
-};
-
-static_assert(sizeof(Header) == HEADER_SIZE, "sizeof(Header) != HEADER_SIZE");
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_HEADER_HPP

  Deleted: lib/grnxx/storage/node_header.cpp (+0 -40) 100644
===================================================================
--- lib/grnxx/storage/node_header.cpp    2013-08-23 10:46:34 +0900 (468d40c)
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-  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/storage/node_header.hpp"
-
-namespace grnxx {
-namespace storage {
-
-NodeHeader::NodeHeader(uint32_t id)
-    : id(id),
-      status(STORAGE_NODE_PHANTOM),
-      reserved_0(0),
-      chunk_id(0),
-      offset(0),
-      size(0),
-      next_node_id(STORAGE_INVALID_NODE_ID),
-      prev_node_id(STORAGE_INVALID_NODE_ID),
-      from_node_id(STORAGE_INVALID_NODE_ID),
-      reserved_1(0),
-      next_phantom_node_id(STORAGE_INVALID_NODE_ID),
-      sibling_node_id(STORAGE_INVALID_NODE_ID),
-      modified_time(0),
-      user_data{} {}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/node_header.hpp (+0 -105) 100644
===================================================================
--- lib/grnxx/storage/node_header.hpp    2013-08-23 10:46:34 +0900 (90d3e0f)
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_NODE_HEADER_HPP
-#define GRNXX_STORAGE_NODE_HEADER_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/storage.hpp"
-#include "grnxx/time.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace storage {
-
-constexpr size_t NODE_HEADER_SIZE = 64;
-
-struct NodeHeader {
-  // The node ID.
-  uint32_t id;
-  // The node status.
-  StorageNodeStatus status;
-  uint8_t reserved_0;
-  // (Non-phantom)
-  // The ID of the chunk to which the node belongs.
-  uint16_t chunk_id;
-  // (Non-phantom)
-  // The offset in chunk.
-  uint64_t offset;
-  // (Non-phantom)
-  // The body size.
-  uint64_t size;
-  // (Non-phantom)
-  // The ID of the next node in chunk.
-  // STORAGE_INVALID_NODE_ID indicates that the node is the last node in chunk.
-  uint32_t next_node_id;
-  // (Non-phantom)
-  // The ID of the previous node in chunk.
-  // STORAGE_INVALID_NODE_ID indicates that the node is the first node in chunk.
-  uint32_t prev_node_id;
-  // (Active)
-  // The ID of the from node.
-  // STORAGE_INVALID_NODE_ID indicates that the node is the root node.
-  uint32_t from_node_id;
-  uint32_t reserved_1;
-  union {
-    // (Phantom)
-    // The ID of the next phantom node.
-    uint32_t next_phantom_node_id;
-    // (Active or unlinked)
-    // The ID of the latest child node.
-    // STORAGE_INVALID_NODE_ID indicates that the node has no children.
-    uint32_t child_node_id;
-    // (Idle)
-    // The ID of the next idle node.
-    // id == next_idle_node_id indicates that the node is the only member of
-    // an idle node list.
-    uint32_t next_idle_node_id;
-  };
-  union {
-    // (Active)
-    // The ID of the next sibling node.
-    // STORAGE_INVALID_NODE_ID indicates that the node has no elder siblings.
-    uint32_t sibling_node_id;
-    // (Unlinked)
-    // The ID of the next unlinked node.
-    // STORAGE_INVALID_NODE_ID indicates that the node is the last unlinked
-    // node.
-    uint32_t next_unlinked_node_id;
-    // (Idle)
-    // The ID of the previous idle node.
-    // id == prev_idle_node_id indicates that the node is the only member of
-    // an idle node list.
-    uint32_t prev_idle_node_id;
-  };
-  // The last modified time.
-  Time modified_time;
-  // User data.
-  uint8_t user_data[8];
-
-  // Initialize the members.
-  explicit NodeHeader(uint32_t id);
-};
-
-static_assert(sizeof(NodeHeader) == NODE_HEADER_SIZE,
-              "sizeof(NodeHeader) != NODE_HEADER_SIZE");
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_NODE_HEADER_HPP

  Deleted: lib/grnxx/storage/path.cpp (+0 -165) 100644
===================================================================
--- lib/grnxx/storage/path.cpp    2013-08-23 10:46:34 +0900 (73d9cd4)
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-  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/storage/path.hpp"
-
-#ifdef GRNXX_WINDOWS
-# include <stdlib.h>
-#else  // GRNXX_WINDOWS
-# include <unistd.h>
-#endif  // GRNXX_WINDOWS
-
-#include <cerrno>
-#include <cstring>
-#include <new>
-#include <random>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace storage {
-namespace {
-
-constexpr size_t MAX_PATH_LENGTH = 1023;
-
-}  // namespace
-
-char *Path::full_path(const char *path) {
-  if (!path) {
-    path = "";
-  }
-  char full_path[MAX_PATH_LENGTH + 1];
-  size_t full_path_length = 0;
-#ifdef GRNXX_WINDOWS
-  if (!::_fullpath(full_path, path, sizeof(full_path))) {
-    const Errno error_code(errno);
-    GRNXX_ERROR() << "failed to generate full path: path = " << path
-                  << ", call = ::_fullpath, errno = " << error_code;
-    throw SystemError(error_code);
-  }
-  full_path_length = std::strlen(full_path);
-#else  // GRNXX_WINDOWS
-  if (path[0] != '/') {
-    if (!::getcwd(full_path, sizeof(full_path))) {
-      const Errno error_code(errno);
-      GRNXX_ERROR() << "failed to get current working directory: "
-                    << "call = ::getcwd, errno = " << error_code;
-      throw SystemError(error_code);
-    }
-    full_path_length = std::strlen(full_path);
-    full_path[full_path_length++] = '/';
-  }
-
-  const size_t path_length = std::strlen(path);
-  if ((full_path_length + path_length) >= sizeof(full_path)) {
-    GRNXX_ERROR() << "failed to generate full path: path = " << path
-                  << ": too long";
-    throw LogicError();
-  }
-  std::memcpy(full_path + full_path_length, path, path_length);
-  full_path_length += path_length;
-  full_path[full_path_length] = '\0';
-
-  size_t src = 0;
-  size_t dest = 0;
-  while (full_path[src] != '\0') {
-    if (full_path[src] == '/') {
-      if (full_path[src + 1] == '\0') {
-        full_path[dest++] = full_path[src++];
-        break;
-      } else if (full_path[src + 1] == '/') {
-        ++src;
-        continue;
-      } else if (full_path[src + 1] == '.') {
-        if ((full_path[src + 2] == '/') || (full_path[src + 2] == '\0')) {
-          src += 2;
-          continue;
-        } else if (full_path[src + 2] == '.') {
-          if ((full_path[src + 3] == '/') || (full_path[src + 3] == '\0')) {
-            if (dest > 0) {
-              do {
-                --dest;
-              } while (full_path[dest] != '/');
-            }
-            src += 3;
-            continue;
-          }
-        }
-      }
-    }
-    full_path[dest++] = full_path[src++];
-  }
-  if (dest == 0) {
-    full_path[0] = '/';
-    full_path_length = 1;
-  } else {
-    full_path_length = dest;
-  }
-#endif  // GRNXX_WINDOWS
-  char * const buf = new (std::nothrow) char[full_path_length + 1];
-  if (!buf) {
-    GRNXX_ERROR() << "new char[" << (full_path_length + 1) << "] failed";
-    throw MemoryError();
-  }
-  std::memcpy(buf, full_path, full_path_length);
-  buf[full_path_length] = '\0';
-  return buf;
-}
-
-char *Path::unique_path(const char *prefix) {
-  if (!prefix) {
-    prefix = "";
-  }
-  constexpr size_t SUFFIX_LENGTH = 8;
-  const size_t prefix_length = std::strlen(prefix);
-  const size_t path_size = prefix_length + SUFFIX_LENGTH + 2;
-  char * const path(new (std::nothrow) char[path_size]);
-  if (!path) {
-    GRNXX_ERROR() << "new char[] failed: path_size = " << path_size;
-    throw MemoryError();
-  }
-  std::memcpy(path, prefix, prefix_length);
-  path[prefix_length] = '_';
-  std::random_device random;
-  for (size_t i = 0; i < SUFFIX_LENGTH; ++i) {
-    const int value = static_cast<int>(random() % 36);
-    path[prefix_length + 1 + i] =
-        (value < 10) ? ('0' + value) : ('A' + value - 10);
-  }
-  path[prefix_length + 1 + SUFFIX_LENGTH] = '\0';
-  return path;
-}
-
-char *Path::clone_path(const char *path) {
-  if (!path) {
-    path = "";
-  }
-  const size_t size = std::strlen(path) + 1;
-  char * const path_clone = new (std::nothrow) char[size];
-  if (!path_clone) {
-    GRNXX_ERROR() << "new char[] failed: size = " << size;
-    throw MemoryError();
-  }
-  std::memcpy(path_clone, path, size);
-  return path_clone;
-}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/path.hpp (+0 -46) 100644
===================================================================
--- lib/grnxx/storage/path.hpp    2013-08-23 10:46:34 +0900 (92d6435)
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_PATH_HPP
-#define GRNXX_STORAGE_PATH_HPP
-
-#include "grnxx/features.hpp"
-
-namespace grnxx {
-namespace storage {
-
-class Path {
- public:
-  // Generate a full path from "path" and return an allocated buffer which
-  // must be freed with delete[].
-  static char *full_path(const char *path);
-
-  // Generate an almost unique path by adding a random suffix and return an
-  // allocated buffer which must be freed with delete[].
-  // For example, when "prefix" == "temp", the result is "temp_XXXXXXXX",
-  // where X indicates a random character ('0'-'9' or 'A'-'Z').
-  static char *unique_path(const char *prefix);
-
-  // Create a clone of "path" and return an allocated buffer which must be
-  // freed with delete[].
-  static char *clone_path(const char *path);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_PATH_HPP

  Deleted: lib/grnxx/storage/storage_impl.cpp (+0 -997) 100644
===================================================================
--- lib/grnxx/storage/storage_impl.cpp    2013-08-23 10:46:34 +0900 (a1ac2f9)
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
-  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/storage/storage_impl.hpp"
-
-#include <cstdio>
-#include <cstring>
-#include <new>
-#include <utility>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/storage/chunk.hpp"
-#include "grnxx/storage/chunk_index.hpp"
-#include "grnxx/storage/file.hpp"
-#include "grnxx/storage/header.hpp"
-#include "grnxx/storage/node_header.hpp"
-#include "grnxx/storage/path.hpp"
-
-namespace grnxx {
-namespace storage {
-namespace {
-
-// The size of chunk must be a multiple of CHUNK_UNIT_SIZE (64KB).
-constexpr uint64_t CHUNK_UNIT_SIZE = 1 << 16;
-// The size of regular node must be a multiple of REGULAR_NODE_UNIT_SIZE (4KB).
-constexpr uint64_t REGULAR_NODE_UNIT_SIZE = 1 << 12;
-// The size of small node must be a multiple of SMALL_NODE_UNIT_SIZE (64 bytes).
-constexpr uint64_t SMALL_NODE_UNIT_SIZE   = 1 << 6;
-// A node larger than NODE_SIZE_THRESHOLD (2KB) is a regular node.
-constexpr uint64_t NODE_SIZE_THRESHOLD    = 1 << 11;
-
-// The chunk size for Header and ChunkIndexes.
-constexpr uint64_t ROOT_CHUNK_SIZE = CHUNK_UNIT_SIZE;
-// The size allocated to ChunkIndexes.
-constexpr uint64_t ROOT_INDEX_SIZE = ROOT_CHUNK_SIZE - HEADER_SIZE;
-
-// The number of NodeHeaders in the minimum header chunk.
-constexpr uint32_t HEADER_CHUNK_MIN_SIZE = CHUNK_UNIT_SIZE / NODE_HEADER_SIZE;
-
-// The maximum node ID.
-constexpr uint32_t MAX_NODE_ID =
-    STORAGE_INVALID_NODE_ID - HEADER_CHUNK_MIN_SIZE;
-
-// The maximum number of chunks for NodeHeaders.
-constexpr uint16_t MAX_NUM_HEADER_CHUNKS = 32;
-// The maximum number of chunks for node bodies.
-constexpr uint16_t MAX_NUM_BODY_CHUNKS   =
-    (ROOT_INDEX_SIZE / CHUNK_INDEX_SIZE) - MAX_NUM_HEADER_CHUNKS;
-
-static_assert(MAX_NUM_BODY_CHUNKS >= 2000, "MAX_NUM_BODY_CHUNKS < 2000");
-
-// The minimum size of regular body chunks.
-constexpr uint64_t REGULAR_BODY_CHUNK_MIN_SIZE = 1 << 21;
-// The ratio of the next regular body chunk size to the storage total size.
-constexpr double REGULAR_BODY_CHUNK_SIZE_RATIO = 1.0 / 64;
-// The size of the minimum small body chunk.
-constexpr uint64_t SMALL_BODY_CHUNK_MIN_SIZE = CHUNK_UNIT_SIZE;
-
-}  // namespace
-
-StorageImpl::StorageImpl()
-    : Storage(),
-      path_(),
-      flags_(STORAGE_DEFAULT),
-      header_(nullptr),
-      header_chunk_indexes_(nullptr),
-      body_chunk_indexes_(nullptr),
-      files_(),
-      root_chunk_(),
-      header_chunks_(),
-      body_chunks_(),
-      mutex_(),
-      clock_() {}
-
-StorageImpl::~StorageImpl() {}
-
-StorageImpl *StorageImpl::create(const char *path, StorageFlags flags,
-                                 const StorageOptions &options) {
-  if (!options) {
-    GRNXX_ERROR() << "invalid argument: options = " << options;
-    throw LogicError();
-  }
-  std::unique_ptr<StorageImpl> storage(new (std::nothrow) StorageImpl);
-  if (!storage) {
-    GRNXX_ERROR() << "new grnxx::storage::StorageImpl failed";
-    throw MemoryError();
-  }
-  if (path || (flags & STORAGE_TEMPORARY)) {
-    storage->create_file_backed_storage(path, flags, options);
-  } else {
-    storage->create_anonymous_storage(flags, options);
-  }
-  return storage.release();
-}
-
-StorageImpl *StorageImpl::open(const char *path, StorageFlags flags) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<StorageImpl> storage(new (std::nothrow) StorageImpl);
-  if (!storage) {
-    GRNXX_ERROR() << "new grnxx::storage::StorageImpl failed";
-    throw MemoryError();
-  }
-  storage->open_storage(path, flags);
-  return storage.release();
-}
-
-StorageImpl *StorageImpl::open_or_create(const char *path, StorageFlags flags,
-                                         const StorageOptions &options) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  if (!options) {
-    GRNXX_ERROR() << "invalid argument: options = " << options;
-    throw LogicError();
-  }
-  std::unique_ptr<StorageImpl> storage(new (std::nothrow) StorageImpl);
-  if (!storage) {
-    GRNXX_ERROR() << "new grnxx::storage::StorageImpl failed";
-    throw MemoryError();
-  }
-  storage->open_or_create_storage(path, flags, options);
-  return storage.release();
-}
-
-bool StorageImpl::exists(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  if (!File::exists(path)) {
-    return false;
-  }
-  std::unique_ptr<Storage> storage(open(path, STORAGE_READ_ONLY));
-  return true;
-}
-
-void StorageImpl::unlink(const char *path) {
-  if (!path) {
-    GRNXX_ERROR() << "invalid argument: path = nullptr";
-    throw LogicError();
-  }
-  std::unique_ptr<StorageImpl> storage(open(path, STORAGE_READ_ONLY));
-  storage->unlink_storage();
-}
-
-StorageNode StorageImpl::create_node(uint32_t parent_node_id, uint64_t size) {
-  if (flags_ & STORAGE_READ_ONLY) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  Lock data_lock(&header_->data_mutex);
-  if (parent_node_id >= header_->num_nodes) {
-    GRNXX_ERROR() << "invalid argument: parent_node_id = " << parent_node_id
-                  << ", num_nodes = " << header_->num_nodes;
-    throw LogicError();
-  } else if (size > header_->max_file_size) {
-    GRNXX_ERROR() << "invalid argument: size = " << size
-                  << ", max_file_size = " << header_->max_file_size;
-    throw LogicError();
-  }
-  NodeHeader * const parent_node_header = get_node_header(parent_node_id);
-  if ((parent_node_header->status != STORAGE_NODE_ACTIVE) &&
-      (parent_node_header->status != STORAGE_NODE_UNLINKED)) {
-    GRNXX_ERROR() << "invalid argument: status = "
-                  << parent_node_header->status;
-    throw LogicError();
-  }
-  NodeHeader *child_node_header = nullptr;
-  if (parent_node_header->child_node_id != STORAGE_INVALID_NODE_ID) {
-    child_node_header = get_node_header(parent_node_header->child_node_id);
-  }
-  NodeHeader * const node_header = create_active_node(size);
-  node_header->sibling_node_id = parent_node_header->child_node_id;
-  node_header->from_node_id = parent_node_id;
-  parent_node_header->child_node_id = node_header->id;
-  if (child_node_header) {
-    child_node_header->from_node_id = node_header->id;
-  }
-  void * const body = get_node_body(node_header);
-  return StorageNode(node_header, body);
-}
-
-StorageNode StorageImpl::open_node(uint32_t node_id) {
-  NodeHeader * const node_header = get_node_header(node_id);
-  if ((node_header->status != STORAGE_NODE_ACTIVE) &&
-      (node_header->status != STORAGE_NODE_UNLINKED)) {
-    GRNXX_ERROR() << "invalid argument: status = " << node_header->status;
-    throw LogicError();
-  }
-  void * const body = get_node_body(node_header);
-  return StorageNode(node_header, body);
-}
-
-void StorageImpl::unlink_node(uint32_t node_id) {
-  if (flags_ & STORAGE_READ_ONLY) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  Lock data_lock(&header_->data_mutex);
-  if ((node_id == STORAGE_ROOT_NODE_ID) || (node_id >= header_->num_nodes)) {
-    GRNXX_ERROR() << "invalid argument: node_id = " << node_id
-                  << ", num_nodes = " << header_->num_nodes;
-    throw LogicError();
-  }
-  NodeHeader * const node_header = get_node_header(node_id);
-  if (node_header->status != STORAGE_NODE_ACTIVE) {
-    GRNXX_ERROR() << "invalid status: expected = " << STORAGE_NODE_ACTIVE
-                  << ", actual = " << node_header->status;
-    throw LogicError();
-  }
-  NodeHeader * const from_node_header =
-      get_node_header(node_header->from_node_id);
-  if (node_id == from_node_header->child_node_id) {
-    from_node_header->child_node_id = node_header->sibling_node_id;
-  } else if (node_id == from_node_header->sibling_node_id) {
-    from_node_header->sibling_node_id = node_header->sibling_node_id;
-  } else {
-    // This error must not occur.
-    GRNXX_ERROR() << "broken link: node_id = " << node_id
-                  << ", from_node_id = " << from_node_header->id
-                  << ", child_node_id = " << from_node_header->child_node_id
-                  << ", sibling_node_id = "
-                  << from_node_header->sibling_node_id;
-    throw LogicError();
-  }
-  if (node_header->sibling_node_id != STORAGE_INVALID_NODE_ID) {
-    NodeHeader * const sibling_node_header =
-        get_node_header(node_header->sibling_node_id);
-    sibling_node_header->from_node_id = node_header->from_node_id;
-  }
-  NodeHeader *latest_node_header = nullptr;
-  if (header_->latest_unlinked_node_id != STORAGE_INVALID_NODE_ID) {
-    latest_node_header = get_node_header(header_->latest_unlinked_node_id);
-  }
-  node_header->status = STORAGE_NODE_UNLINKED;
-  if (latest_node_header) {
-    node_header->next_unlinked_node_id =
-        latest_node_header->next_unlinked_node_id;
-    latest_node_header->next_unlinked_node_id = node_id;
-  } else {
-    node_header->next_unlinked_node_id = node_id;
-  }
-  header_->latest_unlinked_node_id = node_id;
-  node_header->modified_time = clock_.now();
-}
-
-void StorageImpl::sweep(Duration lifetime) {
-  if (flags_ & STORAGE_READ_ONLY) {
-    GRNXX_ERROR() << "invalid operation: flags = " << flags_;
-    throw LogicError();
-  }
-  Lock data_lock(&header_->data_mutex);
-  if (header_->latest_unlinked_node_id == STORAGE_INVALID_NODE_ID) {
-    // Nothing to do.
-    return;
-  }
-  NodeHeader * const latest_node_header =
-      get_node_header(header_->latest_unlinked_node_id);
-  const Time threshold = clock_.now() - lifetime;
-  do {
-    NodeHeader * const oldest_node_header =
-        get_node_header(latest_node_header->next_unlinked_node_id);
-    if (oldest_node_header->status != STORAGE_NODE_UNLINKED) {
-      // This error must not occur.
-      GRNXX_ERROR() << "invalid argument: status = "
-                    << oldest_node_header->status;
-      throw LogicError();
-    }
-    if (oldest_node_header->modified_time > threshold) {
-      // Remaining unlinked nodes are too early for reuse.
-      break;
-    }
-    const uint32_t next_node_id = oldest_node_header->next_unlinked_node_id;
-    sweep_subtree(oldest_node_header);
-    if (oldest_node_header != latest_node_header) {
-      latest_node_header->next_unlinked_node_id = next_node_id;
-    } else {
-      header_->latest_unlinked_node_id = STORAGE_INVALID_NODE_ID;
-    }
-  } while (header_->latest_unlinked_node_id != STORAGE_INVALID_NODE_ID);
-}
-
-const char *StorageImpl::path() const {
-  return path_.get();
-}
-
-StorageFlags StorageImpl::flags() const {
-  return flags_;
-}
-
-uint64_t StorageImpl::max_file_size() const {
-  return header_->max_file_size;
-}
-
-uint16_t StorageImpl::max_num_files() const {
-  return header_->max_num_files;
-}
-
-uint32_t StorageImpl::num_nodes() const {
-  return header_->num_active_or_unlinked_nodes;
-}
-
-uint16_t StorageImpl::num_chunks() const {
-  return header_->num_body_chunks;
-}
-
-uint64_t StorageImpl::body_usage() const {
-  return header_->body_usage;
-}
-
-uint64_t StorageImpl::body_size() const {
-  return header_->body_size;
-}
-
-uint64_t StorageImpl::total_size() const {
-  return header_->total_size;
-}
-
-void StorageImpl::create_file_backed_storage(const char *path,
-                                             StorageFlags flags,
-                                             const StorageOptions &options) {
-  if (path) {
-    path_.reset(Path::clone_path(path));
-  }
-  if (flags & STORAGE_TEMPORARY) {
-    flags_ |= STORAGE_TEMPORARY;
-  }
-  if (flags & STORAGE_HUGE_TLB) {
-    flags_ |= STORAGE_HUGE_TLB;
-  }
-  FileFlags file_flags = FILE_DEFAULT;
-  if (flags_ & STORAGE_TEMPORARY) {
-    file_flags |= FILE_TEMPORARY;
-  }
-  std::unique_ptr<File> header_file(File::create(path, file_flags));
-  try {
-    header_file->resize(ROOT_CHUNK_SIZE);
-    std::unique_ptr<Chunk> root_chunk(
-        create_chunk(header_file.get(), 0, ROOT_CHUNK_SIZE));
-    header_ = static_cast<Header *>(root_chunk->address());
-    *header_ = Header();
-    header_->max_file_size = options.max_file_size & ~(CHUNK_UNIT_SIZE - 1);
-    header_->max_num_files = options.max_num_files;
-    header_->total_size = ROOT_CHUNK_SIZE;
-    prepare_pointers();
-    prepare_indexes();
-    files_[0] = std::move(header_file);
-    root_chunk_ = std::move(root_chunk);
-    create_active_node(options.root_size);
-    header_->validate();
-  } catch (...) {
-    unlink_storage();
-    throw;
-  }
-}
-
-void StorageImpl::create_anonymous_storage(StorageFlags flags,
-                                           const StorageOptions &options) {
-  flags_ |= STORAGE_ANONYMOUS;
-  if (flags & STORAGE_HUGE_TLB) {
-    flags_ |= STORAGE_HUGE_TLB;
-  }
-  std::unique_ptr<Chunk> root_chunk(create_chunk(nullptr, 0, ROOT_CHUNK_SIZE));
-  header_ = static_cast<Header *>(root_chunk->address());
-  *header_ = Header();
-  header_->max_file_size = options.max_file_size & ~(CHUNK_UNIT_SIZE - 1);
-  header_->max_num_files = options.max_num_files;
-  header_->total_size = ROOT_CHUNK_SIZE;
-  prepare_pointers();
-  prepare_indexes();
-  root_chunk_ = std::move(root_chunk);
-  create_active_node(options.root_size);
-  header_->validate();
-}
-
-void StorageImpl::open_storage(const char *path, StorageFlags flags) {
-  path_.reset(Path::clone_path(path));
-  if (flags & STORAGE_READ_ONLY) {
-    flags_ |= STORAGE_READ_ONLY;
-  }
-  if (flags & STORAGE_HUGE_TLB) {
-    flags_ |= STORAGE_HUGE_TLB;
-  }
-  FileFlags file_flags = FILE_DEFAULT;
-  if (flags_ & STORAGE_READ_ONLY) {
-    file_flags |= FILE_READ_ONLY;
-  }
-  std::unique_ptr<File> header_file(File::open(path, file_flags));
-  std::unique_ptr<Chunk> root_chunk(
-      create_chunk(header_file.get(), 0, ROOT_CHUNK_SIZE));
-  header_ = static_cast<Header *>(root_chunk->address());
-  if (!*header_) {
-    GRNXX_ERROR() << "invalid format: path = " << path_.get();
-    throw LogicError();
-  }
-  prepare_pointers();
-  files_[0] = std::move(header_file);
-  root_chunk_ = std::move(root_chunk);
-}
-
-void StorageImpl::open_or_create_storage(const char *path, StorageFlags flags,
-                                         const StorageOptions &options) {
-  path_.reset(Path::clone_path(path));
-  if (flags & STORAGE_HUGE_TLB) {
-    flags_ |= STORAGE_HUGE_TLB;
-  }
-  std::unique_ptr<File> header_file;
-  if (File::exists(path)) {
-    header_file.reset(File::open(path));
-  }
-  if (header_file) {
-    // Open an existing storage.
-    std::unique_ptr<Chunk> root_chunk(
-        create_chunk(header_file.get(), 0, ROOT_CHUNK_SIZE));
-    header_ = static_cast<Header *>(root_chunk->address());
-    if (!*header_) {
-      GRNXX_ERROR() << "invalid format: path = " << path_.get();
-      throw LogicError();
-    }
-    prepare_pointers();
-    files_[0] = std::move(header_file);
-    root_chunk_ = std::move(root_chunk);
-  } else {
-    // Create a storage.
-    header_file.reset(File::create(path));
-    try {
-      header_file->resize(ROOT_CHUNK_SIZE);
-      std::unique_ptr<Chunk> root_chunk(
-          create_chunk(header_file.get(), 0, ROOT_CHUNK_SIZE));
-      header_ = static_cast<Header *>(root_chunk->address());
-      *header_ = Header();
-      header_->max_file_size = options.max_file_size & ~(CHUNK_UNIT_SIZE - 1);
-      header_->max_num_files = options.max_num_files;
-      header_->total_size = ROOT_CHUNK_SIZE;
-      prepare_pointers();
-      prepare_indexes();
-      files_[0] = std::move(header_file);
-      root_chunk_ = std::move(root_chunk);
-      create_active_node(options.root_size);
-      header_->validate();
-    } catch (...) {
-      unlink_storage();
-      throw;
-    }
-  }
-}
-
-void StorageImpl::unlink_storage() {
-  if (flags_ & STORAGE_TEMPORARY) {
-    // Nothing to do.
-    return;
-  }
-  uint16_t max_file_id = 0;
-  if (header_) {
-    max_file_id = header_->total_size / header_->max_file_size;
-  }
-  File::unlink(path_.get());
-  for (uint16_t i = 1; i <= max_file_id; ++i) {
-    // Component files may be left if an error occurs.
-    std::unique_ptr<char[]> numbered_path(generate_path(i));
-    File::unlink(numbered_path.get());
-  }
-}
-
-void StorageImpl::prepare_pointers() {
-  header_chunk_indexes_ = reinterpret_cast<ChunkIndex *>(header_ + 1);
-  body_chunk_indexes_ = header_chunk_indexes_ + MAX_NUM_HEADER_CHUNKS;
-  if (~flags_ & STORAGE_ANONYMOUS) {
-    files_.reset(
-        new (std::nothrow) std::unique_ptr<File>[header_->max_num_files]);
-    if (!files_) {
-      GRNXX_ERROR() << "new std::unique_ptr<grnxx::storage::File>[] failed: "
-                    << "size = " << header_->max_num_files;
-      throw MemoryError();
-    }
-  }
-  header_chunks_.reset(
-      new (std::nothrow) std::unique_ptr<Chunk>[MAX_NUM_HEADER_CHUNKS]);
-  if (!header_chunks_) {
-    GRNXX_ERROR() << "new std::unique_ptr<grnxx::storage::Chunk>[] failed: "
-                  << "size = " << MAX_NUM_HEADER_CHUNKS;
-    throw MemoryError();
-  }
-  body_chunks_.reset(
-      new (std::nothrow) std::unique_ptr<Chunk>[MAX_NUM_BODY_CHUNKS]);
-  if (!header_chunks_) {
-    GRNXX_ERROR() << "new std::unique_ptr<grnxx::storage::Chunk>[] failed: "
-                  << "size = " << MAX_NUM_BODY_CHUNKS;
-    throw MemoryError();
-  }
-}
-
-void StorageImpl::prepare_indexes() {
-  for (uint16_t i = 0; i < MAX_NUM_HEADER_CHUNKS; ++i) {
-    header_chunk_indexes_[i] = ChunkIndex(i, HEADER_CHUNK);
-  }
-  for (uint16_t i = 0; i < MAX_NUM_BODY_CHUNKS; ++i) {
-    body_chunk_indexes_[i] = ChunkIndex(i, REGULAR_BODY_CHUNK);
-  }
-}
-
-NodeHeader *StorageImpl::create_active_node(uint64_t size) {
-  if (size == 0) {
-    size = SMALL_NODE_UNIT_SIZE;
-  } else if (size <= NODE_SIZE_THRESHOLD) {
-    size = (size + SMALL_NODE_UNIT_SIZE - 1) & ~(SMALL_NODE_UNIT_SIZE - 1);
-  } else {
-    size = (size + REGULAR_NODE_UNIT_SIZE - 1) & ~(REGULAR_NODE_UNIT_SIZE - 1);
-  }
-  NodeHeader *node_header = find_idle_node(size);
-  if (!node_header) {
-    node_header = create_idle_node(size);
-  }
-  if (node_header->size > size) {
-    divide_idle_node(node_header, size);
-  }
-  activate_idle_node(node_header);
-  return node_header;
-}
-
-NodeHeader *StorageImpl::find_idle_node(uint64_t size) {
-  const size_t begin = bit_scan_reverse(size);
-  const size_t end = (size <= NODE_SIZE_THRESHOLD) ?
-      bit_scan_reverse(NODE_SIZE_THRESHOLD << 1) : NUM_IDLE_NODE_LISTS;
-  for (size_t i = begin; i < end; ++i) {
-    if (header_->oldest_idle_node_ids[i] != STORAGE_INVALID_NODE_ID) {
-      NodeHeader * const node_header =
-          get_node_header(header_->oldest_idle_node_ids[i]);
-      if (node_header->size >= size) {
-        return node_header;
-      }
-    }
-  }
-  return nullptr;
-}
-
-NodeHeader *StorageImpl::create_idle_node(uint64_t size) {
-  NodeHeader * const node_header = reserve_phantom_node();
-  ChunkIndex *remainder_chunk_index = nullptr;
-  ChunkIndex * const chunk_index =
-      create_body_chunk(size, &remainder_chunk_index);
-  associate_node_with_chunk(node_header, chunk_index);
-  if (remainder_chunk_index) {
-    // Create an idle node for the remaining space.
-    NodeHeader * const remainder_node_header = create_phantom_node();
-    // The following may fail but the requested node is ready.
-    associate_node_with_chunk(remainder_node_header, remainder_chunk_index);
-  }
-  return node_header;
-}
-
-void StorageImpl::divide_idle_node(NodeHeader *node_header, uint64_t size) {
-  NodeHeader *next_node_header = nullptr;
-  if (node_header->next_node_id != STORAGE_INVALID_NODE_ID) {
-    next_node_header = get_node_header(node_header->next_node_id);
-  }
-  NodeHeader * const second_node_header = reserve_phantom_node();
-  unregister_idle_node(node_header);
-  header_->latest_phantom_node_id = second_node_header->next_phantom_node_id;
-  second_node_header->status = STORAGE_NODE_IDLE;
-  second_node_header->chunk_id = node_header->chunk_id;
-  second_node_header->offset = node_header->offset + size;
-  second_node_header->size = node_header->size - size;
-  second_node_header->next_node_id = node_header->next_node_id;
-  second_node_header->prev_node_id = node_header->id;
-  second_node_header->modified_time = clock_.now();
-  if (next_node_header) {
-    next_node_header->prev_node_id = second_node_header->id;
-  }
-  node_header->size = size;
-  node_header->next_node_id = second_node_header->id;
-  second_node_header->modified_time = clock_.now();
-  register_idle_node(node_header);
-  register_idle_node(second_node_header);
-}
-
-void StorageImpl::activate_idle_node(NodeHeader *node_header) {
-  unregister_idle_node(node_header);
-  node_header->status = STORAGE_NODE_ACTIVE;
-  node_header->child_node_id = STORAGE_INVALID_NODE_ID;
-  node_header->sibling_node_id = STORAGE_INVALID_NODE_ID;
-  node_header->modified_time = clock_.now();
-  ++header_->num_active_or_unlinked_nodes;
-  header_->body_usage += node_header->size;
-}
-
-NodeHeader *StorageImpl::reserve_phantom_node() {
-  if (header_->latest_phantom_node_id != STORAGE_INVALID_NODE_ID) {
-    return get_node_header(header_->latest_phantom_node_id);
-  } else {
-    return create_phantom_node();
-  }
-}
-
-NodeHeader *StorageImpl::create_phantom_node() {
-  const uint32_t node_id = header_->num_nodes;
-  ChunkIndex *remainder_chunk_index = nullptr;
-  if (node_id == header_->max_num_nodes) {
-    create_header_chunk(&remainder_chunk_index);
-  }
-  // Create a phantom node.
-  NodeHeader * const node_header = get_node_header(node_id);
-  *node_header = NodeHeader(node_id);
-  node_header->next_phantom_node_id = header_->latest_phantom_node_id;
-  node_header->modified_time = clock_.now();
-  ++header_->num_nodes;
-  header_->latest_phantom_node_id = node_id;
-  if (remainder_chunk_index) {
-    // Create an idle node for the remaining space.
-    NodeHeader * const remainder_node_header = create_phantom_node();
-    // The following may fail but the requested node is ready.
-    associate_node_with_chunk(remainder_node_header, remainder_chunk_index);
-  }
-  return node_header;
-}
-
-void StorageImpl::associate_node_with_chunk(NodeHeader *node_header,
-                                            ChunkIndex *chunk_index) {
-  if ((node_header->id != header_->latest_phantom_node_id) ||
-      (node_header->status != STORAGE_NODE_PHANTOM)) {
-    // This error must not occur.
-    GRNXX_ERROR() << "invalid argument: id = " << node_header->id
-                  << ", status = " << node_header->status
-                  << ", num_nodes = " << header_->num_nodes
-                  << ", latest_phantom_node_id = "
-                  << header_->latest_phantom_node_id;
-    throw LogicError();
-  }
-  header_->latest_phantom_node_id = node_header->next_phantom_node_id;
-  node_header->status = STORAGE_NODE_IDLE;
-  node_header->chunk_id = chunk_index->id;
-  node_header->offset = 0;
-  node_header->size = chunk_index->size;
-  node_header->modified_time = clock_.now();
-  register_idle_node(node_header);
-}
-
-void StorageImpl::sweep_subtree(NodeHeader *node_header) {
-  uint32_t child_node_id = node_header->child_node_id;
-  while (child_node_id != STORAGE_INVALID_NODE_ID) {
-    NodeHeader * const child_node_header = get_node_header(child_node_id);
-    child_node_id = child_node_header->sibling_node_id;
-    sweep_subtree(child_node_header);
-    node_header->child_node_id = child_node_id;
-  }
-  node_header->status = STORAGE_NODE_IDLE;
-  node_header->modified_time = clock_.now();
-  --header_->num_active_or_unlinked_nodes;
-  header_->body_usage -= node_header->size;
-  register_idle_node(node_header);
-  if (node_header->next_node_id != STORAGE_INVALID_NODE_ID) {
-    NodeHeader * const next_node_header =
-        get_node_header(node_header->next_node_id);
-    if (next_node_header->status == STORAGE_NODE_IDLE) {
-      merge_idle_nodes(node_header, next_node_header);
-    }
-  }
-  if (node_header->prev_node_id != STORAGE_INVALID_NODE_ID) {
-    NodeHeader * const prev_node_header =
-        get_node_header(node_header->prev_node_id);
-    if (prev_node_header->status == STORAGE_NODE_IDLE) {
-      merge_idle_nodes(prev_node_header, node_header);
-    }
-  }
-}
-
-void StorageImpl::merge_idle_nodes(NodeHeader *node_header,
-                                   NodeHeader *next_node_header) {
-  NodeHeader *next_next_node_header = nullptr;
-  if (next_node_header->next_node_id != STORAGE_INVALID_NODE_ID) {
-    next_next_node_header = get_node_header(next_node_header->next_node_id);
-  }
-  unregister_idle_node(node_header);
-  unregister_idle_node(next_node_header);
-  node_header->size += next_node_header->size;
-  node_header->next_node_id = next_node_header->next_node_id;
-  if (next_next_node_header) {
-    next_next_node_header->prev_node_id = node_header->id;
-  }
-  *next_node_header = NodeHeader(next_node_header->id);
-  next_node_header->next_phantom_node_id = header_->latest_phantom_node_id;
-  next_node_header->modified_time = clock_.now();
-  header_->latest_phantom_node_id = next_node_header->id;
-  register_idle_node(node_header);
-}
-
-ChunkIndex *StorageImpl::create_header_chunk(
-    ChunkIndex **remainder_chunk_index) {
-  if (header_->num_nodes > MAX_NODE_ID) {
-    GRNXX_ERROR() << "too many nodes: "
-                  << "num_nodes = " << header_->num_nodes
-                  << ", max_node_id = " << MAX_NODE_ID;
-    throw LogicError();
-  }
-  const uint16_t chunk_id =
-      bit_scan_reverse(header_->num_nodes + HEADER_CHUNK_MIN_SIZE);
-  const uint64_t size = static_cast<uint64_t>(NODE_HEADER_SIZE) << chunk_id;
-  if (size > header_->max_file_size) {
-    GRNXX_ERROR() << "too large chunk: size = " << size
-                  << ", max_file_size = " << header_->max_file_size;
-    throw LogicError();
-  }
-  uint16_t file_id = header_->total_size / header_->max_file_size;
-  uint64_t offset = header_->total_size % header_->max_file_size;
-  uint64_t size_left = header_->max_file_size - offset;
-  if (size_left < size) {
-    *remainder_chunk_index = create_body_chunk(size_left);
-    file_id = header_->total_size / header_->max_file_size;
-    offset = header_->total_size % header_->max_file_size;
-    size_left = header_->max_file_size - offset;
-    if (size_left < size) {
-      // This error must not occur.
-      GRNXX_ERROR() << "too large chunk: size = " << size
-                    << ", size_left = " << size_left;
-      throw LogicError();
-    }
-  }
-  if (file_id == header_->max_num_files) {
-    GRNXX_ERROR() << "too many files: file_id = " << file_id
-                  << ", max_num_files = " << header_->max_num_files;
-    throw LogicError();
-  }
-  ChunkIndex * const chunk_index = &header_chunk_indexes_[chunk_id];
-  chunk_index->file_id = file_id;
-  chunk_index->offset = offset;
-  chunk_index->size = size;
-  header_->total_size += size;
-  header_->max_num_nodes += size / NODE_HEADER_SIZE;
-  return chunk_index;
-}
-
-ChunkIndex *StorageImpl::create_body_chunk(
-    uint64_t size, ChunkIndex **remainder_chunk_index) {
-  uint64_t chunk_size = size;
-  if (size <= NODE_SIZE_THRESHOLD) {
-    chunk_size = SMALL_BODY_CHUNK_MIN_SIZE << header_->num_small_body_chunks;
-  }
-  uint64_t offset = header_->total_size % header_->max_file_size;
-  uint64_t size_left = header_->max_file_size - offset;
-  if (size_left < chunk_size) {
-    *remainder_chunk_index = create_body_chunk(size_left);
-    size_left = header_->max_file_size;
-  }
-  if (size > NODE_SIZE_THRESHOLD) {
-    chunk_size = static_cast<uint64_t>(
-        header_->total_size * REGULAR_BODY_CHUNK_SIZE_RATIO);
-    chunk_size &= ~(CHUNK_UNIT_SIZE - 1);
-    if (size > chunk_size) {
-      chunk_size = size;
-    }
-    if (chunk_size > size_left) {
-      chunk_size = size_left;
-    }
-    if (chunk_size < REGULAR_BODY_CHUNK_MIN_SIZE) {
-      chunk_size = REGULAR_BODY_CHUNK_MIN_SIZE;
-    }
-  }
-  ChunkIndex * const chunk_index = create_body_chunk(chunk_size);
-  if (size <= NODE_SIZE_THRESHOLD) {
-    chunk_index->type = SMALL_BODY_CHUNK;
-    ++header_->num_small_body_chunks;
-  }
-  return chunk_index;
-}
-
-ChunkIndex *StorageImpl::create_body_chunk(uint64_t size) {
-  const uint16_t chunk_id = header_->num_body_chunks;
-  if (header_->num_body_chunks >= MAX_NUM_BODY_CHUNKS) {
-    GRNXX_ERROR() << "too many chunks: "
-                  << "num_chunks = " << header_->num_body_chunks
-                  << ", max_num_chunks = " << MAX_NUM_BODY_CHUNKS;
-    throw LogicError();
-  }
-  const uint16_t file_id = header_->total_size / header_->max_file_size;
-  const uint64_t offset = header_->total_size % header_->max_file_size;
-  const uint64_t size_left = header_->max_file_size - offset;
-  if (file_id >= header_->max_num_files) {
-    GRNXX_ERROR() << "too many files: file_id = " << file_id
-                  << ", max_num_files = " << header_->max_num_files;
-    throw LogicError();
-  }
-  if (size_left < size) {
-    // This error must not occur.
-    GRNXX_ERROR() << "too large chunk: size = " << size
-                  << ", size_left = " << size_left;
-    throw LogicError();
-  }
-  ChunkIndex * const chunk_index = &body_chunk_indexes_[chunk_id];
-  chunk_index->file_id = file_id;
-  chunk_index->offset = offset;
-  chunk_index->size = size;
-  header_->body_size += size;
-  header_->total_size += size;
-  ++header_->num_body_chunks;
-  return chunk_index;
-}
-
-void StorageImpl::register_idle_node(NodeHeader *node_header) {
-  if (node_header->status != STORAGE_NODE_IDLE) {
-    // This error must not occur.
-    GRNXX_ERROR() << "invalid argument: status = " << node_header->status;
-    throw LogicError();
-  }
-  size_t list_id = bit_scan_reverse(node_header->size);
-  if (body_chunk_indexes_[node_header->chunk_id].type == SMALL_BODY_CHUNK) {
-    if (list_id > bit_scan_reverse(NODE_SIZE_THRESHOLD)) {
-      list_id = bit_scan_reverse(NODE_SIZE_THRESHOLD);
-    }
-  }
-  if (header_->oldest_idle_node_ids[list_id] == STORAGE_INVALID_NODE_ID) {
-    // The given node is appended to the empty list.
-    node_header->next_idle_node_id = node_header->id;
-    node_header->prev_idle_node_id = node_header->id;
-    header_->oldest_idle_node_ids[list_id] = node_header->id;
-  } else {
-    // The given node is inserted as the new lastest idle node.
-    NodeHeader * const oldest_idle_node_header =
-        get_node_header(header_->oldest_idle_node_ids[list_id]);
-    NodeHeader * const latest_idle_node_header =
-        get_node_header(oldest_idle_node_header->prev_idle_node_id);
-    node_header->next_idle_node_id = oldest_idle_node_header->id;
-    node_header->prev_idle_node_id = latest_idle_node_header->id;
-    latest_idle_node_header->next_idle_node_id = node_header->id;
-    oldest_idle_node_header->prev_idle_node_id = node_header->id;
-  }
-}
-
-void StorageImpl::unregister_idle_node(NodeHeader *node_header) {
-  if (node_header->status != STORAGE_NODE_IDLE) {
-    // This error must not occur.
-    GRNXX_ERROR() << "invalid argument: status = " << node_header->status;
-    throw LogicError();
-  }
-  size_t list_id = bit_scan_reverse(node_header->size);
-  if (body_chunk_indexes_[node_header->chunk_id].type == SMALL_BODY_CHUNK) {
-    if (list_id > bit_scan_reverse(NODE_SIZE_THRESHOLD)) {
-      list_id = bit_scan_reverse(NODE_SIZE_THRESHOLD);
-    }
-  }
-  if (node_header->id == node_header->next_idle_node_id) {
-    // The list becomes empty.
-    header_->oldest_idle_node_ids[list_id] = STORAGE_INVALID_NODE_ID;
-  } else {
-    // The specified node is removed from the list.
-    NodeHeader * const next_idle_node_header =
-        get_node_header(node_header->next_idle_node_id);
-    NodeHeader * const prev_idle_node_header =
-        get_node_header(node_header->prev_idle_node_id);
-    next_idle_node_header->prev_idle_node_id = prev_idle_node_header->id;
-    prev_idle_node_header->next_idle_node_id = next_idle_node_header->id;
-    if (node_header->id == header_->oldest_idle_node_ids[list_id]) {
-      header_->oldest_idle_node_ids[list_id] = next_idle_node_header->id;
-    }
-  }
-}
-
-NodeHeader *StorageImpl::get_node_header(uint32_t node_id) {
-  if (node_id >= header_->max_num_nodes) {
-    GRNXX_ERROR() << "invalid argument: node_id = " << node_id
-                  << ", max_num_nodes = " << header_->max_num_nodes;
-    throw LogicError();
-  }
-  const uint16_t chunk_id =
-      bit_scan_reverse(node_id + HEADER_CHUNK_MIN_SIZE);
-  Chunk * const chunk = get_header_chunk(chunk_id);
-  const uint32_t chunk_size = 1U << chunk_id;
-  NodeHeader * const headers = static_cast<NodeHeader *>(chunk->address());
-  return headers + (node_id & (chunk_size - 1));
-}
-
-void *StorageImpl::get_node_body(const NodeHeader *node_header) {
-  Chunk * const chunk = get_body_chunk(node_header->chunk_id);
-  return static_cast<uint8_t *>(chunk->address()) + node_header->offset;
-}
-
-Chunk *StorageImpl::get_header_chunk(uint16_t chunk_id) {
-  if (!header_chunks_[chunk_id]) {
-    const ChunkIndex &chunk_index = header_chunk_indexes_[chunk_id];
-    File *file = nullptr;
-    if (~flags_ & STORAGE_ANONYMOUS) {
-      file = reserve_file(chunk_index.file_id,
-                          chunk_index.offset + chunk_index.size);
-    }
-    Lock lock(&mutex_);
-    if (!header_chunks_[chunk_id]) {
-      header_chunks_[chunk_id].reset(
-          create_chunk(file, chunk_index.offset, chunk_index.size));
-    }
-  }
-  return header_chunks_[chunk_id].get();
-}
-
-Chunk *StorageImpl::get_body_chunk(uint16_t chunk_id) {
-  if (!body_chunks_[chunk_id]) {
-    const ChunkIndex &chunk_index = body_chunk_indexes_[chunk_id];
-    File *file = nullptr;
-    if (~flags_ & STORAGE_ANONYMOUS) {
-      file = reserve_file(chunk_index.file_id,
-                          chunk_index.offset + chunk_index.size);
-    }
-    Lock lock(&mutex_);
-    if (!body_chunks_[chunk_id]) {
-      body_chunks_[chunk_id].reset(
-          create_chunk(file, chunk_index.offset, chunk_index.size));
-    }
-  }
-  return body_chunks_[chunk_id].get();
-}
-
-File *StorageImpl::reserve_file(uint16_t file_id, uint64_t size) {
-  if (!files_[file_id]) {
-    // Create a file if missing.
-    Lock file_lock(&header_->file_mutex);
-    if (!files_[file_id]) {
-      FileFlags file_flags = FILE_DEFAULT;
-      if (flags_ & STORAGE_READ_ONLY) {
-        file_flags |= FILE_READ_ONLY;
-        std::unique_ptr<char[]> path(generate_path(file_id));
-        files_[file_id].reset(File::open(path.get(), file_flags));
-      } else {
-        if (flags_ & STORAGE_TEMPORARY) {
-          file_flags |= FILE_TEMPORARY;
-          files_[file_id].reset(File::create(path_.get(), file_flags));
-        } else {
-          std::unique_ptr<char[]> path(generate_path(file_id));
-          files_[file_id].reset(File::open_or_create(path.get(), file_flags));
-        }
-      }
-    }
-  }
-  // Expand the file if its size is not enough 
-  uint64_t file_size = files_[file_id]->get_size();
-  if (file_size < size) {
-    Lock file_lock(&header_->file_mutex);
-    file_size = files_[file_id]->get_size();
-    if (file_size < size) {
-      files_[file_id]->resize(size);
-    }
-  }
-  return files_[file_id].get();
-}
-
-char *StorageImpl::generate_path(uint16_t file_id) {
-  // If "path_" ends with ".grn", the generated path also ends with ".grn".
-  // In this case, "file_id" is inserted before the ".grn".
-  // Otherwise, "file_id" is appended as a suffix.
-  const Bytes prefix = path_.get();
-  const bool has_extension = prefix.ends_with(".grn");
-  const size_t path_size = prefix.size() + 5;
-  char * const path = new (std::nothrow) char[path_size];
-  if (!path) {
-    GRNXX_ERROR() << "new char[] failed: size = " << path_size;
-    throw MemoryError();
-  }
-  if (has_extension) {
-    std::memcpy(path, prefix.data(), prefix.size() - 4);
-    std::sprintf(path + prefix.size() - 4, "_%03d", file_id);
-    std::strcpy(path + prefix.size(), ".grn");
-  } else {
-    std::memcpy(path, prefix.data(), prefix.size());
-    std::sprintf(path + prefix.size(), "_%03d", file_id);
-  }
-  return path;
-}
-
-Chunk *StorageImpl::create_chunk(File *file, uint64_t offset, uint64_t size) {
-  ChunkFlags chunk_flags = CHUNK_DEFAULT;
-  if (flags_ & STORAGE_HUGE_TLB) {
-    chunk_flags |= CHUNK_HUGE_TLB;
-  }
-  return Chunk::create(file, offset, size, chunk_flags);
-}
-
-}  // namespace storage
-}  // namespace grnxx

  Deleted: lib/grnxx/storage/storage_impl.hpp (+0 -133) 100644
===================================================================
--- lib/grnxx/storage/storage_impl.hpp    2013-08-23 10:46:34 +0900 (e8fee14)
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STORAGE_STORAGE_IMPL_HPP
-#define GRNXX_STORAGE_STORAGE_IMPL_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/duration.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/periodic_clock.hpp"
-#include "grnxx/storage.hpp"
-#include "grnxx/time.hpp"
-
-namespace grnxx {
-namespace storage {
-
-struct Header;
-class File;
-class Chunk;
-struct ChunkIndex;
-struct NodeHeader;
-
-class StorageImpl : public Storage {
- public:
-  StorageImpl();
-  ~StorageImpl();
-
-  static StorageImpl *create(const char *path,
-                             StorageFlags flags,
-                             const StorageOptions &options);
-  static StorageImpl *open(const char *path,
-                           StorageFlags flags);
-  static StorageImpl *open_or_create(const char *path,
-                                     StorageFlags flags,
-                                     const StorageOptions &options);
-
-  static bool exists(const char *path);
-  static void unlink(const char *path);
-
-  StorageNode create_node(uint32_t parent_node_id, uint64_t size);
-  StorageNode open_node(uint32_t node_id);
-
-  void unlink_node(uint32_t node_id);
-
-  void sweep(Duration lifetime);
-
-  const char *path() const;
-  StorageFlags flags() const;
-  uint64_t max_file_size() const;
-  uint16_t max_num_files() const;
-  uint32_t num_nodes() const;
-  uint16_t num_chunks() const;
-  uint64_t body_usage() const;
-  uint64_t body_size() const;
-  uint64_t total_size() const;
-
- private:
-  std::unique_ptr<char[]> path_;
-  StorageFlags flags_;
-  Header *header_;
-  ChunkIndex *header_chunk_indexes_;
-  ChunkIndex *body_chunk_indexes_;
-  std::unique_ptr<std::unique_ptr<File>[]> files_;
-  std::unique_ptr<Chunk> root_chunk_;
-  std::unique_ptr<std::unique_ptr<Chunk>[]> header_chunks_;
-  std::unique_ptr<std::unique_ptr<Chunk>[]> body_chunks_;
-  Mutex mutex_;
-  PeriodicClock clock_;
-
-  void create_file_backed_storage(const char *path, StorageFlags flags,
-                                  const StorageOptions &options);
-  void create_anonymous_storage(StorageFlags flags,
-                                const StorageOptions &options);
-  void open_storage(const char *path, StorageFlags flags);
-  void open_or_create_storage(const char *path, StorageFlags flags,
-                              const StorageOptions &options);
-  void unlink_storage();
-
-  void prepare_pointers();
-  void prepare_indexes();
-
-  NodeHeader *create_active_node(uint64_t size);
-  NodeHeader *find_idle_node(uint64_t size);
-  NodeHeader *create_idle_node(uint64_t size);
-  void divide_idle_node(NodeHeader *node_header, uint64_t size);
-  void activate_idle_node(NodeHeader *node_header);
-  NodeHeader *reserve_phantom_node();
-  NodeHeader *create_phantom_node();
-  void associate_node_with_chunk(NodeHeader *node_header,
-                                 ChunkIndex *chunk_index);
-
-  void sweep_subtree(NodeHeader *node_header);
-  void merge_idle_nodes(NodeHeader *node_header, NodeHeader *next_node_header);
-
-  ChunkIndex *create_header_chunk(ChunkIndex **remainder_chunk_index);
-  ChunkIndex *create_body_chunk(uint64_t size,
-                                ChunkIndex **remainder_chunk_index);
-  ChunkIndex *create_body_chunk(uint64_t size);
-
-  void register_idle_node(NodeHeader *node_header);
-  void unregister_idle_node(NodeHeader *node_header);
-
-  NodeHeader *get_node_header(uint32_t node_id);
-  void *get_node_body(const NodeHeader *node_header);
-  Chunk *get_header_chunk(uint16_t chunk_id);
-  Chunk *get_body_chunk(uint16_t chunk_id);
-  File *reserve_file(uint16_t file_id, uint64_t size);
-  char *generate_path(uint16_t file_id);
-
-  Chunk *create_chunk(File *file, uint64_t offset, uint64_t size);
-};
-
-}  // namespace storage
-}  // namespace grnxx
-
-#endif  // GRNXX_STORAGE_STORAGE_IMPL_HPP

  Deleted: lib/grnxx/string_builder.cpp (+0 -311) 100644
===================================================================
--- lib/grnxx/string_builder.cpp    2013-08-23 10:46:34 +0900 (0343164)
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
-  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/string_builder.hpp"
-
-#include <cmath>
-#include <cstdio>
-#include <cstring>
-#include <new>
-#include <utility>
-
-#include "grnxx/exception.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace {
-
-constexpr size_t STRING_BUILDER_MIN_BUF_SIZE = 64;
-
-}  // namespace
-
-StringBuilder::StringBuilder(StringBuilderFlags flags)
-    : buf_(),
-      begin_(nullptr),
-      end_(nullptr),
-      ptr_(nullptr),
-      flags_(flags),
-      failed_(false) {}
-
-StringBuilder::StringBuilder(size_t size, StringBuilderFlags flags)
-    : buf_(),
-      begin_(nullptr),
-      end_(nullptr),
-      ptr_(nullptr),
-      flags_(flags),
-      failed_(false) {
-  if (size != 0) {
-    buf_.reset(new (std::nothrow) char[size]);
-    if (!buf_) {
-      failed_ = true;
-      if (~flags_ & STRING_BUILDER_NOEXCEPT) {
-        GRNXX_ERROR() << "new char[" << size << "] failed";
-        throw MemoryError();
-      }
-    } else {
-      begin_ = buf_.get();
-      end_ = begin_ + size - 1;
-      ptr_ = begin_;
-      *ptr_ = '\0';
-    }
-  }
-}
-
-StringBuilder::StringBuilder(char *buf, size_t size, StringBuilderFlags flags)
-    : buf_(),
-      begin_(buf),
-      end_(buf + size - 1),
-      ptr_(buf),
-      flags_(flags),
-      failed_(false) {
-  *ptr_ = '\0';
-}
-
-StringBuilder::~StringBuilder() {}
-
-StringBuilder &StringBuilder::append(int byte) {
-  if (failed_) {
-    return *this;
-  }
-  if (ptr_ == end_) {
-    if (!auto_resize(length() + 2)) {
-      return *this;
-    }
-  }
-  *ptr_ = static_cast<char>(byte);
-  *++ptr_ = '\0';
-  return *this;
-}
-
-StringBuilder &StringBuilder::append(int byte, size_t length) {
-  if (failed_ || (length == 0)) {
-    return *this;
-  }
-  const size_t size_left = end_ - ptr_;
-  if (length > size_left) {
-    if (!auto_resize(this->length() + length + 1)) {
-      length = size_left;
-      if (length == 0) {
-        return *this;
-      }
-    }
-  }
-  std::memset(ptr_, byte, length);
-  ptr_ += length;
-  *ptr_ = '\0';
-  return *this;
-}
-
-StringBuilder &StringBuilder::append(const char *ptr, size_t length) {
-  if (failed_ || !ptr || (length == 0)) {
-    return *this;
-  }
-  const size_t size_left = end_ - ptr_;
-  if (length > size_left) {
-    if (!auto_resize(this->length() + length + 1)) {
-      length = size_left;
-      if (length == 0) {
-        return *this;
-      }
-    }
-  }
-  std::memcpy(ptr_, ptr, length);
-  ptr_ += length;
-  *ptr_ = '\0';
-  return *this;
-}
-
-StringBuilder &StringBuilder::resize(size_t length) {
-  const size_t size = end_ - ptr_;
-  if (length > size) {
-    if (!resize_buf(length + 1)) {
-      return *this;
-    }
-  }
-  ptr_ = begin_ + length;
-  *ptr_ = '\0';
-  return *this;
-}
-
-void StringBuilder::clear() {
-  ptr_ = begin_;
-  if (ptr_) {
-    *ptr_ = '\0';
-  }
-  failed_ = false;
-}
-
-bool StringBuilder::auto_resize(size_t size) {
-  if (~flags_ & STRING_BUILDER_AUTO_RESIZE) {
-    failed_ = true;
-    return false;
-  }
-  return resize_buf(size);
-}
-
-bool StringBuilder::resize_buf(size_t size) {
-  if (size < STRING_BUILDER_MIN_BUF_SIZE) {
-    size = STRING_BUILDER_MIN_BUF_SIZE;
-  } else {
-    size = size_t(2) << bit_scan_reverse(size - 1);
-  }
-  std::unique_ptr<char[]> new_buf(new (std::nothrow) char[size]);
-  if (!new_buf) {
-    failed_ = true;
-    if (~flags_ & STRING_BUILDER_NOEXCEPT) {
-      GRNXX_ERROR() << "new char [" << size << "] failed";
-      throw MemoryError();
-    }
-    return false;
-  }
-  const size_t length = ptr_ - begin_;
-  std::memcpy(new_buf.get(), begin_, length);
-  buf_ = std::move(new_buf);
-  begin_ = buf_.get();
-  end_ = begin_ + size - 1;
-  ptr_ = begin_ + length;
-  return true;
-}
-
-StringBuilder &operator<<(StringBuilder &builder, long long value) {
-  if (!builder) {
-    return builder;
-  }
-  char buf[32];
-  char *ptr = buf;
-  char *left = ptr;
-  if (value >= 0) {
-    do {
-      *ptr++ = static_cast<char>('0' + (value % 10));
-      value /= 10;
-    } while (value != 0);
-  } else {
-    *ptr++ = '-';
-    ++left;
-    do {
-      // C++11 always rounds the result toward 0.
-      *ptr++ = static_cast<char>('0' - (value % 10));
-      value /= 10;
-    } while (value != 0);
-  }
-  char *right = ptr - 1;
-  while (left < right) {
-    using std::swap;
-    swap(*left++, *right--);
-  }
-  return builder.append(buf, ptr - buf);
-}
-StringBuilder &operator<<(StringBuilder &builder, unsigned long long value) {
-  if (!builder) {
-    return builder;
-  }
-  char buf[32];
-  char *ptr = buf;
-  do {
-    *ptr++ = static_cast<char>('0' + (value % 10));
-    value /= 10;
-  } while (value != 0);
-  char *left = buf;
-  char *right = ptr - 1;
-  while (left < right) {
-    using std::swap;
-    swap(*left++, *right--);
-  }
-  return builder.append(buf, ptr - buf);
-}
-
-StringBuilder &operator<<(StringBuilder &builder, double value) {
-  if (!builder) {
-    return builder;
-  }
-  switch (std::fpclassify(value)) {
-    case FP_NORMAL:
-    case FP_SUBNORMAL:
-    case FP_ZERO: {
-      break;
-    }
-    case FP_INFINITE: {
-      if (value > 0.0) {
-        return builder.append("inf", 3);
-      } else {
-        return builder.append("-inf", 4);
-      }
-    }
-    case FP_NAN:
-    default: {
-      return builder.append("nan", 3);
-    }
-  }
-  // The maximum value of double-precision floating point number (IEEE754)
-  // is 1.797693134862316E+308.
-  char buf[512];
-  int length = std::snprintf(buf, sizeof(buf), "%f", value);
-  if (length < 0) {
-    return builder.append("n/a", 3);
-  }
-  if (static_cast<size_t>(length) >= sizeof(buf)) {
-    length = sizeof(buf) - 1;
-  }
-  return builder.append(buf, length);
-}
-
-StringBuilder &operator<<(StringBuilder &builder, bool value) {
-  return value ? builder.append("true", 4) : builder.append("false", 5);
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const void *value) {
-  if (!builder) {
-    return builder;
-  }
-  if (!value) {
-    return builder.append("nullptr", 7);
-  }
-  char buf[(sizeof(value) * 2) + 2];
-  buf[0] = '0';
-  buf[1] = 'x';
-  uintptr_t address = reinterpret_cast<uintptr_t>(value);
-  for (size_t i = 2; i < sizeof(buf); ++i) {
-    const uintptr_t digit = address >> ((sizeof(value) * 8) - 4);
-    buf[i] = static_cast<char>(
-        (digit < 10) ? ('0' + digit) : ('A' + digit - 10));
-    address <<= 4;
-  }
-  return builder.append(buf, sizeof(buf));
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const char *value) {
-  if (!builder) {
-    return builder;
-  }
-  if (!value) {
-    return builder.append("nullptr", 7);
-  }
-  return builder.append(value, std::strlen(value));
-}
-
-StringBuilder &operator<<(StringBuilder &builder, const Bytes &bytes) {
-  return builder.append(reinterpret_cast<const char *>(bytes.data()),
-                        bytes.size());
-}
-
-StringBuilder &operator<<(StringBuilder &builder,
-                          const std::exception &exception) {
-  return builder << "{ what = " << exception.what() << " }";
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/string_builder.hpp (+0 -194) 100644
===================================================================
--- lib/grnxx/string_builder.hpp    2013-08-23 10:46:34 +0900 (36cd09d)
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STRING_BUILDER_HPP
-#define GRNXX_STRING_BUILDER_HPP
-
-#include "grnxx/features.hpp"
-
-#include <exception>
-#include <memory>
-
-#include "grnxx/bytes.hpp"
-#include "grnxx/flags_impl.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-typedef FlagsImpl<StringBuilder> StringBuilderFlags;
-
-// Use the default settings.
-constexpr StringBuilderFlags STRING_BUILDER_DEFAULT     =
-    StringBuilderFlags::define(0x00);
-// Automatically resize the buffer.
-constexpr StringBuilderFlags STRING_BUILDER_AUTO_RESIZE =
-    StringBuilderFlags::define(0x01);
-// Don't throw even if memory allocation fails.
-constexpr StringBuilderFlags STRING_BUILDER_NOEXCEPT    =
-    StringBuilderFlags::define(0x02);
-
-class StringBuilder {
- public:
-  // Create an empty StringBuilder.
-  explicit StringBuilder(StringBuilderFlags flags = STRING_BUILDER_DEFAULT);
-  // Allocate "size" bytes to the internal buffer.
-  explicit StringBuilder(size_t size,
-                         StringBuilderFlags flags = STRING_BUILDER_DEFAULT);
-  // Use "buf" ("T" bytes) as the internal buffer.
-  template <size_t T>
-  explicit StringBuilder(char (&buf)[T],
-                         StringBuilderFlags flags = STRING_BUILDER_DEFAULT)
-      : buf_(),
-        begin_(buf),
-        end_(buf + T - 1),
-        ptr_(buf),
-        flags_(flags),
-        failed_(false) {
-    *ptr_ = '\0';
-  }
-  // Use "buf" ("size" bytes) as the internal buffer.
-  StringBuilder(char *buf, size_t size,
-                StringBuilderFlags flags = STRING_BUILDER_DEFAULT);
-  ~StringBuilder();
-
-  // Return true iff the builder is appendable.
-  explicit operator bool() const {
-    return !failed_;
-  }
-
-  // Return "*this" for one-liners.
-  StringBuilder &builder() {
-    return *this;
-  }
-
-  // Append a character.
-  StringBuilder &append(int byte);
-  // Append a sequence of the same character.
-  StringBuilder &append(int byte, size_t length);
-  // Append a sequence of length characters.
-  StringBuilder &append(const char *ptr, size_t length);
-
-  // Resize the string.
-  // Note that the contents of the extended part are undefined.
-  StringBuilder &resize(size_t length);
-
-  // Move the pointer to the beginning and clear the failure flag.
-  void clear();
-
-  // Return the "i"-th byte.
-  const char &operator[](size_t i) const {
-    return begin_[i];
-  }
-  // Return the "i"-th byte.
-  char &operator[](size_t i) {
-    return begin_[i];
-  }
-
-  // Return the string as a sequence of bytes.
-  Bytes bytes() const {
-    return Bytes(begin_, ptr_ - begin_);
-  }
-  // Return the address of the string.
-  const char *c_str() const {
-    return begin_ ? begin_ : "";
-  }
-  // Return the length of the string.
-  size_t length() const {
-    return ptr_ - begin_;
-  }
-
- private:
-  std::unique_ptr<char[]> buf_;
-  char *begin_;
-  char *end_;
-  char *ptr_;
-  StringBuilderFlags flags_;
-  bool failed_;
-
-  // Resize the internal buffer.
-  bool auto_resize(size_t size);
-  // Resize the internal buffer to greater than or equal to "size" bytes.
-  bool resize_buf(size_t size);
-
-  StringBuilder(const StringBuilder &) = delete;
-  StringBuilder &operator=(const StringBuilder &) = delete;
-};
-
-// Append a character.
-inline StringBuilder &operator<<(StringBuilder &builder, char value) {
-  return builder.append(value);
-}
-
-// Append a signed integer.
-StringBuilder &operator<<(StringBuilder &builder, long long value);
-
-inline StringBuilder &operator<<(StringBuilder &builder, signed char value) {
-  return builder << static_cast<long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, short value) {
-  return builder << static_cast<long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, int value) {
-  return builder << static_cast<long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, long value) {
-  return builder << static_cast<long long>(value);
-}
-
-// Append an unsigned integer.
-StringBuilder &operator<<(StringBuilder &builder, unsigned long long value);
-
-inline StringBuilder &operator<<(StringBuilder &builder, unsigned char value) {
-  return builder << static_cast<unsigned long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, unsigned short value) {
-  return builder << static_cast<unsigned long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, unsigned int value) {
-  return builder << static_cast<unsigned long long>(value);
-}
-inline StringBuilder &operator<<(StringBuilder &builder, unsigned long value) {
-  return builder << static_cast<unsigned long long>(value);
-}
-
-// Append a floating point number.
-StringBuilder &operator<<(StringBuilder &builder, double value);
-
-inline StringBuilder &operator<<(StringBuilder &builder, float value) {
-  return builder << static_cast<double>(value);
-}
-
-// Append a boolean value (true/false).
-StringBuilder &operator<<(StringBuilder &builder, bool value);
-
-// Append a pointer.
-StringBuilder &operator<<(StringBuilder &builder, const void *value);
-
-// Append a zero-terminated string.
-StringBuilder &operator<<(StringBuilder &builder, const char *value);
-
-// Append a sequence of bytes.
-StringBuilder &operator<<(StringBuilder &builder, const Bytes &bytes);
-
-// Append an exception.
-StringBuilder &operator<<(StringBuilder &builder,
-                          const std::exception &exception);
-
-}  // namespace grnxx
-
-#endif  // GRNXX_STRING_BUILDER_HPP

  Deleted: lib/grnxx/string_format.hpp (+0 -137) 100644
===================================================================
--- lib/grnxx/string_format.hpp    2013-08-23 10:46:34 +0900 (60ffda8)
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STRING_FORMAT_HPP
-#define GRNXX_STRING_FORMAT_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/string_builder.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-constexpr size_t STRING_FORMAT_LOCAL_BUF_SIZE = 64;
-
-enum StringFormatAlignmentAttribute {
-  STRING_FORMAT_ALIGNMENT_LEFT,
-  STRING_FORMAT_ALIGNMENT_RIGHT,
-  STRING_FORMAT_ALIGNMENT_CENTER
-};
-
-template <typename T>
-class StringFormatAlignment {
- public:
-  constexpr StringFormatAlignment(const T &value, size_t width, int pad,
-                                  StringFormatAlignmentAttribute attribute)
-      : value_(value),
-        width_(width),
-        pad_(pad),
-        attribute_(attribute) {}
-
-  constexpr const T &value() const {
-    return value_;
-  }
-  constexpr size_t width() const {
-    return width_;
-  }
-  constexpr int pad() const {
-    return pad_;
-  }
-  constexpr StringFormatAlignmentAttribute attribute() const {
-    return attribute_;
-  }
-
- private:
-  const T &value_;
-  size_t width_;
-  int pad_;
-  StringFormatAlignmentAttribute attribute_;
-};
-
-class StringFormat {
- public:
-  StringFormat() = delete;
-  ~StringFormat() = delete;
-
-  StringFormat(const StringFormat &) = delete;
-  StringFormat &operator=(const StringFormat &) = delete;
-
-  template <typename T>
-  static constexpr StringFormatAlignment<T> align_left(
-      const T &value, size_t width, int pad = ' ') {
-    return align<T>(value, width, pad, STRING_FORMAT_ALIGNMENT_LEFT);
-  }
-  template <typename T>
-  static constexpr StringFormatAlignment<T> align_right(
-      const T &value, size_t width, int pad = ' ') {
-    return align<T>(value, width, pad, STRING_FORMAT_ALIGNMENT_RIGHT);
-  }
-  template <typename T>
-  static constexpr StringFormatAlignment<T> align_center(
-      const T &value, size_t width, int pad = ' ') {
-    return align<T>(value, width, pad, STRING_FORMAT_ALIGNMENT_CENTER);
-  }
-
-  template <typename T>
-  static constexpr StringFormatAlignment<T> align(
-      const T &value, size_t width, int pad = ' ',
-      StringFormatAlignmentAttribute attribute = STRING_FORMAT_ALIGNMENT_LEFT) {
-    return StringFormatAlignment<T>(value, width, pad, attribute);
-  }
-};
-
-template <typename T>
-StringBuilder &operator<<(StringBuilder &builder,
-                          const StringFormatAlignment<T> &alignment) {
-  char local_buf[STRING_FORMAT_LOCAL_BUF_SIZE];
-  const StringBuilderFlags local_flags =
-      (alignment.width() >= sizeof(local_buf)) ?
-      STRING_BUILDER_AUTO_RESIZE : STRING_BUILDER_DEFAULT;
-
-  StringBuilder local_builder(local_buf, local_flags);
-  local_builder << alignment.value();
-  if (local_builder.length() >= alignment.width()) {
-    return builder.append(local_builder.c_str(), alignment.width());
-  }
-
-  const size_t unused_size = alignment.width() - local_builder.length();
-  switch (alignment.attribute()) {
-    case STRING_FORMAT_ALIGNMENT_LEFT: {
-      builder.append(local_builder.c_str(), local_builder.length());
-      builder.append(alignment.pad(), unused_size);
-      break;
-    }
-    case STRING_FORMAT_ALIGNMENT_RIGHT: {
-      builder.append(alignment.pad(), unused_size);
-      builder.append(local_builder.c_str(), local_builder.length());
-      break;
-    }
-    case STRING_FORMAT_ALIGNMENT_CENTER: {
-      const size_t offset = unused_size / 2;
-      builder.append(alignment.pad(), offset);
-      builder.append(local_builder.c_str(), local_builder.length());
-      builder.append(alignment.pad(), unused_size - offset);
-      break;
-    }
-  }
-  return builder;
-}
-
-}  // namespace grnxx
-
-#endif  // GRNXX_STRING_FORMAT_HPP

  Deleted: lib/grnxx/system_clock.cpp (+0 -32) 100644
===================================================================
--- lib/grnxx/system_clock.cpp    2013-08-23 10:46:34 +0900 (39d390a)
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-  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/system_clock.hpp"
-
-#include <chrono>
-
-namespace grnxx {
-
-Time SystemClock::now() {
-  // The epoch of std::chrono::system_clock is not guaranteed to be the Unix
-  // epoch. So, (now() - from_time_t(0)) is used instead of time_since_epoch().
-  return Time(std::chrono::duration_cast<std::chrono::microseconds>(
-              (std::chrono::system_clock::now() -
-               std::chrono::system_clock::from_time_t(0))).count());
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/system_clock.hpp (+0 -35) 100644
===================================================================
--- lib/grnxx/system_clock.hpp    2013-08-23 10:46:34 +0900 (c92ee3f)
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_SYSTEM_CLOCK_HPP
-#define GRNXX_SYSTEM_CLOCK_HPP
-
-#include "grnxx/features.hpp"
-
-#include "grnxx/time.hpp"
-
-namespace grnxx {
-
-class SystemClock {
- public:
-  // Return the current time.
-  static Time now();
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_SYSTEM_CLOCK_HPP

  Deleted: lib/grnxx/thread.cpp (+0 -298) 100644
===================================================================
--- lib/grnxx/thread.cpp    2013-08-23 10:46:34 +0900 (b8f2ec3)
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
-  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/thread.hpp"
-
-#ifdef GRNXX_WINDOWS
-# include <process.h>
-# include <windows.h>
-#else  // GRNXX_WINDOWS
-# include <pthread.h>
-#endif  // GRNXX_WINDOWS
-
-#ifdef GRNXX_HAS_SCHED_YIELD
-# include <sched.h>
-#endif  // GRNXX_HAS_SCHED_YIELD
-
-#ifdef GRNXX_HAS_NANOSLEEP
-# include <time.h>
-#endif  // GRNXX_HAS_NANOSLEEP
-
-#ifdef GRNXX_WINDOWS
-# include <cerrno>
-#endif  // GRNXX_WINDOWS
-
-#include <limits>
-#include <memory>
-#include <new>
-
-// TODO: Use the following in future.
-//#include <chrono>
-//#include <thread>
-
-#include "grnxx/errno.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/string_builder.hpp"
-#include "grnxx/system_clock.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-namespace {
-
-enum ThreadStatus : uint32_t {
-  THREAD_INITIAL  = 0,
-  THREAD_JOINABLE = 1,
-  THREAD_JOINED   = 2,
-  THREAD_DETACHED = 3
-};
-
-StringBuilder &operator<<(StringBuilder &builder, ThreadStatus status) {
-  switch (status) {
-    case THREAD_INITIAL: {
-      return builder << "THREAD_INITIAL";
-    }
-    case THREAD_JOINABLE: {
-      return builder << "THREAD_JOINABLE";
-    }
-    case THREAD_JOINED: {
-      return builder << "THREAD_JOINED";
-    }
-    case THREAD_DETACHED: {
-      return builder << "THREAD_DETACHED";
-    }
-    default: {
-      return builder << "n/a";
-    }
-  }
-}
-
-class ThreadImpl : public Thread {
- public:
-  using Routine = Thread::Routine;
-
-  ThreadImpl();
-  ~ThreadImpl();
-
-  void start(const Routine &routine);
-
-  void join();
-  void detach();
-
- private:
-#ifdef GRNXX_WINDOWS
-  HANDLE thread_;
-#else  // GRNXX_WINDOWS
-  pthread_t thread_;
-#endif  // GRNXX_WINDOWS
-  ThreadStatus status_;
-
-#ifdef GRNXX_WINDOWS
-  static unsigned thread_main(void *arg);
-#else  // GRNXX_WINDOWS
-  static void *thread_main(void *arg);
-#endif  // GRNXX_WINDOWS
-};
-
-ThreadImpl::ThreadImpl() : thread_(), status_(THREAD_INITIAL) {}
-
-ThreadImpl::~ThreadImpl() {
-  // A thread must be joined or detached before destruction.
-  if (status_ == THREAD_JOINABLE) {
-    GRNXX_WARNING() << "Bad thread destruction: status = " << status_;
-  }
-}
-
-void ThreadImpl::start(const Routine &routine) {
-  std::unique_ptr<Routine> routine_clone(new (std::nothrow) Routine(routine));
-  if (!routine_clone) {
-    GRNXX_ERROR() << "new grnxx::Thread::Routine failed";
-    throw MemoryError();
-  }
-#ifdef GRNXX_WINDOWS
-  const uintptr_t handle = ::_beginthreadex(nullptr, 0, thread_main,
-                                            routine_clone.get(), 0, nullptr);
-  if (handle == 0) {
-    const Errno error_code(errno);
-    GRNXX_ERROR() << "failed to create thread: call = _beginthreadex"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-  thread_ = reinterpret_cast<HANDLE>(handle);
-#else  // GRNXX_WINDOWS
-  const int error = ::pthread_create(&thread_, nullptr, thread_main,
-                                     routine_clone.get());
-  if (error != 0) {
-    const Errno error_code(error);
-    GRNXX_ERROR() << "failed to create thread: call = ::pthread_create"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-#endif  // GRNXX_WINDOWS
-  routine_clone.release();
-  status_ = THREAD_JOINABLE;
-}
-
-void ThreadImpl::join() {
-  if (status_ != THREAD_JOINABLE) {
-    GRNXX_ERROR() << "invalid operation: status = " << status_;
-    throw LogicError();
-  }
-  status_ = THREAD_JOINED;
-#ifdef GRNXX_WINDOWS
-  if (::WaitForSingleObject(thread_, INFINITE) == WAIT_FAILED) {
-    const Errno error_code(::GetLastError());
-    GRNXX_ERROR() << "failed to join thread: call = ::WaitForSingleObject"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-  if (::CloseHandle(thread_) != 0) {
-    const Errno error_code(::GetLastError());
-    GRNXX_ERROR() << "failed to close thread: call = ::CloseHandle"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-#else  // GRNXX_WINDOWS
-  const int error = ::pthread_join(thread_, nullptr);
-  if (error != 0) {
-    const Errno error_code(error);
-    GRNXX_ERROR() << "failed to join thread: call = ::pthread_join"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-#endif  // GRNXX_WINDOWS
-}
-
-void ThreadImpl::detach() {
-  if (status_ != THREAD_JOINABLE) {
-    GRNXX_ERROR() << "invalid operation: status = " << status_;
-    throw LogicError();
-  }
-  status_ = THREAD_DETACHED;
-#ifdef GRNXX_WINDOWS
-  if (::CloseHandle(thread_) != 0) {
-    const Errno error_code(::GetLastError());
-    GRNXX_ERROR() << "failed to detach thread: call = ::CloseHandle"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-#else  // GRNXX_WINDOWS
-  const int error = ::pthread_detach(thread_);
-  if (error != 0) {
-    const Errno error_code(error);
-    GRNXX_ERROR() << "failed to detach thread: call = ::pthread_detach"
-                  << ", errno = " << error_code;
-    throw SystemError(error_code);
-  }
-#endif  // GRNXX_WINDOWS
-}
-
-#ifdef GRNXX_WINDOWS
-unsigned ThreadImpl::thread_main(void *arg) {
-  std::unique_ptr<Routine> routine(static_cast<Routine *>(arg));
-  (*routine)();
-  ::_endthreadex(0);
-  return 0;
-}
-#else  // GRNXX_WINDOWS
-void *ThreadImpl::thread_main(void *arg) {
-  std::unique_ptr<Routine> routine(static_cast<Routine *>(arg));
-  (*routine)();
-  return nullptr;
-}
-#endif  // GRNXX_WINDOWS
-
-}  // namespace
-
-Thread::Thread() {}
-Thread::~Thread() {}
-
-Thread *Thread::create(const Routine &routine) {
-  std::unique_ptr<ThreadImpl> thread(new (std::nothrow) ThreadImpl);
-  if (!thread) {
-    GRNXX_ERROR() << "new grnxx::ThreadImpl failed";
-    throw MemoryError();
-  }
-  thread->start(routine);
-  return thread.release();
-}
-
-void Thread::yield() {
-#ifdef GRNXX_WINDOWS
-  ::SwitchToThread();
-#elif defined(GRNXX_HAS_SCHED_YIELD)
-  ::sched_yield();
-#else  // defined(GRNXX_HAS_SCHED_YIELD)
-  sleep_for(Duration(0));
-#endif  // defined(GRNXX_HAS_SCHED_YIELD)
-  // TODO: Use the following in future.
-//  std::this_thread::yield();
-}
-
-void Thread::sleep_for(Duration duration) {
-#ifdef GRNXX_WINDOWS
-  if (duration.count() <= 0) {
-    ::Sleep(0);
-  } else {
-    const int64_t milliseconds = duration.count() / 1000;
-    if (milliseconds <
-        static_cast<int64_t>(std::numeric_limits<DWORD>::max())) {
-      ::Sleep(static_cast<DWORD>(milliseconds));
-    } else {
-      ::Sleep(std::numeric_limits<DWORD>::max());
-    }
-  }
-#elif defined(GRNXX_HAS_NANOSLEEP)
-  struct timespec request;
-  if (duration.count() <= 0) {
-    request.tv_sec = 0;
-    request.tv_nsec = 0;
-  } else {
-    const int64_t seconds = duration.count() / 1000000;
-    if (seconds < std::numeric_limits<time_t>::max()) {
-      request.tv_sec = static_cast<time_t>(seconds);
-    } else {
-      request.tv_sec = std::numeric_limits<time_t>::max();
-    }
-    duration %= Duration::seconds(1);
-    request.tv_nsec = static_cast<long>(duration.count() * 1000);
-  }
-  // Note that ::nanosleep() requires -lrt option.
-  ::nanosleep(&request, nullptr);
-#else // defined(GRNXX_HAS_NANOSLEEP)
-  // Note that POSIX.1-2008 removes the specification of ::usleep().
-  if (duration.count() <= 0) {
-    ::usleep(0);
-  } else {
-    const int64_t microseconds = duration.count();
-    if (microseconds < std::numeric_limits<useconds_t>::max()) {
-      ::usleep(static_cast<useconds_t>(microseconds));
-    } else {
-      ::usleep(std::numeric_limits<useconds_t>::max());
-    }
-  }
-#endif // defined(GRNXX_HAS_NANOSLEEP)
-  // TODO: Use the following in future.
-//  std::this_thread::sleep_for(std::chrono::microseconds(duration.count()));
-}
-
-void Thread::sleep_until(Time time) {
-  const Time now = SystemClock::now();
-  sleep_for((time > now) ? (time - now) : Duration(0));
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/thread.hpp (+0 -56) 100644
===================================================================
--- lib/grnxx/thread.hpp    2013-08-23 10:46:34 +0900 (2ebde3e)
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_THREAD_HPP
-#define GRNXX_THREAD_HPP
-
-#include "grnxx/features.hpp"
-
-#include <functional>
-
-#include "grnxx/duration.hpp"
-#include "grnxx/time.hpp"
-
-namespace grnxx {
-
-class Thread {
- public:
-  using Routine = std::function<void()>;
-
-  Thread();
-  virtual ~Thread();
-
-  // Create a thread.
-  static Thread *create(const Routine &routine);
-
-  // Yield the processor/core associated with the current thread.
-  static void yield();
-
-  // Sleep for "duration".
-  static void sleep_for(Duration duration);
-  // Sleep until "time".
-  static void sleep_until(Time time);
-
-  // Wait until the thread finishes.
-  virtual void join() = 0;
-  // Separate the thread from this object.
-  virtual void detach() = 0;
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_THREAD_HPP

  Deleted: lib/grnxx/time.cpp (+0 -117) 100644
===================================================================
--- lib/grnxx/time.cpp    2013-08-23 10:46:34 +0900 (abd3e53)
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-  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/time.hpp"
-
-#include <ctime>
-
-#include "grnxx/lock.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/string_builder.hpp"
-#include "grnxx/string_format.hpp"
-
-namespace grnxx {
-namespace {
-
-// Note: std::tm does not support usec (microseconds).
-BrokenDownTime create_broken_down_time(const std::tm &tm, int64_t count) {
-  BrokenDownTime time;
-  time.usec = static_cast<int>(count % 1000000);
-  time.sec = tm.tm_sec;
-  time.min = tm.tm_min;
-  time.hour = tm.tm_hour;
-  time.mday = tm.tm_mday;
-  time.mon = tm.tm_mon;
-  time.year = tm.tm_year;
-  time.wday = tm.tm_wday;
-  time.yday = tm.tm_yday;
-  time.isdst = tm.tm_isdst;
-  return time;
-}
-
-}  // namespace
-
-BrokenDownTime Time::universal_time() const {
-  const std::time_t posix_time = static_cast<std::time_t>(count_ / 1000000);
-  std::tm tm;
-#ifdef GRNXX_MSC
-  if (::gmtime_s(&posix_time, &tm) != 0) {
-    return BrokenDownTime::invalid_value();
-  }
-#elif defined(GRNXX_HAS_GMTIME_R)
-  if (::gmtime_r(&posix_time, &tm) == nullptr) {
-    return BrokenDownTime::invalid_value();
-  }
-#else  // defined(GRNXX_HAS_GMTIME_R)
-  // Lock is used for exclusive access, but it is still not thread-safe
-  // because other threads may call std::gmtime().
-  static Mutex mutex;
-  Lock lock(&mutex);
-  std::tm * const shared_tm = std::gmtime(&posix_time);
-  if (!shared_tm) {
-    return BrokenDownTime::invalid_value();
-  }
-  tm = *shared_tm;
-#endif  // defined(GRNXX_HAS_GMTIME_R)
-  return create_broken_down_time(tm, count_);
-}
-
-BrokenDownTime Time::local_time() const {
-  const std::time_t posix_time = static_cast<std::time_t>(count_ / 1000000);
-  std::tm tm;
-#ifdef GRNXX_MSC
-  if (::localtime_s(&posix_time, &tm) != 0) {
-    return BrokenDownTime::invalid_value();
-  }
-#elif defined(GRNXX_HAS_LOCALTIME_R)
-  if (::localtime_r(&posix_time, &tm) == nullptr) {
-    return BrokenDownTime::invalid_value();
-  }
-#else  // defined(GRNXX_HAS_LOCALTIME_R)
-  // Lock is used for exclusive access, but it is still not thread-safe
-  // because other threads may call std::localtime().
-  static Mutex mutex;
-  Lock lock(&mutex);
-  std::tm * const shared_tm = std::localtime(&posix_time);
-  if (!shared_tm) {
-    return BrokenDownTime::invalid_value();
-  }
-  tm = *shared_tm;
-#endif  // defined(GRNXX_HAS_LOCALTIME_R)
-  return create_broken_down_time(tm, count_);
-}
-
-StringBuilder &operator<<(StringBuilder &builder, Time time) {
-  if (!builder) {
-    return builder;
-  }
-  uint64_t count;
-  if (time.count() >= 0) {
-    count = time.count();
-  } else {
-    builder << '-';
-    count = -time.count();
-  }
-  builder << (count / 1000000);
-  count %= 1000000;
-  if (count != 0) {
-    builder << '.' << StringFormat::align_right(count, 6, '0');
-  }
-  return builder;
-}
-
-}  // namespace grnxx

  Deleted: lib/grnxx/time.hpp (+0 -116) 100644
===================================================================
--- lib/grnxx/time.hpp    2013-08-23 10:46:34 +0900 (c8748b3)
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_TIME_HPP
-#define GRNXX_TIME_HPP
-
-#include "grnxx/features.hpp"
-
-#include <limits>
-
-#include "grnxx/broken_down_time.hpp"
-#include "grnxx/duration.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class StringBuilder;
-
-// Time in microseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
-// 64-bit tick count (usec) is used.
-class Time {
- public:
-  // Trivial default constructor.
-  Time() = default;
-  // Construct a time object whose tick count is "count".
-  explicit constexpr Time(int64_t count) : count_(count) {}
-
-  // Return the minimum tick count.
-  static constexpr Time min() {
-    return Time(std::numeric_limits<int64_t>::min());
-  }
-  // Return the maximum tick count.
-  static constexpr Time max() {
-    return Time(std::numeric_limits<int64_t>::max());
-  }
-
-  // Transform tick count to broken-down time (UTC).
-  BrokenDownTime universal_time() const;
-  // Transform tick count to broken-down time (local).
-  BrokenDownTime local_time() const;
-
-  // Return the tick count.
-  constexpr int64_t count() const {
-    return count_;
-  }
-  // Set the tick count.
-  void set_count(int64_t count) {
-    count_ = count;
-  }
-
- private:
-  int64_t count_;
-
-  // Copyable.
-};
-
-inline Time &operator+=(Time &lhs, Duration rhs) {
-  lhs.set_count(lhs.count() + rhs.count());
-  return lhs;
-}
-inline Time &operator-=(Time &lhs, Duration rhs) {
-  lhs.set_count(lhs.count() - rhs.count());
-  return lhs;
-}
-
-inline constexpr Time operator+(Time lhs, Duration rhs) {
-  return Time(lhs.count() + rhs.count());
-}
-inline constexpr Time operator+(Duration lhs, Time rhs) {
-  return Time(lhs.count() + rhs.count());
-}
-inline constexpr Time operator-(Time lhs, Duration rhs) {
-  return Time(lhs.count() - rhs.count());
-}
-inline constexpr Duration operator-(Time lhs, Time rhs) {
-  return Duration(lhs.count() - rhs.count());
-}
-
-inline constexpr bool operator==(Time lhs, Time rhs) {
-  return lhs.count() == rhs.count();
-}
-inline constexpr bool operator!=(Time lhs, Time rhs) {
-  return lhs.count() != rhs.count();
-}
-inline constexpr bool operator<(Time lhs, Time rhs) {
-  return lhs.count() < rhs.count();
-}
-inline constexpr bool operator<=(Time lhs, Time rhs) {
-  return lhs.count() <= rhs.count();
-}
-inline constexpr bool operator>(Time lhs, Time rhs) {
-  return lhs.count() > rhs.count();
-}
-inline constexpr bool operator>=(Time lhs, Time rhs) {
-  return lhs.count() >= rhs.count();
-}
-
-StringBuilder &operator<<(StringBuilder &builder, Time time);
-
-}  // namespace grnxx
-
-#endif  // GRNXX_TIME_HPP

  Deleted: lib/grnxx/traits.hpp (+0 -89) 100644
===================================================================
--- lib/grnxx/traits.hpp    2013-08-23 10:46:34 +0900 (cb57723)
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_TRAITS_HPP
-#define GRNXX_TRAITS_HPP
-
-#include "grnxx/features.hpp"
-
-#include <type_traits>
-
-namespace grnxx {
-
-class GeoPoint;
-
-// A simple/complex type should use pass by value/reference.
-template <typename T>
-struct PreferredArgument {
-  using Type = typename std::conditional<std::is_scalar<T>::value,
-                                         T, const T &>::type;
-};
-// GeoPoint is not a scalar type but a simple type.
-template <> struct PreferredArgument<GeoPoint> {
-  using Type = GeoPoint;
-};
-
-//// Check if operator<() is defined or not.
-//struct HasLessHelper {
-//  template <typename T>
-//  static auto check(T *p) -> decltype(p->operator<(*p), std::true_type());
-//  template <typename T>
-//  static auto check(T *p) -> decltype(operator<(*p, *p), std::true_type());
-//  template <typename>
-//  static auto check(...) -> decltype(std::false_type());
-//};
-//// Check if T has operator<() or not.
-//template <typename T>
-//struct HasLess {
-//  static constexpr bool value() {
-//    return std::conditional<std::is_scalar<T>::value, std::true_type,
-//                            decltype(HasLessHelper::check<T>(0))>::type::value;
-//  }
-//};
-
-//// Check if T has starts_with() or not.
-//struct HasStartsWithHelper {
-//  template <typename T>
-//  static auto check(T *p) -> decltype(p->starts_with(*p), std::true_type());
-//  template <typename>
-//  static auto check(...) -> decltype(std::false_type());
-//};
-//// Check if T has operator<() or not.
-//template <typename T>
-//struct HasStartsWith {
-//  static constexpr bool value() {
-//    return decltype(HasStartsWithHelper::check<T>(0))::value;
-//  }
-//};
-
-// Type traits.
-template <typename T>
-struct Traits {
-  using Type = T;
-  using ArgumentType = typename PreferredArgument<T>::Type;
-
-//  static constexpr bool has_less() {
-//    return HasLess<T>::value();
-//  }
-//  static constexpr bool has_starts_with() {
-//    return HasStartsWith<T>::value();
-//  }
-};
-
-}  // namespace grnxx
-
-#endif  // GRNXX_TRAITS_HPP

  Deleted: lib/grnxx/types.hpp (+0 -47) 100644
===================================================================
--- lib/grnxx/types.hpp    2013-08-23 10:46:34 +0900 (670f4f1)
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_STDINT_HPP
-#define GRNXX_STDINT_HPP
-
-#include "grnxx/features.hpp"
-
-#include <cstddef>
-#include <cstdint>
-
-namespace grnxx {
-
-using std::nullptr_t;
-
-using std::size_t;
-
-using std::int8_t;
-using std::int16_t;
-using std::int32_t;
-using std::int64_t;
-
-using std::uint8_t;
-using std::uint16_t;
-using std::uint32_t;
-using std::uint64_t;
-
-using std::intptr_t;
-using std::uintptr_t;
-
-}  // namespace grnxx
-
-#endif  // GRNXX_STDINT_HPP

  Deleted: obsolete/lib/grnxx/alpha/Makefile.am (+0 -20) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/Makefile.am    2013-08-23 10:46:34 +0900 (ab734ad)
+++ /dev/null
@@ -1,20 +0,0 @@
-SUBDIRS = map
-
-noinst_LTLIBRARIES = libgrnxx_alpha.la
-
-libgrnxx_alpha_la_LIBADD =		\
-	map/libgrnxx_alpha_map.la
-
-libgrnxx_alpha_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_alpha_la_SOURCES =		\
-	double_array.cpp		\
-	dummy.cpp			\
-	map.cpp
-
-libgrnxx_alpha_includedir = ${includedir}/grnxx/alpha
-libgrnxx_alpha_include_HEADERS =	\
-	double_array.hpp		\
-	dummy.hpp			\
-	map.hpp				\
-	map_range.hpp

  Deleted: obsolete/lib/grnxx/alpha/double_array.cpp (+0 -814) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/double_array.cpp    2013-08-23 10:46:34 +0900 (95a2f44)
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
-  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/alpha/double_array.hpp"
-
-#include "grnxx/exception.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-DoubleArrayCreate DOUBLE_ARRAY_CREATE;
-DoubleArrayOpen DOUBLE_ARRAY_OPEN;
-
-DoubleArrayHeader::DoubleArrayHeader()
-  : nodes_block_id_(io::BLOCK_INVALID_ID),
-    siblings_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_(MUTEX_UNLOCKED) {
-  for (uint32_t i = 0; i < DOUBLE_ARRAY_MAX_CHUNK_LEVEL; ++i) {
-    leaders_[i] = DOUBLE_ARRAY_INVALID_LEADER;
-  }
-}
-
-DoubleArrayKey::DoubleArrayKey(uint64_t id, const void *address,
-                               uint64_t length)
-  : id_low_(static_cast<uint32_t>(id)),
-    id_high_(static_cast<uint8_t>(id >> 32)),
-    buf_{ '\0', '\0', '\0' } {
-  std::memcpy(buf_, address, length);
-}
-
-DoubleArrayImpl::~DoubleArrayImpl() {
-  if (!initialized_) try {
-    // Allocated blocks are unlinked if initialization failed.
-    if (header_->nodes_block_id() != io::BLOCK_INVALID_ID) {
-      nodes_.unlink(pool_, header_->nodes_block_id());
-    }
-    if (header_->siblings_block_id() != io::BLOCK_INVALID_ID) {
-      siblings_.unlink(pool_, header_->siblings_block_id());
-    }
-    if (header_->chunks_block_id() != io::BLOCK_INVALID_ID) {
-      chunks_.unlink(pool_, header_->chunks_block_id());
-    }
-    if (header_->entries_block_id() != io::BLOCK_INVALID_ID) {
-      entries_.unlink(pool_, header_->entries_block_id());
-    }
-    if (header_->keys_block_id() != io::BLOCK_INVALID_ID) {
-      keys_.unlink(pool_, header_->keys_block_id());
-    }
-    if (block_info_) {
-      pool_.free_block(*block_info_);
-    }
-  } catch (...) {
-  }
-}
-
-std::unique_ptr<DoubleArrayImpl> DoubleArrayImpl::create(io::Pool pool) {
-  std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::alpha::DoubleArrayImpl failed";
-    GRNXX_THROW();
-  }
-  impl->create_double_array(pool);
-  return impl;
-}
-
-std::unique_ptr<DoubleArrayImpl> DoubleArrayImpl::open(io::Pool pool,
-                                                       uint32_t block_id) {
-  std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
-  if (!impl) {
-    GRNXX_ERROR() << "new grnxx::alpha::DoubleArrayImpl failed";
-    GRNXX_THROW();
-  }
-  impl->open_double_array(pool, block_id);
-  return impl;
-}
-
-bool DoubleArrayImpl::search(const uint8_t *ptr, uint64_t length,
-                             uint64_t *key_pos) {
-  uint64_t node_id = root_node_id();
-  uint64_t query_pos = 0;
-  if (!search_leaf(ptr, length, node_id, query_pos)) {
-    return false;
-  }
-
-  // Note that nodes_[node_id] might be updated by other threads/processes.
-  const DoubleArrayNode node = nodes_[node_id];
-  if (!node.is_leaf()) {
-    return false;
-  }
-
-  if (node.key_length() == length) {
-    if (get_key(node.key_pos()).equals_to(ptr, length, query_pos)) {
-      if (key_pos) {
-        *key_pos = node.key_pos();
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-bool DoubleArrayImpl::insert(const uint8_t *ptr, uint64_t length,
-                             uint64_t *key_pos) {
-  // 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(ptr, length, node_id, query_pos);
-  if (!insert_leaf(ptr, length, node_id, query_pos)) {
-    if (key_pos) {
-      *key_pos = nodes_[node_id].key_pos();
-    }
-    return false;
-  }
-
-  const int64_t new_key_id = header_->next_key_id();
-  const uint64_t new_key_pos = append_key(ptr, length, new_key_id);
-
-  header_->set_total_key_length(header_->total_key_length() + length);
-  header_->set_num_keys(header_->num_keys() + 1);
-
-  // 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_->set_max_key_id(new_key_id);
-    header_->set_next_key_id(new_key_id + 1);
-  } else {
-    header_->set_next_key_id(entries_[new_key_id].next());
-  }
-
-  entries_[new_key_id].set_key(new_key_pos, length);
-  nodes_[node_id].set_key(new_key_pos, length);
-  if (key_pos) {
-    *key_pos = new_key_pos;
-  }
-  return true;
-}
-
-bool DoubleArrayImpl::remove(int64_t key_id) {
-  // TODO: Exclusive access control is required.
-  if ((key_id < 0) || (key_id > header_->max_key_id())) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const DoubleArrayKey &key = get_key(entry.key_pos());
-  return remove_key(static_cast<const uint8_t *>(
-      key.ptr()), entry.key_length());
-}
-
-bool DoubleArrayImpl::remove(const uint8_t *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(ptr, length);
-}
-
-bool DoubleArrayImpl::update(int64_t key_id, const uint8_t *ptr,
-                             uint64_t length, uint64_t *key_pos) {
-  // TODO: Exclusive access control is required.
-  if ((key_id < 0) || (key_id > header_->max_key_id())) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const DoubleArrayKey &key = get_key(entry.key_pos());
-  return update_key(static_cast<const uint8_t *>(key.ptr()), entry.key_length(),
-                    key_id, ptr, length, key_pos);
-}
-
-bool DoubleArrayImpl::update(const uint8_t *src_ptr, uint64_t src_length,
-                             const uint8_t *dest_ptr, uint64_t dest_length,
-                             uint64_t *key_pos) {
-  // TODO: Exclusive access control is required.
-  uint64_t src_key_id;
-  if (!search(src_ptr, src_length, &src_key_id)) {
-    return false;
-  }
-  return update_key(src_ptr, src_length, src_key_id,
-                    dest_ptr, dest_length, key_pos);
-}
-
-bool DoubleArrayImpl::update_key(const uint8_t *src_ptr, uint64_t src_length,
-                                 uint64_t src_key_id, const uint8_t *dest_ptr,
-                                 uint64_t dest_length, uint64_t *key_pos) {
-//  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)) {
-    if (key_pos) {
-      *key_pos = nodes_[node_id].key_pos();
-    }
-    return false;
-  }
-
-  const uint64_t new_key_pos = append_key(dest_ptr, dest_length, src_key_id);
-  header_->set_total_key_length(
-      header_->total_key_length() + dest_length - src_length);
-  entries_[src_key_id].set_key(new_key_pos, dest_length);
-  nodes_[node_id].set_key(new_key_pos, dest_length);
-  if (key_pos) {
-    *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(DOUBLE_ARRAY_INVALID_OFFSET);
-  return true;
-}
-
-DoubleArrayImpl::DoubleArrayImpl()
-  : pool_(),
-    block_info_(nullptr),
-    header_(nullptr),
-    nodes_(),
-    siblings_(),
-    chunks_(),
-    entries_(),
-    keys_(),
-    initialized_(false) {}
-
-void DoubleArrayImpl::create_double_array(io::Pool pool) {
-  pool_ = pool;
-
-  block_info_ = pool_.create_block(sizeof(DoubleArrayHeader));
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<DoubleArrayHeader *>(block_address);
-  *header_ = DoubleArrayHeader();
-
-  nodes_.create(pool);
-  header_->set_nodes_block_id(nodes_.block_id());
-  siblings_.create(pool);
-  header_->set_siblings_block_id(siblings_.block_id());
-  chunks_.create(pool);
-  header_->set_chunks_block_id(chunks_.block_id());
-  entries_.create(pool);
-  header_->set_entries_block_id(entries_.block_id());
-  keys_.create(pool);
-  header_->set_keys_block_id(keys_.block_id());
-
-  reserve_node(root_node_id());
-  nodes_[DOUBLE_ARRAY_INVALID_OFFSET].set_is_origin(true);
-
-  initialized_ = true;
-}
-
-void DoubleArrayImpl::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<DoubleArrayHeader *>(block_address);
-
-  // TODO: Check the format.
-
-  nodes_.open(pool_, header_->nodes_block_id());
-  siblings_.open(pool_, header_->siblings_block_id());
-  chunks_.open(pool_, header_->chunks_block_id());
-  entries_.open(pool_, header_->entries_block_id());
-  keys_.open(pool_, header_->keys_block_id());
-}
-
-bool DoubleArrayImpl::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;
-  }
-
-  if (length != nodes_[node_id].key_length()) {
-    return false;
-  }
-
-  const uint64_t key_pos = nodes_[node_id].key_pos();
-  const DoubleArrayKey &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(DOUBLE_ARRAY_INVALID_OFFSET);
-  entries_[key_id].set_next(header_->next_key_id());
-
-  header_->set_next_key_id(key_id);
-  header_->set_total_key_length(header_->total_key_length() - length);
-  header_->set_num_keys(header_->num_keys() - 1);
-  return true;
-}
-
-bool DoubleArrayImpl::search_leaf(const uint8_t *ptr, uint64_t length,
-                                  uint64_t &node_id, uint64_t &query_pos) {
-  for ( ; query_pos < length; ++query_pos) {
-    const DoubleArrayNode 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 DoubleArrayNode node = nodes_[node_id];
-  if (node.is_leaf()) {
-    return true;
-  }
-
-  if (node.child() != DOUBLE_ARRAY_TERMINAL_LABEL) {
-    return false;
-  }
-  node_id = node.offset() ^ DOUBLE_ARRAY_TERMINAL_LABEL;
-  return nodes_[node_id].is_leaf();
-}
-
-bool DoubleArrayImpl::insert_leaf(const uint8_t *ptr, uint64_t length,
-                                  uint64_t &node_id, uint64_t query_pos) {
-  const DoubleArrayNode node = nodes_[node_id];
-  if (node.is_leaf()) {
-    const DoubleArrayKey &key = get_key(node.key_pos());
-    uint64_t i = query_pos;
-    while ((i < length) && (i < node.key_length())) {
-      if (ptr[i] != key[i]) {
-        break;
-      }
-      ++i;
-    }
-    if ((i == length) && (i == node.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() == DOUBLE_ARRAY_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]) : DOUBLE_ARRAY_TERMINAL_LABEL;
-    if ((node.offset() == DOUBLE_ARRAY_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 DoubleArrayImpl::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 DoubleArrayNode node = nodes_[node_id];
-  uint64_t offset;
-  if (node.is_leaf() || (node.offset() == DOUBLE_ARRAY_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(node.key_pos(), node.key_length());
-    // TODO: Must be update at once.
-  } else if (node.offset() == DOUBLE_ARRAY_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 == DOUBLE_ARRAY_INVALID_LABEL) {
-    nodes_[node_id].set_child(label);
-  } else if ((label == DOUBLE_ARRAY_TERMINAL_LABEL) ||
-             ((child_label != DOUBLE_ARRAY_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);
-    siblings_[next] = child_label;
-    nodes_[next].set_has_sibling(true);
-    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].has_sibling() ?
-        siblings_[prev] : DOUBLE_ARRAY_INVALID_LABEL;
-    while (label > sibling_label) {
-      prev = offset ^ sibling_label;
-//      GRN_DAT_DEBUG_THROW_IF(nodes_[prev].label() != sibling_label);
-      sibling_label = nodes_[prev].has_sibling() ?
-          siblings_[prev] : DOUBLE_ARRAY_INVALID_LABEL;
-    }
-//    GRN_DAT_DEBUG_THROW_IF(label == sibling_label);
-    siblings_[next] = siblings_[prev];
-    siblings_[prev] = label;
-    nodes_[next].set_has_sibling(nodes_[prev].has_sibling());
-    nodes_[prev].set_has_sibling(true);
-  }
-  return next;
-}
-
-uint64_t DoubleArrayImpl::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 = DoubleArrayKey::estimate_size(length);
-
-  // TODO
-//  GRN_DAT_THROW_IF(SIZE_ERROR, key_size > (key_buf_size() - key_pos));
-  const uint64_t size_left_in_page =
-      (~key_pos + 1) % DOUBLE_ARRAY_KEYS_PAGE_SIZE;
-  if (size_left_in_page < key_size) {
-    key_pos += size_left_in_page;
-  }
-  new (&keys_[key_pos]) DoubleArrayKey(key_id, ptr, length);
-
-  header_->set_next_key_pos(key_pos + key_size);
-  return key_pos;
-}
-
-uint64_t DoubleArrayImpl::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 DoubleArrayNode node = nodes_[node_id];
-  const DoubleArrayKey &key = get_key(node.key_pos());
-
-  uint16_t labels[2];
-  labels[0] = (i < node.key_length()) ?
-      static_cast<uint16_t>(key[i]) : DOUBLE_ARRAY_TERMINAL_LABEL;
-  labels[1] = (i < length) ?
-      static_cast<uint16_t>(ptr[i]) : DOUBLE_ARRAY_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(node.key_pos(), node.key_length());
-
-  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] == DOUBLE_ARRAY_TERMINAL_LABEL) ||
-      ((labels[1] != DOUBLE_ARRAY_TERMINAL_LABEL) &&
-       (labels[0] < labels[1]))) {
-    siblings_[offset ^ labels[0]] = labels[1];
-    nodes_[offset ^ labels[0]].set_has_sibling(true);
-    nodes_[node_id].set_child(labels[0]);
-  } else {
-    siblings_[offset ^ labels[1]] = labels[0];
-    nodes_[offset ^ labels[1]].set_has_sibling(true);
-    nodes_[node_id].set_child(labels[1]);
-  }
-  return next;
-}
-
-void DoubleArrayImpl::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 != DOUBLE_ARRAY_INVALID_OFFSET) {
-    uint16_t labels[DOUBLE_ARRAY_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 != DOUBLE_ARRAY_INVALID_LABEL) {
-//      GRN_DAT_DEBUG_THROW_IF(next_label > MAX_LABEL);
-      labels[num_labels++] = next_label;
-      next_label = nodes_[offset ^ next_label].has_sibling() ?
-          siblings_[offset ^ next_label] : DOUBLE_ARRAY_INVALID_LABEL;
-    }
-//    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_nodes()) {
-//      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 DoubleArrayImpl::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 > (DOUBLE_ARRAY_MAX_LABEL + 1));
-
-  const uint64_t src_offset = nodes_[node_id].offset();
-//  GRN_DAT_DEBUG_THROW_IF(src_offset == DOUBLE_ARRAY_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);
-    DoubleArrayNode dest_node = nodes_[src_node_id];
-    dest_node.set_is_origin(nodes_[dest_node_id].is_origin());
-    nodes_[dest_node_id] = dest_node;
-    siblings_[dest_node_id] = siblings_[src_node_id];
-  }
-  header_->set_num_zombies(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 DoubleArrayImpl::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 < DOUBLE_ARRAY_MAX_CHUNK_LEVEL) ?
-      (DOUBLE_ARRAY_MAX_CHUNK_LEVEL - level) : 0;
-
-  uint64_t chunk_count = 0;
-  do {
-    uint64_t leader = header_->ith_leader(level);
-    if (leader == DOUBLE_ARRAY_INVALID_LEADER) {
-      // This level group is skipped because it is empty.
-      continue;
-    }
-
-    uint64_t chunk_id = leader;
-    do {
-      const DoubleArrayChunk &chunk = chunks_[chunk_id];
-//      GRN_DAT_DEBUG_THROW_IF(chunk.level() != level);
-
-      const uint64_t first =
-          (chunk_id * DOUBLE_ARRAY_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 * DOUBLE_ARRAY_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 DOUBLE_ARRAY_MAX_FAILURE_COUNT times, in that chunk.
-      if (chunks_[prev].failure_count() == DOUBLE_ARRAY_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_->ith_leader(level);
-          continue;
-        }
-      }
-    } while ((++chunk_count < DOUBLE_ARRAY_MAX_CHUNK_COUNT) &&
-             (chunk_id != leader));
-  } while ((chunk_count < DOUBLE_ARRAY_MAX_CHUNK_COUNT) && (level-- != 0));
-
-  return header_->num_nodes() ^ labels[0];
-}
-
-void DoubleArrayImpl::reserve_node(uint64_t node_id) {
-  if (node_id >= header_->num_nodes()) {
-    reserve_chunk(node_id / DOUBLE_ARRAY_CHUNK_SIZE);
-  }
-
-  DoubleArrayNode &node = nodes_[node_id];
-//  GRN_DAT_DEBUG_THROW_IF(!node.is_phantom());
-
-  const uint64_t chunk_id = node_id / DOUBLE_ARRAY_CHUNK_SIZE;
-  DoubleArrayChunk &chunk = chunks_[chunk_id];
-//  GRN_DAT_DEBUG_THROW_IF(chunk.num_phantoms() == 0);
-
-  const uint64_t next = (chunk_id * DOUBLE_ARRAY_CHUNK_SIZE) | node.next();
-  const uint64_t prev = (chunk_id * DOUBLE_ARRAY_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 & DOUBLE_ARRAY_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 & DOUBLE_ARRAY_CHUNK_MASK);
-  }
-
-  nodes_[next].set_prev(prev & DOUBLE_ARRAY_CHUNK_MASK);
-  nodes_[prev].set_next(next & DOUBLE_ARRAY_CHUNK_MASK);
-
-  if (chunk.level() != DOUBLE_ARRAY_MAX_CHUNK_LEVEL) {
-    const uint64_t threshold =
-        uint64_t(1) << ((DOUBLE_ARRAY_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() != DOUBLE_ARRAY_INVALID_OFFSET);
-//  GRN_DAT_DEBUG_THROW_IF(node.label() != DOUBLE_ARRAY_INVALID_LABEL);
-
-  header_->set_num_phantoms(header_->num_phantoms() - 1);
-}
-
-void DoubleArrayImpl::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_->set_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(DOUBLE_ARRAY_CHUNK_SIZE);
-
-  const uint64_t begin = chunk_id * DOUBLE_ARRAY_CHUNK_SIZE;
-  const uint64_t end = begin + DOUBLE_ARRAY_CHUNK_SIZE;
-//  GRN_DAT_DEBUG_THROW_IF(end != num_nodes());
-
-  DoubleArrayNode node;
-  node.set_is_phantom(true);
-
-  for (uint64_t i = begin; i < end; ++i) {
-    node.set_prev((i - 1) & DOUBLE_ARRAY_CHUNK_MASK);
-    node.set_next((i + 1) & DOUBLE_ARRAY_CHUNK_MASK);
-    nodes_[i] = node;
-    siblings_[i] = '\0';
-  }
-
-  // The level of the new chunk is 0.
-  set_chunk_level(chunk_id, 0);
-  header_->set_num_phantoms(header_->num_phantoms() + DOUBLE_ARRAY_CHUNK_SIZE);
-}
-
-void DoubleArrayImpl::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 > DOUBLE_ARRAY_MAX_CHUNK_LEVEL);
-
-  unset_chunk_level(chunk_id);
-  set_chunk_level(chunk_id, level);
-}
-
-void DoubleArrayImpl::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 > DOUBLE_ARRAY_MAX_CHUNK_LEVEL);
-
-  const uint64_t leader = header_->ith_leader(level);
-  if (leader == DOUBLE_ARRAY_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_->set_ith_leader(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 DoubleArrayImpl::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 > DOUBLE_ARRAY_MAX_CHUNK_LEVEL);
-
-  const uint64_t leader = header_->ith_leader(level);
-//  GRN_DAT_DEBUG_THROW_IF(leader == DOUBLE_ARRAY_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_->set_ith_leader(level, DOUBLE_ARRAY_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_->set_ith_leader(level, next);
-    }
-  }
-}
-
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/double_array.hpp (+0 -701) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/double_array.hpp    2013-08-23 10:46:34 +0900 (9ce7169)
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ALPHA_DOUBLE_ARRAY_HPP
-#define GRNXX_ALPHA_DOUBLE_ARRAY_HPP
-
-#include "grnxx/db/vector.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-// FIXME: To be removed in future.
-using namespace grnxx::db;
-
-extern struct DoubleArrayCreate {} DOUBLE_ARRAY_CREATE;
-extern struct DoubleArrayOpen {} DOUBLE_ARRAY_OPEN;
-
-constexpr uint64_t DOUBLE_ARRAY_MAX_ID         = (uint64_t(1) << 40) - 2;
-constexpr uint64_t DOUBLE_ARRAY_INVALID_ID     = DOUBLE_ARRAY_MAX_ID + 1;
-constexpr uint64_t DOUBLE_ARRAY_INVALID_OFFSET = 0;
-
-constexpr uint16_t DOUBLE_ARRAY_TERMINAL_LABEL  = 0x100;
-constexpr uint16_t DOUBLE_ARRAY_MAX_LABEL       = DOUBLE_ARRAY_TERMINAL_LABEL;
-constexpr uint16_t DOUBLE_ARRAY_INVALID_LABEL   = 0x1FF;
-
-constexpr uint64_t DOUBLE_ARRAY_CHUNK_SIZE      = 0x200;
-constexpr uint64_t DOUBLE_ARRAY_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. DOUBLE_ARRAY_MAX_FAILURE_COUNT
-// is the threshold. Also, in order to limit the time cost, find_offset() scans
-// at most DOUBLE_ARRAY_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 DOUBLE_ARRAY_MAX_FAILURE_COUNT  = 4;
-constexpr uint64_t DOUBLE_ARRAY_MAX_CHUNK_COUNT    = 16;
-constexpr uint64_t DOUBLE_ARRAY_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. DOUBLE_ARRAY_INVALID_LEADER means that
-// the linked list is empty and there exists no leader.
-constexpr uint64_t DOUBLE_ARRAY_INVALID_LEADER     = 0x7FFFFFFF;
-
-// The memory allocation unit size for keys.
-constexpr uint64_t DOUBLE_ARRAY_KEYS_PAGE_SIZE     =
-    VECTOR_DEFAULT_PAGE_SIZE;
-
-class DoubleArrayHeader {
- public:
-  DoubleArrayHeader();
-
-  uint32_t nodes_block_id() const {
-    return nodes_block_id_;
-  }
-  uint32_t siblings_block_id() const {
-    return siblings_block_id_;
-  }
-  uint32_t chunks_block_id() const {
-    return chunks_block_id_;
-  }
-  uint32_t entries_block_id() const {
-    return entries_block_id_;
-  }
-  uint32_t keys_block_id() const {
-    return keys_block_id_;
-  }
-  uint64_t root_node_id() const {
-    return root_node_id_;
-  }
-  uint64_t total_key_length() const {
-    return total_key_length_;
-  }
-  uint64_t next_key_id() const {
-    return next_key_id_;
-  }
-  uint64_t next_key_pos() const {
-    return next_key_pos_;
-  }
-  int64_t max_key_id() const {
-    return max_key_id_;
-  }
-  uint64_t num_keys() const {
-    return num_keys_;
-  }
-  uint64_t num_chunks() const {
-    return num_chunks_;
-  }
-  uint64_t num_nodes() const {
-    return num_chunks_ * DOUBLE_ARRAY_CHUNK_SIZE;
-  }
-  uint64_t num_phantoms() const {
-    return num_phantoms_;
-  }
-  uint64_t num_zombies() const {
-    return num_zombies_;
-  }
-  uint64_t ith_leader(uint64_t i) const {
-    return leaders_[i];
-  }
-
-  void set_nodes_block_id(uint32_t value) {
-    nodes_block_id_ = value;
-  }
-  void set_siblings_block_id(uint32_t value) {
-    siblings_block_id_ = value;
-  }
-  void set_chunks_block_id(uint32_t value) {
-    chunks_block_id_ = value;
-  }
-  void set_entries_block_id(uint32_t value) {
-    entries_block_id_ = value;
-  }
-  void set_keys_block_id(uint32_t value) {
-    keys_block_id_ = value;
-  }
-  void set_root_node_id(uint64_t value) {
-    root_node_id_ = value;
-  }
-  void set_total_key_length(uint64_t value) {
-    total_key_length_ = value;
-  }
-  void set_next_key_id(uint64_t value) {
-    next_key_id_ = value;
-  }
-  void set_next_key_pos(uint64_t value) {
-    next_key_pos_ = value;
-  }
-  void set_max_key_id(int64_t value) {
-    max_key_id_ = value;
-  }
-  void set_num_keys(uint64_t value) {
-    num_keys_ = value;
-  }
-  void set_num_chunks(uint64_t value) {
-    num_chunks_ = value;
-  }
-  void set_num_phantoms(uint64_t value) {
-    num_phantoms_ = value;
-  }
-  void set_num_zombies(uint64_t value) {
-    num_zombies_ = value;
-  }
-  void set_ith_leader(uint64_t i, uint64_t x) {
-    leaders_[i] = x;
-  }
-
-  Mutex *mutable_inter_process_mutex() {
-    return &inter_process_mutex_;
-  }
-
- private:
-  uint32_t nodes_block_id_;
-  uint32_t siblings_block_id_;
-  uint32_t chunks_block_id_;
-  uint32_t entries_block_id_;
-  uint32_t keys_block_id_;
-  uint64_t root_node_id_;
-  uint64_t total_key_length_;
-  uint64_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_[DOUBLE_ARRAY_MAX_CHUNK_LEVEL + 1];
-  Mutex inter_process_mutex_;
-};
-
-class DoubleArrayNode {
- public:
-  DoubleArrayNode() : qword_(0) {}
-
-  // 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;
-  }
-  // This node has an elder sibling (true) or not (false).
-  bool has_sibling() const {
-    // 1 bit.
-    return qword_ & HAS_SIBLING_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) |
-          (DOUBLE_ARRAY_INVALID_OFFSET << OFFSET_SHIFT) |
-          (uint64_t(DOUBLE_ARRAY_INVALID_LABEL) << CHILD_SHIFT) |
-          DOUBLE_ARRAY_INVALID_LABEL;
-    }
-  }
-  void set_is_leaf(bool value) {
-    if (value) {
-      qword_ |= IS_LEAF_FLAG;
-    } else {
-      qword_ &= ~IS_LEAF_FLAG;
-    }
-  }
-  void set_has_sibling(bool value) {
-    if (value) {
-      qword_ |= HAS_SIBLING_FLAG;
-    } else {
-      qword_ &= ~HAS_SIBLING_FLAG;
-    }
-  }
-
-  // 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);
-  }
-
-  void set_label(uint16_t value) {
-    qword_ = (qword_ & ~LABEL_MASK) | value;
-  }
-
-  // A leaf node stores the start position and the length of the associated
-  // key.
-  uint64_t key_pos() const {
-    // 39 bits.
-    return (qword_ >> KEY_POS_SHIFT) & KEY_POS_MASK;
-  }
-  uint64_t key_length() const {
-    // 12 bits.
-    return (qword_ >> KEY_LENGTH_SHIFT) & KEY_LENGTH_MASK;
-  }
-
-  void set_key(uint64_t key_pos, uint64_t key_length) {
-    qword_ = (qword_ & ~((KEY_POS_MASK << KEY_POS_SHIFT) |
-                         (KEY_LENGTH_MASK << KEY_LENGTH_SHIFT))) |
-             (key_pos << KEY_POS_SHIFT) |
-             (key_length << KEY_LENGTH_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 {
-    // 42 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(DOUBLE_ARRAY_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_;
-
-  // 60 - 63.
-  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;
-  static constexpr uint64_t HAS_SIBLING_FLAG = uint64_t(1) << 60;
-
-  // 0 - 17.
-  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 - 8.
-  static constexpr uint64_t LABEL_MASK = (uint64_t(1) << 9) - 1;
-
-  // 9 - 59
-  static constexpr uint64_t KEY_POS_MASK     = (uint64_t(1) << 39) - 1;
-  static constexpr uint8_t  KEY_POS_SHIFT    = 9;
-  static constexpr uint64_t KEY_LENGTH_MASK  = (uint64_t(1) << 12) - 1;
-  static constexpr uint8_t  KEY_LENGTH_SHIFT = 48;
-
-  static constexpr uint64_t OFFSET_MASK   = (uint64_t(1) << 42) - 1;
-  static constexpr uint8_t  OFFSET_SHIFT  = 9;
-  static constexpr uint64_t CHILD_MASK    = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  CHILD_SHIFT   = 51;
-};
-
-class DoubleArrayChunk {
- public:
-  // 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 DoubleArrayEntry {
- public:
-  DoubleArrayEntry() : qword_(0) {}
-
-  // This entry is associated with a key (true) or not (false).
-  explicit operator bool() const {
-    return qword_ & IS_VALID_FLAG;
-  }
-
-  // A valid entry stores the offset and the length of its associated key.
-  uint64_t key_pos() const {
-    return qword_ & POS_MASK;
-  }
-  uint64_t key_length() const {
-    return qword_ >> 48;
-  }
-
-  void set_key(uint64_t pos, uint64_t length) {
-    qword_ = IS_VALID_FLAG | pos | (length << 48);
-  }
-
-  // An invalid entry stores the index of the next invalid entry.
-  uint64_t next() const {
-    return qword_;
-  }
-
-  void set_next(uint64_t next) {
-    qword_ = next;
-  }
-
- private:
-  uint64_t qword_;
-
-  // 11 (= 64 - (1 + 40 + 12)) bits are not used.
-  static constexpr uint64_t POS_MASK = (uint64_t(1) << 40) - 1;
-  static constexpr uint64_t IS_VALID_FLAG = uint64_t(1) << 47;
-};
-
-// TODO
-class DoubleArrayKey {
- public:
-  DoubleArrayKey(uint64_t id, const void *address, uint64_t length);
-
-  explicit operator bool() const {
-    return id() != DOUBLE_ARRAY_INVALID_ID;
-  }
-
-  const uint8_t &operator[](uint64_t i) const {
-    return buf_[i];
-  }
-
-  uint64_t id() const {
-    return id_low_ | (static_cast<uint64_t>(id_high_) << 32);
-  }
-  const void *ptr() const {
-    return buf_;
-  }
-
-  bool equals_to(const void *ptr, uint64_t length, uint64_t offset = 0) const {
-    for ( ; offset < length; ++offset) {
-      if (buf_[offset] != static_cast<const uint8_t *>(ptr)[offset]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  static const DoubleArrayKey &invalid_key() {
-    static const DoubleArrayKey invalid_key(
-        DOUBLE_ARRAY_INVALID_ID, nullptr, 0);
-    return invalid_key;
-  }
-
-  static uint64_t estimate_size(uint64_t length) {
-    return 2 + (length / sizeof(uint32_t));
-  }
-
- private:
-  uint32_t id_low_;
-  uint8_t id_high_;
-  uint8_t buf_[3];
-};
-
-// FIXME
-class DoubleArrayImpl {
- public:
-  ~DoubleArrayImpl();
-
-  static std::unique_ptr<DoubleArrayImpl> create(io::Pool pool);
-  static std::unique_ptr<DoubleArrayImpl> open(io::Pool pool,
-                                               uint32_t block_id);
-
-  bool search(const uint8_t *ptr, uint64_t length,
-              uint64_t *key_pos = nullptr);
-  bool insert(const uint8_t *ptr, uint64_t length,
-              uint64_t *key_pos = nullptr);
-
-  bool remove(int64_t key_id);
-  bool remove(const uint8_t *ptr, uint64_t length);
-
-  bool update(int64_t key_id, const uint8_t *ptr, uint64_t length,
-              uint64_t *key_pos = nullptr);
-  bool update(const uint8_t *src_ptr, uint64_t src_length,
-              const uint8_t *dest_ptr, uint64_t dest_length,
-              uint64_t *key_pos = nullptr);
-
-  const DoubleArrayKey &get_key(uint64_t key_pos) {
-    return *reinterpret_cast<const DoubleArrayKey *>(&keys_[key_pos]);
-  }
-  const DoubleArrayKey &ith_key(uint64_t key_id) {
-    if (entries_[key_id]) {
-      return get_key(entries_[key_id].key_pos());
-    }
-    return DoubleArrayKey::invalid_key();
-  }
-
-  const DoubleArrayHeader &header() const {
-    return *header_;
-  }
-
-  uint32_t block_id() const {
-    return block_info_->id();
-  }
-  uint64_t root_node_id() const {
-    return header_->root_node_id();
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const;
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  DoubleArrayHeader *header_;
-  Vector<DoubleArrayNode> nodes_;
-  Vector<uint8_t> siblings_;
-  Vector<DoubleArrayChunk> chunks_;
-  Vector<DoubleArrayEntry> entries_;
-  Vector<uint32_t> keys_;
-  bool initialized_;
-
-  DoubleArrayImpl();
-
-  void create_double_array(io::Pool pool);
-  void open_double_array(io::Pool pool, uint32_t block_id);
-
-  bool remove_key(const uint8_t *ptr, uint64_t length);
-  bool update_key(const uint8_t *src_ptr, uint64_t src_length,
-                  uint64_t src_key_id, const uint8_t *dest_ptr,
-                  uint64_t dest_length, uint64_t *key_pos);
-
-  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);
-};
-
-// TODO
-class DoubleArray {
- public:
-  DoubleArray() = default;
-  DoubleArray(const DoubleArrayCreate &, io::Pool pool)
-    : impl_(DoubleArrayImpl::create(pool)) {}
-  DoubleArray(const DoubleArrayOpen &, io::Pool pool, uint32_t block_id)
-    : impl_(DoubleArrayImpl::open(pool, block_id)) {}
-
-  explicit operator bool() const {
-    return static_cast<bool>(impl_);
-  }
-
-  void create(io::Pool pool) {
-    *this = DoubleArray(DOUBLE_ARRAY_CREATE, pool);
-  }
-  void open(io::Pool pool, uint32_t block_id) {
-    *this = DoubleArray(DOUBLE_ARRAY_OPEN, pool, block_id);
-  }
-  void close() {
-    *this = DoubleArray();
-  }
-
-  bool search(const void *ptr, uint64_t length,
-              uint64_t *key_id = nullptr) {
-    if (key_id) {
-      uint64_t key_pos;
-      if (!impl_->search(static_cast<const uint8_t *>(ptr), length, &key_pos)) {
-        return false;
-      }
-      *key_id = impl_->get_key(key_pos).id();
-      return true;
-    } else {
-      return impl_->search(static_cast<const uint8_t *>(ptr), length, nullptr);
-    }
-  }
-  bool insert(const void *ptr, uint64_t length,
-              uint64_t *key_id = nullptr) {
-    if (key_id) {
-      uint64_t key_pos;
-      if (!impl_->insert(static_cast<const uint8_t *>(ptr), length, &key_pos)) {
-        return false;
-      }
-      *key_id = impl_->get_key(key_pos).id();
-      return true;
-    } else {
-      return impl_->insert(static_cast<const uint8_t *>(ptr), length, nullptr);
-    }
-  }
-
-  bool remove(int64_t key_id) {
-    return impl_->remove(key_id);
-  }
-  bool remove(const void *ptr, uint64_t length) {
-    return impl_->remove(static_cast<const uint8_t *>(ptr), length);
-  }
-
-  bool update(int64_t key_id, const void *ptr, uint64_t length) {
-    return impl_->update(key_id, static_cast<const uint8_t *>(ptr), length);
-  }
-  bool update(const void *src_ptr, uint64_t src_length,
-              const void *dest_ptr, uint64_t dest_length,
-              uint64_t *key_id = nullptr) {
-    if (key_id) {
-      uint64_t key_pos;
-      if (!impl_->update(static_cast<const uint8_t *>(src_ptr), src_length,
-                         static_cast<const uint8_t *>(dest_ptr), dest_length,
-                         &key_pos)) {
-        return false;
-      }
-      *key_id = impl_->get_key(key_pos).id();
-      return true;
-    } else {
-      return impl_->update(static_cast<const uint8_t *>(src_ptr), src_length,
-                           static_cast<const uint8_t *>(dest_ptr), dest_length);
-    }
-  }
-
-  const DoubleArrayHeader &header() const {
-    return impl_->header();
-  }
-
-  uint32_t block_id() const {
-    return impl_->block_id();
-  }
-
-  void swap(DoubleArray &rhs) {
-    impl_.swap(rhs.impl_);
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const {
-    return impl_ ? impl_->write_to(builder) : (builder << "n/a");
-  }
-
- private:
-  std::shared_ptr<DoubleArrayImpl> impl_;
-};
-
-inline void swap(DoubleArray &lhs, DoubleArray &rhs) {
-  lhs.swap(rhs);
-}
-
-inline StringBuilder &operator<<(StringBuilder &builder,
-                                 const DoubleArray &da) {
-  return da.write_to(builder);
-}
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_DOUBLE_ARRAY_HPP

  Deleted: obsolete/lib/grnxx/alpha/dummy.cpp (+0 -24) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/dummy.cpp    2013-08-23 10:46:34 +0900 (ca66023)
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-  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/alpha/dummy.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/dummy.hpp (+0 -29) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/dummy.hpp    2013-08-23 10:46:34 +0900 (e398c83)
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ALPHA_DUMMY_HPP
-#define GRNXX_ALPHA_DUMMY_HPP
-
-#include "grnxx/features.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_DUMMY_HPP

  Deleted: obsolete/lib/grnxx/alpha/map.cpp (+0 -453) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map.cpp    2013-08-23 10:46:34 +0900 (d1b6ab6)
+++ /dev/null
@@ -1,453 +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 "grnxx/alpha/map.hpp"
-
-#include "grnxx/alpha/map/array.hpp"
-#include "grnxx/alpha/map/cursor.hpp"
-#include "grnxx/alpha/map/double_array.hpp"
-#include "grnxx/alpha/map/header.hpp"
-#include "grnxx/alpha/map/scan.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/slice.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-template <typename T>
-MapCursor<T>::MapCursor() : key_id_(-1), key_() {}
-
-template <typename T>
-MapCursor<T>::~MapCursor() {}
-
-template <typename T>
-bool MapCursor<T>::next() {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool MapCursor<T>::remove() {
-  // Not supported.
-  return false;
-}
-
-template class MapCursor<int8_t>;
-template class MapCursor<int16_t>;
-template class MapCursor<int32_t>;
-template class MapCursor<int64_t>;
-template class MapCursor<uint8_t>;
-template class MapCursor<uint16_t>;
-template class MapCursor<uint32_t>;
-template class MapCursor<uint64_t>;
-template class MapCursor<double>;
-template class MapCursor<GeoPoint>;
-template class MapCursor<Slice>;
-
-template <typename T>
-Map<T>::Map() {}
-
-template <typename T>
-Map<T>::~Map() {}
-
-template <typename T>
-Map<T> *Map<T>::create(MapType type, io::Pool pool,
-                       const MapOptions &options) {
-  switch (type) {
-    case MAP_ARRAY: {
-      return map::Array<T>::create(pool, options);
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return map::DoubleArray<T>::create(pool, options);
-    }
-    case MAP_PATRICIA: {
-      // TODO: Not supported yet.
-      return nullptr;
-    }
-    case MAP_HASH_TABLE: {
-      // TODO: Not supported yet.
-      return nullptr;
-    }
-    default: {
-      return nullptr;
-    }
-  }
-}
-
-template <typename T>
-Map<T> *Map<T>::open(io::Pool pool, uint32_t block_id) {
-  const map::Header *header = static_cast<const map::Header *>(
-      pool.get_block_address(block_id));
-  switch (header->type) {
-    case MAP_ARRAY: {
-      return map::Array<T>::open(pool, block_id);
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return map::DoubleArray<T>::open(pool, block_id);
-    }
-    case MAP_PATRICIA: {
-      // TODO: Not supported yet.
-      return nullptr;
-    }
-    case MAP_HASH_TABLE: {
-      // TODO: Not supported yet.
-      return nullptr;
-    }
-    default: {
-      return nullptr;
-    }
-  }
-}
-
-template <typename T>
-bool Map<T>::unlink(io::Pool pool, uint32_t block_id) {
-  const map::Header *header = static_cast<const map::Header *>(
-      pool.get_block_address(block_id));
-  switch (header->type) {
-    case MAP_ARRAY: {
-      return map::Array<T>::unlink(pool, block_id);
-    }
-    case MAP_DOUBLE_ARRAY: {
-      return map::DoubleArray<T>::unlink(pool, block_id);
-    }
-    case MAP_PATRICIA: {
-      // TODO: Not supported yet.
-      return false;
-    }
-    case MAP_HASH_TABLE: {
-      // TODO: Not supported yet.
-      return false;
-    }
-    default: {
-      // Not supported yet.
-      return false;
-    }
-  }
-}
-
-template <typename T>
-uint32_t Map<T>::block_id() const {
-  // Not supported.
-  return io::BLOCK_INVALID_ID;
-}
-
-template <typename T>
-MapType Map<T>::type() const {
-  // Not supported.
-  return MAP_UNKNOWN;
-}
-
-template <typename T>
-int64_t Map<T>::max_key_id() const {
-  // Not supported.
-  return -1;
-}
-
-template <typename T>
-int64_t Map<T>::next_key_id() const {
-  // Not supported.
-  return -1;
-}
-
-template <typename T>
-uint64_t Map<T>::num_keys() const {
-  // Not supported.
-  return 0;
-}
-
-template <typename T>
-bool Map<T>::get(int64_t, T *) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::get_next(int64_t, int64_t *, T *) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::unset(int64_t) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::reset(int64_t, T) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::find(T, int64_t *) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::insert(T, int64_t *) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::remove(T) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::update(T, T, int64_t *) {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-bool Map<T>::find_longest_prefix_match(T, int64_t *, T *) {
-  // Not supported.
-  return false;
-}
-
-template <>
-bool Map<Slice>::find_longest_prefix_match(Slice query, int64_t *key_id,
-                                           Slice *key) {
-  // Naive implementation.
-  for (size_t size = query.size(); size > 0; --size) {
-    const Slice prefix = query.prefix(size);
-    if (find(prefix, key_id)) {
-      if (key) {
-        *key = prefix;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool Map<T>::truncate() {
-  // Not supported.
-  return false;
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_basic_cursor(const MapCursorOptions &options) {
-  return new (std::nothrow) map::IDCursor<T>(this, -1, -1, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_id_cursor(int64_t min, int64_t max,
-                                     const MapCursorOptions &options) {
-  return new (std::nothrow) map::IDCursor<T>(this, min, max, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_key_cursor(T min, T max,
-                                      const MapCursorOptions &options) {
-  return new (std::nothrow) map::KeyCursor<T>(this, min, max, options);
-}
-
-template <>
-MapCursor<GeoPoint> *Map<GeoPoint>::open_key_cursor(GeoPoint, GeoPoint,
-                                                    const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_bitwise_completion_cursor(
-    T, size_t, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<GeoPoint> *Map<GeoPoint>::open_bitwise_completion_cursor(
-    GeoPoint query, size_t bit_size, const MapCursorOptions &options) {
-  return new (std::nothrow) map::BitwiseCompletionCursor(
-      this, query, bit_size, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_prefix_cursor(
-    T, size_t, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<Slice> *Map<Slice>::open_prefix_cursor(
-    Slice query, size_t min_size, const MapCursorOptions &options) {
-  return new (std::nothrow) map::PrefixCursor(this, query, min_size, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_completion_cursor(T, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<Slice> *Map<Slice>::open_completion_cursor(
-    Slice query, const MapCursorOptions &options) {
-  return new (std::nothrow) map::CompletionCursor(this, query, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_reverse_completion_cursor(
-    T, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<Slice> *Map<Slice>::open_reverse_completion_cursor(
-    Slice query, const MapCursorOptions &options) {
-  return new (std::nothrow) map::ReverseCompletionCursor(this, query, options);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_cursor(const MapIDRange &range,
-                                  const MapCursorOptions &options) {
-  int64_t min = -1;
-  int64_t max = -1;
-  MapCursorOptions options_clone = options;
-  options_clone.flags &= ~(MAP_CURSOR_EXCEPT_MIN | MAP_CURSOR_EXCEPT_MAX);
-  if (range.flags & (MAP_RANGE_GREATER | MAP_RANGE_GREATER_EQUAL)) {
-    min = range.min;
-    if (range.flags & MAP_RANGE_GREATER) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MIN;
-    }
-  }
-  if (range.flags & (MAP_RANGE_LESS | MAP_RANGE_LESS_EQUAL)) {
-    max = range.max;
-    if (range.flags & MAP_RANGE_LESS) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MAX;
-    }
-  }
-  return new (std::nothrow) map::IDCursor<T>(this, min, max, options_clone);
-}
-
-template <typename T>
-MapCursor<T> *Map<T>::open_cursor(const MapKeyRange<T> &range,
-                                  const MapCursorOptions &options) {
-  T min = std::numeric_limits<T>::min();
-  T max = std::numeric_limits<T>::max();
-  MapCursorOptions options_clone = options;
-  options_clone.flags &= ~(MAP_CURSOR_EXCEPT_MIN | MAP_CURSOR_EXCEPT_MAX);
-  if (range.flags & (MAP_RANGE_GREATER | MAP_RANGE_GREATER_EQUAL)) {
-    min = range.min;
-    if (range.flags & MAP_RANGE_GREATER) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MIN;
-    }
-  }
-  if (range.flags & (MAP_RANGE_LESS | MAP_RANGE_LESS_EQUAL)) {
-    max = range.max;
-    if (range.flags & MAP_RANGE_LESS) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MAX;
-    }
-  }
-  return new (std::nothrow) map::KeyCursor<T>(this, min, max, options_clone);
-}
-
-template <>
-MapCursor<double> *Map<double>::open_cursor(
-    const MapKeyRange<double> &range, const MapCursorOptions &options) {
-  double min = -std::numeric_limits<double>::infinity();
-  double max = +std::numeric_limits<double>::infinity();
-  MapCursorOptions options_clone = options;
-  options_clone.flags &= ~(MAP_CURSOR_EXCEPT_MIN | MAP_CURSOR_EXCEPT_MAX);
-  if (range.flags & (MAP_RANGE_GREATER | MAP_RANGE_GREATER_EQUAL)) {
-    min = range.min;
-    if (range.flags & MAP_RANGE_GREATER) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MIN;
-    }
-  }
-  if (range.flags & (MAP_RANGE_LESS | MAP_RANGE_LESS_EQUAL)) {
-    max = range.max;
-    if (range.flags & MAP_RANGE_LESS) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MAX;
-    }
-  }
-  return new (std::nothrow) map::KeyCursor<double>(this, min, max, options_clone);
-}
-
-template <>
-MapCursor<GeoPoint> *Map<GeoPoint>::open_cursor(
-    const MapKeyRange<GeoPoint> &, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<Slice> *Map<Slice>::open_cursor(
-    const MapKeyRange<Slice> &range, const MapCursorOptions &options) {
-  Slice min = nullptr;
-  Slice max = nullptr;
-  MapCursorOptions options_clone = options;
-  options_clone.flags &= ~(MAP_CURSOR_EXCEPT_MIN | MAP_CURSOR_EXCEPT_MAX);
-  if (range.flags & (MAP_RANGE_GREATER | MAP_RANGE_GREATER_EQUAL)) {
-    min = range.min;
-    if (range.flags & MAP_RANGE_GREATER) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MIN;
-    }
-  }
-  if (range.flags & (MAP_RANGE_LESS | MAP_RANGE_LESS_EQUAL)) {
-    max = range.max;
-    if (range.flags & MAP_RANGE_LESS) {
-      options_clone.flags |= MAP_CURSOR_EXCEPT_MAX;
-    }
-  }
-  return new (std::nothrow) map::KeyCursor<Slice>(this, min, max, options_clone);
-}
-
-template <typename T>
-MapScan<T> *Map<T>::open_scan(T, const Charset *) {
-  // Not supported
-  return nullptr;
-}
-
-template <>
-MapScan<Slice> *Map<Slice>::open_scan(Slice query, const Charset *charset) {
-  return new (std::nothrow) map::Scan(this, query, charset);
-}
-
-template class Map<int8_t>;
-template class Map<int16_t>;
-template class Map<int32_t>;
-template class Map<int64_t>;
-template class Map<uint8_t>;
-template class Map<uint16_t>;
-template class Map<uint32_t>;
-template class Map<uint64_t>;
-template class Map<double>;
-template class Map<GeoPoint>;
-template class Map<Slice>;
-
-template <typename T>
-MapScan<T>::MapScan() : offset_(0), size_(0), key_id_(-1), key_() {}
-
-template <typename T>
-MapScan<T>::~MapScan() {}
-
-template class MapScan<Slice>;
-
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map.hpp (+0 -262) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map.hpp    2013-08-23 10:46:34 +0900 (d9c5448)
+++ /dev/null
@@ -1,262 +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_MAP_HPP
-#define GRNXX_ALPHA_MAP_HPP
-
-#include "grnxx/alpha/map_range.hpp"
-#include "grnxx/io/pool.hpp"
-#include "grnxx/slice.hpp"
-
-namespace grnxx {
-
-class Charset;
-
-namespace alpha {
-
-template <typename T> class Map;
-template <typename T> class MapCursor;
-template <typename T> class MapScan;
-
-enum MapType : int32_t {
-  MAP_UNKNOWN      = 0,
-  MAP_ARRAY        = 1,  // Array-based implementation.
-  MAP_DOUBLE_ARRAY = 2,  // DoubleArray-based implementation.
-  MAP_PATRICIA     = 3,  // TODO: Patricia-based implementation.
-  MAP_HASH_TABLE   = 4   // TODO: HashTable-based implementation.
-};
-
-struct MapOptions {
-};
-
-struct MapCursorFlagsIdentifier;
-using MapCursorFlags = FlagsImpl<MapCursorFlagsIdentifier>;
-
-// Use the default settings.
-constexpr MapCursorFlags MAP_CURSOR_DEFAULT           =
-    MapCursorFlags::define(0x000);
-// Sort keys by ID.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_ID       =
-    MapCursorFlags::define(0x001);
-// Sort keys by key.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_KEY      =
-    MapCursorFlags::define(0x002);
-// TODO: Sort keys by distance.
-//constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_DISTANCE =
-//    MapCursorFlags::define(0x004);
-// Access keys in reverse order.
-constexpr MapCursorFlags MAP_CURSOR_REVERSE_ORDER     =
-    MapCursorFlags::define(0x010);
-// Return keys except min.
-constexpr MapCursorFlags MAP_CURSOR_EXCEPT_MIN        =
-    MapCursorFlags::define(0x100);
-// Return keys except max.
-constexpr MapCursorFlags MAP_CURSOR_EXCEPT_MAX        =
-    MapCursorFlags::define(0x200);
-// Return keys except exact match.
-constexpr MapCursorFlags MAP_CURSOR_EXCEPT_QUERY      =
-    MapCursorFlags::define(0x400);
-
-struct MapCursorOptions {
-  MapCursorFlags flags;
-  uint64_t offset;
-  uint64_t limit;
-
-  MapCursorOptions() : flags(MAP_CURSOR_DEFAULT), offset(0), limit(-1) {}
-};
-
-template <typename T>
-class Map {
- public:
-  Map();
-  virtual ~Map();
-
-  // Create a map on "pool".
-  static Map *create(MapType type, io::Pool pool,
-                     const MapOptions &options = MapOptions());
-  // Open an existing map.
-  static Map *open(io::Pool pool, uint32_t block_id);
-
-  // Free blocks allocated to a map.
-  static bool unlink(io::Pool pool, uint32_t block_id);
-
-  // Return the header block ID of "*this".
-  virtual uint32_t block_id() const;
-  // Return the type of "*this".
-  virtual MapType type() const;
-
-  // Return the minimum key ID.
-  constexpr int64_t min_key_id() const {
-    return 0;
-  }
-  // Return the maximum key ID ever used.
-  // If the map is empty, the return value can be -1.
-  virtual int64_t max_key_id() const;
-  // Return the ID of the expected next inserted ID.
-  virtual int64_t next_key_id() const;
-  // Return the number of keys.
-  virtual uint64_t num_keys() const;
-
-  // Get a key associated with "key_id" and return true on success.
-  // Assign the found key to "*key" iff "key" != nullptr.
-  virtual bool get(int64_t key_id, T *key = nullptr);
-  // Find the next key and return true on success. The next key means the key
-  // associated with the smallest valid ID that is greater than "key_id".
-  // If "key_id" < 0, this finds the first key.
-  // Assign the ID to "*next_key_id" iff "next_key_id" != nullptr.
-  // Assign the key to "*next_key" iff "next_key" != nullptr.
-  virtual bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                        T *next_key = nullptr);
-  // Remove a key associated with "key_id" and return true on success.
-  virtual bool unset(int64_t key_id);
-  // Replace a key associated with "key_id" with "dest_key" and return true
-  // on success.
-  virtual bool reset(int64_t key_id, T dest_key);
-
-  // Find "key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool find(T key, int64_t *key_id = nullptr);
-  // Insert "key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool insert(T key, int64_t *key_id = nullptr);
-  // Remove "key" and return true on success.
-  virtual bool remove(T key);
-  // Replace "src_key" with "dest_key" and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  virtual bool update(T src_key, T dest_key, int64_t *key_id = nullptr);
-
-  // Perform the longest prefix matching and return true on success.
-  // Assign the ID to "*key_id" iff "key_id" != nullptr.
-  // Assign the key to "*key" iff "key" != nullptr.
-  virtual bool find_longest_prefix_match(T query, int64_t *key_id = nullptr,
-                                         T *key = nullptr);
-
-  // Remove all the keys in "*this" and return true on success.
-  virtual bool truncate();
-
-  // Create a cursor for accessing all the keys.
-  virtual MapCursor<T> *open_basic_cursor(
-      const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys in range [min, max].
-  virtual MapCursor<T> *open_id_cursor(
-      int64_t min, int64_t max,
-      const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys in range [min, max].
-  virtual MapCursor<T> *open_key_cursor(
-      T min, T max, const MapCursorOptions &options = MapCursorOptions());
-
-  // Only for GeoPoint.
-  // Create a cursor for accessing keys whose most significant "bit_size" bits
-  // are same as the MSBs of "query".
-  virtual MapCursor<T> *open_bitwise_completion_cursor(
-      T query, size_t bit_size,
-      const MapCursorOptions &options = MapCursorOptions());
-
-  // Only for Slice.
-  // Create a cursor for accessing keys matching a prefix of "query".
-  virtual MapCursor<T> *open_prefix_cursor(
-      T query, size_t min_size,
-      const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys starting with "query".
-  virtual MapCursor<T> *open_completion_cursor(
-      T query, const MapCursorOptions &options = MapCursorOptions());
-  // Create a cursor for accessing keys ending with "query".
-  virtual MapCursor<T> *open_reverse_completion_cursor(
-      T query, const MapCursorOptions &options = MapCursorOptions());
-
-  MapID id() const {
-    return MapID();
-  }
-  MapKey<T> key() const {
-    return MapKey<T>();
-  }
-
-  virtual MapCursor<T> *open_cursor(
-      const MapIDRange &range,
-      const MapCursorOptions &options = MapCursorOptions());
-  virtual MapCursor<T> *open_cursor(
-      const MapKeyRange<T> &range,
-      const MapCursorOptions &options = MapCursorOptions());
-
-  // Only for Slice.
-  // Create a MapScan object to find keys in "query".
-  virtual MapScan<T> *open_scan(T query, const Charset *charset = nullptr);
-};
-
-template <typename T>
-class MapCursor {
- public:
-  MapCursor();
-  virtual ~MapCursor();
-
-  // Move the cursor to the next key and return true on success.
-  virtual bool next();
-  // Remove the current key and return true on success.
-  virtual bool remove();
-
-  // Return the ID of the current key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return a reference to the current key.
-  const T &key() const {
-    return key_;
-  }
-
- protected:
-  int64_t key_id_;
-  T key_;
-};
-
-template <typename T>
-class MapScan {
- public:
-  MapScan();
-  virtual ~MapScan();
-
-  // Scan the rest of the query and return true iff a key is found (success).
-  // On success, the found key is accessible via accessors.
-  virtual bool next() = 0;
-
-  // Return the start position of the found key.
-  uint64_t offset() const {
-    return offset_;
-  }
-  // Return the size of the found key.
-  uint64_t size() const {
-    return size_;
-  }
-  // Return the ID of the found key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return a reference to the found key.
-  const T &key() const {
-    return key_;
-  }
-
- protected:
-  uint64_t offset_;
-  uint64_t size_;
-  int64_t key_id_;
-  T key_;
-};
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_HPP

  Deleted: obsolete/lib/grnxx/alpha/map/Makefile.am (+0 -18) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/Makefile.am    2013-08-23 10:46:34 +0900 (ab16b6e)
+++ /dev/null
@@ -1,18 +0,0 @@
-noinst_LTLIBRARIES = libgrnxx_alpha_map.la
-
-libgrnxx_alpha_map_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_alpha_map_la_SOURCES =		\
-	array.cpp			\
-	cursor.cpp			\
-	double_array.cpp		\
-	double_array-slice.cpp		\
-	scan.cpp
-
-libgrnxx_alpha_map_includedir = ${includedir}/grnxx/alpha/map
-libgrnxx_alpha_map_include_HEADERS =	\
-	array.hpp			\
-	cursor.hpp			\
-	double_array.hpp		\
-	header.hpp			\
-	scan.hpp

  Deleted: obsolete/lib/grnxx/alpha/map/array.cpp (+0 -538) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/array.cpp    2013-08-23 10:46:34 +0900 (38f1db4)
+++ /dev/null
@@ -1,538 +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 "grnxx/alpha/map/array.hpp"
-
-#include <cmath>
-#include <string>
-
-#include "grnxx/geo_point.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-namespace {
-
-template <typename T, bool HAS_NAN = std::numeric_limits<T>::has_quiet_NaN>
-struct Helper;
-
-template <typename T>
-struct Helper<T, true> {
-  static bool equal_to(T x, T y) {
-    return *reinterpret_cast<const uint64_t *>(&x) ==
-           *reinterpret_cast<const uint64_t *>(&y);
-  }
-  static T normalize(T x) {
-    if (std::isnan(x)) {
-      return std::numeric_limits<T>::quiet_NaN();
-    } else if (x == 0.0) {
-      return +0.0;
-    }
-    return x;
-  }
-};
-
-template <typename T>
-struct Helper<T, false> {
-  static bool equal_to(T x, T y) {
-    return x == y;
-  }
-  static T normalize(T x) {
-    return x;
-  }
-};
-
-db::Blob slice_to_blob(Slice slice, std::string *buf) {
-  buf->assign(reinterpret_cast<const char *>(slice.ptr()), slice.size());
-  buf->resize(buf->size() + 7, ' ');
-  return db::Blob(buf->data(), buf->size());
-}
-
-Slice blob_to_slice(const db::Blob &blob) {
-  return Slice(blob.address(), blob.length() - 7);
-}
-
-}  // namespace
-
-ArrayHeader::ArrayHeader()
-    : map_type(MAP_ARRAY),
-      bits_block_id(io::BLOCK_INVALID_ID),
-      keys_block_id(io::BLOCK_INVALID_ID),
-      max_key_id(-1),
-      next_key_id(0),
-      num_keys(0) {}
-
-template <typename T>
-Array<T>::Array()
-    : pool_(),
-      block_info_(nullptr),
-      header_(nullptr),
-      bits_(),
-      keys_() {}
-
-template <typename T>
-Array<T>::~Array() {}
-
-template <typename T>
-Array<T> *Array<T>::create(io::Pool pool, const MapOptions &) {
-  std::unique_ptr<Array<T>> array(new (std::nothrow) Array<T>);
-  array->pool_ = pool;
-  array->block_info_ = pool.create_block(sizeof(ArrayHeader));
-  array->header_ = static_cast<ArrayHeader *>(
-      pool.get_block_address(*array->block_info_));
-  *array->header_ = ArrayHeader();
-  array->bits_.create(pool, 0);
-  array->header_->bits_block_id = array->bits_.block_id();
-  array->keys_.create(pool);
-  array->header_->keys_block_id = array->keys_.block_id();
-  return array.release();
-}
-
-template <typename T>
-Array<T> *Array<T>::open(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<Array<T>> array(new (std::nothrow) Array<T>);
-  array->pool_ = pool;
-  array->block_info_ = pool.get_block_info(block_id);
-  array->header_ = static_cast<ArrayHeader *>(
-      pool.get_block_address(*array->block_info_));
-  array->bits_.open(pool, array->header_->bits_block_id);
-  array->keys_.open(pool, array->header_->keys_block_id);
-  return array.release();
-}
-
-template <typename T>
-bool Array<T>::unlink(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<Array<T>> array(open(pool, block_id));
-  array->bits_.unlink(pool, array->header_->bits_block_id);
-  array->keys_.unlink(pool, array->header_->keys_block_id);
-  pool.free_block(array->block_id());
-  return false;
-}
-
-template <typename T>
-uint32_t Array<T>::block_id() const {
-  return block_info_->id();
-}
-
-template <typename T>
-MapType Array<T>::type() const {
-  return MAP_ARRAY;
-}
-
-template <typename T>
-int64_t Array<T>::max_key_id() const {
-  return header_->max_key_id;
-}
-
-template <typename T>
-int64_t Array<T>::next_key_id() const {
-  return header_->next_key_id;
-}
-
-template <typename T>
-uint64_t Array<T>::num_keys() const {
-  return header_->num_keys;
-}
-
-template <typename T>
-bool Array<T>::get(int64_t key_id, T *key) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  if (!get_bit(key_id)) {
-    return false;
-  }
-  if (key) {
-    *key = keys_[key_id];
-  }
-  return true;
-}
-
-template <typename T>
-bool Array<T>::get_next(int64_t key_id, int64_t *next_key_id, T *next_key) {
-  if (key_id >= header_->max_key_id) {
-    return false;
-  }
-  if (key_id < 0) {
-    key_id = -1;
-  }
-  for (++key_id; key_id <= header_->max_key_id; ++key_id) {
-    if (get_bit(key_id)) {
-      if (next_key_id) {
-        *next_key_id = key_id;
-      }
-      if (next_key) {
-        *next_key = keys_[key_id];
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool Array<T>::unset(int64_t key_id) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  if (!get_bit(key_id)) {
-    return false;
-  }
-  set_bit(key_id, false);
-  if (key_id < header_->next_key_id) {
-    header_->next_key_id = key_id;
-  }
-  --header_->num_keys;
-  return true;
-}
-
-template <typename T>
-bool Array<T>::reset(int64_t key_id, T dest_key) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  if (!get_bit(key_id)) {
-    return false;
-  }
-  if (find(dest_key)) {
-    return false;
-  }
-  keys_[key_id] = Helper<T>::normalize(dest_key);
-  return true;
-}
-
-template <typename T>
-bool Array<T>::find(T key, int64_t *key_id) {
-  key = Helper<T>::normalize(key);
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    if (get_bit(i)) {
-      if (Helper<T>::equal_to(key, keys_[i])) {
-        if (key_id) {
-          *key_id = i;
-        }
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool Array<T>::insert(T key, int64_t *key_id) {
-  key = Helper<T>::normalize(key);
-  int64_t key_id_candidate = -1;
-  int64_t next_key_id_candidate = -1;
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    if (get_bit(i)) {
-      if (Helper<T>::equal_to(key, keys_[i])) {
-        if (key_id) {
-          *key_id = i;
-        }
-        return false;
-      }
-    } else if (key_id_candidate == -1) {
-      // Use the first invalid ID if exists.
-      key_id_candidate = i;
-    } else if (next_key_id_candidate == -1) {
-      // Use the second invalid ID if exists.
-      next_key_id_candidate = i;
-    }
-  }
-  if (key_id_candidate == -1) {
-    key_id_candidate = ++header_->max_key_id;
-  }
-  keys_[key_id_candidate] = Helper<T>::normalize(key);
-  set_bit(key_id_candidate, true);
-  header_->next_key_id = (next_key_id_candidate != -1) ?
-      next_key_id_candidate : (header_->max_key_id + 1);
-  ++header_->num_keys;
-  if (key_id) {
-    *key_id = key_id_candidate;
-  }
-  return true;
-}
-
-template <typename T>
-bool Array<T>::remove(T key) {
-  int64_t key_id;
-  if (!find(key, &key_id)) {
-    return false;
-  }
-  set_bit(key_id, false);
-  if (key_id < header_->next_key_id) {
-    header_->next_key_id = key_id;
-  }
-  --header_->num_keys;
-  return true;
-}
-
-template <typename T>
-bool Array<T>::update(T src_key, T dest_key, int64_t *key_id) {
-  int64_t src_key_id;
-  if (!find(src_key, &src_key_id)) {
-    return false;
-  }
-  if (find(dest_key)) {
-    return false;
-  }
-  keys_[src_key_id] = Helper<T>::normalize(dest_key);
-  if (key_id) {
-    *key_id = src_key_id;
-  }
-  return true;
-}
-
-template <typename T>
-bool Array<T>::truncate() {
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    set_bit(i, false);
-  }
-  header_->max_key_id = -1;
-  header_->next_key_id = 0;
-  header_->num_keys = 0;
-  return true;
-}
-
-template class Array<int8_t>;
-template class Array<int16_t>;
-template class Array<int32_t>;
-template class Array<int64_t>;
-template class Array<uint8_t>;
-template class Array<uint16_t>;
-template class Array<uint32_t>;
-template class Array<uint64_t>;
-template class Array<double>;
-template class Array<GeoPoint>;
-
-Array<Slice>::Array()
-    : pool_(),
-      block_info_(nullptr),
-      header_(nullptr),
-      keys_() {}
-
-Array<Slice>::~Array() {}
-
-Array<Slice> *Array<Slice>::create(io::Pool pool, const MapOptions &) {
-  std::unique_ptr<Array<Slice>> array(new (std::nothrow) Array<Slice>);
-  array->pool_ = pool;
-  array->block_info_ = pool.create_block(sizeof(ArrayHeader));
-  array->header_ = static_cast<ArrayHeader *>(
-      pool.get_block_address(*array->block_info_));
-  *array->header_ = ArrayHeader();
-  array->keys_.create(pool);
-  array->header_->keys_block_id = array->keys_.block_id();
-  return array.release();
-}
-
-Array<Slice> *Array<Slice>::open(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<Array<Slice>> array(new (std::nothrow) Array<Slice>);
-  array->pool_ = pool;
-  array->block_info_ = pool.get_block_info(block_id);
-  array->header_ = static_cast<ArrayHeader *>(
-      pool.get_block_address(*array->block_info_));
-  array->keys_.open(pool, array->header_->keys_block_id);
-  return array.release();
-}
-
-bool Array<Slice>::unlink(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<Array<Slice>> array(open(pool, block_id));
-  array->keys_.unlink(pool, array->header_->keys_block_id);
-  pool.free_block(array->block_id());
-  return false;
-}
-
-uint32_t Array<Slice>::block_id() const {
-  return block_info_->id();
-}
-
-MapType Array<Slice>::type() const {
-  return MAP_ARRAY;
-}
-
-int64_t Array<Slice>::max_key_id() const {
-  return header_->max_key_id;
-}
-
-int64_t Array<Slice>::next_key_id() const {
-  return header_->next_key_id;
-}
-
-uint64_t Array<Slice>::num_keys() const {
-  return header_->num_keys;
-}
-
-bool Array<Slice>::get(int64_t key_id, Slice *key) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  db::Blob blob = keys_[key_id].get();
-  if (!blob) {
-    return false;
-  }
-  if (key) {
-    *key = blob_to_slice(blob);
-  }
-  return true;
-}
-
-bool Array<Slice>::get_next(int64_t key_id, int64_t *next_key_id,
-                            Slice *next_key) {
-  if (key_id >= header_->max_key_id) {
-    return false;
-  }
-  if (key_id < 0) {
-    key_id = -1;
-  }
-  for (++key_id; key_id <= header_->max_key_id; ++key_id) {
-    db::Blob blob = keys_[key_id].get();
-    if (blob) {
-      if (next_key_id) {
-        *next_key_id = key_id;
-      }
-      if (next_key) {
-        *next_key = blob_to_slice(blob);
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-bool Array<Slice>::unset(int64_t key_id) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  db::Blob blob = keys_[key_id].get();
-  if (!blob) {
-    return false;
-  }
-  keys_[key_id] = nullptr;
-  if (key_id < header_->next_key_id) {
-    header_->next_key_id = key_id;
-  }
-  --header_->num_keys;
-  return true;
-}
-
-bool Array<Slice>::reset(int64_t key_id, Slice dest_key) {
-  if ((key_id < 0) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  db::Blob blob = keys_[key_id].get();
-  if (!blob) {
-    return false;
-  }
-  if (!dest_key || find(dest_key)) {
-    return false;
-  }
-  std::string buf;
-  keys_[key_id] = slice_to_blob(dest_key, &buf);
-  return true;
-}
-
-bool Array<Slice>::find(Slice key, int64_t *key_id) {
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    db::Blob blob = keys_[i].get();
-    if (key == blob_to_slice(blob)) {
-      if (key_id) {
-        *key_id = i;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-bool Array<Slice>::insert(Slice key, int64_t *key_id) {
-  if (!key) {
-    return false;
-  }
-  int64_t key_id_candidate = -1;
-  int64_t next_key_id_candidate = -1;
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    db::Blob blob = keys_[i].get();
-    if (key == blob_to_slice(blob)) {
-      if (key_id) {
-        *key_id = i;
-      }
-      return false;
-    } else if (!blob) {
-      if (key_id_candidate == -1) {
-        // Use the first invalid ID if exists.
-        key_id_candidate = i;
-      } else if (next_key_id_candidate == -1) {
-        // Use the second invalid ID if exists.
-        next_key_id_candidate = i;
-      }
-    }
-  }
-  if (key_id_candidate == -1) {
-    key_id_candidate = ++header_->max_key_id;
-  }
-  std::string buf;
-  keys_[key_id_candidate] = slice_to_blob(key, &buf);
-  header_->next_key_id = (next_key_id_candidate != -1) ?
-      next_key_id_candidate : (header_->max_key_id + 1);
-  ++header_->num_keys;
-  if (key_id) {
-    *key_id = key_id_candidate;
-  }
-  return true;
-}
-
-bool Array<Slice>::remove(Slice key) {
-  int64_t key_id;
-  if (!find(key, &key_id)) {
-    return false;
-  }
-  keys_[key_id] = nullptr;
-  if (key_id < header_->next_key_id) {
-    header_->next_key_id = key_id;
-  }
-  --header_->num_keys;
-  return true;
-}
-
-bool Array<Slice>::update(Slice src_key, Slice dest_key, int64_t *key_id) {
-  int64_t src_key_id;
-  if (!find(src_key, &src_key_id)) {
-    return false;
-  }
-  if (!dest_key || find(dest_key)) {
-    return false;
-  }
-  std::string buf;
-  keys_[src_key_id] = slice_to_blob(dest_key, &buf);
-  if (key_id) {
-    *key_id = src_key_id;
-  }
-  return true;
-}
-
-bool Array<Slice>::truncate() {
-  for (int64_t i = 0; i <= header_->max_key_id; ++i) {
-    keys_[i] = nullptr;
-  }
-  header_->max_key_id = -1;
-  header_->next_key_id = 0;
-  header_->num_keys = 0;
-  return true;
-}
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map/array.hpp (+0 -134) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/array.hpp    2013-08-23 10:46:34 +0900 (908b6e6)
+++ /dev/null
@@ -1,134 +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_MAP_ARRAY_HPP
-#define GRNXX_ALPHA_MAP_ARRAY_HPP
-
-#include "grnxx/alpha/map.hpp"
-#include "grnxx/db/vector.hpp"
-#include "grnxx/db/blob_vector.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-struct ArrayHeader {
-  MapType map_type;
-  uint32_t bits_block_id;
-  uint32_t keys_block_id;
-  int64_t max_key_id;
-  int64_t next_key_id;
-  uint64_t num_keys;
-
-  ArrayHeader();
-};
-
-template <typename T>
-class Array : public grnxx::alpha::Map<T> {
- public:
-  Array();
-  ~Array();
-
-  static Array *create(io::Pool pool,
-                       const MapOptions &options = MapOptions());
-  static Array *open(io::Pool pool, uint32_t block_id);
-
-  static bool unlink(io::Pool pool, uint32_t block_id);
-
-  uint32_t block_id() const;
-  MapType type() const;
-
-  int64_t max_key_id() const;
-  int64_t next_key_id() const;
-  uint64_t num_keys() const;
-
-  bool get(int64_t key_id, T *key = nullptr);
-  bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                T *next_key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, T dest_key);
-
-  bool find(T key, int64_t *key_id = nullptr);
-  bool insert(T key, int64_t *key_id = nullptr);
-  bool remove(T key);
-  bool update(T src_key, T dest_key, int64_t *key_id = nullptr);
-
-  bool truncate();
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  ArrayHeader *header_;
-  db::Vector<uint32_t> bits_;
-  db::Vector<T> keys_;
-
-  bool get_bit(int64_t key_id) {
-    return bits_[key_id / 32] & (1U << (key_id % 32));
-  }
-  void set_bit(int64_t key_id, bool bit) {
-    if (bit) {
-      bits_[key_id / 32] |= 1U << (key_id % 32);
-    } else {
-      bits_[key_id / 32] &= ~(1U << (key_id % 32));
-    }
-  }
-};
-
-template <>
-class Array<Slice> : public grnxx::alpha::Map<Slice> {
- public:
-  Array();
-  ~Array();
-
-  static Array *create(io::Pool pool,
-                       const MapOptions &options = MapOptions());
-  static Array *open(io::Pool pool, uint32_t block_id);
-
-  static bool unlink(io::Pool pool, uint32_t block_id);
-
-  uint32_t block_id() const;
-  MapType type() const;
-
-  int64_t max_key_id() const;
-  int64_t next_key_id() const;
-  uint64_t num_keys() const;
-
-  bool get(int64_t key_id, Slice *key = nullptr);
-  bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                Slice *next_key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, Slice dest_key);
-
-  bool find(Slice key, int64_t *key_id = nullptr);
-  bool insert(Slice key, int64_t *key_id = nullptr);
-  bool remove(Slice key);
-  bool update(Slice src_key, Slice dest_key, int64_t *key_id = nullptr);
-
-  bool truncate();
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  ArrayHeader *header_;
-  db::BlobVector keys_;
-};
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_ARRAY_HPP

  Deleted: obsolete/lib/grnxx/alpha/map/cursor.cpp (+0 -417) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/cursor.cpp    2013-08-23 10:46:34 +0900 (97b7cb7)
+++ /dev/null
@@ -1,417 +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 "grnxx/alpha/map/cursor.hpp"
-
-#include <algorithm>
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-template <typename T>
-IDCursor<T>::IDCursor(Map<T> *map, int64_t min, int64_t max,
-                      const MapCursorOptions &options)
-    : MapCursor<T>(), map_(map), cur_(), end_(), step_(), count_(0),
-      options_(options), keys_() {
-  if (min < 0) {
-    min = 0;
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-    ++min;
-  }
-  if ((max < 0) || (max > map_->max_key_id())) {
-    max = map_->max_key_id();
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-    --max;
-  }
-  if (min > max) {
-    cur_ = end_ = 0;
-    return;
-  }
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id(min, max);
-  } else {
-    init_order_by_key(min, max);
-  }
-}
-
-template <typename T>
-IDCursor<T>::~IDCursor() {}
-
-template <typename T>
-bool IDCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    while (cur_ != end_) {
-      cur_ += step_;
-      if (map_->get(cur_, &this->key_)) {
-        this->key_id_ = cur_;
-        ++count_;
-        return true;
-      }
-    }
-  } else if (cur_ != end_) {
-    cur_ += step_;
-    this->key_ = keys_[cur_].first;
-    this->key_id_ = keys_[cur_].second;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool IDCursor<T>::remove() {
-  return map_->unset(this->key_id_);
-}
-
-template <typename T>
-void IDCursor<T>::init_order_by_id(int64_t min, int64_t max) {
-  options_.flags |= MAP_CURSOR_ORDER_BY_ID;
-  options_.flags &= ~MAP_CURSOR_ORDER_BY_KEY;
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = min - 1;
-    end_ = max;
-    step_ = 1;
-  } else {
-    cur_ = max + 1;
-    end_ = min;
-    step_ = -1;
-  }
-  uint64_t count = 0;
-  while ((count < options_.offset) && (cur_ != end_)) {
-    cur_ += step_;
-    if (map_->get(cur_)) {
-      ++count;
-    }
-  }
-}
-
-template <typename T>
-void IDCursor<T>::init_order_by_key(int64_t min, int64_t max) {
-  cur_ = min - 1;
-  end_ = max;
-  while (cur_ != end_) {
-    ++cur_;
-    T key;
-    if (map_->get(cur_, &key)) {
-      keys_.push_back(std::make_pair(key, cur_));
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = -1;
-    end_ = keys_.size() - 1;
-    step_ = 1;
-  } else {
-    cur_ = keys_.size();
-    end_ = 0;
-    step_ = -1;
-  }
-}
-
-template <>
-void IDCursor<GeoPoint>::init_order_by_key(int64_t min, int64_t max) {
-  // Ignore MAP_CURSOR_ORDER_BY_KEY.
-  init_order_by_id(min, max);
-}
-
-template class IDCursor<int8_t>;
-template class IDCursor<int16_t>;
-template class IDCursor<int32_t>;
-template class IDCursor<int64_t>;
-template class IDCursor<uint8_t>;
-template class IDCursor<uint16_t>;
-template class IDCursor<uint32_t>;
-template class IDCursor<uint64_t>;
-template class IDCursor<double>;
-template class IDCursor<GeoPoint>;
-template class IDCursor<Slice>;
-
-template <typename T>
-ConditionalCursor<T>::ConditionalCursor(Map<T> *map,
-                                        const MapCursorOptions &options)
-    : MapCursor<T>(), map_(map), cur_(), end_(), step_(), count_(0),
-      options_(options), keys_() {}
-
-template <typename T>
-ConditionalCursor<T>::~ConditionalCursor() {}
-
-template <typename T>
-bool ConditionalCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    while (cur_ != end_) {
-      cur_ += step_;
-      if (map_->get(cur_, &this->key_)) {
-        if (is_valid(this->key_)) {
-          this->key_id_ = cur_;
-          ++count_;
-          return true;
-        }
-      }
-    }
-  } else if (cur_ != end_) {
-    cur_ += step_;
-    this->key_ = keys_[cur_].first;
-    this->key_id_ = keys_[cur_].second;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool ConditionalCursor<T>::remove() {
-  return map_->unset(this->key_id_);
-}
-
-template <typename T>
-void ConditionalCursor<T>::init() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id();
-  } else {
-    init_order_by_key();
-  }
-}
-
-template <>
-void ConditionalCursor<GeoPoint>::init() {
-  init_order_by_id();
-}
-
-template <typename T>
-void ConditionalCursor<T>::init_order_by_id() {
-  options_.flags |= MAP_CURSOR_ORDER_BY_ID;
-  options_.flags &= ~MAP_CURSOR_ORDER_BY_KEY;
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = -1;
-    end_ = map_->max_key_id();
-    step_ = 1;
-  } else {
-    cur_ = map_->max_key_id() + 1;
-    end_ = 0;
-    step_ = -1;
-  }
-  uint64_t count = 0;
-  while ((count < options_.offset) && (cur_ != end_)) {
-    cur_ += step_;
-    if (map_->get(cur_, &this->key_)) {
-      if (is_valid(this->key_)) {
-        ++count;
-      }
-    }
-  }
-}
-
-template <typename T>
-void ConditionalCursor<T>::init_order_by_key() {
-  const std::int64_t max_key_id = map_->max_key_id();
-  for (std::int64_t i = 0; i <= max_key_id; ++i) {
-    T key;
-    if (map_->get(i, &key)) {
-      if (is_valid(key)) {
-        keys_.push_back(std::make_pair(key, i));
-      }
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = -1;
-    end_ = keys_.size() - 1;
-    step_ = 1;
-  } else {
-    cur_ = keys_.size();
-    end_ = 0;
-    step_ = -1;
-  }
-}
-
-template <>
-void ConditionalCursor<GeoPoint>::init_order_by_key() {
-  // Ignore MAP_CURSOR_ORDER_BY_KEY.
-  init_order_by_id();
-}
-
-template class ConditionalCursor<int8_t>;
-template class ConditionalCursor<int16_t>;
-template class ConditionalCursor<int32_t>;
-template class ConditionalCursor<int64_t>;
-template class ConditionalCursor<uint8_t>;
-template class ConditionalCursor<uint16_t>;
-template class ConditionalCursor<uint32_t>;
-template class ConditionalCursor<uint64_t>;
-template class ConditionalCursor<double>;
-template class ConditionalCursor<Slice>;
-
-template <typename T>
-KeyCursor<T>::KeyCursor(Map<T> *map, T min, T max,
-                        const MapCursorOptions &options)
-    : ConditionalCursor<T>(map, options), min_(min), max_(max) {
-  this->init();
-}
-
-template <typename T>
-KeyCursor<T>::~KeyCursor() {}
-
-template <typename T>
-bool KeyCursor<T>::is_valid(T key) const {
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-    if (key <= min_) {
-      return false;
-    }
-  } else if (key < min_) {
-    return false;
-  }
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-    if (key >= max_) {
-      return false;
-    }
-  } else if (key > max_) {
-    return false;
-  }
-  return true;
-}
-
-template <>
-bool KeyCursor<Slice>::is_valid(Slice key) const {
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-    if (key <= min_) {
-      return false;
-    }
-  } else if (key < min_) {
-    return false;
-  }
-  if (max_) {
-    if (this->options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-      if (key >= max_) {
-        return false;
-      }
-    } else if (key > max_) {
-      return false;
-    }
-  }
-  return true;
-}
-
-template class KeyCursor<int8_t>;
-template class KeyCursor<int16_t>;
-template class KeyCursor<int32_t>;
-template class KeyCursor<int64_t>;
-template class KeyCursor<uint8_t>;
-template class KeyCursor<uint16_t>;
-template class KeyCursor<uint32_t>;
-template class KeyCursor<uint64_t>;
-template class KeyCursor<double>;
-template class KeyCursor<Slice>;
-
-BitwiseCompletionCursor::BitwiseCompletionCursor(
-    Map<GeoPoint> *map, GeoPoint query, size_t bit_size,
-    const MapCursorOptions &options)
-    : ConditionalCursor<GeoPoint>(map, options),
-      query_(query),
-      mask_() {
-  if (bit_size >= 64) {
-    bit_size = 64;
-  }
-  switch (bit_size) {
-    case 0: {
-      mask_ = 0;
-      break;
-    }
-    case 1: {
-      mask_ = GeoPoint(1 << 31, 0).value();
-      break;
-    }
-    default: {
-      mask_ = GeoPoint(0xFFFFFFFFU << (32 - (bit_size / 2) - (bit_size % 2)),
-                       0xFFFFFFFFU << (32 - (bit_size / 2))).value();
-      break;
-    }
-  }
-  this->init();
-}
-
-BitwiseCompletionCursor::~BitwiseCompletionCursor() {}
-
-bool BitwiseCompletionCursor::is_valid(GeoPoint key) const {
-  return ((key.value() ^ query_.value()) & mask_) == 0;
-}
-
-PrefixCursor::PrefixCursor(Map<Slice> *map, Slice query, size_t min_size,
-                           const MapCursorOptions &options)
-    : ConditionalCursor<Slice>(map, options),
-      query_(query), min_size_(min_size) {
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_QUERY) {
-    query_.remove_suffix(1);
-  }
-  this->init();
-}
-
-PrefixCursor::~PrefixCursor() {}
-
-bool PrefixCursor::is_valid(Slice key) const {
-  if (key.size() < min_size_) {
-    return false;
-  }
-  return query_.starts_with(key);
-}
-
-CompletionCursor::CompletionCursor(Map<Slice> *map, Slice query,
-                                   const MapCursorOptions &options)
-    : ConditionalCursor<Slice>(map, options), query_(query) {
-  this->init();
-}
-
-CompletionCursor::~CompletionCursor() {}
-
-bool CompletionCursor::is_valid(Slice key) const {
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_QUERY) {
-    if (key.size() <= query_.size()) {
-      return false;
-    }
-  }
-  return key.starts_with(query_);
-}
-
-ReverseCompletionCursor::ReverseCompletionCursor(
-    Map<Slice> *map, Slice query, const MapCursorOptions &options)
-    : ConditionalCursor<Slice>(map, options), query_(query) {
-  this->init();
-}
-
-ReverseCompletionCursor::~ReverseCompletionCursor() {}
-
-bool ReverseCompletionCursor::is_valid(Slice key) const {
-  if (this->options_.flags & MAP_CURSOR_EXCEPT_QUERY) {
-    if (key.size() <= query_.size()) {
-      return false;
-    }
-  }
-  return key.ends_with(query_);
-}
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map/cursor.hpp (+0 -148) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/cursor.hpp    2013-08-23 10:46:34 +0900 (f92195f)
+++ /dev/null
@@ -1,148 +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_MAP_CURSOR_HPP
-#define GRNXX_ALPHA_MAP_CURSOR_HPP
-
-#include "grnxx/alpha/map.hpp"
-
-#include <vector>
-
-#include "grnxx/geo_point.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-template <typename T>
-class IDCursor : public MapCursor<T> {
- public:
-  IDCursor(Map<T> *map, int64_t min, int64_t max,
-           const MapCursorOptions &options);
-  ~IDCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  Map<T> *map_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-  std::vector<std::pair<T, int64_t>> keys_;
-
-  void init_order_by_id(int64_t min, int64_t max);
-  void init_order_by_key(int64_t min, int64_t max);
-};
-
-template <typename T>
-class ConditionalCursor : public MapCursor<T> {
- public:
-  ConditionalCursor(Map<T> *map, const MapCursorOptions &options);
-  virtual ~ConditionalCursor();
-
-  bool next();
-  bool remove();
-
- protected:
-  Map<T> *map_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-  std::vector<std::pair<T, int64_t>> keys_;
-
-  void init();
-
-  virtual bool is_valid(T key) const = 0;
-
- private:
-  void init_order_by_id();
-  void init_order_by_key();
-};
-
-template <typename T>
-class KeyCursor : public ConditionalCursor<T> {
- public:
-  KeyCursor(Map<T> *map, T min, T max, const MapCursorOptions &options);
-  ~KeyCursor();
-
- private:
-  T min_;
-  T max_;
-
-  bool is_valid(T key) const;
-};
-
-class BitwiseCompletionCursor : public ConditionalCursor<GeoPoint> {
- public:
-  BitwiseCompletionCursor(Map<GeoPoint> *map, GeoPoint query, size_t bit_size,
-                          const MapCursorOptions &options);
-  ~BitwiseCompletionCursor();
-
- private:
-  GeoPoint query_;
-  uint64_t mask_;
-
-  bool is_valid(GeoPoint key) const;
-};
-
-class PrefixCursor : public ConditionalCursor<Slice> {
- public:
-  PrefixCursor(Map<Slice> *map, Slice query, size_t min_size,
-               const MapCursorOptions &options);
-  ~PrefixCursor();
-
- private:
-  Slice query_;
-  size_t min_size_;
-
-  bool is_valid(Slice key) const;
-};
-
-class CompletionCursor : public ConditionalCursor<Slice> {
- public:
-  CompletionCursor(Map<Slice> *map, Slice query,
-                   const MapCursorOptions &options);
-  ~CompletionCursor();
-
- private:
-  Slice query_;
-
-  bool is_valid(Slice key) const;
-};
-
-class ReverseCompletionCursor : public ConditionalCursor<Slice> {
- public:
-  ReverseCompletionCursor(Map<Slice> *map, Slice query,
-                          const MapCursorOptions &options);
-  ~ReverseCompletionCursor();
-
- private:
-  Slice query_;
-
-  bool is_valid(Slice key) const;
-};
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_CURSOR_HPP

  Deleted: obsolete/lib/grnxx/alpha/map/double_array-slice.cpp (+0 -2161) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/double_array-slice.cpp    2013-08-23 10:46:34 +0900 (f18b539)
+++ /dev/null
@@ -1,2161 +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 "grnxx/alpha/map/double_array.hpp"
-
-#include <algorithm>
-#include <vector>
-
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-namespace {
-
-constexpr  int32_t MIN_KEY_ID     = 0;
-constexpr  int32_t MAX_KEY_ID     = 0x7FFFFFFE;
-
-constexpr   size_t MIN_KEY_SIZE   = 1;
-constexpr   size_t MAX_KEY_SIZE   = 4095;
-
-constexpr uint32_t INVALID_OFFSET = 0;
-
-constexpr uint32_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 uint32_t CHUNK_SIZE     = 0x200;
-constexpr uint32_t CHUNK_MASK     = 0x1FF;
-
-// Assume that #nodes per key is 4 and #uint32_ts per key is 8.
-// Note that an entries is associated with a key.
-constexpr uint32_t INITIAL_NODES_SIZE   = 1 << 16;
-constexpr uint32_t INITIAL_ENTRIES_SIZE = 1 << 14;
-constexpr uint32_t INITIAL_KEYS_SIZE    = 1 << 17;
-
-constexpr uint32_t MAX_NODES_SIZE    =
-    std::numeric_limits<uint32_t>::max() & ~CHUNK_MASK;
-constexpr uint32_t MAX_ENTRIES_SIZE  = uint32_t(MAX_KEY_ID) + 1;
-constexpr uint32_t MAX_KEYS_SIZE     = uint32_t(1) << 31;
-
-// 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 uint32_t MAX_FAILURE_COUNT = 4;
-constexpr uint32_t MAX_CHUNK_COUNT   = 16;
-constexpr uint32_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 uint32_t INVALID_LEADER    = std::numeric_limits<uint32_t>::max();
-
-}  // namespace
-
-struct SliceDoubleArrayHeader {
-  MapType map_type;
-  uint32_t nodes_block_id;
-  uint32_t chunks_block_id;
-  uint32_t entries_block_id;
-  uint32_t keys_block_id;
-  uint32_t nodes_size;
-  uint32_t chunks_size;
-  uint32_t entries_size;
-  uint32_t keys_size;
-  int32_t next_key_id;
-  uint32_t next_key_pos;
-  int32_t max_key_id;
-  uint64_t total_key_length;
-  uint32_t num_keys;
-  uint32_t num_chunks;
-  uint32_t num_phantoms;
-  uint32_t num_zombies;
-  uint32_t leaders[MAX_CHUNK_LEVEL + 1];
-  Mutex inter_process_mutex;
-
-  SliceDoubleArrayHeader();
-};
-
-SliceDoubleArrayHeader::SliceDoubleArrayHeader()
-    : map_type(MAP_DOUBLE_ARRAY),
-      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),
-      nodes_size(0),
-      chunks_size(0),
-      entries_size(0),
-      keys_size(0),
-      next_key_id(0),
-      next_key_pos(0),
-      max_key_id(-1),
-      total_key_length(0),
-      num_keys(0),
-      num_chunks(0),
-      num_phantoms(0),
-      num_zombies(0),
-      leaders(),
-      inter_process_mutex(MUTEX_UNLOCKED) {
-  for (uint32_t i = 0; i <= MAX_CHUNK_LEVEL; ++i) {
-    leaders[i] = INVALID_LEADER;
-  }
-}
-
-class SliceDoubleArrayNode {
- public:
-  SliceDoubleArrayNode() : qword_(IS_PHANTOM_FLAG) {}
-
-  // Structure overview.
-  //  0- 8 ( 9): next (is_phantom).
-  //  9-17 ( 9): prev (is_phantom).
-  //  0- 8 ( 9): label (!is_phantom).
-  //  9-17 ( 9): sibling (!is_phantom).
-  // 18-48 (31): key_pos (!is_phantom && is_leaf).
-  // 18-49 (32): offset (!is_phantom && !is_leaf).
-  // 50-58 ( 9): child (!is_phantom && !is_leaf).
-  // 61-61 ( 1): is_leaf.
-  // 62-62 ( 1): is_phantom.
-  // 63-63 ( 1): is_origin.
-  // Note that 0 is the LSB and 63 is the MSB.
-
-  // The ID of this node is used as an offset (true) or not (false).
-  bool is_origin() const {
-    return qword_ & IS_ORIGIN_FLAG;
-  }
-  // This node is valid (false) or not (true).
-  bool is_phantom() const {
-    return qword_ & IS_PHANTOM_FLAG;
-  }
-  // This node is associated with a key (true) or not (false).
-  bool is_leaf() const {
-    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) |
-               (uint64_t(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 {
-    return static_cast<uint16_t>(qword_ & NEXT_MASK);
-  }
-  uint16_t prev() const {
-    return static_cast<uint16_t>((qword_ >> PREV_SHIFT) & PREV_MASK);
-  }
-
-  void set_next(uint16_t value) {
-    qword_ = (qword_ & ~NEXT_MASK) | value;
-  }
-  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 and the label of its next sibling.
-  // A phantom node returns an invalid label with IS_PHANTOM_FLAG.
-  // sibling() == INVALID_LABEL means that the node doesn't have next sibling.
-  uint64_t label() const {
-    return qword_ & (IS_PHANTOM_FLAG | LABEL_MASK);
-  }
-  uint16_t sibling() const {
-    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 of the associated key.
-  uint32_t key_pos() const {
-    return static_cast<uint32_t>((qword_ >> KEY_POS_SHIFT) & KEY_POS_MASK);
-  }
-
-  void set_key_pos(uint32_t value) {
-    qword_ = (qword_ & ~(KEY_POS_MASK << KEY_POS_SHIFT)) |
-             (static_cast<uint64_t>(value) << KEY_POS_SHIFT) | IS_LEAF_FLAG;
-  }
-
-  // A non-phantom and non-leaf node stores the offset to its children and the
-  // label of its first child.
-  // child() == INVALID_LABEL means that the node has no child.
-  uint32_t offset() const {
-    return static_cast<uint32_t>((qword_ >> OFFSET_SHIFT) & OFFSET_MASK);
-  }
-  uint16_t child() const {
-    return static_cast<uint16_t>((qword_ >> CHILD_SHIFT) & CHILD_MASK);
-  }
-
-  void set_offset(uint32_t value) {
-    if (qword_ & IS_LEAF_FLAG) {
-      qword_ = ((qword_ & ~IS_LEAF_FLAG) & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (static_cast<uint64_t>(value) << OFFSET_SHIFT) |
-               (uint64_t(INVALID_LABEL) << CHILD_SHIFT);
-    } else {
-      qword_ = (qword_ & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (static_cast<uint64_t>(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.
-  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 (is_phantom).
-  static constexpr uint64_t NEXT_MASK       = (uint64_t(1) << 9) - 1;
-  static constexpr uint64_t PREV_MASK       = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  PREV_SHIFT      = 9;
-
-  //  0-17 (!is_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-48 (!is_phantom && is_leaf)
-  static constexpr uint64_t KEY_POS_MASK    = (uint64_t(1) << 31) - 1;
-  static constexpr uint8_t  KEY_POS_SHIFT   = 18;
-
-  // 18-58 (!is_phantom && !is_leaf)
-  static constexpr uint64_t OFFSET_MASK     = (uint64_t(1) << 32) - 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     = 50;
-};
-
-class SliceDoubleArrayChunk {
- public:
-  SliceDoubleArrayChunk() : next_(0), prev_(0), others_(0) {}
-
-  // Chunks in the same level are doubly linked.
-  uint32_t next() const {
-    return next_;
-  }
-  uint32_t prev() const {
-    return prev_;
-  }
-
-  void set_next(uint32_t value) {
-    next_ = value;
-  }
-  void set_prev(uint32_t value) {
-    prev_ = value;
-  }
-
-  // The chunk level indicates how easily nodes can be put in this chunk.
-  uint32_t level() const {
-    return (others_ >> LEVEL_SHIFT) & LEVEL_MASK;
-  }
-  uint32_t failure_count() const {
-    return (others_ >> FAILURE_COUNT_SHIFT) & FAILURE_COUNT_MASK;
-  }
-
-  void set_level(uint32_t value) {
-    others_ = (others_ & ~(LEVEL_MASK << LEVEL_SHIFT)) |
-              (value << LEVEL_SHIFT);
-  }
-  void set_failure_count(uint32_t value) {
-    others_ = (others_ & ~(FAILURE_COUNT_MASK << FAILURE_COUNT_SHIFT)) |
-              (value << FAILURE_COUNT_SHIFT);
-  }
-
-  // The first phantom node and the number of phantom nodes in this chunk.
-  uint32_t first_phantom() const {
-    return (others_ >> FIRST_PHANTOM_SHIFT) & FIRST_PHANTOM_MASK;
-  }
-  uint32_t num_phantoms() const {
-    return (others_ >> NUM_PHANTOMS_SHIFT) & NUM_PHANTOMS_MASK;
-  }
-
-  void set_first_phantom(uint32_t value) {
-    others_ = (others_ & ~(FIRST_PHANTOM_MASK << FIRST_PHANTOM_SHIFT)) |
-              (value << FIRST_PHANTOM_SHIFT);
-  }
-  void set_num_phantoms(uint32_t value) {
-    others_ = (others_ & ~(NUM_PHANTOMS_MASK << NUM_PHANTOMS_SHIFT)) |
-              (value << NUM_PHANTOMS_SHIFT);
-  }
-
- private:
-  uint32_t next_;
-  uint32_t prev_;
-  uint32_t others_;
-
-  static constexpr uint32_t LEVEL_MASK          = (1 << 4) - 1;
-  static constexpr uint8_t  LEVEL_SHIFT         = 0;
-
-  static constexpr uint32_t FAILURE_COUNT_MASK  = (1 << 6) - 1;
-  static constexpr uint8_t  FAILURE_COUNT_SHIFT = 4;
-
-  static constexpr uint32_t FIRST_PHANTOM_MASK  = (1 << 10) - 1;
-  static constexpr uint32_t FIRST_PHANTOM_SHIFT = 10;
-
-  static constexpr uint32_t NUM_PHANTOMS_MASK   = (1 << 10) - 1;
-  static constexpr uint32_t NUM_PHANTOMS_SHIFT  = 20;
-};
-
-class SliceDoubleArrayEntry {
- public:
-  // Create a valid entry.
-  static SliceDoubleArrayEntry valid_entry(uint32_t key_pos) {
-    return SliceDoubleArrayEntry(IS_VALID_FLAG | key_pos);
-  }
-  // Create an invalid entry.
-  static SliceDoubleArrayEntry invalid_entry(uint32_t next) {
-    return SliceDoubleArrayEntry(next);
-  }
-
-  // Return true iff "*this" is valid (associated with a key).
-  explicit operator bool() const {
-    return dword_ & IS_VALID_FLAG;
-  }
-
-  // Return the starting address of the associated key.
-  // Available iff "*this' is valid.
-  uint32_t key_pos() const {
-    return dword_ & ~IS_VALID_FLAG;
-  }
-
-  // Return the next invalid entry.
-  // Available iff "*this' is invalid.
-  uint32_t next() const {
-    return dword_;
-  }
-
- private:
-  uint32_t dword_;
-
-  static constexpr uint32_t IS_VALID_FLAG = uint32_t(1) << 31;
-
-  explicit SliceDoubleArrayEntry(uint32_t x) : dword_(x) {}
-};
-
-class SliceDoubleArrayKey {
- public:
-  SliceDoubleArrayKey(int32_t id, const Slice &key)
-      : id_(id),
-        size_(static_cast<uint16_t>(key.size())),
-        buf_{ '\0', '\0' } {
-    std::memcpy(buf_, key.ptr(), key.size());
-  }
-
-  const uint8_t &operator[](size_t i) const {
-    return buf_[i];
-  }
-
-  int32_t id() const {
-    return id_;
-  }
-  size_t size() const {
-    return size_;
-  }
-  const uint8_t *ptr() const {
-    return buf_;
-  }
-  Slice slice() const {
-    return Slice(buf_, size_);
-  }
-
-  bool equals_to(const Slice &key, size_t offset = 0) const {
-    if (key.size() != size_) {
-      return false;
-    }
-    for ( ; offset < key.size(); ++offset) {
-      if (buf_[offset] != key[offset]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  static uint32_t estimate_size(const size_t key_size) {
-    return (9 + key_size) / sizeof(uint32_t);
-  }
-
- private:
-  int32_t id_;
-  uint16_t size_;
-  uint8_t buf_[2];
-};
-
-constexpr uint64_t IS_ROOT_FLAG    = uint64_t(1) << 63;
-constexpr uint64_t POST_ORDER_FLAG = uint64_t(1) << 63;
-
-template <>
-class DoubleArrayIDCursor<Slice> : public MapCursor<Slice> {
- public:
-  DoubleArrayIDCursor(DoubleArray<Slice> *double_array,
-                      int64_t min, int64_t max,
-                      const MapCursorOptions &options);
-  ~DoubleArrayIDCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<Slice> *double_array_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-  std::vector<std::pair<Slice, int64_t>> keys_;
-
-  void init_order_by_id(int64_t min, int64_t max);
-  void init_order_by_key(int64_t min, int64_t max);
-};
-
-DoubleArrayIDCursor<Slice>::DoubleArrayIDCursor(
-    DoubleArray<Slice> *double_array, int64_t min, int64_t max,
-    const MapCursorOptions &options)
-    : MapCursor<Slice>(), double_array_(double_array), cur_(), end_(), step_(),
-      count_(0), options_(options), keys_() {
-  if (min < 0) {
-    min = 0;
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-    ++min;
-  }
-  if ((max < 0) || (max > double_array_->max_key_id())) {
-    max = double_array_->max_key_id();
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-    --max;
-  }
-  if (min > max) {
-    cur_ = end_ = 0;
-    return;
-  }
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id(min, max);
-  } else {
-    init_order_by_key(min, max);
-  }
-}
-
-DoubleArrayIDCursor<Slice>::~DoubleArrayIDCursor() {}
-
-bool DoubleArrayIDCursor<Slice>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    while (cur_ != end_) {
-      cur_ += step_;
-      if (double_array_->get(cur_, &this->key_)) {
-        this->key_id_ = cur_;
-        ++count_;
-        return true;
-      }
-    }
-  } else if (cur_ != end_) {
-    cur_ += step_;
-    this->key_ = keys_[cur_].first;
-    this->key_id_ = keys_[cur_].second;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArrayIDCursor<Slice>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-void DoubleArrayIDCursor<Slice>::init_order_by_id(int64_t min, int64_t max) {
-  options_.flags |= MAP_CURSOR_ORDER_BY_ID;
-  options_.flags &= ~MAP_CURSOR_ORDER_BY_KEY;
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = min - 1;
-    end_ = max;
-    step_ = 1;
-  } else {
-    cur_ = max + 1;
-    end_ = min;
-    step_ = -1;
-  }
-  uint64_t count = 0;
-  while ((count < options_.offset) && (cur_ != end_)) {
-    cur_ += step_;
-    if (double_array_->get(cur_)) {
-      ++count;
-    }
-  }
-}
-
-void DoubleArrayIDCursor<Slice>::init_order_by_key(int64_t min, int64_t max) {
-  cur_ = min - 1;
-  end_ = max;
-  while (cur_ != end_) {
-    ++cur_;
-    Slice key;
-    if (double_array_->get(cur_, &key)) {
-      keys_.push_back(std::make_pair(key, cur_));
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = -1;
-    end_ = keys_.size() - 1;
-    step_ = 1;
-  } else {
-    cur_ = keys_.size();
-    end_ = 0;
-    step_ = -1;
-  }
-}
-
-template <>
-class DoubleArrayKeyCursor<Slice> : public MapCursor<Slice> {
- public:
-  DoubleArrayKeyCursor(DoubleArray<Slice> *double_array,
-                       Slice min, Slice max,
-                       const MapCursorOptions &options);
-  ~DoubleArrayKeyCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<Slice> *double_array_;
-  uint64_t cur_;
-  uint64_t count_;
-  Slice min_;
-  Slice max_;
-  MapCursorOptions options_;
-  std::vector<uint64_t> node_ids_;
-  std::vector<std::pair<int64_t, Slice>> keys_;
-
-  void init_order_by_id();
-  void init_order_by_key();
-  void init_reverse_order_by_key();
-
-  bool next_order_by_id();
-  bool next_order_by_key();
-  bool next_reverse_order_by_key();
-};
-
-DoubleArrayKeyCursor<Slice>::DoubleArrayKeyCursor(
-    DoubleArray<Slice> *double_array, Slice min, Slice max,
-    const MapCursorOptions &options)
-    : MapCursor<Slice>(), double_array_(double_array), cur_(), count_(0),
-      min_(min), max_(max), options_(options), node_ids_(), keys_() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id();
-  } else {
-    options_.flags &= ~MAP_CURSOR_ORDER_BY_ID;
-    options_.flags |= MAP_CURSOR_ORDER_BY_KEY;
-    if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-      init_order_by_key();
-    } else {
-      init_reverse_order_by_key();
-    }
-  }
-}
-
-DoubleArrayKeyCursor<Slice>::~DoubleArrayKeyCursor() {}
-
-bool DoubleArrayKeyCursor<Slice>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    return next_order_by_id();
-  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    return next_order_by_key();
-  } else {
-    return next_reverse_order_by_key();
-  }
-}
-
-bool DoubleArrayKeyCursor<Slice>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-void DoubleArrayKeyCursor<Slice>::init_order_by_id() {
-  init_order_by_key();
-  while (!node_ids_.empty()) {
-    const uint64_t node_id = node_ids_.back();
-    node_ids_.pop_back();
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if (max_) {
-        const int result = key.slice().compare(Slice(max_.ptr(), max_.size()));
-        if ((result > 0) ||
-            ((result == 0) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-          break;
-        }
-      }
-      keys_.push_back(std::make_pair(key.id(), key.slice()));
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    std::reverse(keys_.begin(), keys_.end());
-  }
-  cur_ = options_.offset;
-}
-
-void DoubleArrayKeyCursor<Slice>::init_order_by_key() {
-  if (!min_) {
-    node_ids_.push_back(ROOT_NODE_ID);
-    return;
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  SliceDoubleArrayNode node;
-  for (size_t i = 0; i < min_.size(); ++i) {
-    node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      const int result = key.slice().compare(min_, i);
-      if ((result > 0) ||
-          ((result == 0) && (~options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
-        node_ids_.push_back(node_id);
-      } else if (node.sibling() != INVALID_LABEL) {
-        node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-      }
-      return;
-    } else if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    node_id = node.offset() ^ min_[i];
-    if (double_array_->nodes_[node_id].label() != min_[i]) {
-      uint16_t label = node.child();
-      if (label == TERMINAL_LABEL) {
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-      while (label != INVALID_LABEL) {
-        if (label > min_[i]) {
-          node_ids_.push_back(node.offset() ^ label);
-          break;
-        }
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-      return;
-    }
-  }
-
-  node = double_array_->nodes_[node_id];
-  if (node.is_leaf()) {
-    const SliceDoubleArrayKey &key = double_array_->get_key(node.key_pos());
-    if ((key.size() != min_.size()) ||
-        (~options_.flags & MAP_CURSOR_EXCEPT_MIN)) {
-      node_ids_.push_back(node_id);
-    } else if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    return;
-  } else if (node.sibling() != INVALID_LABEL) {
-    node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-  }
-
-  uint16_t label = node.child();
-  if ((label == TERMINAL_LABEL) && (options_.flags & MAP_CURSOR_EXCEPT_MIN)) {
-    label = double_array_->nodes_[node.offset() ^ label].sibling();
-  }
-  if (label != INVALID_LABEL) {
-    node_ids_.push_back(node.offset() ^ label);
-  }
-}
-
-void DoubleArrayKeyCursor<Slice>::init_reverse_order_by_key() {
-  if (!max_) {
-    node_ids_.push_back(ROOT_NODE_ID);
-    return;
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  for (size_t i = 0; i < max_.size(); ++i) {
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      const int result = key.slice().compare(max_, i);
-      if ((result < 0) ||
-          ((result == 0) && (~options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-        node_ids_.push_back(node_id | POST_ORDER_FLAG);
-      }
-      return;
-    }
-    uint16_t label = double_array_->nodes_[node_id].child();
-    if (label == TERMINAL_LABEL) {
-      node_id = node.offset() ^ label;
-      node_ids_.push_back(node_id | POST_ORDER_FLAG);
-      label = double_array_->nodes_[node_id].sibling();
-    }
-    while (label != INVALID_LABEL) {
-      node_id = node.offset() ^ label;
-      if (label < max_[i]) {
-        node_ids_.push_back(node_id);
-      } else if (label > max_[i]) {
-        return;
-      } else {
-        break;
-      }
-      label = double_array_->nodes_[node_id].sibling();
-    }
-    if (label == INVALID_LABEL) {
-      return;
-    }
-  }
-
-  const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-  if (node.is_leaf()) {
-    const SliceDoubleArrayKey &key = double_array_->get_key(node.key_pos());
-    if ((key.size() == max_.size()) &&
-        (~options_.flags & MAP_CURSOR_EXCEPT_MAX)) {
-      node_ids_.push_back(node_id | POST_ORDER_FLAG);
-    }
-    return;
-  }
-
-  uint16_t label = double_array_->nodes_[node_id].child();
-  if ((label == TERMINAL_LABEL) &&
-      (~options_.flags & MAP_CURSOR_EXCEPT_MAX)) {
-    node_ids_.push_back((node.offset() ^ label) | POST_ORDER_FLAG);
-  }
-}
-
-bool DoubleArrayKeyCursor<Slice>::next_order_by_id() {
-  if (cur_ < keys_.size()) {
-    this->key_id_ = keys_[cur_].first;
-    this->key_ = keys_[cur_].second;
-    ++cur_;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArrayKeyCursor<Slice>::next_order_by_key() {
-  while (!node_ids_.empty()) {
-    const uint64_t node_id = node_ids_.back();
-    node_ids_.pop_back();
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if (max_) {
-        const int result = key.slice().compare(Slice(max_.ptr(), max_.size()));
-        if ((result > 0) ||
-            ((result == 0) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-          node_ids_.clear();
-          return false;
-        }
-      }
-      if (options_.offset > 0) {
-        --options_.offset;
-      } else {
-        this->key_id_ = key.id();
-        this->key_ = key.slice();
-        ++count_;
-        return true;
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  return false;
-}
-
-bool DoubleArrayKeyCursor<Slice>::next_reverse_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (post_order) {
-      node_ids_.pop_back();
-      if (node.is_leaf()) {
-        const SliceDoubleArrayKey &key =
-            double_array_->get_key(node.key_pos());
-        if (min_) {
-          const int result =
-              key.slice().compare(Slice(min_.ptr(), min_.size()));
-          if ((result < 0) ||
-              ((result == 0) && (options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
-            node_ids_.clear();
-            return false;
-          }
-        }
-        if (options_.offset > 0) {
-          --options_.offset;
-        } else {
-          this->key_id_ = key.id();
-          this->key_ = key.slice();
-          ++count_;
-          return true;
-        }
-      }
-    } else {
-      node_ids_.back() |= POST_ORDER_FLAG;
-      uint16_t label = double_array_->nodes_[node_id].child();
-      while (label != INVALID_LABEL) {
-        node_ids_.push_back(node.offset() ^ label);
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-    }
-  }
-  return false;
-}
-
-template <>
-class DoubleArrayPrefixCursor<Slice> : public MapCursor<Slice> {
- public:
-  DoubleArrayPrefixCursor(DoubleArray<Slice> *double_array,
-                          Slice query, size_t min_size,
-                          const MapCursorOptions &options);
-  ~DoubleArrayPrefixCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<Slice> *double_array_;
-  uint64_t cur_;
-  uint64_t count_;
-  MapCursorOptions options_;
-  std::vector<std::pair<int64_t, Slice>> keys_;
-
-  void init_order_by_id(Slice query, size_t min_size);
-  void init_order_by_key(Slice query, size_t min_size);
-};
-
-DoubleArrayPrefixCursor<Slice>::DoubleArrayPrefixCursor(
-    DoubleArray<Slice> *double_array, Slice query, size_t min_size,
-    const MapCursorOptions &options)
-    : MapCursor<Slice>(), double_array_(double_array), cur_(),
-      count_(0), options_(options), keys_() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id(query, min_size);
-  } else {
-    options_.flags &= ~MAP_CURSOR_ORDER_BY_ID;
-    options_.flags |= MAP_CURSOR_ORDER_BY_KEY;
-    init_order_by_key(query, min_size);
-  }
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    std::reverse(keys_.begin(), keys_.end());
-  }
-  cur_ = options_.offset;
-}
-
-DoubleArrayPrefixCursor<Slice>::~DoubleArrayPrefixCursor() {}
-
-bool DoubleArrayPrefixCursor<Slice>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (cur_ < keys_.size()) {
-    this->key_id_ = keys_[cur_].first;
-    this->key_ = keys_[cur_].second;
-    ++cur_;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArrayPrefixCursor<Slice>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-void DoubleArrayPrefixCursor<Slice>::init_order_by_id(
-    Slice query, size_t min_size) {
-  init_order_by_key(query, min_size);
-  std::sort(keys_.begin(), keys_.end());
-}
-
-void DoubleArrayPrefixCursor<Slice>::init_order_by_key(
-    Slice query, size_t min_size) {
-  if ((query.size() > 0) && (options_.flags & MAP_CURSOR_EXCEPT_QUERY)) {
-    query.remove_suffix(1);
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  size_t i;
-  for (i = 0; i < query.size(); ++i) {
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if ((key.size() >= min_size) && (key.size() <= query.size()) &&
-          key.equals_to(query.prefix(key.size()), i)) {
-        keys_.push_back(std::make_pair(key.id(), key.slice()));
-      }
-      break;
-    }
-    if ((i >= min_size) &&
-        (double_array_->nodes_[node_id].child() == TERMINAL_LABEL)) {
-      const SliceDoubleArrayNode leaf_node =
-          double_array_->nodes_[node.offset() ^ TERMINAL_LABEL];
-      if (leaf_node.is_leaf()) {
-        const SliceDoubleArrayKey &key =
-            double_array_->get_key(leaf_node.key_pos());
-        keys_.push_back(std::make_pair(key.id(), key.slice()));
-      }
-    }
-    node_id = node.offset() ^ query[i];
-    if (double_array_->nodes_[node_id].label() != query[i]) {
-      break;
-    }
-  }
-
-  if (i == query.size()) {
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if ((key.size() >= min_size) && (key.size() <= query.size())) {
-        keys_.push_back(std::make_pair(key.id(), key.slice()));
-      }
-    } else if (double_array_->nodes_[node_id].child() == TERMINAL_LABEL) {
-      const SliceDoubleArrayNode leaf_node =
-          double_array_->nodes_[node.offset() ^ TERMINAL_LABEL];
-      if (leaf_node.is_leaf()) {
-        const SliceDoubleArrayKey &key =
-            double_array_->get_key(leaf_node.key_pos());
-        keys_.push_back(std::make_pair(key.id(), key.slice()));
-      }
-    }
-  }
-}
-
-template <>
-class DoubleArrayCompletionCursor<Slice> : public MapCursor<Slice> {
- public:
-  DoubleArrayCompletionCursor(DoubleArray<Slice> *double_array,
-                              Slice query,
-                              const MapCursorOptions &options);
-  ~DoubleArrayCompletionCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<Slice> *double_array_;
-  uint64_t cur_;
-  uint64_t count_;
-  Slice query_;
-  size_t min_size_;
-  MapCursorOptions options_;
-  std::vector<uint64_t> node_ids_;
-  std::vector<std::pair<int64_t, Slice>> keys_;
-
-  void init_order_by_id();
-  void init_order_by_key();
-
-  bool next_order_by_id();
-  bool next_order_by_key();
-  bool next_reverse_order_by_key();
-};
-
-DoubleArrayCompletionCursor<Slice>::DoubleArrayCompletionCursor(
-    DoubleArray<Slice> *double_array, Slice query,
-    const MapCursorOptions &options)
-    : MapCursor<Slice>(), double_array_(double_array), cur_(), count_(0),
-      query_(query), min_size_(), options_(options), node_ids_(), keys_() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id();
-  } else {
-    options_.flags &= ~MAP_CURSOR_ORDER_BY_ID;
-    options_.flags |= MAP_CURSOR_ORDER_BY_KEY;
-    init_order_by_key();
-  }
-}
-
-DoubleArrayCompletionCursor<Slice>::~DoubleArrayCompletionCursor() {}
-
-bool DoubleArrayCompletionCursor<Slice>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    return next_order_by_id();
-  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    return next_order_by_key();
-  } else {
-    return next_reverse_order_by_key();
-  }
-}
-
-bool DoubleArrayCompletionCursor<Slice>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-void DoubleArrayCompletionCursor<Slice>::init_order_by_id() {
-  init_order_by_key();
-  while (!node_ids_.empty()) {
-    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
-    node_ids_.pop_back();
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (!is_root && (node.sibling() != INVALID_LABEL)) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if (key.size() >= min_size_) {
-        keys_.push_back(std::make_pair(key.id(), key.slice()));
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    std::reverse(keys_.begin(), keys_.end());
-  }
-  cur_ = options_.offset;
-}
-
-void DoubleArrayCompletionCursor<Slice>::init_order_by_key() {
-  min_size_ = query_.size();
-  if (options_.flags & MAP_CURSOR_EXCEPT_QUERY) {
-    ++min_size_;
-  }
-  uint64_t node_id = ROOT_NODE_ID;
-  for (size_t i = 0; i < query_.size(); ++i) {
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if ((key.size() >= min_size_) &&
-          (key.slice().subslice(i, query_.size() - i) ==
-           query_.subslice(i, query_.size() - i))) {
-        if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-          node_id |= IS_ROOT_FLAG;
-        }
-        node_ids_.push_back(node_id);
-      }
-      return;
-    }
-    node_id = node.offset() ^ query_[i];
-    if (double_array_->nodes_[node_id].label() != query_[i]) {
-      return;
-    }
-  }
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    node_id |= IS_ROOT_FLAG;
-  }
-  node_ids_.push_back(node_id);
-}
-
-bool DoubleArrayCompletionCursor<Slice>::next_order_by_id() {
-  if (cur_ < keys_.size()) {
-    this->key_id_ = keys_[cur_].first;
-    this->key_ = keys_[cur_].second;
-    ++cur_;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArrayCompletionCursor<Slice>::next_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
-    node_ids_.pop_back();
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (!is_root && (node.sibling() != INVALID_LABEL)) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const SliceDoubleArrayKey &key =
-          double_array_->get_key(node.key_pos());
-      if (key.size() >= min_size_) {
-        if (options_.offset > 0) {
-          --options_.offset;
-        } else {
-          this->key_id_ = key.id();
-          this->key_ = key.slice();
-          ++count_;
-          return true;
-        }
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  return false;
-}
-
-bool DoubleArrayCompletionCursor<Slice>::next_reverse_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
-    const SliceDoubleArrayNode node = double_array_->nodes_[node_id];
-    if (post_order) {
-      node_ids_.pop_back();
-      if (node.is_leaf()) {
-        const SliceDoubleArrayKey &key =
-            double_array_->get_key(node.key_pos());
-        if (key.size() >= min_size_) {
-          if (options_.offset > 0) {
-            --options_.offset;
-          } else {
-            this->key_id_ = key.id();
-            this->key_ = key.slice();
-            ++count_;
-            return true;
-          }
-        }
-      }
-    } else {
-      node_ids_.back() |= POST_ORDER_FLAG;
-      uint16_t label = double_array_->nodes_[node_id].child();
-      while (label != INVALID_LABEL) {
-        node_ids_.push_back(node.offset() ^ label);
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-    }
-  }
-  return false;
-}
-
-DoubleArray<Slice>::~DoubleArray() {
-  if (!initialized_) try {
-    // Free allocated blocks 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 (...) {
-  }
-}
-
-DoubleArray<Slice> *DoubleArray<Slice>::create(io::Pool pool,
-                                           const MapOptions &options) {
-  std::unique_ptr<DoubleArray<Slice>> double_array(
-      new (std::nothrow) DoubleArray<Slice>);
-  if (!double_array) {
-    GRNXX_ERROR() << "new grnxx::alpha::map::DoubleArray failed";
-    GRNXX_THROW();
-  }
-  double_array->create_double_array(pool, options);
-  return double_array.release();
-}
-
-DoubleArray<Slice> *DoubleArray<Slice>::open(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<DoubleArray<Slice>> double_array(
-      new (std::nothrow) DoubleArray<Slice>);
-  if (!double_array) {
-    GRNXX_ERROR() << "new grnxx::alpha::map::DoubleArray failed";
-    GRNXX_THROW();
-  }
-  double_array->open_double_array(pool, block_id);
-  return double_array.release();
-}
-
-bool DoubleArray<Slice>::unlink(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<DoubleArray<Slice>> double_array(open(pool, block_id));
-
-  pool.free_block(double_array->header_->nodes_block_id);
-  pool.free_block(double_array->header_->chunks_block_id);
-  pool.free_block(double_array->header_->entries_block_id);
-  pool.free_block(double_array->header_->keys_block_id);
-  pool.free_block(block_id);
-  return true;
-}
-
-uint32_t DoubleArray<Slice>::block_id() const {
-  return block_info_->id();
-}
-
-MapType DoubleArray<Slice>::type() const {
-  return MAP_DOUBLE_ARRAY;
-}
-
-int64_t DoubleArray<Slice>::max_key_id() const {
-  return header_->max_key_id;
-}
-
-int64_t DoubleArray<Slice>::next_key_id() const {
-  return header_->next_key_id;
-}
-
-uint64_t DoubleArray<Slice>::num_keys() const {
-  return header_->num_keys;
-}
-
-bool DoubleArray<Slice>::get(int64_t key_id, Slice *key) {
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  if (key) {
-    const DoubleArrayKey &found_key = get_key(entry.key_pos());
-    *key = found_key.slice();
-  }
-  return true;
-}
-
-bool DoubleArray<Slice>::get_next(int64_t key_id, int64_t *next_key_id,
-                                  Slice *next_key) {
-  if (key_id >= header_->max_key_id) {
-    return false;
-  }
-  if (key_id < 0) {
-    key_id = -1;
-  }
-  for (++key_id; key_id <= header_->max_key_id; ++key_id) {
-    const DoubleArrayEntry entry = entries_[key_id];
-    if (entry) {
-      if (next_key_id) {
-        *next_key_id = key_id;
-      }
-      if (next_key) {
-        *next_key = get_key(entry.key_pos()).slice();
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-bool DoubleArray<Slice>::unset(int64_t key_id) {
-  Lock lock(&header_->inter_process_mutex);
-
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const DoubleArrayKey &key = get_key(entry.key_pos());
-  return remove_key(key.slice());
-}
-
-bool DoubleArray<Slice>::reset(int64_t key_id, Slice dest_key) {
-  if ((dest_key.size() < MIN_KEY_SIZE) || (dest_key.size() > MAX_KEY_SIZE)) {
-    GRNXX_ERROR() << "invalid key: size = " << dest_key.size();
-    GRNXX_THROW();
-  }
-
-  Lock lock(&header_->inter_process_mutex);
-
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  const DoubleArrayKey &key = get_key(entry.key_pos());
-  return update_key(key_id, key.slice(), dest_key);
-}
-
-bool DoubleArray<Slice>::find(Slice key, int64_t *key_id) {
-  if ((key.size() < MIN_KEY_SIZE) || (key.size() > MAX_KEY_SIZE)) {
-    return false;
-  }
-
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-  if (!find_leaf(key, node_id, query_pos)) {
-    return false;
-  }
-
-  // Note that nodes_[node_id] might be updated by other threads/processes.
-  const DoubleArrayNode node = nodes_[node_id];
-  if (!node.is_leaf()) {
-    return false;
-  }
-
-  const DoubleArrayKey &found_key = get_key(node.key_pos());
-  if (found_key.equals_to(key, query_pos)) {
-    if (key_id) {
-      *key_id = found_key.id();
-    }
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArray<Slice>::insert(Slice key, int64_t *key_id) {
-  if ((key.size() < MIN_KEY_SIZE) || (key.size() > MAX_KEY_SIZE)) {
-    GRNXX_ERROR() << "invalid key: size = " << key.size();
-    GRNXX_THROW();
-  }
-
-  Lock lock(&header_->inter_process_mutex);
-
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, INSERTING_FLAG);
-
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-
-  find_leaf(key, node_id, query_pos);
-  if (!insert_leaf(key, node_id, query_pos)) {
-    if (key_id) {
-      *key_id = get_key(nodes_[node_id].key_pos()).id();
-    }
-    return false;
-  }
-
-  const int32_t new_key_id = header_->next_key_id;
-  const uint32_t new_key_pos = append_key(key, new_key_id);
-
-  header_->total_key_length += key.size();
-  ++header_->num_keys;
-
-  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] = DoubleArrayEntry::valid_entry(new_key_pos);
-  nodes_[node_id].set_key_pos(new_key_pos);
-  if (key_id) {
-    *key_id = new_key_id;
-  }
-  return true;
-}
-
-bool DoubleArray<Slice>::remove(Slice key) {
-  if ((key.size() < MIN_KEY_SIZE) || (key.size() > MAX_KEY_SIZE)) {
-    GRNXX_ERROR() << "invalid key: size = " << key.size();
-    GRNXX_THROW();
-  }
-
-  Lock lock(&header_->inter_process_mutex);
-
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, REMOVING_FLAG);
-
-  return remove_key(key);
-}
-
-bool DoubleArray<Slice>::update(Slice src_key, Slice dest_key,
-                                int64_t *key_id) {
-  if ((src_key.size() < MIN_KEY_SIZE) || (src_key.size() > MAX_KEY_SIZE)) {
-    GRNXX_ERROR() << "invalid source key: size = " << src_key.size();
-    GRNXX_THROW();
-  }
-  if ((dest_key.size() < MIN_KEY_SIZE) || (dest_key.size() > MAX_KEY_SIZE)) {
-    GRNXX_ERROR() << "invalid destination key: size = " << dest_key.size();
-    GRNXX_THROW();
-  }
-
-  Lock lock(&header_->inter_process_mutex);
-
-  int64_t src_key_id;
-  if (!find(src_key, &src_key_id)) {
-    return false;
-  }
-  if (update_key(static_cast<int32_t>(src_key_id), src_key, dest_key)) {
-    if (key_id) {
-      *key_id = src_key_id;
-    }
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArray<Slice>::find_longest_prefix_match(
-    Slice query, int64_t *key_id, Slice *key) {
-  bool found = false;
-  uint32_t node_id = ROOT_NODE_ID;
-  uint32_t query_pos = 0;
-
-  for ( ; query_pos < query.size(); ++query_pos) {
-    const DoubleArrayNode node = nodes_[node_id];
-    if (node.is_leaf()) {
-      const DoubleArrayKey &match = get_key(node.key_pos());
-      if ((match.size() <= query.size()) &&
-          match.equals_to(Slice(query.address(), match.size()), query_pos)) {
-        if (key_id) {
-          *key_id = match.id();
-        }
-        if (key) {
-          *key = match.slice();
-        }
-        found = true;
-      }
-      return found;
-    }
-
-    if (nodes_[node_id].child() == TERMINAL_LABEL) {
-      const DoubleArrayNode leaf_node = nodes_[node.offset() ^ TERMINAL_LABEL];
-      if (leaf_node.is_leaf()) {
-        if (key_id || key) {
-          const DoubleArrayKey &match = get_key(leaf_node.key_pos());
-          if (key_id) {
-            *key_id = match.id();
-          }
-          if (key) {
-            *key = match.slice();
-          }
-        }
-        found = true;
-      }
-    }
-
-    node_id = node.offset() ^ query[query_pos];
-    if (nodes_[node_id].label() != query[query_pos]) {
-      return found;
-    }
-  }
-
-  const DoubleArrayNode node = nodes_[node_id];
-  if (node.is_leaf()) {
-    const DoubleArrayKey &match = get_key(node.key_pos());
-    if (match.size() <= query.size()) {
-      if (key_id) {
-        *key_id = match.id();
-      }
-      if (key) {
-        *key = match.slice();
-      }
-      found = true;
-    }
-  } else if (nodes_[node_id].child() == TERMINAL_LABEL) {
-    const DoubleArrayNode leaf_node = nodes_[node.offset() ^ TERMINAL_LABEL];
-    if (leaf_node.is_leaf()) {
-      if (key_id || key) {
-        const DoubleArrayKey &match = get_key(leaf_node.key_pos());
-        if (key_id) {
-          *key_id = match.id();
-        }
-        if (key) {
-          *key = match.slice();
-        }
-      }
-      found = true;
-    }
-  }
-  return found;
-}
-
-bool DoubleArray<Slice>::truncate() {
-  nodes_[ROOT_NODE_ID].set_child(INVALID_LABEL);
-  nodes_[ROOT_NODE_ID].set_offset(INVALID_OFFSET);
-  header_->next_key_id = 0;
-  header_->max_key_id = -1;
-  header_->num_keys = 0;
-  return true;
-}
-
-MapCursor<Slice> *DoubleArray<Slice>::open_basic_cursor(
-    const MapCursorOptions &options) {
-  if ((options.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    return open_id_cursor(-1, -1, options);
-  } else {
-    return open_key_cursor(nullptr, nullptr, options);
-  }
-}
-
-MapCursor<Slice> *DoubleArray<Slice>::open_id_cursor(
-    int64_t min, int64_t max, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayIDCursor<Slice>(
-      this, min, max, options);
-}
-
-MapCursor<Slice> *DoubleArray<Slice>::open_key_cursor(
-    Slice min, Slice max, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayKeyCursor<Slice>(
-      this, min, max, options);
-}
-
-MapCursor<Slice> *DoubleArray<Slice>::open_prefix_cursor(
-    Slice query, size_t min_size, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayPrefixCursor<Slice>(
-      this, query, min_size, options);
-}
-
-MapCursor<Slice> *DoubleArray<Slice>::open_completion_cursor(
-    Slice query, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayCompletionCursor<Slice>(
-      this, query, options);
-}
-
-DoubleArray<Slice>::DoubleArray()
-    : pool_(),
-      block_info_(nullptr),
-      header_(nullptr),
-      nodes_(nullptr),
-      chunks_(nullptr),
-      entries_(nullptr),
-      keys_(nullptr),
-      initialized_(false) {}
-
-void DoubleArray<Slice>::create_double_array(io::Pool pool,
-                                             const MapOptions &) {
-  pool_ = pool;
-
-  block_info_ = pool_.create_block(sizeof(DoubleArrayHeader));
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<DoubleArrayHeader *>(block_address);
-  *header_ = DoubleArrayHeader();
-
-  // TODO: The size should be given as options.
-  header_->nodes_size = static_cast<uint32_t>(INITIAL_NODES_SIZE);
-  header_->nodes_size &= ~CHUNK_MASK;
-  if (header_->nodes_size == 0) {
-    header_->nodes_size = INITIAL_NODES_SIZE;
-  }
-  header_->chunks_size = header_->nodes_size / CHUNK_SIZE;
-  header_->entries_size = static_cast<uint32_t>(INITIAL_ENTRIES_SIZE);
-  if (header_->entries_size == 0) {
-    header_->entries_size = INITIAL_ENTRIES_SIZE;
-  }
-  header_->keys_size = static_cast<uint32_t>(INITIAL_KEYS_SIZE);
-  if (header_->keys_size == 0) {
-    header_->keys_size = INITIAL_KEYS_SIZE;
-  }
-
-  create_arrays();
-
-  reserve_node(ROOT_NODE_ID);
-  nodes_[INVALID_OFFSET].set_is_origin(true);
-
-  initialized_ = true;
-}
-
-void DoubleArray<Slice>::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<DoubleArrayHeader *>(block_address);
-
-  // TODO: Check the format.
-
-  nodes_ = static_cast<DoubleArrayNode *>(
-      pool_.get_block_address(header_->nodes_block_id));
-  chunks_ = static_cast<DoubleArrayChunk *>(
-      pool_.get_block_address(header_->chunks_block_id));
-  entries_ = static_cast<DoubleArrayEntry *>(
-      pool_.get_block_address(header_->entries_block_id));
-  keys_ = static_cast<uint32_t *>(
-      pool_.get_block_address(header_->keys_block_id));
-}
-
-void DoubleArray<Slice>::create_arrays() {
-  const io::BlockInfo *block_info;
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayNode) * header_->nodes_size);
-  header_->nodes_block_id = block_info->id();
-  nodes_ = static_cast<DoubleArrayNode *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayChunk) * header_->chunks_size);
-  header_->chunks_block_id = block_info->id();
-  chunks_ = static_cast<DoubleArrayChunk *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayEntry) * header_->entries_size);
-  header_->entries_block_id = block_info->id();
-  entries_ = static_cast<DoubleArrayEntry *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(sizeof(uint32_t) * header_->keys_size);
-  header_->keys_block_id = block_info->id();
-  keys_ = static_cast<uint32_t *>(pool_.get_block_address(*block_info));
-}
-
-bool DoubleArray<Slice>::remove_key(const Slice &key) {
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-  if (!find_leaf(key, node_id, query_pos)) {
-    return false;
-  }
-
-  const uint32_t key_pos = nodes_[node_id].key_pos();
-  const DoubleArrayKey &found_key = get_key(key_pos);
-  if (!found_key.equals_to(key, query_pos)) {
-    return false;
-  }
-
-  const int32_t key_id = found_key.id();
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  entries_[key_id] = DoubleArrayEntry::invalid_entry(header_->next_key_id);
-
-  header_->next_key_id = key_id;
-  header_->total_key_length -= key.size();
-  --header_->num_keys;
-  return true;
-}
-
-bool DoubleArray<Slice>::update_key(int32_t key_id, const Slice &src_key,
-                                    const Slice &dest_key) {
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-
-  find_leaf(dest_key, node_id, query_pos);
-  if (!insert_leaf(dest_key, node_id, query_pos)) {
-    return false;
-  }
-
-  const uint32_t new_key_pos = append_key(dest_key, key_id);
-  header_->total_key_length =
-      header_->total_key_length + dest_key.size() - src_key.size();
-  entries_[key_id] = DoubleArrayEntry::valid_entry(new_key_pos);
-  nodes_[node_id].set_key_pos(new_key_pos);
-
-  node_id = ROOT_NODE_ID;
-  query_pos = 0;
-  if (!find_leaf(src_key, node_id, query_pos)) {
-    GRNXX_ERROR() << "key not found (unexpected)";
-    GRNXX_THROW();
-  }
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  return true;
-}
-
-bool DoubleArray<Slice>::find_leaf(const Slice &key, uint32_t &node_id,
-                                   size_t &query_pos) {
-  for ( ; query_pos < key.size(); ++query_pos) {
-    const DoubleArrayNode node = nodes_[node_id];
-    if (node.is_leaf()) {
-      return true;
-    }
-
-    const uint32_t next = node.offset() ^ key[query_pos];
-    if (nodes_[next].label() != key[query_pos]) {
-      return false;
-    }
-    node_id = next;
-  }
-
-  const DoubleArrayNode 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 DoubleArray<Slice>::insert_leaf(const Slice &key, uint32_t &node_id,
-                                 size_t query_pos) {
-  const DoubleArrayNode node = nodes_[node_id];
-  if (node.is_leaf()) {
-    const DoubleArrayKey &found_key = get_key(node.key_pos());
-    size_t i = query_pos;
-    while ((i < key.size()) && (i < found_key.size())) {
-      if (key[i] != found_key[i]) {
-        break;
-      }
-      ++i;
-    }
-    if ((i == key.size()) && (i == found_key.size())) {
-      return false;
-    }
-
-    if (header_->num_keys >= header_->entries_size) {
-      GRNXX_NOTICE() << "too many keys: num_keys = " << header_->num_keys
-                     << ", entries_size = " << header_->entries_size;
-      throw DoubleArrayException();
-    }
-
-//    GRNXX_DEBUG_THROW_IF(static_cast<uint32_t>(header_->next_key_id) >= header_->entries_size);
-
-    for (size_t j = query_pos; j < i; ++j) {
-      node_id = insert_node(node_id, key[j]);
-    }
-    node_id = separate(key, node_id, i);
-    return true;
-  } else if (node.label() == TERMINAL_LABEL) {
-    return true;
-  } else {
-    if (header_->num_keys >= header_->entries_size) {
-      GRNXX_NOTICE() << "too many keys: num_keys = " << header_->num_keys
-                     << ", entries_size = " << header_->entries_size;
-      throw DoubleArrayException();
-    }
-
-    const uint16_t label = (query_pos < key.size()) ?
-        static_cast<uint16_t>(key[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;
-  }
-}
-
-uint32_t DoubleArray<Slice>::insert_node(uint32_t node_id, uint16_t label) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  const DoubleArrayNode node = nodes_[node_id];
-  uint32_t offset;
-  if (node.is_leaf() || (node.offset() == INVALID_OFFSET)) {
-    offset = find_offset(&label, 1);
-  } else {
-    offset = node.offset();
-  }
-
-  const uint32_t next = offset ^ label;
-  reserve_node(next);
-
-  nodes_[next].set_label(label);
-  if (node.is_leaf()) {
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-    nodes_[next].set_key_pos(node.key_pos());
-  } else if (node.offset() == INVALID_OFFSET) {
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-  } else {
-//    GRNXX_DEBUG_THROW_IF(!nodes_[offset].is_origin());
-  }
-  nodes_[node_id].set_offset(offset);
-
-  const uint16_t child_label = nodes_[node_id].child();
-//  GRNXX_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.
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset ^ child_label].is_phantom());
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset ^ child_label].label() != child_label);
-    nodes_[next].set_sibling(child_label);
-    nodes_[node_id].set_child(label);
-  } else {
-    uint32_t prev = offset ^ child_label;
-//    GRNXX_DEBUG_THROW_IF(nodes_[prev].label() != child_label);
-    uint16_t sibling_label = nodes_[prev].sibling();
-    while (label > sibling_label) {
-      prev = offset ^ sibling_label;
-//      GRNXX_DEBUG_THROW_IF(nodes_[prev].label() != sibling_label);
-      sibling_label = nodes_[prev].sibling();
-    }
-//    GRNXX_DEBUG_THROW_IF(label == sibling_label);
-    nodes_[next].set_sibling(nodes_[prev].sibling());
-    nodes_[prev].set_sibling(label);
-  }
-  return next;
-}
-
-uint32_t DoubleArray<Slice>::append_key(const Slice &key, int32_t key_id) {
-  if (static_cast<uint32_t>(key_id) >= header_->entries_size) {
-    GRNXX_NOTICE() << "too many keys: key_id = " << key_id
-                   << ", entries_size = " << header_->entries_size;
-    throw DoubleArrayException();
-  }
-
-  const uint32_t key_pos = header_->next_key_pos;
-  const uint32_t key_size = DoubleArrayKey::estimate_size(key.size());
-
-  if (key_size > (header_->keys_size - key_pos)) {
-    GRNXX_NOTICE() << "too many keys: key_size = " << key_size
-                   << ", keys_size = " << header_->keys_size
-                   << ", key_pos = " << key_pos;
-    throw DoubleArrayException();
-  }
-  new (&keys_[key_pos]) DoubleArrayKey(key_id, key);
-
-  header_->next_key_pos = key_pos + key_size;
-  return key_pos;
-}
-
-uint32_t DoubleArray<Slice>::separate(const Slice &key, uint32_t node_id,
-                                  size_t i) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(!nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(i > key.size());
-
-  const DoubleArrayNode node = nodes_[node_id];
-  const DoubleArrayKey &found_key = get_key(node.key_pos());
-
-  uint16_t labels[2];
-  labels[0] = (i < found_key.size()) ?
-      static_cast<uint16_t>(found_key[i]) : TERMINAL_LABEL;
-  labels[1] = (i < key.size()) ?
-      static_cast<uint16_t>(key[i]) : TERMINAL_LABEL;
-//  GRNXX_DEBUG_THROW_IF(labels[0] == labels[1]);
-
-  const uint32_t offset = find_offset(labels, 2);
-
-  uint32_t next = offset ^ labels[0];
-  reserve_node(next);
-//  GRNXX_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 DoubleArray<Slice>::resolve(uint32_t node_id, uint16_t label) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  uint32_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();
-//    GRNXX_DEBUG_THROW_IF(next_label == INVALID_LABEL);
-    while (next_label != INVALID_LABEL) {
-//      GRNXX_DEBUG_THROW_IF(next_label > MAX_LABEL);
-      labels[num_labels++] = next_label;
-      next_label = nodes_[offset ^ next_label].sibling();
-    }
-//    GRNXX_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)) {
-//      GRNXX_DEBUG_THROW_IF((offset / CHUNK_SIZE) != header_->num_chunks);
-      reserve_chunk(header_->num_chunks);
-    }
-    nodes_[offset].set_is_origin(true);
-    nodes_[node_id].set_offset(offset);
-  }
-}
-
-void DoubleArray<Slice>::migrate_nodes(uint32_t node_id, uint32_t dest_offset,
-                                       const uint16_t *labels,
-                                       uint16_t num_labels) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(labels == nullptr);
-//  GRNXX_DEBUG_THROW_IF(num_labels == 0);
-//  GRNXX_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1));
-
-  const uint32_t src_offset = nodes_[node_id].offset();
-//  GRNXX_DEBUG_THROW_IF(src_offset == INVALID_OFFSET);
-//  GRNXX_DEBUG_THROW_IF(!nodes_[src_offset].is_origin());
-
-  for (uint16_t i = 0; i < num_labels; ++i) {
-    const uint32_t src_node_id = src_offset ^ labels[i];
-    const uint32_t dest_node_id = dest_offset ^ labels[i];
-//    GRNXX_DEBUG_THROW_IF(nodes_[src_node_id].is_phantom());
-//    GRNXX_DEBUG_THROW_IF(nodes_[src_node_id].label() != labels[i]);
-
-    reserve_node(dest_node_id);
-    DoubleArrayNode 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;
-
-//  GRNXX_DEBUG_THROW_IF(nodes_[dest_offset].is_origin());
-  nodes_[dest_offset].set_is_origin(true);
-  nodes_[node_id].set_offset(dest_offset);
-}
-
-uint32_t DoubleArray<Slice>::find_offset(const uint16_t *labels,
-                                         uint16_t num_labels) {
-//  GRNXX_DEBUG_THROW_IF(labels == nullptr);
-//  GRNXX_DEBUG_THROW_IF(num_labels == 0);
-//  GRNXX_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;
-
-  uint32_t chunk_count = 0;
-  do {
-    uint32_t leader = header_->leaders[level];
-    if (leader == INVALID_LEADER) {
-      // This level group is skipped because it is empty.
-      continue;
-    }
-
-    uint32_t chunk_id = leader;
-    do {
-      const DoubleArrayChunk &chunk = chunks_[chunk_id];
-//      GRNXX_DEBUG_THROW_IF(chunk.level() != level);
-
-      const uint32_t first = (chunk_id * CHUNK_SIZE) | chunk.first_phantom();
-      uint32_t node_id = first;
-      do {
-//        GRNXX_DEBUG_THROW_IF(!nodes_[node_id].is_phantom());
-        const uint32_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 uint32_t prev = chunk_id;
-      const uint32_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 DoubleArray<Slice>::reserve_node(uint32_t node_id) {
-  if (node_id >= (header_->num_chunks * CHUNK_SIZE)) {
-    reserve_chunk(node_id / CHUNK_SIZE);
-  }
-
-  DoubleArrayNode &node = nodes_[node_id];
-//  GRNXX_DEBUG_THROW_IF(!node.is_phantom());
-
-  const uint32_t chunk_id = node_id / CHUNK_SIZE;
-  DoubleArrayChunk &chunk = chunks_[chunk_id];
-//  GRNXX_DEBUG_THROW_IF(chunk.num_phantoms() == 0);
-
-  const uint32_t next = (chunk_id * CHUNK_SIZE) | node.next();
-  const uint32_t prev = (chunk_id * CHUNK_SIZE) | node.prev();
-//  GRNXX_DEBUG_THROW_IF(next >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(prev >= (header_->num_chunks * CHUNK_SIZE));
-
-  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 uint32_t threshold =
-        uint32_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);
-
-//  GRNXX_DEBUG_THROW_IF(node.offset() != INVALID_OFFSET);
-//  GRNXX_DEBUG_THROW_IF(node.label() != INVALID_LABEL);
-
-  --header_->num_phantoms;
-}
-
-void DoubleArray<Slice>::reserve_chunk(uint32_t chunk_id) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id != header_->num_chunks);
-
-  if (chunk_id >= header_->chunks_size) {
-    GRNXX_NOTICE() << "too many chunks: chunk_id = " << chunk_id
-                   << ", chunks_size = " << header_->chunks_size;
-    throw DoubleArrayException();
-  }
-
-  header_->num_chunks = chunk_id + 1;
-
-  DoubleArrayChunk chunk;
-  chunk.set_failure_count(0);
-  chunk.set_first_phantom(0);
-  chunk.set_num_phantoms(CHUNK_SIZE);
-  chunks_[chunk_id] = chunk;
-
-  const uint32_t begin = chunk_id * CHUNK_SIZE;
-  const uint32_t end = begin + CHUNK_SIZE;
-//  GRNXX_DEBUG_THROW_IF(end != (header_->num_chunks * CHUNK_SIZE));
-
-  DoubleArrayNode node;
-  node.set_is_phantom(true);
-  for (uint32_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 DoubleArray<Slice>::update_chunk_level(uint32_t chunk_id, uint32_t level) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  unset_chunk_level(chunk_id);
-  set_chunk_level(chunk_id, level);
-}
-
-void DoubleArray<Slice>::set_chunk_level(uint32_t chunk_id, uint32_t level) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  const uint32_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.
-    const uint32_t next = leader;
-    const uint32_t prev = chunks_[leader].prev();
-//    GRNXX_DEBUG_THROW_IF(next >= header_->num_chunks);
-//    GRNXX_DEBUG_THROW_IF(prev >= header_->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 DoubleArray<Slice>::unset_chunk_level(uint32_t chunk_id) {
-  const uint32_t level = chunks_[chunk_id].level();
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-  const uint32_t leader = header_->leaders[level];
-//  GRNXX_DEBUG_THROW_IF(leader == INVALID_LEADER);
-  const uint32_t next = chunks_[chunk_id].next();
-  const uint32_t prev = chunks_[chunk_id].prev();
-//  GRNXX_DEBUG_THROW_IF(next >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(prev >= header_->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 map
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map/double_array.cpp (+0 -2062) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/double_array.cpp    2013-08-23 10:46:34 +0900 (fdb70cd)
+++ /dev/null
@@ -1,2062 +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 "grnxx/alpha/map/double_array.hpp"
-
-#include <algorithm>
-#include <cmath>
-#include <vector>
-
-#include "../config.h"
-#include "grnxx/geo_point.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-namespace {
-
-constexpr  int32_t MIN_KEY_ID     = 0;
-constexpr  int32_t MAX_KEY_ID     = 0x7FFFFFFE;
-
-constexpr uint32_t INVALID_OFFSET = 0;
-
-constexpr uint32_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 uint32_t CHUNK_SIZE     = 0x200;
-constexpr uint32_t CHUNK_MASK     = 0x1FF;
-
-// Assume that #nodes per key is 4 and #uint32_ts per key is 8.
-// Note that an entries is associated with a key.
-constexpr uint32_t INITIAL_NODES_SIZE   = 1 << 16;
-constexpr uint32_t INITIAL_ENTRIES_SIZE = 1 << 14;
-constexpr uint32_t INITIAL_KEYS_SIZE    = INITIAL_ENTRIES_SIZE;
-
-constexpr uint32_t MAX_NODES_SIZE    =
-    std::numeric_limits<uint32_t>::max() & ~CHUNK_MASK;
-constexpr uint32_t MAX_ENTRIES_SIZE  = uint32_t(MAX_KEY_ID) + 1;
-constexpr uint32_t MAX_KEYS_SIZE     = MAX_ENTRIES_SIZE;
-
-// 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 uint32_t MAX_FAILURE_COUNT = 4;
-constexpr uint32_t MAX_CHUNK_COUNT   = 16;
-constexpr uint32_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 uint32_t INVALID_LEADER    = std::numeric_limits<uint32_t>::max();
-
-template <typename T, bool HAS_NAN = std::numeric_limits<T>::has_quiet_NaN>
-struct Helper;
-
-template <typename T>
-struct Helper<T, true> {
-  static bool equal_to(T x, T y) {
-    return *reinterpret_cast<uint64_t *>(&x) ==
-           *reinterpret_cast<uint64_t *>(&y);
-  }
-  static T normalize(T x) {
-    if (std::isnan(x)) {
-      return std::numeric_limits<T>::quiet_NaN();
-    } else if (x == 0.0) {
-      return +0.0;
-    }
-    return x;
-  }
-};
-
-template <typename T>
-struct Helper<T, false> {
-  static bool equal_to(T x, T y) {
-    return x == y;
-  }
-  static T normalize(T x) {
-    return x;
-  }
-};
-
-void convert_key(int8_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(static_cast<uint8_t>(key));
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-  *key_buf ^= 0x80;
-}
-
-void convert_key(int16_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(static_cast<uint16_t>(key));
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-  *key_buf ^= 0x80;
-}
-
-void convert_key(int32_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(static_cast<uint32_t>(key));
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-  *key_buf ^= 0x80;
-}
-
-void convert_key(int64_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(static_cast<uint64_t>(key));
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-  *key_buf ^= 0x80;
-}
-
-void convert_key(uint8_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(key);
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-}
-
-void convert_key(uint16_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(key);
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-}
-
-void convert_key(uint32_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(key);
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-}
-
-void convert_key(uint64_t key, uint8_t *key_buf) {
-#ifndef WORDS_BIGENDIAN
-  key = byte_swap(key);
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &key, sizeof(key));
-}
-
-void convert_key(double key, uint8_t *key_buf) {
-  int64_t x = *reinterpret_cast<const int64_t *>(&key);
-  x ^= (x >> 63) | (1ULL << 63);
-#ifndef WORDS_BIGENDIAN
-  x = byte_swap(static_cast<uint64_t>(x));
-#endif  // WORDS_BIGENDIAN
-  std::memcpy(key_buf, &x, sizeof(x));
-}
-
-void convert_key(GeoPoint key, uint8_t *key_buf) {
-  uint64_t interleaved_key = key.interleave();
-#ifndef WORDS_BIGENDIAN
-  interleaved_key = byte_swap(interleaved_key);
-#endif  // WORDS_BIGENDIAN
-  memcpy(key_buf, &interleaved_key, sizeof(interleaved_key));
-}
-
-}  // namespace
-
-struct DoubleArrayHeader {
-  MapType map_type;
-  uint32_t nodes_block_id;
-  uint32_t chunks_block_id;
-  uint32_t entries_block_id;
-  uint32_t keys_block_id;
-  uint32_t nodes_size;
-  uint32_t chunks_size;
-  uint32_t entries_size;
-  uint32_t keys_size;
-  int32_t next_key_id;
-  int32_t max_key_id;
-  uint32_t num_keys;
-  uint32_t num_chunks;
-  uint32_t num_phantoms;
-  uint32_t num_zombies;
-  uint32_t leaders[MAX_CHUNK_LEVEL + 1];
-  Mutex inter_process_mutex;
-
-  DoubleArrayHeader();
-};
-
-DoubleArrayHeader::DoubleArrayHeader()
-    : map_type(MAP_DOUBLE_ARRAY),
-      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),
-      nodes_size(0),
-      chunks_size(0),
-      entries_size(0),
-      keys_size(0),
-      next_key_id(0),
-      max_key_id(-1),
-      num_keys(0),
-      num_chunks(0),
-      num_phantoms(0),
-      num_zombies(0),
-      leaders(),
-      inter_process_mutex(MUTEX_UNLOCKED) {
-  for (uint32_t i = 0; i <= MAX_CHUNK_LEVEL; ++i) {
-    leaders[i] = INVALID_LEADER;
-  }
-}
-
-class DoubleArrayNode {
- public:
-  DoubleArrayNode() : qword_(IS_PHANTOM_FLAG) {}
-
-  // Structure overview.
-  //  0- 8 ( 9): next (is_phantom).
-  //  9-17 ( 9): prev (is_phantom).
-  //  0- 8 ( 9): label (!is_phantom).
-  //  9-17 ( 9): sibling (!is_phantom).
-  // 18-48 (31): key_id (!is_phantom && is_leaf).
-  // 18-49 (32): offset (!is_phantom && !is_leaf).
-  // 50-58 ( 9): child (!is_phantom && !is_leaf).
-  // 61-61 ( 1): is_leaf.
-  // 62-62 ( 1): is_phantom.
-  // 63-63 ( 1): is_origin.
-  // Note that 0 is the LSB and 63 is the MSB.
-
-  // The ID of this node is used as an offset (true) or not (false).
-  bool is_origin() const {
-    return qword_ & IS_ORIGIN_FLAG;
-  }
-  // This node is valid (false) or not (true).
-  bool is_phantom() const {
-    return qword_ & IS_PHANTOM_FLAG;
-  }
-  // This node is associated with a key (true) or not (false).
-  bool is_leaf() const {
-    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) |
-               (uint64_t(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 {
-    return static_cast<uint16_t>(qword_ & NEXT_MASK);
-  }
-  uint16_t prev() const {
-    return static_cast<uint16_t>((qword_ >> PREV_SHIFT) & PREV_MASK);
-  }
-
-  void set_next(uint16_t value) {
-    qword_ = (qword_ & ~NEXT_MASK) | value;
-  }
-  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 and the label of its next sibling.
-  // A phantom node returns an invalid label with IS_PHANTOM_FLAG.
-  // sibling() == INVALID_LABEL means that the node doesn't have next sibling.
-  uint64_t label() const {
-    return qword_ & (IS_PHANTOM_FLAG | LABEL_MASK);
-  }
-  uint16_t sibling() const {
-    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 of the associated key.
-  int32_t key_id() const {
-    return static_cast<uint32_t>((qword_ >> KEY_ID_SHIFT) & KEY_ID_MASK);
-  }
-
-  void set_key_id(int32_t value) {
-    qword_ = (qword_ & ~(KEY_ID_MASK << KEY_ID_SHIFT)) |
-             (static_cast<uint64_t>(value) << KEY_ID_SHIFT) | IS_LEAF_FLAG;
-  }
-
-  // A non-phantom and non-leaf node stores the offset to its children and the
-  // label of its first child.
-  // child() == INVALID_LABEL means that the node has no child.
-  uint32_t offset() const {
-    return static_cast<uint32_t>((qword_ >> OFFSET_SHIFT) & OFFSET_MASK);
-  }
-  uint16_t child() const {
-    return static_cast<uint16_t>((qword_ >> CHILD_SHIFT) & CHILD_MASK);
-  }
-
-  void set_offset(uint32_t value) {
-    if (qword_ & IS_LEAF_FLAG) {
-      qword_ = ((qword_ & ~IS_LEAF_FLAG) & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (static_cast<uint64_t>(value) << OFFSET_SHIFT) |
-               (uint64_t(INVALID_LABEL) << CHILD_SHIFT);
-    } else {
-      qword_ = (qword_ & ~(OFFSET_MASK << OFFSET_SHIFT)) |
-               (static_cast<uint64_t>(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.
-  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 (is_phantom).
-  static constexpr uint64_t NEXT_MASK       = (uint64_t(1) << 9) - 1;
-  static constexpr uint64_t PREV_MASK       = (uint64_t(1) << 9) - 1;
-  static constexpr uint8_t  PREV_SHIFT      = 9;
-
-  //  0-17 (!is_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-48 (!is_phantom && is_leaf)
-  static constexpr uint64_t KEY_ID_MASK    = (uint64_t(1) << 31) - 1;
-  static constexpr uint8_t  KEY_ID_SHIFT   = 18;
-
-  // 18-58 (!is_phantom && !is_leaf)
-  static constexpr uint64_t OFFSET_MASK     = (uint64_t(1) << 32) - 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     = 50;
-};
-
-class DoubleArrayChunk {
- public:
-  DoubleArrayChunk() : next_(0), prev_(0), others_(0) {}
-
-  // Chunks in the same level are doubly linked.
-  uint32_t next() const {
-    return next_;
-  }
-  uint32_t prev() const {
-    return prev_;
-  }
-
-  void set_next(uint32_t value) {
-    next_ = value;
-  }
-  void set_prev(uint32_t value) {
-    prev_ = value;
-  }
-
-  // The chunk level indicates how easily nodes can be put in this chunk.
-  uint32_t level() const {
-    return (others_ >> LEVEL_SHIFT) & LEVEL_MASK;
-  }
-  uint32_t failure_count() const {
-    return (others_ >> FAILURE_COUNT_SHIFT) & FAILURE_COUNT_MASK;
-  }
-
-  void set_level(uint32_t value) {
-    others_ = (others_ & ~(LEVEL_MASK << LEVEL_SHIFT)) |
-              (value << LEVEL_SHIFT);
-  }
-  void set_failure_count(uint32_t value) {
-    others_ = (others_ & ~(FAILURE_COUNT_MASK << FAILURE_COUNT_SHIFT)) |
-              (value << FAILURE_COUNT_SHIFT);
-  }
-
-  // The first phantom node and the number of phantom nodes in this chunk.
-  uint32_t first_phantom() const {
-    return (others_ >> FIRST_PHANTOM_SHIFT) & FIRST_PHANTOM_MASK;
-  }
-  uint32_t num_phantoms() const {
-    return (others_ >> NUM_PHANTOMS_SHIFT) & NUM_PHANTOMS_MASK;
-  }
-
-  void set_first_phantom(uint32_t value) {
-    others_ = (others_ & ~(FIRST_PHANTOM_MASK << FIRST_PHANTOM_SHIFT)) |
-              (value << FIRST_PHANTOM_SHIFT);
-  }
-  void set_num_phantoms(uint32_t value) {
-    others_ = (others_ & ~(NUM_PHANTOMS_MASK << NUM_PHANTOMS_SHIFT)) |
-              (value << NUM_PHANTOMS_SHIFT);
-  }
-
- private:
-  uint32_t next_;
-  uint32_t prev_;
-  uint32_t others_;
-
-  static constexpr uint32_t LEVEL_MASK          = (1 << 4) - 1;
-  static constexpr uint8_t  LEVEL_SHIFT         = 0;
-
-  static constexpr uint32_t FAILURE_COUNT_MASK  = (1 << 6) - 1;
-  static constexpr uint8_t  FAILURE_COUNT_SHIFT = 4;
-
-  static constexpr uint32_t FIRST_PHANTOM_MASK  = (1 << 10) - 1;
-  static constexpr uint32_t FIRST_PHANTOM_SHIFT = 10;
-
-  static constexpr uint32_t NUM_PHANTOMS_MASK   = (1 << 10) - 1;
-  static constexpr uint32_t NUM_PHANTOMS_SHIFT  = 20;
-};
-
-class DoubleArrayEntry {
- public:
-  // Create a valid entry.
-  static DoubleArrayEntry valid_entry() {
-    return DoubleArrayEntry(0);
-  }
-  // Create an invalid entry.
-  static DoubleArrayEntry invalid_entry(uint32_t next) {
-    return DoubleArrayEntry(next);
-  }
-
-  // Return true iff "*this" is valid (associated with a key).
-  explicit operator bool() const {
-    return dword_ == 0;
-  }
-
-  // Return the next invalid entry.
-  // Available iff "*this' is invalid.
-  uint32_t next() const {
-    return dword_;
-  }
-
- private:
-  uint32_t dword_;
-
-  explicit DoubleArrayEntry(uint32_t x) : dword_(x) {}
-};
-
-template <typename T>
-class DoubleArrayIDCursor : public MapCursor<T> {
- public:
-  DoubleArrayIDCursor(DoubleArray<T> *double_array,
-                      int64_t min, int64_t max,
-                      const MapCursorOptions &options);
-  ~DoubleArrayIDCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<T> *double_array_;
-  int64_t cur_;
-  int64_t end_;
-  int64_t step_;
-  uint64_t count_;
-  MapCursorOptions options_;
-  std::vector<std::pair<T, int64_t>> keys_;
-
-  void init_order_by_id(int64_t min, int64_t max);
-  void init_order_by_key(int64_t min, int64_t max);
-};
-
-constexpr uint64_t IS_ROOT_FLAG    = uint64_t(1) << 62;
-constexpr uint64_t POST_ORDER_FLAG = uint64_t(1) << 63;
-
-template <typename T>
-DoubleArrayIDCursor<T>::DoubleArrayIDCursor(
-    DoubleArray<T> *double_array, int64_t min, int64_t max,
-    const MapCursorOptions &options)
-    : MapCursor<T>(), double_array_(double_array), cur_(), end_(), step_(),
-      count_(0), options_(options), keys_() {
-  if (min < 0) {
-    min = 0;
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-    ++min;
-  }
-  if ((max < 0) || (max > double_array_->max_key_id())) {
-    max = double_array_->max_key_id();
-  } else if (options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-    --max;
-  }
-  if (min > max) {
-    cur_ = end_ = 0;
-    return;
-  }
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id(min, max);
-  } else {
-    init_order_by_key(min, max);
-  }
-}
-
-template <typename T>
-DoubleArrayIDCursor<T>::~DoubleArrayIDCursor() {}
-
-template <typename T>
-bool DoubleArrayIDCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    while (cur_ != end_) {
-      cur_ += step_;
-      if (double_array_->get(cur_, &this->key_)) {
-        this->key_id_ = cur_;
-        ++count_;
-        return true;
-      }
-    }
-  } else if (cur_ != end_) {
-    cur_ += step_;
-    this->key_ = keys_[cur_].first;
-    this->key_id_ = keys_[cur_].second;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArrayIDCursor<T>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-template <typename T>
-void DoubleArrayIDCursor<T>::init_order_by_id(int64_t min, int64_t max) {
-  options_.flags |= MAP_CURSOR_ORDER_BY_ID;
-  options_.flags &= ~MAP_CURSOR_ORDER_BY_KEY;
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = min - 1;
-    end_ = max;
-    step_ = 1;
-  } else {
-    cur_ = max + 1;
-    end_ = min;
-    step_ = -1;
-  }
-  uint64_t count = 0;
-  while ((count < options_.offset) && (cur_ != end_)) {
-    cur_ += step_;
-    if (double_array_->get(cur_)) {
-      ++count;
-    }
-  }
-}
-
-template <typename T>
-void DoubleArrayIDCursor<T>::init_order_by_key(int64_t min, int64_t max) {
-  cur_ = min - 1;
-  end_ = max;
-  while (cur_ != end_) {
-    ++cur_;
-    T key;
-    if (double_array_->get(cur_, &key)) {
-      keys_.push_back(std::make_pair(key, cur_));
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    cur_ = -1;
-    end_ = keys_.size() - 1;
-    step_ = 1;
-  } else {
-    cur_ = keys_.size();
-    end_ = 0;
-    step_ = -1;
-  }
-}
-
-template <>
-void DoubleArrayIDCursor<GeoPoint>::init_order_by_key(int64_t min,
-                                                      int64_t max) {
-  // Ignore MAP_CURSOR_ORDER_BY_KEY.
-  init_order_by_id(min, max);
-}
-
-template <typename T>
-class DoubleArrayKeyCursor : public MapCursor<T> {
- public:
-  DoubleArrayKeyCursor(DoubleArray<T> *double_array, T min, T max,
-                       const MapCursorOptions &options);
-  ~DoubleArrayKeyCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<T> *double_array_;
-  uint64_t cur_;
-  uint64_t count_;
-  T min_;
-  T max_;
-  MapCursorOptions options_;
-  std::vector<uint64_t> node_ids_;
-  std::vector<std::pair<int64_t, T>> keys_;
-
-  void init_order_by_id();
-  void init_order_by_key();
-  void init_reverse_order_by_key();
-
-  bool next_order_by_id();
-  bool next_order_by_key();
-  bool next_reverse_order_by_key();
-};
-
-template <typename T>
-DoubleArrayKeyCursor<T>::DoubleArrayKeyCursor(
-    DoubleArray<T> *double_array, T min, T max,
-    const MapCursorOptions &options)
-    : MapCursor<T>(), double_array_(double_array), cur_(), count_(0),
-      min_(min), max_(max), options_(options), node_ids_(), keys_() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id();
-  } else {
-    options_.flags &= ~MAP_CURSOR_ORDER_BY_ID;
-    options_.flags |= MAP_CURSOR_ORDER_BY_KEY;
-    if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-      init_order_by_key();
-    } else {
-      init_reverse_order_by_key();
-    }
-  }
-}
-
-template <typename T>
-DoubleArrayKeyCursor<T>::~DoubleArrayKeyCursor() {}
-
-template <typename T>
-bool DoubleArrayKeyCursor<T>::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    return next_order_by_id();
-  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    return next_order_by_key();
-  } else {
-    return next_reverse_order_by_key();
-  }
-}
-
-template <typename T>
-bool DoubleArrayKeyCursor<T>::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-template <typename T>
-void DoubleArrayKeyCursor<T>::init_order_by_id() {
-  init_order_by_key();
-  while (!node_ids_.empty()) {
-    const uint64_t node_id = node_ids_.back();
-    node_ids_.pop_back();
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const T key = double_array_->keys_[node.key_id()];
-      if ((key > max_) ||
-          ((key == max_) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-        break;
-      }
-      keys_.push_back(std::make_pair(node.key_id(), key));
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  std::sort(keys_.begin(), keys_.end());
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    std::reverse(keys_.begin(), keys_.end());
-  }
-  cur_ = options_.offset;
-}
-
-template <typename T>
-void DoubleArrayKeyCursor<T>::init_order_by_key() {
-  uint8_t min_buf[sizeof(T)];
-  convert_key(min_, min_buf);
-
-  uint64_t node_id = ROOT_NODE_ID;
-  DoubleArrayNode node;
-  for (size_t i = 0; i < sizeof(T); ++i) {
-    node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const T key = double_array_->keys_[node.key_id()];
-      if ((key > min_) ||
-          ((key == min_) && (~options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
-        node_ids_.push_back(node_id);
-      } else if (node.sibling() != INVALID_LABEL) {
-        node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-      }
-      return;
-    } else if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    node_id = node.offset() ^ min_buf[i];
-    if (double_array_->nodes_[node_id].label() != min_buf[i]) {
-      uint16_t label = node.child();
-      if (label == TERMINAL_LABEL) {
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-      while (label != INVALID_LABEL) {
-        if (label > min_buf[i]) {
-          node_ids_.push_back(node.offset() ^ label);
-          break;
-        }
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-      return;
-    }
-  }
-
-  node = double_array_->nodes_[node_id];
-  if (node.is_leaf()) {
-    if (~options_.flags & MAP_CURSOR_EXCEPT_MIN) {
-      node_ids_.push_back(node_id);
-    } else if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    return;
-  } else if (node.sibling() != INVALID_LABEL) {
-    node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-  }
-
-  uint16_t label = node.child();
-  if ((label == TERMINAL_LABEL) && (options_.flags & MAP_CURSOR_EXCEPT_MIN)) {
-    label = double_array_->nodes_[node.offset() ^ label].sibling();
-  }
-  if (label != INVALID_LABEL) {
-    node_ids_.push_back(node.offset() ^ label);
-  }
-}
-
-template <typename T>
-void DoubleArrayKeyCursor<T>::init_reverse_order_by_key() {
-  uint8_t max_buf[sizeof(T)];
-  convert_key(max_, max_buf);
-
-  uint64_t node_id = ROOT_NODE_ID;
-  for (size_t i = 0; i < sizeof(T); ++i) {
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const T key = double_array_->keys_[node.key_id()];
-      if ((key < max_) ||
-          ((key == max_) && (~options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-        node_ids_.push_back(node_id | POST_ORDER_FLAG);
-      }
-      return;
-    }
-    uint16_t label = double_array_->nodes_[node_id].child();
-    if (label == TERMINAL_LABEL) {
-      node_id = node.offset() ^ label;
-      node_ids_.push_back(node_id | POST_ORDER_FLAG);
-      label = double_array_->nodes_[node_id].sibling();
-    }
-    while (label != INVALID_LABEL) {
-      node_id = node.offset() ^ label;
-      if (label < max_buf[i]) {
-        node_ids_.push_back(node_id);
-      } else if (label > max_buf[i]) {
-        return;
-      } else {
-        break;
-      }
-      label = double_array_->nodes_[node_id].sibling();
-    }
-    if (label == INVALID_LABEL) {
-      return;
-    }
-  }
-
-  const DoubleArrayNode node = double_array_->nodes_[node_id];
-  if (node.is_leaf()) {
-    if (~options_.flags & MAP_CURSOR_EXCEPT_MAX) {
-      node_ids_.push_back(node_id | POST_ORDER_FLAG);
-    }
-    return;
-  }
-
-  uint16_t label = double_array_->nodes_[node_id].child();
-  if ((label == TERMINAL_LABEL) &&
-      (~options_.flags & MAP_CURSOR_EXCEPT_MAX)) {
-    node_ids_.push_back((node.offset() ^ label) | POST_ORDER_FLAG);
-  }
-}
-
-template <typename T>
-bool DoubleArrayKeyCursor<T>::next_order_by_id() {
-  if (cur_ < keys_.size()) {
-    this->key_id_ = keys_[cur_].first;
-    this->key_ = keys_[cur_].second;
-    ++cur_;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArrayKeyCursor<T>::next_order_by_key() {
-  while (!node_ids_.empty()) {
-    const uint64_t node_id = node_ids_.back();
-    node_ids_.pop_back();
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.sibling() != INVALID_LABEL) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const T key = double_array_->keys_[node.key_id()];
-      if ((key > max_) ||
-          ((key == max_) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
-        node_ids_.clear();
-        return false;
-      }
-      if (options_.offset > 0) {
-        --options_.offset;
-      } else {
-        this->key_id_ = node.key_id();
-        this->key_ = key;
-        ++count_;
-        return true;
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArrayKeyCursor<T>::next_reverse_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (post_order) {
-      node_ids_.pop_back();
-      if (node.is_leaf()) {
-        const T key = double_array_->keys_[node.key_id()];
-        if ((key < min_) ||
-            ((key == min_) && (options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
-          node_ids_.clear();
-          return false;
-        }
-        if (options_.offset > 0) {
-          --options_.offset;
-        } else {
-          this->key_id_ = node.key_id();
-          this->key_ = key;
-          ++count_;
-          return true;
-        }
-      }
-    } else {
-      node_ids_.back() |= POST_ORDER_FLAG;
-      uint16_t label = double_array_->nodes_[node_id].child();
-      while (label != INVALID_LABEL) {
-        node_ids_.push_back(node.offset() ^ label);
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-    }
-  }
-  return false;
-}
-
-class DoubleArrayBitwiseCompletionCursor : public MapCursor<GeoPoint> {
- public:
-  DoubleArrayBitwiseCompletionCursor(DoubleArray<GeoPoint> *double_array,
-                                     GeoPoint query, size_t bit_size,
-                                     const MapCursorOptions &options);
-  ~DoubleArrayBitwiseCompletionCursor();
-
-  bool next();
-  bool remove();
-
- private:
-  DoubleArray<GeoPoint> *double_array_;
-  uint64_t cur_;
-  uint64_t count_;
-  GeoPoint query_;
-  size_t bit_size_;
-  uint64_t mask_;
-  MapCursorOptions options_;
-  std::vector<uint64_t> node_ids_;
-  std::vector<std::pair<int64_t, GeoPoint>> keys_;
-
-  void init_order_by_id();
-  void init_order_by_key();
-
-  bool next_order_by_id();
-  bool next_order_by_key();
-  bool next_reverse_order_by_key();
-};
-
-DoubleArrayBitwiseCompletionCursor::DoubleArrayBitwiseCompletionCursor(
-    DoubleArray<GeoPoint> *double_array, GeoPoint query, size_t bit_size,
-    const MapCursorOptions &options)
-    : MapCursor<GeoPoint>(), double_array_(double_array), cur_(), count_(0),
-      query_(query), bit_size_(bit_size), mask_(), options_(options),
-      node_ids_(), keys_() {
-  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
-      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    init_order_by_id();
-  } else {
-    options_.flags &= ~MAP_CURSOR_ORDER_BY_ID;
-    options_.flags |= MAP_CURSOR_ORDER_BY_KEY;
-    init_order_by_key();
-  }
-}
-
-DoubleArrayBitwiseCompletionCursor::~DoubleArrayBitwiseCompletionCursor() {}
-
-bool DoubleArrayBitwiseCompletionCursor::next() {
-  if (count_ >= options_.limit) {
-    return false;
-  }
-  if (options_.flags & MAP_CURSOR_ORDER_BY_ID) {
-    return next_order_by_id();
-  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    return next_order_by_key();
-  } else {
-    return next_reverse_order_by_key();
-  }
-}
-
-bool DoubleArrayBitwiseCompletionCursor::remove() {
-  return double_array_->unset(this->key_id_);
-}
-
-void DoubleArrayBitwiseCompletionCursor::init_order_by_id() {
-  init_order_by_key();
-
-  while (!node_ids_.empty()) {
-    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
-    node_ids_.pop_back();
-
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (!is_root && (node.sibling() != INVALID_LABEL)) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-
-    if (node.is_leaf()) {
-      const GeoPoint key = double_array_->keys_[node.key_id()];
-      if (((key.value() ^ query_.value()) & mask_) == 0) {
-        keys_.push_back(std::make_pair(node.key_id(), key));
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-
-  std::sort(keys_.begin(), keys_.end(),
-            [](const std::pair<int64_t, GeoPoint> &lhs,
-               const std::pair<int64_t, GeoPoint> &rhs) {
-              return lhs.first < rhs.first;
-            });
-  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    std::reverse(keys_.begin(), keys_.end());
-  }
-  cur_ = options_.offset;
-}
-
-void DoubleArrayBitwiseCompletionCursor::init_order_by_key() {
-  if (bit_size_ >= 64) {
-    bit_size_ = 64;
-  }
-  switch (bit_size_) {
-    case 0: {
-      mask_ = 0;
-      break;
-    }
-    case 1: {
-      mask_ = GeoPoint(1 << 31, 0).value();
-      break;
-    }
-    default: {
-      mask_ = GeoPoint(0xFFFFFFFFU << (32 - (bit_size_ / 2) - (bit_size_ % 2)),
-                       0xFFFFFFFFU << (32 - (bit_size_ / 2))).value();
-      break;
-    }
-  }
-
-  // Note: MAP_CURSOR_EXCEPT_QUERY does not make sense.
-
-  uint8_t query_buf[sizeof(GeoPoint)];
-  convert_key(query_, query_buf);
-
-  size_t min_size = bit_size_ / 8;
-
-  uint64_t node_id = ROOT_NODE_ID;
-  for (size_t i = 0; i < min_size; ++i) {
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (node.is_leaf()) {
-      const GeoPoint key = double_array_->keys_[node.key_id()];
-      if (((key.value() ^ query_.value()) & mask_) == 0) {
-        if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-          node_id |= IS_ROOT_FLAG;
-        }
-        node_ids_.push_back(node_id);
-      }
-      return;
-    }
-    node_id = node.offset() ^ query_buf[i];
-    if (double_array_->nodes_[node_id].label() != query_buf[i]) {
-      return;
-    }
-  }
-
-  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
-    node_id |= IS_ROOT_FLAG;
-  }
-  node_ids_.push_back(node_id);
-}
-
-bool DoubleArrayBitwiseCompletionCursor::next_order_by_id() {
-  if (cur_ < keys_.size()) {
-    this->key_id_ = keys_[cur_].first;
-    this->key_ = keys_[cur_].second;
-    ++cur_;
-    ++count_;
-    return true;
-  }
-  return false;
-}
-
-bool DoubleArrayBitwiseCompletionCursor::next_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
-    node_ids_.pop_back();
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (!is_root && (node.sibling() != INVALID_LABEL)) {
-      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
-    }
-    if (node.is_leaf()) {
-      const GeoPoint key = double_array_->keys_[node.key_id()];
-      if (((key.value() ^ query_.value()) & mask_) == 0) {
-        if (options_.offset > 0) {
-          --options_.offset;
-        } else {
-          this->key_id_ = node.key_id();
-          this->key_ = key;
-          ++count_;
-          return true;
-        }
-      }
-    } else if (node.child() != INVALID_LABEL) {
-      node_ids_.push_back(node.offset() ^ node.child());
-    }
-  }
-  return false;
-}
-
-bool DoubleArrayBitwiseCompletionCursor::next_reverse_order_by_key() {
-  while (!node_ids_.empty()) {
-    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
-    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
-    const DoubleArrayNode node = double_array_->nodes_[node_id];
-    if (post_order) {
-      node_ids_.pop_back();
-      if (node.is_leaf()) {
-        const GeoPoint key = double_array_->keys_[node.key_id()];
-        if (((key.value() ^ query_.value()) & mask_) == 0) {
-          if (options_.offset > 0) {
-            --options_.offset;
-          } else {
-            this->key_id_ = node.key_id();
-            this->key_ = key;
-            ++count_;
-            return true;
-          }
-        }
-      }
-    } else {
-      node_ids_.back() |= POST_ORDER_FLAG;
-      uint16_t label = double_array_->nodes_[node_id].child();
-      while (label != INVALID_LABEL) {
-        node_ids_.push_back(node.offset() ^ label);
-        label = double_array_->nodes_[node.offset() ^ label].sibling();
-      }
-    }
-  }
-  return false;
-}
-
-template <typename T>
-DoubleArray<T>::~DoubleArray() {
-  if (!initialized_) try {
-    // Free allocated blocks 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 (...) {
-  }
-}
-
-template <typename T>
-DoubleArray<T> *DoubleArray<T>::create(io::Pool pool,
-                                       const MapOptions &options) {
-  std::unique_ptr<DoubleArray<T>> double_array(
-      new (std::nothrow) DoubleArray<T>);
-  if (!double_array) {
-    GRNXX_ERROR() << "new grnxx::alpha::map::DoubleArray failed";
-    GRNXX_THROW();
-  }
-  double_array->create_double_array(pool, options);
-  return double_array.release();
-}
-
-template <typename T>
-DoubleArray<T> *DoubleArray<T>::open(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<DoubleArray<T>> double_array(
-      new (std::nothrow) DoubleArray<T>);
-  if (!double_array) {
-    GRNXX_ERROR() << "new grnxx::alpha::map::DoubleArray failed";
-    GRNXX_THROW();
-  }
-  double_array->open_double_array(pool, block_id);
-  return double_array.release();
-}
-
-template <typename T>
-bool DoubleArray<T>::unlink(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<DoubleArray<T>> double_array(open(pool, block_id));
-
-  pool.free_block(double_array->header_->nodes_block_id);
-  pool.free_block(double_array->header_->chunks_block_id);
-  pool.free_block(double_array->header_->entries_block_id);
-  pool.free_block(double_array->header_->keys_block_id);
-  pool.free_block(block_id);
-  return true;
-}
-
-template <typename T>
-uint32_t DoubleArray<T>::block_id() const {
-  return block_info_->id();
-}
-
-template <typename T>
-MapType DoubleArray<T>::type() const {
-  return MAP_DOUBLE_ARRAY;
-}
-
-template <typename T>
-int64_t DoubleArray<T>::max_key_id() const {
-  return header_->max_key_id;
-}
-
-template <typename T>
-int64_t DoubleArray<T>::next_key_id() const {
-  return header_->next_key_id;
-}
-
-template <typename T>
-uint64_t DoubleArray<T>::num_keys() const {
-  return header_->num_keys;
-}
-
-template <typename T>
-bool DoubleArray<T>::get(int64_t key_id, T *key) {
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  if (key) {
-    *key = keys_[key_id];
-  }
-  return true;
-}
-
-template <typename T>
-bool DoubleArray<T>::get_next(int64_t key_id, int64_t *next_key_id,
-                              T *next_key) {
-  if (key_id >= header_->max_key_id) {
-    return false;
-  }
-  if (key_id < 0) {
-    key_id = -1;
-  }
-  for (++key_id; key_id <= header_->max_key_id; ++key_id) {
-    const DoubleArrayEntry entry = entries_[key_id];
-    if (entry) {
-      if (next_key_id) {
-        *next_key_id = key_id;
-      }
-      if (next_key) {
-        *next_key = keys_[key_id];
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArray<T>::unset(int64_t key_id) {
-  Lock lock(&header_->inter_process_mutex);
-
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  return remove_key(keys_[key_id]);
-}
-
-template <typename T>
-bool DoubleArray<T>::reset(int64_t key_id, T dest_key) {
-  Lock lock(&header_->inter_process_mutex);
-
-  dest_key = Helper<T>::normalize(dest_key);
-
-  if ((key_id < MIN_KEY_ID) || (key_id > header_->max_key_id)) {
-    return false;
-  }
-  const DoubleArrayEntry entry = entries_[key_id];
-  if (!entry) {
-    return false;
-  }
-  return update_key(key_id, keys_[key_id], dest_key);
-}
-
-template <typename T>
-bool DoubleArray<T>::find(T key, int64_t *key_id) {
-  key = Helper<T>::normalize(key);
-
-  uint8_t key_buf[sizeof(T)];
-  convert_key(key, key_buf);
-
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-  if (!find_leaf(key_buf, node_id, query_pos)) {
-    return false;
-  }
-
-  // Note that nodes_[node_id] might be updated by other threads/processes.
-  const DoubleArrayNode node = nodes_[node_id];
-  if (!node.is_leaf()) {
-    return false;
-  }
-
-  const int32_t found_key_id = node.key_id();
-  if (Helper<T>::equal_to(keys_[found_key_id], key)) {
-    if (key_id) {
-      *key_id = found_key_id;
-    }
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArray<T>::insert(T key, int64_t *key_id) {
-  Lock lock(&header_->inter_process_mutex);
-
-  key = Helper<T>::normalize(key);
-
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, INSERTING_FLAG);
-
-  uint8_t key_buf[sizeof(T)];
-  convert_key(key, key_buf);
-
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-
-  find_leaf(key_buf, node_id, query_pos);
-  if (!insert_leaf(key, key_buf, node_id, query_pos)) {
-    if (key_id) {
-      *key_id = nodes_[node_id].key_id();
-    }
-    return false;
-  }
-
-  const int32_t new_key_id = header_->next_key_id;
-  keys_[new_key_id] = key;
-
-  ++header_->num_keys;
-
-  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] = DoubleArrayEntry::valid_entry();
-  nodes_[node_id].set_key_id(new_key_id);
-  if (key_id) {
-    *key_id = new_key_id;
-  }
-  return true;
-}
-
-template <typename T>
-bool DoubleArray<T>::remove(T key) {
-  Lock lock(&header_->inter_process_mutex);
-
-  key = Helper<T>::normalize(key);
-
-//  GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
-//  StatusFlagManager status_flag_manager(header_, REMOVING_FLAG);
-
-  return remove_key(key);
-}
-
-template <typename T>
-bool DoubleArray<T>::update(T src_key, T dest_key, int64_t *key_id) {
-  Lock lock(&header_->inter_process_mutex);
-
-  src_key = Helper<T>::normalize(src_key);
-  dest_key = Helper<T>::normalize(dest_key);
-
-  int64_t src_key_id;
-  if (!find(src_key, &src_key_id)) {
-    return false;
-  }
-  if (update_key(static_cast<int32_t>(src_key_id), src_key, dest_key)) {
-    if (key_id) {
-      *key_id = src_key_id;
-    }
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-bool DoubleArray<T>::truncate() {
-  nodes_[ROOT_NODE_ID].set_child(INVALID_LABEL);
-  nodes_[ROOT_NODE_ID].set_offset(INVALID_OFFSET);
-  header_->next_key_id = 0;
-  header_->max_key_id = -1;
-  header_->num_keys = 0;
-  return true;
-}
-
-template <typename T>
-MapCursor<T> *DoubleArray<T>::open_basic_cursor(
-    const MapCursorOptions &options) {
-  if ((options.flags & MAP_CURSOR_ORDER_BY_ID) ||
-      (~options.flags & MAP_CURSOR_ORDER_BY_KEY)) {
-    return open_id_cursor(-1, -1, options);
-  } else {
-    // TODO: KeyCursor should be used.
-    return open_id_cursor(-1, -1, options);
-  }
-}
-
-template <typename T>
-MapCursor<T> *DoubleArray<T>::open_id_cursor(int64_t min, int64_t max,
-                                             const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayIDCursor<T>(this, min, max, options);
-}
-
-template <typename T>
-MapCursor<T> *DoubleArray<T>::open_key_cursor(
-    T min, T max, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayKeyCursor<T>(this, min, max, options);
-}
-
-template <>
-MapCursor<GeoPoint> *DoubleArray<GeoPoint>::open_key_cursor(
-    GeoPoint, GeoPoint, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <typename T>
-MapCursor<T> *DoubleArray<T>::open_bitwise_completion_cursor(
-    T, size_t, const MapCursorOptions &) {
-  // Not supported.
-  return nullptr;
-}
-
-template <>
-MapCursor<GeoPoint> *DoubleArray<GeoPoint>::open_bitwise_completion_cursor(
-    GeoPoint query, size_t bit_size, const MapCursorOptions &options) {
-  return new (std::nothrow) DoubleArrayBitwiseCompletionCursor(
-      this, query, bit_size, options);
-}
-
-template <typename T>
-DoubleArray<T>::DoubleArray()
-    : pool_(),
-      block_info_(nullptr),
-      header_(nullptr),
-      nodes_(nullptr),
-      chunks_(nullptr),
-      entries_(nullptr),
-      keys_(nullptr),
-      initialized_(false) {}
-
-template <typename T>
-void DoubleArray<T>::create_double_array(io::Pool pool, const MapOptions &) {
-  pool_ = pool;
-
-  block_info_ = pool_.create_block(sizeof(DoubleArrayHeader));
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<DoubleArrayHeader *>(block_address);
-  *header_ = DoubleArrayHeader();
-
-  // TODO: The size should be given as options.
-  header_->nodes_size = static_cast<uint32_t>(INITIAL_NODES_SIZE);
-  header_->nodes_size &= ~CHUNK_MASK;
-  if (header_->nodes_size == 0) {
-    header_->nodes_size = INITIAL_NODES_SIZE;
-  }
-  header_->chunks_size = header_->nodes_size / CHUNK_SIZE;
-  header_->entries_size = static_cast<uint32_t>(INITIAL_ENTRIES_SIZE);
-  if (header_->entries_size == 0) {
-    header_->entries_size = INITIAL_ENTRIES_SIZE;
-  }
-  header_->keys_size = static_cast<uint32_t>(INITIAL_KEYS_SIZE);
-  if (header_->keys_size == 0) {
-    header_->keys_size = INITIAL_KEYS_SIZE;
-  }
-
-  create_arrays();
-
-  reserve_node(ROOT_NODE_ID);
-  nodes_[INVALID_OFFSET].set_is_origin(true);
-
-  initialized_ = true;
-}
-
-template <typename T>
-void DoubleArray<T>::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<DoubleArrayHeader *>(block_address);
-
-  // TODO: Check the format.
-
-  nodes_ = static_cast<DoubleArrayNode *>(
-      pool_.get_block_address(header_->nodes_block_id));
-  chunks_ = static_cast<DoubleArrayChunk *>(
-      pool_.get_block_address(header_->chunks_block_id));
-  entries_ = static_cast<DoubleArrayEntry *>(
-      pool_.get_block_address(header_->entries_block_id));
-  keys_ = static_cast<T *>(
-      pool_.get_block_address(header_->keys_block_id));
-}
-
-template <typename T>
-void DoubleArray<T>::create_arrays() {
-  const io::BlockInfo *block_info;
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayNode) * header_->nodes_size);
-  header_->nodes_block_id = block_info->id();
-  nodes_ = static_cast<DoubleArrayNode *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayChunk) * header_->chunks_size);
-  header_->chunks_block_id = block_info->id();
-  chunks_ = static_cast<DoubleArrayChunk *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(
-      sizeof(DoubleArrayEntry) * header_->entries_size);
-  header_->entries_block_id = block_info->id();
-  entries_ = static_cast<DoubleArrayEntry *>(
-      pool_.get_block_address(*block_info));
-
-  block_info = pool_.create_block(sizeof(T) * header_->keys_size);
-  header_->keys_block_id = block_info->id();
-  keys_ = static_cast<T *>(pool_.get_block_address(*block_info));
-}
-
-template <typename T>
-bool DoubleArray<T>::remove_key(T key) {
-  uint8_t key_buf[sizeof(T)];
-  convert_key(key, key_buf);
-
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-  if (!find_leaf(key_buf, node_id, query_pos)) {
-    return false;
-  }
-
-  const int32_t key_id = nodes_[node_id].key_id();
-  if (!Helper<T>::equal_to(keys_[key_id], key)) {
-    return false;
-  }
-
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  entries_[key_id] = DoubleArrayEntry::invalid_entry(header_->next_key_id);
-
-  header_->next_key_id = key_id;
-  --header_->num_keys;
-  return true;
-}
-
-template <typename T>
-bool DoubleArray<T>::update_key(int32_t key_id, T src_key, T dest_key) {
-  uint32_t node_id = ROOT_NODE_ID;
-  size_t query_pos = 0;
-
-  uint8_t dest_key_buf[sizeof(T)];
-  convert_key(dest_key, dest_key_buf);
-
-  find_leaf(dest_key_buf, node_id, query_pos);
-  if (!insert_leaf(dest_key, dest_key_buf, node_id, query_pos)) {
-    return false;
-  }
-
-  keys_[key_id] = dest_key;
-  entries_[key_id] = DoubleArrayEntry::valid_entry();
-  nodes_[node_id].set_key_id(key_id);
-
-  uint8_t src_key_buf[sizeof(T)];
-  convert_key(src_key, src_key_buf);
-
-  node_id = ROOT_NODE_ID;
-  query_pos = 0;
-  if (!find_leaf(src_key_buf, node_id, query_pos)) {
-    GRNXX_ERROR() << "key not found (unexpected)";
-    GRNXX_THROW();
-  }
-  nodes_[node_id].set_offset(INVALID_OFFSET);
-  return true;
-}
-
-template <typename T>
-bool DoubleArray<T>::find_leaf(const uint8_t *key_buf, uint32_t &node_id,
-                               size_t &query_pos) {
-  for ( ; query_pos < sizeof(T); ++query_pos) {
-    const DoubleArrayNode node = nodes_[node_id];
-    if (node.is_leaf()) {
-      return true;
-    }
-
-    const uint32_t next = node.offset() ^ key_buf[query_pos];
-    if (nodes_[next].label() != key_buf[query_pos]) {
-      return false;
-    }
-    node_id = next;
-  }
-
-  const DoubleArrayNode 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();
-}
-
-template <typename T>
-bool DoubleArray<T>::insert_leaf(T key, const uint8_t *key_buf,
-                                 uint32_t &node_id, size_t query_pos) {
-  const DoubleArrayNode node = nodes_[node_id];
-  if (node.is_leaf()) {
-    const T found_key = keys_[node.key_id()];
-    if (Helper<T>::equal_to(key, found_key)) {
-      return false;
-    }
-
-    uint8_t found_key_buf[sizeof(T)];
-    convert_key(found_key, found_key_buf);
-    size_t i = query_pos;
-    while (i < sizeof(T)) {
-      if (key_buf[i] != found_key_buf[i]) {
-        break;
-      }
-      ++i;
-    }
-
-    if (header_->num_keys >= header_->entries_size) {
-      GRNXX_NOTICE() << "too many keys: num_keys = " << header_->num_keys
-                     << ", entries_size = " << header_->entries_size;
-      throw DoubleArrayException();
-    }
-
-//    GRNXX_DEBUG_THROW_IF(static_cast<uint32_t>(header_->next_key_id) >= header_->entries_size);
-
-    for (size_t j = query_pos; j < i; ++j) {
-      node_id = insert_node(node_id, key_buf[j]);
-    }
-    node_id = separate(key_buf, node_id, i);
-    return true;
-  } else if (node.label() == TERMINAL_LABEL) {
-    return true;
-  } else {
-    if (header_->num_keys >= header_->entries_size) {
-      GRNXX_NOTICE() << "too many keys: num_keys = " << header_->num_keys
-                     << ", entries_size = " << header_->entries_size;
-      throw DoubleArrayException();
-    }
-
-    const uint16_t label = (query_pos < sizeof(T)) ?
-        static_cast<uint16_t>(key_buf[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;
-  }
-}
-
-template <typename T>
-uint32_t DoubleArray<T>::insert_node(uint32_t node_id, uint16_t label) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  const DoubleArrayNode node = nodes_[node_id];
-  uint32_t offset;
-  if (node.is_leaf() || (node.offset() == INVALID_OFFSET)) {
-    offset = find_offset(&label, 1);
-  } else {
-    offset = node.offset();
-  }
-
-  const uint32_t next = offset ^ label;
-  reserve_node(next);
-
-  nodes_[next].set_label(label);
-  if (node.is_leaf()) {
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-    nodes_[next].set_key_id(node.key_id());
-  } else if (node.offset() == INVALID_OFFSET) {
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset].is_origin());
-    nodes_[offset].set_is_origin(true);
-  } else {
-//    GRNXX_DEBUG_THROW_IF(!nodes_[offset].is_origin());
-  }
-  nodes_[node_id].set_offset(offset);
-
-  const uint16_t child_label = nodes_[node_id].child();
-//  GRNXX_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.
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset ^ child_label].is_phantom());
-//    GRNXX_DEBUG_THROW_IF(nodes_[offset ^ child_label].label() != child_label);
-    nodes_[next].set_sibling(child_label);
-    nodes_[node_id].set_child(label);
-  } else {
-    uint32_t prev = offset ^ child_label;
-//    GRNXX_DEBUG_THROW_IF(nodes_[prev].label() != child_label);
-    uint16_t sibling_label = nodes_[prev].sibling();
-    while (label > sibling_label) {
-      prev = offset ^ sibling_label;
-//      GRNXX_DEBUG_THROW_IF(nodes_[prev].label() != sibling_label);
-      sibling_label = nodes_[prev].sibling();
-    }
-//    GRNXX_DEBUG_THROW_IF(label == sibling_label);
-    nodes_[next].set_sibling(nodes_[prev].sibling());
-    nodes_[prev].set_sibling(label);
-  }
-  return next;
-}
-
-template <typename T>
-uint32_t DoubleArray<T>::separate(const uint8_t *key_buf, uint32_t node_id,
-                                  size_t i) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(!nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(i > sizeof(T));
-
-  const DoubleArrayNode node = nodes_[node_id];
-  uint8_t found_key_buf[sizeof(T)];
-  convert_key(keys_[node.key_id()], found_key_buf);
-
-  uint16_t labels[2];
-  labels[0] = (i < sizeof(T)) ?
-      static_cast<uint16_t>(found_key_buf[i]) : TERMINAL_LABEL;
-  labels[1] = (i < sizeof(T)) ?
-      static_cast<uint16_t>(key_buf[i]) : TERMINAL_LABEL;
-//  GRNXX_DEBUG_THROW_IF(labels[0] == labels[1]);
-
-  const uint32_t offset = find_offset(labels, 2);
-
-  uint32_t next = offset ^ labels[0];
-  reserve_node(next);
-//  GRNXX_DEBUG_THROW_IF(nodes_[offset].is_origin());
-
-  nodes_[next].set_label(labels[0]);
-  nodes_[next].set_key_id(node.key_id());
-
-  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;
-}
-
-template <typename T>
-void DoubleArray<T>::resolve(uint32_t node_id, uint16_t label) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(label > MAX_LABEL);
-
-  uint32_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();
-//    GRNXX_DEBUG_THROW_IF(next_label == INVALID_LABEL);
-    while (next_label != INVALID_LABEL) {
-//      GRNXX_DEBUG_THROW_IF(next_label > MAX_LABEL);
-      labels[num_labels++] = next_label;
-      next_label = nodes_[offset ^ next_label].sibling();
-    }
-//    GRNXX_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)) {
-//      GRNXX_DEBUG_THROW_IF((offset / CHUNK_SIZE) != header_->num_chunks);
-      reserve_chunk(header_->num_chunks);
-    }
-    nodes_[offset].set_is_origin(true);
-    nodes_[node_id].set_offset(offset);
-  }
-}
-
-template <typename T>
-void DoubleArray<T>::migrate_nodes(uint32_t node_id, uint32_t dest_offset,
-                                   const uint16_t *labels,
-                                   uint16_t num_labels) {
-//  GRNXX_DEBUG_THROW_IF(node_id >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(nodes_[node_id].is_leaf());
-//  GRNXX_DEBUG_THROW_IF(labels == nullptr);
-//  GRNXX_DEBUG_THROW_IF(num_labels == 0);
-//  GRNXX_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1));
-
-  const uint32_t src_offset = nodes_[node_id].offset();
-//  GRNXX_DEBUG_THROW_IF(src_offset == INVALID_OFFSET);
-//  GRNXX_DEBUG_THROW_IF(!nodes_[src_offset].is_origin());
-
-  for (uint16_t i = 0; i < num_labels; ++i) {
-    const uint32_t src_node_id = src_offset ^ labels[i];
-    const uint32_t dest_node_id = dest_offset ^ labels[i];
-//    GRNXX_DEBUG_THROW_IF(nodes_[src_node_id].is_phantom());
-//    GRNXX_DEBUG_THROW_IF(nodes_[src_node_id].label() != labels[i]);
-
-    reserve_node(dest_node_id);
-    DoubleArrayNode 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;
-
-//  GRNXX_DEBUG_THROW_IF(nodes_[dest_offset].is_origin());
-  nodes_[dest_offset].set_is_origin(true);
-  nodes_[node_id].set_offset(dest_offset);
-}
-
-template <typename T>
-uint32_t DoubleArray<T>::find_offset(const uint16_t *labels,
-                                     uint16_t num_labels) {
-//  GRNXX_DEBUG_THROW_IF(labels == nullptr);
-//  GRNXX_DEBUG_THROW_IF(num_labels == 0);
-//  GRNXX_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;
-
-  uint32_t chunk_count = 0;
-  do {
-    uint32_t leader = header_->leaders[level];
-    if (leader == INVALID_LEADER) {
-      // This level group is skipped because it is empty.
-      continue;
-    }
-
-    uint32_t chunk_id = leader;
-    do {
-      const DoubleArrayChunk &chunk = chunks_[chunk_id];
-//      GRNXX_DEBUG_THROW_IF(chunk.level() != level);
-
-      const uint32_t first = (chunk_id * CHUNK_SIZE) | chunk.first_phantom();
-      uint32_t node_id = first;
-      do {
-//        GRNXX_DEBUG_THROW_IF(!nodes_[node_id].is_phantom());
-        const uint32_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 uint32_t prev = chunk_id;
-      const uint32_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];
-}
-
-template <typename T>
-void DoubleArray<T>::reserve_node(uint32_t node_id) {
-  if (node_id >= (header_->num_chunks * CHUNK_SIZE)) {
-    reserve_chunk(node_id / CHUNK_SIZE);
-  }
-
-  DoubleArrayNode &node = nodes_[node_id];
-//  GRNXX_DEBUG_THROW_IF(!node.is_phantom());
-
-  const uint32_t chunk_id = node_id / CHUNK_SIZE;
-  DoubleArrayChunk &chunk = chunks_[chunk_id];
-//  GRNXX_DEBUG_THROW_IF(chunk.num_phantoms() == 0);
-
-  const uint32_t next = (chunk_id * CHUNK_SIZE) | node.next();
-  const uint32_t prev = (chunk_id * CHUNK_SIZE) | node.prev();
-//  GRNXX_DEBUG_THROW_IF(next >= (header_->num_chunks * CHUNK_SIZE));
-//  GRNXX_DEBUG_THROW_IF(prev >= (header_->num_chunks * CHUNK_SIZE));
-
-  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 uint32_t threshold =
-        uint32_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);
-
-//  GRNXX_DEBUG_THROW_IF(node.offset() != INVALID_OFFSET);
-//  GRNXX_DEBUG_THROW_IF(node.label() != INVALID_LABEL);
-
-  --header_->num_phantoms;
-}
-
-template <typename T>
-void DoubleArray<T>::reserve_chunk(uint32_t chunk_id) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id != header_->num_chunks);
-
-  if (chunk_id >= header_->chunks_size) {
-    GRNXX_NOTICE() << "too many chunks: chunk_id = " << chunk_id
-                   << ", chunks_size = " << header_->chunks_size;
-    throw DoubleArrayException();
-  }
-
-  header_->num_chunks = chunk_id + 1;
-
-  DoubleArrayChunk chunk;
-  chunk.set_failure_count(0);
-  chunk.set_first_phantom(0);
-  chunk.set_num_phantoms(CHUNK_SIZE);
-  chunks_[chunk_id] = chunk;
-
-  const uint32_t begin = chunk_id * CHUNK_SIZE;
-  const uint32_t end = begin + CHUNK_SIZE;
-//  GRNXX_DEBUG_THROW_IF(end != (header_->num_chunks * CHUNK_SIZE));
-
-  DoubleArrayNode node;
-  node.set_is_phantom(true);
-  for (uint32_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;
-}
-
-template <typename T>
-void DoubleArray<T>::update_chunk_level(uint32_t chunk_id, uint32_t level) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  unset_chunk_level(chunk_id);
-  set_chunk_level(chunk_id, level);
-}
-
-template <typename T>
-void DoubleArray<T>::set_chunk_level(uint32_t chunk_id, uint32_t level) {
-//  GRNXX_DEBUG_THROW_IF(chunk_id >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-
-  const uint32_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.
-    const uint32_t next = leader;
-    const uint32_t prev = chunks_[leader].prev();
-//    GRNXX_DEBUG_THROW_IF(next >= header_->num_chunks);
-//    GRNXX_DEBUG_THROW_IF(prev >= header_->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);
-}
-
-template <typename T>
-void DoubleArray<T>::unset_chunk_level(uint32_t chunk_id) {
-  const uint32_t level = chunks_[chunk_id].level();
-//  GRNXX_DEBUG_THROW_IF(level > MAX_CHUNK_LEVEL);
-  const uint32_t leader = header_->leaders[level];
-//  GRNXX_DEBUG_THROW_IF(leader == INVALID_LEADER);
-  const uint32_t next = chunks_[chunk_id].next();
-  const uint32_t prev = chunks_[chunk_id].prev();
-//  GRNXX_DEBUG_THROW_IF(next >= header_->num_chunks);
-//  GRNXX_DEBUG_THROW_IF(prev >= header_->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;
-    }
-  }
-}
-
-template class DoubleArray<int8_t>;
-template class DoubleArray<int16_t>;
-template class DoubleArray<int32_t>;
-template class DoubleArray<int64_t>;
-template class DoubleArray<uint8_t>;
-template class DoubleArray<uint16_t>;
-template class DoubleArray<uint32_t>;
-template class DoubleArray<uint64_t>;
-template class DoubleArray<double>;
-template class DoubleArray<GeoPoint>;
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map/double_array.hpp (+0 -259) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/double_array.hpp    2013-08-23 10:46:34 +0900 (a19f9f6)
+++ /dev/null
@@ -1,259 +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_MAP_DOUBLE_ARRAY_HPP
-#define GRNXX_ALPHA_MAP_DOUBLE_ARRAY_HPP
-
-#include "grnxx/alpha/map.hpp"
-#include "grnxx/exception.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-template <typename T> class DoubleArrayIDCursor;
-template <typename T> class DoubleArrayKeyCursor;
-template <typename T> class DoubleArrayPrefixCursor;
-template <typename T> class DoubleArrayCompletionCursor;
-class DoubleArrayBitwiseCompletionCursor;
-
-struct DoubleArrayHeader;
-class DoubleArrayNode;
-class DoubleArrayChunk;
-class DoubleArrayEntry;
-
-struct SliceDoubleArrayHeader;
-class SliceDoubleArrayNode;
-class SliceDoubleArrayChunk;
-class SliceDoubleArrayEntry;
-class SliceDoubleArrayKey;
-
-class DoubleArrayException : Exception {
- public:
-  DoubleArrayException() noexcept : Exception() {}
-  ~DoubleArrayException() noexcept {}
-
-  DoubleArrayException(const DoubleArrayException &x) noexcept : Exception(x) {}
-  DoubleArrayException &operator=(const DoubleArrayException &) noexcept {
-    return *this;
-  }
-
-  const char *what() const noexcept {
-    return "";
-  }
-};
-
-template <typename T>
-class DoubleArray : public Map<T> {
-  friend class DoubleArrayIDCursor<T>;
-  friend class DoubleArrayKeyCursor<T>;
-  friend class DoubleArrayBitwiseCompletionCursor;
-
- public:
-  ~DoubleArray();
-
-  static DoubleArray<T> *create(io::Pool pool,
-                                const MapOptions &options = MapOptions());
-  static DoubleArray<T> *open(io::Pool pool, uint32_t block_id);
-
-  static bool unlink(io::Pool pool, uint32_t block_id);
-
-  uint32_t block_id() const;
-  MapType type() const;
-
-  int64_t max_key_id() const;
-  int64_t next_key_id() const;
-  uint64_t num_keys() const;
-
-  bool get(int64_t key_id, T *key = nullptr);
-  bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                T *next_key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, T dest_key);
-
-  bool find(T key, int64_t *key_id = nullptr);
-  bool insert(T key, int64_t *key_id = nullptr);
-  bool remove(T key);
-  bool update(T src_key, T dest_key, int64_t *key_id = nullptr);
-
-  bool truncate();
-
-  MapCursor<T> *open_basic_cursor(
-      const MapCursorOptions &options = MapCursorOptions());
-  MapCursor<T> *open_id_cursor(
-      int64_t min, int64_t max,
-      const MapCursorOptions &options = MapCursorOptions());
-  MapCursor<T> *open_key_cursor(
-      T min, T max,
-      const MapCursorOptions &options = MapCursorOptions());
-
-  MapCursor<T> *open_bitwise_completion_cursor(
-      T query, size_t bit_size,
-      const MapCursorOptions &options = MapCursorOptions());
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  DoubleArrayHeader *header_;
-  DoubleArrayNode *nodes_;
-  DoubleArrayChunk *chunks_;
-  DoubleArrayEntry *entries_;
-  T *keys_;
-  bool initialized_;
-
-  DoubleArray();
-
-  void create_double_array(io::Pool pool, const MapOptions &options);
-  void open_double_array(io::Pool pool, uint32_t block_id);
-
-  void create_arrays();
-
-  bool remove_key(T key);
-  bool update_key(int32_t key_id, T src_key, T dest_key);
-
-  bool find_leaf(const uint8_t *key_buf, uint32_t &node_id, size_t &query_pos);
-  bool insert_leaf(T key, const uint8_t *key_buf, uint32_t &node_id,
-                   size_t query_pos);
-
-  uint32_t insert_node(uint32_t node_id, uint16_t label);
-
-  uint32_t separate(const uint8_t *key_buf, uint32_t node_id, size_t i);
-  void resolve(uint32_t node_id, uint16_t label);
-  void migrate_nodes(uint32_t node_id, uint32_t dest_offset,
-                     const uint16_t *labels, uint16_t num_labels);
-
-  uint32_t find_offset(const uint16_t *labels, uint16_t num_labels);
-
-  void reserve_node(uint32_t node_id);
-  void reserve_chunk(uint32_t chunk_id);
-
-  void update_chunk_level(uint32_t chunk_id, uint32_t level);
-  void set_chunk_level(uint32_t chunk_id, uint32_t level);
-  void unset_chunk_level(uint32_t chunk_id);
-};
-
-template <>
-class DoubleArray<Slice> : public Map<Slice> {
-  friend class DoubleArrayIDCursor<Slice>;
-  friend class DoubleArrayKeyCursor<Slice>;
-  friend class DoubleArrayPrefixCursor<Slice>;
-  friend class DoubleArrayCompletionCursor<Slice>;
-
- public:
-  typedef SliceDoubleArrayHeader DoubleArrayHeader;
-  typedef SliceDoubleArrayNode DoubleArrayNode;
-  typedef SliceDoubleArrayChunk DoubleArrayChunk;
-  typedef SliceDoubleArrayEntry DoubleArrayEntry;
-  typedef SliceDoubleArrayKey DoubleArrayKey;
-
-  ~DoubleArray();
-
-  static DoubleArray<Slice> *create(io::Pool pool,
-                                    const MapOptions &options = MapOptions());
-  static DoubleArray<Slice> *open(io::Pool pool, uint32_t block_id);
-
-  static bool unlink(io::Pool pool, uint32_t block_id);
-
-  uint32_t block_id() const;
-  MapType type() const;
-
-  int64_t max_key_id() const;
-  int64_t next_key_id() const;
-  uint64_t num_keys() const;
-
-  bool get(int64_t key_id, Slice *key = nullptr);
-  bool get_next(int64_t key_id, int64_t *next_key_id = nullptr,
-                Slice *next_key = nullptr);
-  bool unset(int64_t key_id);
-  bool reset(int64_t key_id, Slice dest_key);
-
-  bool find(Slice key, int64_t *key_id = nullptr);
-  bool insert(Slice key, int64_t *key_id = nullptr);
-  bool remove(Slice key);
-  bool update(Slice src_key, Slice dest_key, int64_t *key_id = nullptr);
-
-  bool find_longest_prefix_match(Slice query, int64_t *key_id = nullptr,
-                                 Slice *key = nullptr);
-
-  bool truncate();
-
-  MapCursor<Slice> *open_basic_cursor(
-      const MapCursorOptions &options = MapCursorOptions());
-  MapCursor<Slice> *open_id_cursor(
-      int64_t min, int64_t max,
-      const MapCursorOptions &options = MapCursorOptions());
-  MapCursor<Slice> *open_key_cursor(
-      Slice min, Slice max,
-      const MapCursorOptions &options = MapCursorOptions());
-
-  MapCursor<Slice> *open_prefix_cursor(
-      Slice query, size_t min_size,
-      const MapCursorOptions &options = MapCursorOptions());
-  MapCursor<Slice> *open_completion_cursor(
-      Slice query, const MapCursorOptions &options = MapCursorOptions());
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  DoubleArrayHeader *header_;
-  DoubleArrayNode *nodes_;
-  DoubleArrayChunk *chunks_;
-  DoubleArrayEntry *entries_;
-  uint32_t *keys_;
-  bool initialized_;
-
-  DoubleArray();
-
-  void create_double_array(io::Pool pool, const MapOptions &options);
-  void open_double_array(io::Pool pool, uint32_t block_id);
-
-  void create_arrays();
-
-  const DoubleArrayKey &get_key(uint32_t key_pos) const {
-    return *reinterpret_cast<const DoubleArrayKey *>(&keys_[key_pos]);
-  }
-
-  bool remove_key(const Slice &key);
-  bool update_key(int32_t key_id, const Slice &src_key,
-                  const Slice &dest_key);
-
-  bool find_leaf(const Slice &key, uint32_t &node_id, size_t &query_pos);
-  bool insert_leaf(const Slice &key, uint32_t &node_id, size_t query_pos);
-
-  uint32_t insert_node(uint32_t node_id, uint16_t label);
-  uint32_t append_key(const Slice &key, int32_t key_id);
-
-  uint32_t separate(const Slice &key, uint32_t node_id, size_t i);
-  void resolve(uint32_t node_id, uint16_t label);
-  void migrate_nodes(uint32_t node_id, uint32_t dest_offset,
-                     const uint16_t *labels, uint16_t num_labels);
-
-  uint32_t find_offset(const uint16_t *labels, uint16_t num_labels);
-
-  void reserve_node(uint32_t node_id);
-  void reserve_chunk(uint32_t chunk_id);
-
-  void update_chunk_level(uint32_t chunk_id, uint32_t level);
-  void set_chunk_level(uint32_t chunk_id, uint32_t level);
-  void unset_chunk_level(uint32_t chunk_id);
-};
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_DOUBLE_ARRAY_HPP

  Deleted: obsolete/lib/grnxx/alpha/map/header.hpp (+0 -35) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/header.hpp    2013-08-23 10:46:34 +0900 (1c2ee92)
+++ /dev/null
@@ -1,35 +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_MAP_HEADER_HPP
-#define GRNXX_ALPHA_MAP_HEADER_HPP
-
-#include "grnxx/alpha/map.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-struct Header {
-  MapType type;
-};
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_HEADER_HPP

  Deleted: obsolete/lib/grnxx/alpha/map/scan.cpp (+0 -57) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/scan.cpp    2013-08-23 10:46:34 +0900 (8bcfb2e)
+++ /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
-*/
-#include "grnxx/alpha/map/scan.hpp"
-
-#include "grnxx/charset.hpp"
-
-namespace grnxx {
-namespace alpha {
-namespace map {
-
-Scan::Scan(Map<Slice> *map, const Slice &query, const Charset *charset)
-    : MapScan<Slice>(),
-      map_(map),
-      query_(query),
-      charset_(charset) {}
-
-Scan::~Scan() {}
-
-bool Scan::next() {
-  this->offset_ += this->size_;
-  while (this->offset_ < query_.size()) {
-    const Slice query_left =
-       query_.subslice(this->offset_, query_.size() - this->offset_);
-    if (map_->find_longest_prefix_match(query_left,
-                                        &this->key_id_, &this->key_)) {
-      this->size_ = this->key_.size();
-      return true;
-    }
-    // Move to the next character.
-    if (charset_) {
-      this->offset_ += charset_->get_char_size(query_left);
-    } else {
-      ++this->offset_;
-    }
-  }
-  this->size_ = 0;
-  return false;
-}
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/map/scan.hpp (+0 -47) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map/scan.hpp    2013-08-23 10:46:34 +0900 (3e80527)
+++ /dev/null
@@ -1,47 +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_MAP_SCAN_HPP
-#define GRNXX_ALPHA_MAP_SCAN_HPP
-
-#include "grnxx/alpha/map.hpp"
-
-namespace grnxx {
-
-class Charset;
-
-namespace alpha {
-namespace map {
-
-class Scan : public MapScan<Slice> {
- public:
-  Scan(Map<Slice> *map, const Slice &query, const Charset *charset);
-  ~Scan();
-
-  bool next();
-
- protected:
-  Map<Slice> *map_;
-  Slice query_;
-  const Charset *charset_;
-};
-
-}  // namespace map
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_SCAN_HPP

  Deleted: obsolete/lib/grnxx/alpha/map_range.hpp (+0 -263) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/map_range.hpp    2013-08-23 10:46:34 +0900 (eec0b27)
+++ /dev/null
@@ -1,263 +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_MAP_RANGE_HPP
-#define GRNXX_ALPHA_MAP_RANGE_HPP
-
-#include "grnxx/basic.hpp"
-#include "grnxx/flags_impl.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-struct MapRangeFlagsIdentifier;
-using MapRangeFlags = FlagsImpl<MapRangeFlagsIdentifier>;
-
-constexpr MapRangeFlags MAP_RANGE_LESS          = MapRangeFlags::define(0x01);
-constexpr MapRangeFlags MAP_RANGE_LESS_EQUAL    = MapRangeFlags::define(0x02);
-constexpr MapRangeFlags MAP_RANGE_GREATER       = MapRangeFlags::define(0x04);
-constexpr MapRangeFlags MAP_RANGE_GREATER_EQUAL = MapRangeFlags::define(0x08);
-
-struct MapID {};
-
-struct MapIDRange {
-  int64_t min;
-  int64_t max;
-  MapRangeFlags flags;
-};
-
-struct MapIDLess {
-  int64_t max;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_LESS;
-  }
-  operator MapIDRange() const {
-    return MapIDRange{ int64_t(), max, flags() };
-  }
-};
-
-struct MapIDLessEqual {
-  int64_t max;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_LESS_EQUAL;
-  }
-  operator MapIDRange() const {
-    return MapIDRange{ int64_t(), max, flags() };
-  }
-};
-
-struct MapIDGreater {
-  int64_t min;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_GREATER;
-  }
-  operator MapIDRange() const {
-    return MapIDRange{ min, int64_t(), flags() };
-  }
-};
-
-struct MapIDGreaterEqual {
-  int64_t min;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_GREATER_EQUAL;
-  }
-  operator MapIDRange() const {
-    return MapIDRange{ min, int64_t(), flags() };
-  }
-};
-
-inline MapIDLess operator<(MapID, int64_t max) {
-  return MapIDLess{ max };
-}
-inline MapIDLessEqual operator<=(MapID, int64_t max) {
-  return MapIDLessEqual{ max };
-}
-inline MapIDGreater operator>(MapID, int64_t min) {
-  return MapIDGreater{ min };
-}
-inline MapIDGreaterEqual operator>=(MapID, int64_t min) {
-  return MapIDGreaterEqual{ min };
-}
-
-inline MapIDGreater operator<(int64_t min, MapID) {
-  return MapIDGreater{ min };
-}
-inline MapIDGreaterEqual operator<=(int64_t min, MapID) {
-  return MapIDGreaterEqual{ min };
-}
-inline MapIDLess operator>(int64_t max, MapID) {
-  return MapIDLess{ max };
-}
-inline MapIDLessEqual operator>=(int64_t max, MapID) {
-  return MapIDLessEqual{ max };
-}
-
-inline MapIDRange operator&&(MapIDLess less, MapIDGreater greater) {
-  return MapIDRange{ greater.min, less.max, less.flags() | greater.flags() };
-}
-inline MapIDRange operator&&(MapIDLess less, MapIDGreaterEqual greater) {
-  return MapIDRange{ greater.min, less.max, less.flags() | greater.flags() };
-}
-inline MapIDRange operator&&(MapIDLessEqual less, MapIDGreater greater) {
-  return MapIDRange{ greater.min, less.max, less.flags() | greater.flags() };
-}
-inline MapIDRange operator&&(MapIDLessEqual less, MapIDGreaterEqual greater) {
-  return MapIDRange{ greater.min, less.max, less.flags() | greater.flags() };
-}
-inline MapIDRange operator&&(MapIDGreater greater, MapIDLess less) {
-  return less && greater;
-}
-inline MapIDRange operator&&(MapIDGreater greater, MapIDLessEqual less) {
-  return less && greater;
-}
-inline MapIDRange operator&&(MapIDGreaterEqual greater, MapIDLess less) {
-  return less && greater;
-}
-inline MapIDRange operator&&(MapIDGreaterEqual greater, MapIDLessEqual less) {
-  return less && greater;
-}
-
-template <typename T> struct MapKey {};
-
-template <typename T>
-struct MapKeyRange {
-  T min;
-  T max;
-  MapRangeFlags flags;
-};
-
-template <typename T>
-struct MapKeyLess {
-  T max;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_LESS;
-  }
-  operator MapKeyRange<T>() const {
-    return MapKeyRange<T>{ int64_t(), max, flags() };
-  }
-};
-
-template <typename T>
-struct MapKeyLessEqual {
-  T max;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_LESS_EQUAL;
-  }
-  operator MapKeyRange<T>() const {
-    return MapKeyRange<T>{ int64_t(), max, flags() };
-  }
-};
-
-template <typename T>
-struct MapKeyGreater {
-  T min;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_GREATER;
-  }
-  operator MapKeyRange<T>() const {
-    return MapKeyRange<T>{ min, int64_t(), flags() };
-  }
-};
-
-template <typename T>
-struct MapKeyGreaterEqual {
-  T min;
-  constexpr MapRangeFlags flags() const {
-    return MAP_RANGE_GREATER_EQUAL;
-  }
-  operator MapKeyRange<T>() const {
-    return MapKeyRange<T>{ min, int64_t(), flags() };
-  }
-};
-
-template <typename T>
-MapKeyLess<T> operator<(MapKey<T>, T max) {
-  return MapKeyLess<T>{ max };
-}
-template <typename T>
-MapKeyLessEqual<T> operator<=(MapKey<T>, T max) {
-  return MapKeyLessEqual<T>{ max };
-}
-template <typename T>
-MapKeyGreater<T> operator>(MapKey<T>, T min) {
-  return MapKeyGreater<T>{ min };
-}
-template <typename T>
-MapKeyGreaterEqual<T> operator>=(MapKey<T>, T min) {
-  return MapKeyGreaterEqual<T>{ min };
-}
-
-template <typename T>
-MapKeyGreater<T> operator<(T min, MapKey<T>) {
-  return MapKeyGreater<T>{ min };
-}
-template <typename T>
-MapKeyGreaterEqual<T> operator<=(T min, MapKey<T>) {
-  return MapKeyGreaterEqual<T>{ min };
-}
-template <typename T>
-MapKeyLess<T> operator>(T max, MapKey<T>) {
-  return MapKeyLess<T>{ max };
-}
-template <typename T>
-MapKeyLessEqual<T> operator>=(T max, MapKey<T>) {
-  return MapKeyLessEqual<T>{ max };
-}
-
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyLess<T> less, MapKeyGreater<T> greater) {
-  return MapKeyRange<T>{ greater.min, less.max,
-                         less.flags() | greater.flags() };
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyLess<T> less, MapKeyGreaterEqual<T> greater) {
-  return MapKeyRange<T>{ greater.min, less.max,
-                         less.flags() | greater.flags() };
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyLessEqual<T> less, MapKeyGreater<T> greater) {
-  return MapKeyRange<T>{ greater.min, less.max,
-                         less.flags() | greater.flags() };
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyLessEqual<T> less,
-                          MapKeyGreaterEqual<T> greater) {
-  return MapKeyRange<T>{ greater.min, less.max,
-                         less.flags() | greater.flags() };
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyGreater<T> greater, MapKeyLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyGreater<T> greater, MapKeyLessEqual<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyGreaterEqual<T> greater, MapKeyLess<T> less) {
-  return less && greater;
-}
-template <typename T>
-MapKeyRange<T> operator&&(MapKeyGreaterEqual<T> greater,
-                          MapKeyLessEqual<T> less) {
-  return less && greater;
-}
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_ALPHA_MAP_RANGE_HPP

  Deleted: obsolete/lib/grnxx/alpha/paged_array.cpp (+0 -335) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/paged_array.cpp    2013-08-23 10:46:34 +0900 (780f043)
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
-  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/alpha/paged_array.hpp"
-
-#include <new>
-
-#include "grnxx/alpha/common_header.hpp"
-#include "grnxx/bytes.hpp"
-#include "grnxx/exception.hpp"
-#include "grnxx/intrinsic.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-#include "grnxx/mutex.hpp"
-#include "grnxx/storage.hpp"
-
-namespace grnxx {
-namespace alpha {
-
-constexpr char PAGED_ARRAY_FORMAT[CommonHeader::FORMAT_SIZE] =
-    "grnxx::alpha::PagedArray";
-
-constexpr uint64_t PAGED_ARRAY_MIN_TABLE_SIZE = 16;
-
-struct PagedArrayHeader {
-  CommonHeader common_header;
-  uint64_t value_size;
-  uint64_t size;
-  uint64_t page_size;
-  uint64_t has_default_value;
-  uint64_t table_size;
-  uint32_t table_storage_node_id;
-  Mutex mutex;
-
-  PagedArrayHeader();
-};
-
-PagedArrayHeader::PagedArrayHeader()
-    : common_header(PAGED_ARRAY_FORMAT),
-      value_size(0),
-      size(0),
-      page_size(0),
-      has_default_value(0),
-      table_size(0),
-      table_storage_node_id(STORAGE_INVALID_NODE_ID),
-      mutex() {}
-
-PagedArrayImpl::PagedArrayImpl()
-    : storage_(nullptr),
-      storage_node_id_(STORAGE_INVALID_NODE_ID),
-      size_(0),
-      page_size_(0),
-      page_shift_(0),
-      page_mask_(0),
-      table_size_(0),
-      pages_(),
-      table_(nullptr),
-      header_(nullptr),
-      default_value_(nullptr),
-      fill_page_(nullptr) {}
-
-PagedArrayImpl::~PagedArrayImpl() {}
-
-void PagedArrayImpl::create(Storage *storage, uint32_t storage_node_id,
-                            uint64_t value_size, uint64_t size,
-                            uint64_t page_size,
-                            const void *default_value, FillPage fill_page) {
-  if (page_size == 0) {
-    GRNXX_ERROR() << "invalid argument: page_size = " << page_size;
-    throw LogicError();
-  }
-  if ((page_size & (page_size - 1)) != 0) {
-    const uint64_t revised_page_size = 2ULL << bit_scan_reverse(page_size);
-    GRNXX_WARNING() << "page_size must be a power of two: "
-                    << "page_size = " << page_size
-                    << ", revised_page_size = " << revised_page_size;
-    page_size = revised_page_size;
-  }
-  if ((size % page_size) != 0) {
-    const uint64_t revised_size = size + page_size - (size % page_size);
-    GRNXX_WARNING() << "size must be a multiple of page_size: size = " << size
-                    << ", revised_size = " << revised_size
-                    << ", page_size = " << page_size;
-    size = revised_size;
-  }
-  PagedArrayImpl new_impl;
-  new_impl.create_array(storage, storage_node_id, value_size, size, page_size,
-                        default_value, fill_page);
-  swap(new_impl);
-}
-
-void PagedArrayImpl::open(Storage *storage, uint32_t storage_node_id,
-                          uint64_t value_size, FillPage fill_page) {
-  PagedArrayImpl new_impl;
-  new_impl.open_array(storage, storage_node_id, value_size, fill_page);
-  swap(new_impl);
-}
-
-bool PagedArrayImpl::unlink(Storage *storage, uint32_t storage_node_id,
-                            uint64_t value_size) {
-  PagedArrayImpl impl;
-  impl.open(storage, storage_node_id, value_size);
-  return storage->unlink_node(storage_node_id);
-}
-
-void PagedArrayImpl::create_array(Storage *storage, uint32_t storage_node_id,
-                                  uint64_t value_size, uint64_t size,
-                                  uint64_t page_size,
-                                  const void *default_value,
-                                  FillPage fill_page) {
-  storage_ = storage;
-  uint64_t header_node_size = sizeof(PagedArrayHeader);
-  if (default_value) {
-    header_node_size += value_size;
-  }
-  StorageNode header_node =
-      storage->create_node(storage_node_id, header_node_size);
-  storage_node_id_ = header_node.id();
-  try {
-    header_ = static_cast<PagedArrayHeader *>(header_node.body());
-    *header_ = PagedArrayHeader();
-    header_->value_size = value_size;
-    header_->size = size;
-    header_->page_size = page_size;
-    header_->has_default_value = default_value != nullptr;
-    size_ = size;
-    page_size_ = page_size;
-    page_shift_ = bit_scan_reverse(page_size_);
-    page_mask_ = page_size_ - 1;
-    if (header_->has_default_value) {
-      default_value_ = header_ + 1;
-      fill_page_ = fill_page;
-    }
-  } catch (...) {
-    storage->unlink_node(header_node.id());
-    throw;
-  }
-}
-
-void PagedArrayImpl::open_array(Storage *storage, uint32_t storage_node_id,
-                                uint64_t value_size, FillPage fill_page) {
-  storage_ = storage;
-  storage_node_id_ = storage_node_id;
-  StorageNode header_node = storage->open_node(storage_node_id);
-  if (header_node.size() < sizeof(CommonHeader)) {
-    GRNXX_ERROR() << "too small header: size = " << header_node.size();
-    throw LogicError();
-  }
-  header_ = static_cast<PagedArrayHeader *>(header_node.body());
-  if (header_->common_header.format() !=
-      Bytes(PAGED_ARRAY_FORMAT, CommonHeader::FORMAT_SIZE)) {
-    GRNXX_ERROR() << "invalid format: expected = " << PAGED_ARRAY_FORMAT
-                  << ", actual = " << header_->common_header.format();
-    throw LogicError();
-  }
-  if (header_->value_size != value_size) {
-    GRNXX_ERROR() << "invalid value size: expected = " << value_size
-                  << ", actual = " << header_->value_size;
-    throw LogicError();
-  }
-  size_ = header_->size;
-  page_size_ = header_->page_size;
-  page_shift_ = bit_scan_reverse(page_size_);
-  page_mask_ = page_size_ - 1;
-  if (header_->has_default_value) {
-    default_value_ = header_ + 1;
-    fill_page_ = fill_page;
-  }
-}
-
-void PagedArrayImpl::resize_table(uint64_t table_size) {
-  Lock lock(&header_->mutex);
-  update_table();
-  if (table_size <= table_size_) {
-    // Nothing to do.
-    return;
-  }
-  const uint64_t max_table_size = size_ / page_size_;
-  if (table_size > max_table_size) {
-    GRNXX_ERROR() << "too large size: table_size = " << table_size
-                  << ", size = " << size_ << ", page_size = " << page_size_;
-    throw LogicError();
-  }
-  if (table_size < PAGED_ARRAY_MIN_TABLE_SIZE) {
-    table_size = PAGED_ARRAY_MIN_TABLE_SIZE;
-  }
-  if ((table_size & (table_size - 1)) != 0) {
-    table_size = 2ULL << bit_scan_reverse(table_size);
-  }
-  if (table_size > max_table_size) {
-    table_size = max_table_size;
-  }
-  // Create a new table cache.
-  std::unique_ptr<void *[]> new_pages(new (std::nothrow) void *[table_size]);
-  if (!new_pages) {
-    GRNXX_ERROR() << "new void *[] failed: size = " << table_size;
-    throw MemoryError();
-  }
-  for (uint64_t i = 0; i < table_size_; ++i) {
-    new_pages[i] = pages_[i];
-  }
-  for (uint64_t i = table_size_; i < table_size; ++i) {
-    new_pages[i] = invalid_page_address();
-  }
-  // Create a new table.
-  StorageNode table_node =
-      storage_->create_node(storage_node_id_, sizeof(uint32_t) * table_size);
-  uint32_t * const new_table = static_cast<uint32_t *>(table_node.body());
-  for (uint64_t i = 0; i < table_size_; ++i) {
-    new_table[i] = table_[i];
-  }
-  for (uint64_t i = table_size_; i < table_size; ++i) {
-    new_table[i] = STORAGE_INVALID_NODE_ID;
-  }
-  // Unlink the current table.
-  try {
-    if (header_->table_storage_node_id != STORAGE_INVALID_NODE_ID) {
-      storage_->unlink_node(header_->table_storage_node_id);
-    }
-  } catch (...) {
-    storage_->unlink_node(table_node.id());
-    throw;
-  }
-  // Update pointers and the header.
-  table_ = new_table;
-  // TODO: Old table caches should be kept.
-  pages_.swap(new_pages);
-  header_->table_size = table_size_ = table_size;
-  header_->table_storage_node_id = table_node.id();
-}
-
-void *PagedArrayImpl::reserve_page(uint64_t page_id) {
-  Lock lock(&header_->mutex);
-  if (pages_[page_id] != invalid_page_address()) {
-    // Nothing to do.
-    return pages_[page_id];
-  }
-  update_table();
-  StorageNode page_node;
-  if (table_[page_id] != STORAGE_INVALID_NODE_ID) {
-    // Open an existing page.
-    page_node = storage_->open_node(table_[page_id]);
-  } else {
-    // Create a new page.
-    page_node = storage_->create_node(header_->table_storage_node_id,
-                                      header_->value_size * page_size_);
-    table_[page_id] = page_node.id();
-  }
-  pages_[page_id] = static_cast<char *>(page_node.body()) -
-                    (header_->value_size * page_size_ * page_id);
-  return pages_[page_id];
-}
-
-void PagedArrayImpl::update_table() {
-  if (table_size_ == header_->table_size) {
-    // Nothing to do.
-    return;
-  }
-  StorageNode table_node = storage_->open_node(header_->table_storage_node_id);
-  std::unique_ptr<void *[]> new_pages(
-      new (std::nothrow) void *[header_->table_size]);
-  if (!new_pages) {
-    GRNXX_ERROR() << "new void *[] failed: size = " << header_->table_size;
-    throw MemoryError();
-  }
-  for (uint64_t i = 0; i < table_size_; ++i) {
-    new_pages[i] = pages_[i];
-  }
-  for (uint64_t i = table_size_; i < header_->table_size; ++i) {
-    new_pages[i] = invalid_page_address();
-  }
-  table_ = static_cast<uint32_t *>(table_node.body());
-  // TODO: Old table caches should be kept.
-  pages_.swap(new_pages);
-  table_size_ = header_->table_size;
-}
-
-void PagedArrayImpl::swap(PagedArrayImpl &rhs) {
-  std::swap(storage_, rhs.storage_);
-  std::swap(storage_node_id_, rhs.storage_node_id_);
-  std::swap(size_, rhs.size_);
-  std::swap(page_size_, rhs.page_size_);
-  std::swap(page_shift_, rhs.page_shift_);
-  std::swap(page_mask_, rhs.page_mask_);
-  std::swap(table_size_, rhs.table_size_);
-  std::swap(pages_, rhs.pages_);
-  std::swap(table_, rhs.table_);
-  std::swap(header_, rhs.header_);
-  std::swap(default_value_, rhs.default_value_);
-  std::swap(fill_page_, rhs.fill_page_);
-}
-
-//void Array<bool>::create(Storage *storage, uint32_t storage_node_id,
-//                         uint64_t size) {
-//  if ((size % UNIT_SIZE) != 0) {
-//    const uint64_t revised_size = size + UNIT_SIZE - (size % UNIT_SIZE);
-//    GRNXX_WARNING() << "size must be a multiple of UNIT_SIZE: size = " << size
-//                    << ", revised_size = " << revised_size
-//                    << ", UNIT_SIZE = " << UNIT_SIZE;
-//    size = revised_size;
-//  }
-//  impl_.create(storage, storage_node_id, size / UNIT_SIZE);
-//  size_ = size;
-//}
-
-//void Array<bool>::create(Storage *storage, uint32_t storage_node_id,
-//                         uint64_t size, ValueArg default_value) {
-//  if ((size % UNIT_SIZE) != 0) {
-//    const uint64_t revised_size = size + UNIT_SIZE - (size % UNIT_SIZE);
-//    GRNXX_WARNING() << "size must be a multiple of UNIT_SIZE: size = " << size
-//                    << ", revised_size = " << revised_size
-//                    << ", UNIT_SIZE = " << UNIT_SIZE;
-//    size = revised_size;
-//  }
-//  impl_.create(storage, storage_node_id, size / UNIT_SIZE,
-//               default_value ? ~Unit(0) : Unit(0));
-//  size_ = size;
-//}
-
-}  // namespace alpha
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/alpha/paged_array.hpp (+0 -200) 100644
===================================================================
--- obsolete/lib/grnxx/alpha/paged_array.hpp    2013-08-23 10:46:34 +0900 (4b5457a)
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
-  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
-*/
-#ifndef GRNXX_ALPHA_PAGED_ARRAY_HPP
-#define GRNXX_ALPHA_PAGED_ARRAY_HPP
-
-#include "grnxx/features.hpp"
-
-#include <memory>
-
-#include "grnxx/traits.hpp"
-#include "grnxx/types.hpp"
-
-namespace grnxx {
-
-class Storage;
-
-namespace alpha {
-
-struct PagedArrayHeader;
-
-class PagedArrayImpl {
-  using FillPage = void (*)(void *page, const void *value, uint64_t page_size);
-
- public:
-  PagedArrayImpl();
-  ~PagedArrayImpl();
-
-  // Return true iff "*this" is initialized.
-  explicit operator bool() const {
-    return storage_ != nullptr;
-  }
-
-  // Create an array and fill it with "value".
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t value_size, uint64_t size, uint64_t page_size,
-              const void *default_value = nullptr,
-              FillPage fill_page = nullptr);
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id,
-            uint64_t value_size, FillPage fill_page = nullptr);
-
-  // Unlink an array.
-  static bool unlink(Storage *storage, uint32_t storage_node_id,
-                     uint64_t value_size);
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return storage_node_id_;
-  }
-  // Return the size.
-  uint64_t size() const {
-    return size_;
-  }
-  // Return the page size.
-  uint64_t page_size() const {
-    return page_size_;
-  }
-
-  // Return a reference to a value.
-  template <typename T>
-  T &get_reference(uint64_t value_id) {
-    const uint64_t page_id = value_id >> page_shift_;
-    if (page_id >= table_size_) {
-      resize_table(page_id + 1);
-    }
-    void *page = pages_[page_id];
-    if (page == invalid_page_address()) {
-      page = reserve_page(page_id);
-    }
-    return static_cast<T *>(page)[value_id];
-  }
-
- private:
-  Storage *storage_;
-  uint32_t storage_node_id_;
-  uint64_t size_;
-  uint64_t page_size_;
-  uint64_t page_shift_;
-  uint64_t page_mask_;
-  uint64_t table_size_;
-  std::unique_ptr<void *[]> pages_;
-  uint32_t *table_;
-  PagedArrayHeader *header_;
-  const void *default_value_;
-  FillPage fill_page_;
-
-  void create_array(Storage *storage, uint32_t storage_node_id,
-                    uint64_t value_size, uint64_t size, uint64_t page_size,
-                    const void *default_value, FillPage fill_page);
-  void open_array(Storage *storage, uint32_t storage_node_id,
-                  uint64_t value_size, FillPage fill_page);
-
-  void resize_table(uint64_t table_size);
-  void *reserve_page(uint64_t page_id);
-  void update_table();
-
-  static void *invalid_page_address() {
-    return reinterpret_cast<void *>(~uintptr_t(0));
-  }
-
-  void swap(PagedArrayImpl &rhs);
-};
-
-template <typename T>
-class PagedArray {
- public:
-  using Value = typename Traits<T>::Type;
-  using ValueArg = typename Traits<T>::ArgumentType;
-
-  PagedArray() : impl_() {}
-  ~PagedArray() {}
-
-  // Return true iff "*this" is initialized.
-  explicit operator bool() const {
-    return bool(impl_);
-  }
-
-  // Create an array.
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t size, uint64_t page_size) {
-    impl_.create(storage, storage_node_id, sizeof(Value), size, page_size);
-  }
-  // Create an array and fill it with "value".
-  void create(Storage *storage, uint32_t storage_node_id,
-              uint64_t size, uint64_t page_size, ValueArg default_value) {
-    impl_.create(storage, storage_node_id, sizeof(Value), size, page_size,
-                 &default_value, fill_page);
-  }
-  // Open an array.
-  void open(Storage *storage, uint32_t storage_node_id) {
-    impl_.open(storage, storage_node_id, sizeof(Value));
-  }
-
-  // Unlink an array.
-  static bool unlink(Storage *storage, uint32_t storage_node_id) {
-    return PagedArrayImpl::unlink(storage, storage_node_id, sizeof(Value));
-  }
-
-  // Return the storage node ID.
-  uint32_t storage_node_id() const {
-    return impl_.storage_node_id();
-  }
-  // Return the size.
-  uint64_t size() const {
-    return impl_.size();
-  }
-  // Return the page size.
-  uint64_t page_size() const {
-    return impl_.page_size();
-  }
-
-  // Return a reference to a value.
-  Value &operator[](uint64_t value_id) {
-    return get_reference(value_id);
-  }
-
-  // Return a value.
-  Value get(uint64_t value_id) {
-    return get_reference(value_id);
-  }
-  // Set a value.
-  void set(uint64_t value_id, ValueArg value) {
-    get_reference(value_id) = value;
-  }
-
- private:
-  PagedArrayImpl impl_;
-
-  // Return a reference to a value.
-  Value &get_reference(uint64_t value_id) {
-    return impl_.get_reference<Value>(value_id);
-  }
-
-  // This function is used to fill a new page with the default value.
-  static void fill_page(void *page, const void *value, uint64_t page_size) {
-    for (uint64_t i = 0; i < page_size; ++i) {
-      static_cast<Value *>(page)[i] = *static_cast<const Value *>(value);
-    }
-  }
-};
-
-}  // namespace alpha
-}  // namespace grnxx
-
-#endif  // GRNXX_PAGED_ARRAY_HPP

  Deleted: obsolete/lib/grnxx/basic.hpp (+0 -59) 100644
===================================================================
--- obsolete/lib/grnxx/basic.hpp    2013-08-23 10:46:34 +0900 (251120f)
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_BASIC_HPP
-#define GRNXX_BASIC_HPP
-
-#include "grnxx/features.hpp"
-
-#include <cstdint>
-#include <cstdio>
-#include <cstring>
-#include <exception>
-#include <iosfwd>
-#include <limits>
-#include <memory>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-namespace grnxx {
-
-using std::size_t;
-
-using std::int8_t;
-using std::int16_t;
-using std::int32_t;
-using std::int64_t;
-
-using std::uint8_t;
-using std::uint16_t;
-using std::uint32_t;
-using std::uint64_t;
-
-using std::intptr_t;
-using std::uintptr_t;
-
-// TODO: This should use std::is_pod. However, gcc-4.7 uses the C++03 concept.
-#define GRNXX_ASSERT_POD(type)\
-  static_assert(std::is_trivial<type>::value &&\
-                std::is_standard_layout<type>::value,\
-                #type " is not a POD type")
-
-}  // namespace grnxx
-
-#endif  // GRNXX_BASIC_HPP

  Deleted: obsolete/lib/grnxx/db/Makefile.am (+0 -12) 100644
===================================================================
--- obsolete/lib/grnxx/db/Makefile.am    2013-08-23 10:46:34 +0900 (822d206)
+++ /dev/null
@@ -1,12 +0,0 @@
-noinst_LTLIBRARIES = libgrnxx_db.la
-
-libgrnxx_db_la_LDFLAGS = @AM_LTLDFLAGS@
-
-libgrnxx_db_la_SOURCES =	\
-	blob_vector.cpp		\
-	vector.cpp
-
-libgrnxx_db_includedir = ${includedir}/grnxx/db
-libgrnxx_db_include_HEADERS =	\
-	blob_vector.hpp		\
-	vector.hpp

  Deleted: obsolete/lib/grnxx/db/blob_vector.cpp (+0 -491) 100644
===================================================================
--- obsolete/lib/grnxx/db/blob_vector.cpp    2013-08-23 10:46:34 +0900 (a9ec58e)
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "grnxx/db/blob_vector.hpp"
-
-#include "grnxx/exception.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace db {
-
-BlobVectorCreate BLOB_VECTOR_CREATE;
-BlobVectorOpen BLOB_VECTOR_OPEN;
-
-BlobVectorHeader::BlobVectorHeader(uint32_t table_block_id)
-  : table_block_id_(table_block_id),
-    value_store_block_id_(io::BLOCK_INVALID_ID),
-    index_store_block_id_(io::BLOCK_INVALID_ID),
-    next_page_id_(0),
-    next_value_offset_(0),
-    latest_frozen_page_id_(BLOB_VECTOR_INVALID_PAGE_ID),
-    latest_large_value_block_id_(io::BLOCK_INVALID_ID),
-    inter_process_mutex_(MUTEX_UNLOCKED) {}
-
-StringBuilder &BlobVectorHeader::write_to(StringBuilder &builder) const {
-  if (!builder) {
-    return builder;
-  }
-
-  builder << "{ table_block_id = " << table_block_id_
-          << ", value_store_block_id = " << value_store_block_id_
-          << ", index_store_block_id = " << index_store_block_id_
-          << ", next_page_id = " << next_page_id_
-          << ", next_value_offset = " << next_value_offset_
-          << ", latest_large_value_block_id = " << latest_large_value_block_id_
-          << ", inter_process_mutex = " << inter_process_mutex_;
-  return builder << " }";
-}
-
-std::unique_ptr<BlobVectorImpl> BlobVectorImpl::create(io::Pool pool) {
-  std::unique_ptr<BlobVectorImpl> vector(new (std::nothrow) BlobVectorImpl);
-  if (!vector) {
-    GRNXX_ERROR() << "new grnxx::db::BlobVectorImpl failed";
-    GRNXX_THROW();
-  }
-  vector->create_vector(pool);
-  return vector;
-}
-
-std::unique_ptr<BlobVectorImpl> BlobVectorImpl::open(io::Pool pool,
-                                                     uint32_t block_id) {
-  std::unique_ptr<BlobVectorImpl> vector(new (std::nothrow) BlobVectorImpl);
-  if (!vector) {
-    GRNXX_ERROR() << "new grnxx::db::BlobVectorImpl failed";
-    GRNXX_THROW();
-  }
-  vector->open_vector(pool, block_id);
-  return vector;
-}
-
-void BlobVectorImpl::set_value(uint64_t id, const Blob &value) {
-  const BlobVectorCell new_cell = create_value(value);
-  BlobVectorCell old_cell;
-  try {
-    do {
-      old_cell = table_[id];
-    } while (!atomic_compare_and_swap(old_cell, new_cell, &table_[id]));
-  } catch (...) {
-    // The new value is freed on failure.
-    free_value(new_cell);
-    throw;
-  }
-  // The old value is freed on success.
-  free_value(old_cell);
-}
-
-void BlobVectorImpl::append(uint64_t id, const Blob &value) {
-  if (!value || (value.length() == 0)) {
-    return;
-  }
-
-  for ( ; ; ) {
-    const BlobVectorCell old_cell = table_[id];
-    const Blob old_value = get_value(old_cell);
-    const BlobVectorCell new_cell = join_values(old_value, value);
-    if (atomic_compare_and_swap(old_cell, new_cell, &table_[id])) {
-      // The old value is freed on success.
-      free_value(old_cell);
-      break;
-    } else {
-      // The new value is freed on failure.
-      free_value(new_cell);
-    }
-  }
-}
-
-void BlobVectorImpl::prepend(uint64_t id, const Blob &value) {
-  if (!value || (value.length() == 0)) {
-    return;
-  }
-
-  for ( ; ; ) {
-    const BlobVectorCell old_cell = table_[id];
-    const Blob old_value = get_value(old_cell);
-    const BlobVectorCell new_cell = join_values(value, old_value);
-    if (atomic_compare_and_swap(old_cell, new_cell, &table_[id])) {
-      // The old value is freed on success.
-      free_value(old_cell);
-      break;
-    } else {
-      // The new value is freed on failure.
-      free_value(new_cell);
-    }
-  }
-}
-
-void BlobVectorImpl::defrag() {
-  // TODO: To be more efficient.
-  table_.scan([this](uint64_t, BlobVectorCell *cell) -> bool {
-    if (cell->type() != BLOB_VECTOR_MEDIUM) {
-      return true;
-    }
-
-    const BlobVectorCell old_cell = *cell;
-    const BlobVectorCell new_cell = create_value(get_value(old_cell));
-    if (atomic_compare_and_swap(old_cell, new_cell, cell)) {
-      free_value(old_cell);
-    } else {
-      free_value(new_cell);
-    }
-    return true;
-  });
-}
-
-StringBuilder &BlobVectorImpl::write_to(StringBuilder &builder) const {
-  if (!builder) {
-    return builder;
-  }
-
-  builder << "{ pool = " << pool_.path()
-          << ", block_info = " << *block_info_
-          << ", header = " << *header_
-          << ", inter_thread_mutex = " << inter_thread_mutex_;
-  return builder << " }";
-}
-
-void BlobVectorImpl::unlink(io::Pool pool, uint32_t block_id) {
-  std::unique_ptr<BlobVectorImpl> vector =
-      BlobVectorImpl::open(pool, block_id);
-
-  if (vector->header_->latest_large_value_block_id() != io::BLOCK_INVALID_ID) {
-    uint32_t block_id = vector->header_->latest_large_value_block_id();
-    do {
-      auto value_header = static_cast<const BlobVectorValueHeader *>(
-          pool.get_block_address(block_id));
-      const uint32_t prev_block_id = value_header->prev_value_block_id();
-      pool.free_block(block_id);
-      block_id = prev_block_id;
-    } while (block_id != vector->header_->latest_large_value_block_id());
-  }
-  BlobVectorTable::unlink(pool, vector->header_->table_block_id());
-  pool.free_block(vector->block_info_->id());
-}
-
-BlobVectorImpl::BlobVectorImpl()
-  : pool_(),
-    block_info_(nullptr),
-    header_(nullptr),
-    recycler_(nullptr),
-    table_(),
-    value_store_(),
-    index_store_(),
-    inter_thread_mutex_(MUTEX_UNLOCKED) {}
-
-void BlobVectorImpl::create_vector(io::Pool pool) {
-  pool_ = pool;
-  block_info_ = pool.create_block(sizeof(BlobVectorHeader));
-
-  try {
-    table_.create(pool_, BlobVectorCell::null_value());
-  } catch (...) {
-    pool_.free_block(*block_info_);
-    throw;
-  }
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<BlobVectorHeader *>(block_address);
-  *header_ = BlobVectorHeader(table_.block_id());
-
-  recycler_ = pool.mutable_recycler();
-}
-
-void BlobVectorImpl::open_vector(io::Pool pool, uint32_t block_id) {
-  pool_ = pool;
-  block_info_ = pool.get_block_info(block_id);
-  if (block_info_->size() < sizeof(BlobVectorHeader)) {
-    GRNXX_ERROR() << "invalid argument: block_info = " << *block_info_
-                  << ", header_size = " << sizeof(BlobVectorHeader);
-    GRNXX_THROW();
-  }
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<BlobVectorHeader *>(block_address);
-
-  // TODO: Check the format!
-
-  recycler_ = pool.mutable_recycler();
-
-  // Open the core table.
-  table_.open(pool, header_->table_block_id());
-}
-
-Blob BlobVectorImpl::get_value(BlobVectorCell cell) {
-  switch (cell.type()) {
-    case BLOB_VECTOR_NULL: {
-      return Blob(nullptr);
-    }
-    case BLOB_VECTOR_SMALL: {
-      return Blob(cell);
-    }
-    case BLOB_VECTOR_MEDIUM: {
-      if (!value_store_) {
-        Lock lock(mutable_inter_thread_mutex());
-        if (!value_store_) {
-          value_store_.open(pool_, header_->value_store_block_id());
-        }
-      }
-      return Blob(&value_store_[cell.offset()], cell.medium_length());
-    }
-    case BLOB_VECTOR_LARGE: {
-      const auto value_header = static_cast<const BlobVectorValueHeader *>(
-          pool_.get_block_address(cell.block_id()));
-      return Blob(value_header + 1, value_header->length());
-    }
-    default: {
-      GRNXX_ERROR() << "invalid value type";
-      GRNXX_THROW();
-    }
-  }
-}
-
-BlobVectorCell BlobVectorImpl::create_value(const Blob &value) {
-  if (!value) {
-    return BlobVectorCell::null_value();
-  }
-
-  BlobVectorCell cell;
-  void *address;
-  if (value.length() < BLOB_VECTOR_MEDIUM_VALUE_MIN_LENGTH) {
-    address = create_small_value(value.length(), &cell);
-  } else if (value.length() < BLOB_VECTOR_LARGE_VALUE_MIN_LENGTH) {
-    address = create_medium_value(value.length(), &cell);
-  } else {
-    address = create_large_value(value.length(), &cell);
-  }
-  std::memcpy(address, value.address(), value.length());
-  return cell;
-}
-
-BlobVectorCell BlobVectorImpl::join_values(const Blob &lhs, const Blob &rhs) {
-  const uint64_t length = lhs.length() + rhs.length();
-  BlobVectorCell cell;
-  void *address;
-  if (length < BLOB_VECTOR_MEDIUM_VALUE_MIN_LENGTH) {
-    address = create_small_value(length, &cell);
-  } else if (length < BLOB_VECTOR_LARGE_VALUE_MIN_LENGTH) {
-    address = create_medium_value(length, &cell);
-  } else {
-    address = create_large_value(length, &cell);
-  }
-  std::memcpy(address, lhs.address(), lhs.length());
-  std::memcpy(static_cast<char *>(address) + lhs.length(),
-              rhs.address(), rhs.length());
-  return cell;
-}
-
-void *BlobVectorImpl::create_small_value(uint64_t length,
-                                         BlobVectorCell *cell) {
-  *cell = BlobVectorCell::small_value(length);
-  return cell->value();
-}
-
-void *BlobVectorImpl::create_medium_value(uint64_t length,
-                                          BlobVectorCell *cell) {
-  Lock lock(mutable_inter_thread_mutex());
-
-  if (!value_store_) {
-    if (header_->value_store_block_id() == io::BLOCK_INVALID_ID) {
-      Lock lock(mutable_inter_process_mutex());
-      if (header_->value_store_block_id() == io::BLOCK_INVALID_ID) {
-        value_store_.create(pool_);
-        header_->set_value_store_block_id(value_store_.block_id());
-      }
-    }
-    if (!value_store_) {
-      value_store_.open(pool_, header_->value_store_block_id());
-    }
-  }
-
-  if (!index_store_) {
-    if (header_->index_store_block_id() == io::BLOCK_INVALID_ID) {
-      Lock lock(mutable_inter_process_mutex());
-      if (header_->index_store_block_id() == io::BLOCK_INVALID_ID) {
-        index_store_.create(pool_, BlobVectorPageInfo());
-        header_->set_index_store_block_id(index_store_.block_id());
-      }
-    }
-    if (!index_store_) {
-      index_store_.open(pool_, header_->index_store_block_id());
-    }
-  }
-
-  // Unfreeze the oldest frozen page for reuse.
-  unfreeze_oldest_frozen_page();
-
-  uint64_t offset = header_->next_value_offset();
-  const uint64_t offset_in_page =
-      ((offset - 1) & (BLOB_VECTOR_VALUE_STORE_PAGE_SIZE - 1)) + 1;
-  const uint64_t size_left_in_page =
-      BLOB_VECTOR_VALUE_STORE_PAGE_SIZE - offset_in_page;
-
-  // Reserve a new page if there is not enough space in the current page.
-  if (length > size_left_in_page) {
-    if (offset != 0) {
-      // Freeze the current page if it is empty.
-      const uint32_t page_id = static_cast<uint32_t>(
-          (offset - 1) >> BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
-      if (index_store_[page_id].num_values() == 0) {
-        freeze_page(page_id);
-      }
-    }
-
-    const uint32_t page_id = header_->next_page_id();
-    offset = static_cast<uint64_t>(
-        page_id << BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
-    if (index_store_[page_id].next_page_id() != BLOB_VECTOR_INVALID_PAGE_ID) {
-      header_->set_next_page_id(index_store_[page_id].next_page_id());
-    } else {
-      header_->set_next_page_id(page_id + 1);
-    }
-    index_store_[page_id].set_num_values(0);
-  }
-  header_->set_next_value_offset(offset + length);
-
-  const uint32_t page_id = static_cast<uint32_t>(
-      offset >> BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
-  index_store_[page_id].set_num_values(index_store_[page_id].num_values() + 1);
-
-  *cell = BlobVectorCell::medium_value(offset, length);
-  return &value_store_[offset];
-}
-
-void *BlobVectorImpl::create_large_value(uint64_t length,
-                                         BlobVectorCell *cell) {
-  const io::BlockInfo *block_info =
-      pool_.create_block(sizeof(BlobVectorValueHeader) + length);
-  auto value_header = static_cast<BlobVectorValueHeader *>(
-      pool_.get_block_address(*block_info));
-  value_header->set_length(length);
-  register_large_value(block_info->id(), value_header);
-  *cell = BlobVectorCell::large_value(block_info->id());
-  return value_header + 1;
-}
-
-void BlobVectorImpl::free_value(BlobVectorCell cell) {
-  switch (cell.type()) {
-    case BLOB_VECTOR_NULL:
-    case BLOB_VECTOR_SMALL: {
-      break;
-    }
-    case BLOB_VECTOR_MEDIUM: {
-      Lock lock(mutable_inter_thread_mutex());
-
-      if (!index_store_) {
-        index_store_.open(pool_, header_->index_store_block_id());
-      }
-
-      const uint32_t page_id = static_cast<uint32_t>(
-          cell.offset() >> BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
-      index_store_[page_id].set_num_values(
-          index_store_[page_id].num_values() - 1);
-      if (index_store_[page_id].num_values() == 0) {
-        const uint32_t current_page_id =
-            static_cast<uint32_t>(header_->next_value_offset()
-                                  >> BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
-        if (page_id != current_page_id) {
-          freeze_page(page_id);
-        }
-      }
-      break;
-    }
-    case BLOB_VECTOR_LARGE: {
-      const io::BlockInfo * const block_info =
-          pool_.get_block_info(cell.block_id());
-      unregister_large_value(block_info->id(),
-          static_cast<BlobVectorValueHeader *>(
-              pool_.get_block_address(*block_info)));
-      pool_.free_block(*block_info);
-      break;
-    }
-  }
-}
-
-void BlobVectorImpl::register_large_value(uint32_t block_id,
-    BlobVectorValueHeader *value_header) {
-  Lock lock(mutable_inter_process_mutex());
-  if (header_->latest_large_value_block_id() == io::BLOCK_INVALID_ID) {
-    value_header->set_next_value_block_id(block_id);
-    value_header->set_prev_value_block_id(block_id);
-  } else {
-    const uint32_t prev_id = header_->latest_large_value_block_id();
-    auto prev_header = static_cast<BlobVectorValueHeader *>(
-        pool_.get_block_address(prev_id));
-    const uint32_t next_id = prev_header->next_value_block_id();
-    auto next_header = static_cast<BlobVectorValueHeader *>(
-        pool_.get_block_address(next_id));
-    value_header->set_next_value_block_id(next_id);
-    value_header->set_prev_value_block_id(prev_id);
-    prev_header->set_next_value_block_id(block_id);
-    next_header->set_prev_value_block_id(block_id);
-  }
-  header_->set_latest_large_value_block_id(block_id);
-}
-
-void BlobVectorImpl::unregister_large_value(uint32_t block_id,
-    BlobVectorValueHeader *value_header) {
-  Lock lock(mutable_inter_process_mutex());
-  const uint32_t next_id = value_header->next_value_block_id();
-  const uint32_t prev_id = value_header->prev_value_block_id();
-  auto next_header = static_cast<BlobVectorValueHeader *>(
-      pool_.get_block_address(next_id));
-  auto prev_header = static_cast<BlobVectorValueHeader *>(
-      pool_.get_block_address(prev_id));
-  next_header->set_prev_value_block_id(prev_id);
-  prev_header->set_next_value_block_id(next_id);
-  if (block_id == header_->latest_large_value_block_id()) {
-    header_->set_latest_large_value_block_id(prev_id);
-  }
-}
-
-void BlobVectorImpl::freeze_page(uint32_t page_id) {
-  BlobVectorPageInfo &page_info = index_store_[page_id];
-  if (header_->latest_frozen_page_id() != BLOB_VECTOR_INVALID_PAGE_ID) {
-    BlobVectorPageInfo &latest_frozen_page_info =
-        index_store_[header_->latest_frozen_page_id()];
-    page_info.set_next_page_id(latest_frozen_page_info.next_page_id());
-    latest_frozen_page_info.set_next_page_id(page_id);
-  } else {
-    page_info.set_next_page_id(page_id);
-  }
-  page_info.set_stamp(recycler_->stamp());
-  header_->set_latest_frozen_page_id(page_id);
-}
-
-void BlobVectorImpl::unfreeze_oldest_frozen_page() {
-  if (header_->latest_frozen_page_id() != BLOB_VECTOR_INVALID_PAGE_ID) {
-    BlobVectorPageInfo &latest_frozen_page_info =
-        index_store_[header_->latest_frozen_page_id()];
-    const uint32_t oldest_frozen_page_id =
-        latest_frozen_page_info.next_page_id();
-    BlobVectorPageInfo &oldest_frozen_page_info =
-        index_store_[oldest_frozen_page_id];
-    if (recycler_->check(oldest_frozen_page_info.stamp())) {
-      latest_frozen_page_info.set_next_page_id(
-          oldest_frozen_page_info.next_page_id());
-      oldest_frozen_page_info.set_next_page_id(header_->next_page_id());
-      header_->set_next_page_id(oldest_frozen_page_id);
-      if (oldest_frozen_page_id == header_->latest_frozen_page_id()) {
-        header_->set_latest_frozen_page_id(BLOB_VECTOR_INVALID_PAGE_ID);
-      }
-    }
-  }
-}
-
-}  // namespace db
-}  // namespace grnxx

  Deleted: obsolete/lib/grnxx/db/blob_vector.hpp (+0 -574) 100644
===================================================================
--- obsolete/lib/grnxx/db/blob_vector.hpp    2013-08-23 10:46:34 +0900 (d25a8a2)
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef GRNXX_DB_BLOB_VECTOR_HPP
-#define GRNXX_DB_BLOB_VECTOR_HPP
-
-#include "grnxx/db/vector.hpp"
-#include "grnxx/string_builder.hpp"
-
-namespace grnxx {
-namespace db {
-
-constexpr uint64_t BLOB_VECTOR_MAX_ID = (uint64_t(1) << 40) - 1;
-
-constexpr uint32_t BLOB_VECTOR_INVALID_PAGE_ID = 0xFFFFFFFFU;
-
-constexpr uint64_t BLOB_VECTOR_SMALL_VALUE_MAX_LENGTH  = 7;
-
-constexpr uint64_t BLOB_VECTOR_MEDIUM_VALUE_MIN_LENGTH =
-    BLOB_VECTOR_SMALL_VALUE_MAX_LENGTH + 1;
-constexpr uint64_t BLOB_VECTOR_MEDIUM_VALUE_MAX_LENGTH = 65535;
-
-constexpr uint64_t BLOB_VECTOR_LARGE_VALUE_MIN_LENGTH  =
-    BLOB_VECTOR_MEDIUM_VALUE_MAX_LENGTH + 1;
-
-constexpr uint8_t  BLOB_VECTOR_UNIT_SIZE_BITS  = 3;
-constexpr uint64_t BLOB_VECTOR_UNIT_SIZE       =
-    uint64_t(1) << BLOB_VECTOR_UNIT_SIZE_BITS;
-
-constexpr uint8_t  BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS            = 19;
-constexpr uint8_t  BLOB_VECTOR_VALUE_STORE_TABLE_SIZE_BITS           = 12;
-constexpr uint8_t  BLOB_VECTOR_VALUE_STORE_SECONDARY_TABLE_SIZE_BITS = 16;
-
-constexpr uint64_t BLOB_VECTOR_VALUE_STORE_PAGE_SIZE            =
-    uint64_t(1) << BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS;
-constexpr uint64_t BLOB_VECTOR_VALUE_STORE_TABLE_SIZE           =
-    uint64_t(1) << BLOB_VECTOR_VALUE_STORE_TABLE_SIZE_BITS;
-constexpr uint64_t BLOB_VECTOR_VALUE_STORE_SECONDARY_TABLE_SIZE =
-    uint64_t(1) << BLOB_VECTOR_VALUE_STORE_SECONDARY_TABLE_SIZE_BITS;
-
-extern class BlobVectorCreate {} BLOB_VECTOR_CREATE;
-extern class BlobVectorOpen {} BLOB_VECTOR_OPEN;
-
-class BlobVectorHeader {
- public:
-  explicit BlobVectorHeader(uint32_t table_block_id);
-
-  uint32_t table_block_id() const {
-    return table_block_id_;
-  }
-  uint32_t value_store_block_id() const {
-    return value_store_block_id_;
-  }
-  uint32_t index_store_block_id() const {
-    return index_store_block_id_;
-  }
-  uint32_t next_page_id() const {
-    return next_page_id_;
-  }
-  uint64_t next_value_offset() const {
-    return next_value_offset_;
-  }
-  uint32_t latest_frozen_page_id() const {
-    return latest_frozen_page_id_;
-  }
-  uint32_t latest_large_value_block_id() const {
-    return latest_large_value_block_id_;
-  }
-
-  void set_value_store_block_id(uint32_t value) {
-    value_store_block_id_ = value;
-  }
-  void set_index_store_block_id(uint32_t value) {
-    index_store_block_id_ = value;
-  }
-  void set_next_page_id(uint32_t value) {
-    next_page_id_ = value;
-  }
-  void set_next_value_offset(uint64_t value) {
-    next_value_offset_ = value;
-  }
-  void set_latest_frozen_page_id(uint32_t value) {
-    latest_frozen_page_id_ = value;
-  }
-  void set_latest_large_value_block_id(uint32_t value) {
-    latest_large_value_block_id_ = value;
-  }
-
-  Mutex *mutable_inter_process_mutex() {
-    return &inter_process_mutex_;
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const;
-
- private:
-  uint32_t table_block_id_;
-  uint32_t value_store_block_id_;
-  uint32_t index_store_block_id_;
-  uint32_t next_page_id_;
-  uint64_t next_value_offset_;
-  uint32_t latest_frozen_page_id_;
-  uint32_t latest_large_value_block_id_;
-  Mutex inter_process_mutex_;
-};
-
-inline StringBuilder &operator<<(StringBuilder &builder,
-                                 const BlobVectorHeader &header) {
-  return header.write_to(builder);
-}
-
-enum BlobVectorValueType : uint8_t {
-  BLOB_VECTOR_NULL   = 0x00,
-  BLOB_VECTOR_SMALL  = 0x10,
-  BLOB_VECTOR_MEDIUM = 0x20,
-  BLOB_VECTOR_LARGE  = 0x30
-};
-
-constexpr uint8_t BLOB_VECTOR_TYPE_MASK = 0x30;
-
-class BlobVectorPageInfo {
- public:
-  BlobVectorPageInfo()
-    : next_page_id_(BLOB_VECTOR_INVALID_PAGE_ID), stamp_(0), reserved_(0) {}
-
-  uint32_t next_page_id() const {
-    return next_page_id_;
-  }
-  uint32_t num_values() const {
-    return num_values_;
-  }
-  uint16_t stamp() const {
-    return reserved_;
-  }
-
-  void set_next_page_id(uint32_t value) {
-    next_page_id_ = value;
-  }
-  void set_num_values(uint32_t value) {
-    num_values_ = value;
-  }
-  void set_stamp(uint16_t value) {
-    stamp_ = value;
-  }
-
- private:
-  union {
-    uint32_t next_page_id_;
-    uint32_t num_values_;
-  };
-  uint16_t stamp_;
-  uint16_t reserved_;
-};
-
-class BlobVectorValueHeader {
- public:
-  uint64_t length() const {
-    return length_;
-  }
-  uint32_t next_value_block_id() const {
-    return next_value_block_id_;
-  }
-  uint32_t prev_value_block_id() const {
-    return prev_value_block_id_;
-  }
-
-  void set_length(uint64_t value) {
-    length_ = value;
-  }
-  void set_next_value_block_id(uint32_t value) {
-    next_value_block_id_ = value;
-  }
-  void set_prev_value_block_id(uint32_t value) {
-    prev_value_block_id_ = value;
-  }
-
- private:
-  uint64_t length_;
-  uint32_t next_value_block_id_;
-  uint32_t prev_value_block_id_;
-};
-
-const uint8_t BLOB_VECTOR_CELL_FLAGS_MASK = 0xF0;
-
-class BlobVectorCell {
- public:
-  BlobVectorCell() = default;
-  explicit BlobVectorCell(std::nullptr_t) : qword_(0) {}
-
-  static BlobVectorCell null_value() {
-    return BlobVectorCell(nullptr);
-  }
-  static BlobVectorCell small_value(uint64_t length) {
-    BlobVectorCell cell(nullptr);
-    cell.bytes_[0] = BLOB_VECTOR_SMALL | static_cast<uint8_t>(length);
-    return cell;
-  }
-  static BlobVectorCell medium_value(uint64_t offset, uint64_t length) {
-    BlobVectorCell cell;
-    cell.bytes_[0] = BLOB_VECTOR_MEDIUM | static_cast<uint8_t>(offset >> 40);
-    cell.bytes_[1] = static_cast<uint8_t>(offset >> 32);
-    cell.words_[1] = static_cast<uint16_t>(length);
-    cell.dwords_[1] = static_cast<uint32_t>(offset);
-    return cell;
-  }
-  static BlobVectorCell large_value(uint32_t block_id) {
-    BlobVectorCell cell(nullptr);
-    cell.bytes_[0] = BLOB_VECTOR_LARGE;
-    cell.dwords_[1] = block_id;
-    return cell;
-  }
-
-  BlobVectorValueType type() const {
-    Flags flags;
-    flags.byte = flags_.byte & BLOB_VECTOR_TYPE_MASK;
-    return flags.type;
-  }
-
-  // Accessors to small values.
-  uint64_t small_length() const {
-    return bytes_[0] & ~BLOB_VECTOR_CELL_FLAGS_MASK;
-  }
-  const void *value() const {
-    return &bytes_[1];
-  }
-  void *value() {
-    return &bytes_[1];
-  }
-
-  // Accessors to medium values.
-  uint64_t medium_length() const {
-    return words_[1];
-  }
-  uint64_t offset() const {
-    return (static_cast<uint64_t>(bytes_[0] &
-                                  ~BLOB_VECTOR_CELL_FLAGS_MASK) << 40) |
-           (static_cast<uint64_t>(bytes_[1]) << 32) | dwords_[1];
-  }
-
-  // Accessors to large values.
-  uint32_t block_id() const {
-    return dwords_[1];
-  }
-
- private:
-  union Flags {
-    uint8_t byte;
-    BlobVectorValueType type;
-  };
-
-  union {
-    Flags flags_;
-    uint8_t bytes_[8];
-    uint16_t words_[4];
-    uint32_t dwords_[2];
-    uint64_t qword_;
-  };
-};
-
-static_assert(sizeof(BlobVectorCell) == sizeof(uint64_t),
-              "sizeof(BlobVectorCell) != sizeof(uint64_t)");
-
-class Blob {
- public:
-  Blob() : address_(nullptr), length_(0), cell_() {}
-  explicit Blob(std::nullptr_t) : address_(nullptr), length_(0), cell_() {}
-  Blob(const void *address, uint64_t length)
-    : address_(address), length_(length), cell_() {}
-  explicit Blob(BlobVectorCell small_value_cell)
-    : address_(), length_(), cell_(small_value_cell) {
-    address_ = cell_.value();
-    length_ = cell_.small_length();
-  }
-
-  // Note: address_ refers to the own value if it is small.
-  Blob(const Blob &rhs) : address_(), length_(rhs.length_), cell_(rhs.cell_) {
-    if (rhs.address() == rhs.cell_.value()) {
-      address_ = cell_.value();
-    } else {
-      address_ = rhs.address_;
-    }
-  }
-  Blob &operator=(const Blob &rhs) {
-    length_ = rhs.length_;
-    cell_ = rhs.cell_;
-    if (rhs.address() == rhs.cell_.value()) {
-      address_ = cell_.value();
-    } else {
-      address_ = rhs.address_;
-    }
-    return *this;
-  }
-
-  Blob &operator=(std::nullptr_t) {
-    return *this = Blob(nullptr);
-  }
-
-  // Return true if address_ != nullptr.
-  explicit operator bool() const {
-    return static_cast<bool>(address_);
-  }
-
-  const void *address() const {
-    return address_;
-  }
-  uint64_t length() const {
-    return length_;
-  }
-
-  void set_address(const void *value) {
-    address_ = value;
-  }
-  void set_length(uint64_t value) {
-    length_ = value;
-  }
-
- private:
-  const void *address_;
-  uint64_t length_;
-  BlobVectorCell cell_;
-};
-
-class BlobVector;
-
-class BlobRef {
- public:
-  BlobRef(BlobVector *vector, uint64_t id) : vector_(*vector), id_(id) {}
-
-  // This conversion may throw an exception.
-  operator Blob() const {
-    return get();
-  }
-
-  // Update the current value to NULL.
-  BlobRef &operator=(std::nullptr_t) {
-    set(nullptr);
-    return *this;
-  }
-  // Update the current value.
-  BlobRef &operator=(const Blob &value) {
-    set(value);
-    return *this;
-  }
-
-  // Get the address and the length of the current value.
-  Blob get() const;
-  // Update the current value to NULL.
-  void set(std::nullptr_t) {
-    set(Blob(nullptr));
-  }
-  // Update the current value.
-  void set(const Blob &value);
-  void set(const void *ptr, uint64_t length) {
-    set(Blob(ptr, length));
-  }
-
-  // Append a value to the current value.
-  void append(const Blob &value);
-  void append(const void *ptr, uint64_t length) {
-    append(Blob(ptr, length));
-  }
-  // Prepend a value to the current value.
-  void prepend(const Blob &value);
-  void prepend(const void *ptr, uint64_t length) {
-    prepend(Blob(ptr, length));
-  }
-
- private:
-  BlobVector &vector_;
-  uint64_t id_;
-};
-
-typedef Vector<BlobVectorCell> BlobVectorTable;
-
-typedef Vector<char, BLOB_VECTOR_VALUE_STORE_PAGE_SIZE,
-                     BLOB_VECTOR_VALUE_STORE_TABLE_SIZE,
-                     BLOB_VECTOR_VALUE_STORE_SECONDARY_TABLE_SIZE>
-BlobVectorValueStore;
-
-typedef Vector<BlobVectorPageInfo,
-               BLOB_VECTOR_VALUE_STORE_TABLE_SIZE,
-               BLOB_VECTOR_VALUE_STORE_SECONDARY_TABLE_SIZE>
-BlobVectorIndexStore;
-
-class BlobVectorImpl {
- public:
-  static std::unique_ptr<BlobVectorImpl> create(io::Pool pool);
-  static std::unique_ptr<BlobVectorImpl> open(io::Pool pool,
-                                              uint32_t block_id);
-
-  Blob get_value(uint64_t id) {
-    return get_value(table_[id]);
-  }
-  void set_value(uint64_t id, const Blob &value);
-
-  void append(uint64_t id, const Blob &value);
-  void prepend(uint64_t id, const Blob &value);
-
-  void defrag();
-
-  uint32_t block_id() const {
-    return block_info_->id();
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const;
-
-  static void unlink(io::Pool pool, uint32_t block_id);
-
- private:
-  io::Pool pool_;
-  const io::BlockInfo *block_info_;
-  BlobVectorHeader *header_;
-  Recycler *recycler_;
-  BlobVectorTable table_;
-  BlobVectorValueStore value_store_;
-  BlobVectorIndexStore index_store_;
-  Mutex inter_thread_mutex_;
-
-  BlobVectorImpl();
-
-  void create_vector(io::Pool pool);
-  void open_vector(io::Pool pool, uint32_t block_id);
-
-  Blob get_value(BlobVectorCell cell);
-
-  inline BlobVectorCell create_value(const Blob &value);
-  inline BlobVectorCell join_values(const Blob &lhs, const Blob &rhs);
-
-  inline void *create_small_value(uint64_t length, BlobVectorCell *cell);
-  inline void *create_medium_value(uint64_t length, BlobVectorCell *cell);
-  inline void *create_large_value(uint64_t length, BlobVectorCell *cell);
-
-  void free_value(BlobVectorCell cell);
-
-  void register_large_value(uint32_t block_id,
-                            BlobVectorValueHeader *value_header);
-  void unregister_large_value(uint32_t block_id,
-                              BlobVectorValueHeader *value_header);
-
-  void freeze_page(uint32_t page_id);
-  void unfreeze_oldest_frozen_page();
-
-  Mutex *mutable_inter_thread_mutex() {
-    return &inter_thread_mutex_;
-  }
-  Mutex *mutable_inter_process_mutex() {
-    return header_->mutable_inter_process_mutex();
-  }
-};
-
-inline StringBuilder &operator<<(StringBuilder &builder,
-                                 const BlobVectorImpl &vector) {
-  return vector.write_to(builder);
-}
-
-class BlobVector {
- public:
-  // BLOB_VECTOR_CREATE is available as an instance of BlobVectorCreate.
-  // BLOB_VECTOR_OPEN is available as an instance of BlobVectorOpen.
-  BlobVector() = default;
-  BlobVector(const BlobVectorCreate &, io::Pool pool)
-    : impl_(BlobVectorImpl::create(pool)) {}
-  BlobVector(const BlobVectorOpen &, io::Pool pool, uint32_t block_id)
-    : impl_(BlobVectorImpl::open(pool, block_id)) {}
-
-  explicit operator bool() const {
-    return static_cast<bool>(impl_);
-  }
-
-  void create(io::Pool pool) {
-    *this = BlobVector(BLOB_VECTOR_CREATE, pool);
-  }
-  void open(io::Pool pool, uint32_t block_id) {
-    *this = BlobVector(BLOB_VECTOR_OPEN, pool, block_id);
-  }
-  void close() {
-    *this = BlobVector();
-  }
-
-  // Access a value. Return a pseudo reference to a value.
-  // See also Blob and BlobRef.
-  BlobRef operator[](uint64_t id) {
-    return BlobRef(this, id);
-  }
-
-  // Get/set blob_vector[id].
-  Blob get_value(uint64_t id) {
-    return impl_->get_value(id);
-  }
-  void set_value(uint64_t id, const Blob &value) {
-    impl_->set_value(id, value);
-  }
-
-  // Append/prepend a value to blob_vector[id].
-  void append(uint64_t id, const Blob &value) {
-    impl_->append(id, value);
-  }
-  void prepend(uint64_t id, const Blob &value) {
-    impl_->prepend(id, value);
-  }
-
-  // Defrag a blob vector.
-  void defrag() {
-    impl_->defrag();
-  }
-
-  // The ID of the lead block.
-  uint32_t block_id() const {
-    return impl_->block_id();
-  }
-
-  void swap(BlobVector &rhs) {
-    impl_.swap(rhs.impl_);
-  }
-
-  StringBuilder &write_to(StringBuilder &builder) const {
-    return impl_ ? impl_->write_to(builder) : (builder << "n/a");
-  }
-
-  static constexpr uint64_t max_id() {
-    return BLOB_VECTOR_MAX_ID;
-  }
-
-  // Free blocks associated with a blob vector.
-  static void unlink(io::Pool pool, uint32_t block_id) {
-    BlobVectorImpl::unlink(pool, block_id);
-  }
-
- private:
-  std::shared_ptr<BlobVectorImpl> impl_;
-};
-
-inline void swap(BlobVector &lhs, BlobVector &rhs) {
-  lhs.swap(rhs);
-}
-
-inline StringBuilder &operator<<(StringBuilder &builder,
-                                 const BlobVector &vector) {
-  return vector.write_to(builder);
-}
-
-inline Blob BlobRef::get() const {
-  return vector_.get_value(id_);
-}
-
-inline void BlobRef::set(const Blob &value) {
-  vector_.set_value(id_, value);
-}
-
-inline void BlobRef::append(const Blob &value) {
-  vector_.append(id_, value);
-}
-
-inline void BlobRef::prepend(const Blob &value) {
-  vector_.prepend(id_, value);
-}
-
-}  // namespace db
-}  // namespace grnxx
-
-#endif  // GRNXX_DB_BLOB_VECTOR_HPP

  Deleted: obsolete/lib/grnxx/db/vector.cpp (+0 -504) 100644
===================================================================
--- obsolete/lib/grnxx/db/vector.cpp    2013-08-23 10:46:34 +0900 (c373131)
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
-  Copyright (C) 2012  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "grnxx/db/vector.hpp"
-
-#include <vector>
-
-#include "grnxx/exception.hpp"
-#include "grnxx/lock.hpp"
-#include "grnxx/logger.hpp"
-
-namespace grnxx {
-namespace db {
-
-VectorCreate VECTOR_CREATE;
-VectorOpen VECTOR_OPEN;
-
-VectorHeader::VectorHeader(const void *default_value,
-                           uint64_t value_size,
-                           uint64_t page_size,
-                           uint64_t table_size,
-                           uint64_t secondary_table_size)
-  : value_size_(value_size),
-    page_size_(page_size),
-    table_size_(table_size),
-    secondary_table_size_(secondary_table_size),
-    has_default_value_(default_value ? 1 : 0),
-    first_table_block_id_(io::BLOCK_INVALID_ID),
-    secondary_table_block_id_(io::BLOCK_INVALID_ID),
-    inter_process_mutex_(MUTEX_UNLOCKED) {}
-
-StringBuilder &VectorHeader::write_to(StringBuilder &builder) const {
-  if (!builder) {
-    return builder;
-  }
-
-  builder << "{ value_size = " << value_size_
-          << ", page_size = " << page_size_
-          << ", table_size = " << table_size_
-          << ", secondary_table_size = " << secondary_table_size_
-          << ", has_default_value = " << has_default_value_
-          << ", first_table_block_id = " << first_table_block_id_
-          << ", secondary_table_block_id = " << secondary_table_block_id_
-          << ", inter_process_mutex = " << inter_process_mutex_;
-  return builder << " }";
-}
-
-std::unique_ptr<VectorImpl> VectorImpl::create(io::Pool pool,
-                                               const void *default_value,
-                                               uint64_t value_size,
-                                               uint64_t page_size,
-                                               uint64_t table_size,
-                                               uint64_t secondary_table_size,
-                                               FillPage fill_page) {
-  std::unique_ptr<VectorImpl> vector(new (std::nothrow) VectorImpl);
-  if (!vector) {
-    GRNXX_ERROR() << "new grnxx::db::VectorImpl failed";
-    GRNXX_THROW();
-  }
-  vector->create_vector(pool, default_value, value_size, page_size, table_size,
-                        secondary_table_size, fill_page);
-  return vector;
-}
-
-std::unique_ptr<VectorImpl> VectorImpl::open(io::Pool pool,
-                                             uint32_t block_id,
-                                             uint64_t value_size,
-                                             uint64_t page_size,
-                                             uint64_t table_size,
-                                             uint64_t secondary_table_size,
-                                             FillPage fill_page) {
-  std::unique_ptr<VectorImpl> vector(new (std::nothrow) VectorImpl);
-  if (!vector) {
-    GRNXX_ERROR() << "new grnxx::db::VectorImpl failed";
-    GRNXX_THROW();
-  }
-  vector->open_vector(pool, block_id, value_size, page_size, table_size,
-                      secondary_table_size, fill_page);
-  return vector;
-}
-
-bool VectorImpl::scan_pages(bool (*callback)(uint64_t page_id,
-                                             void *page_address,
-                                             void *argument),
-                            void *argument) {
-  for (uint64_t page_id = 0; page_id < header_->table_size(); ++page_id) {
-    if (!first_table_cache_[page_id]) {
-      if (first_table_[page_id] == io::BLOCK_INVALID_ID) {
-        continue;
-      }
-      first_table_cache_[page_id] =
-          pool_.get_block_address(first_table_[page_id]);
-    }
-    if (!callback(page_id, first_table_cache_[page_id], argument)) {
-      return false;
-    }
-  }
-
-  if (header_->secondary_table_block_id() == io::BLOCK_INVALID_ID) {
-    return true;
-  }
-
-  if (!tables_cache_) {
-    if (!secondary_table_cache_) {
-      if (!secondary_table_) {
-        secondary_table_ = static_cast<uint32_t *>(
-            pool_.get_block_address(header_->secondary_table_block_id()));
-      }
-      initialize_secondary_table_cache();
-    }
-    initialize_tables_cache();
-  }
-
-  for (uint64_t table_id = 0; table_id < header_->secondary_table_size();
-       ++table_id) {
-    std::unique_ptr<void *[]> &table_cache = tables_cache_[table_id];
-    if (!table_cache) {
-      if (secondary_table_[table_id] == io::BLOCK_INVALID_ID) {
-        continue;
-      }
-      secondary_table_cache_[table_id] = static_cast<uint32_t *>(
-          pool_.get_block_address(secondary_table_[table_id]));
-      initialize_table_cache(&table_cache);
-    }
-
-    const uint64_t offset = table_id << table_size_bits_;
-    for (uint64_t page_id = 0; page_id < header_->table_size(); ++page_id) {
-      if (!table_cache[page_id]) {
-        uint32_t * const table = secondary_table_cache_[table_id];
-        if (table[page_id] == io::BLOCK_INVALID_ID) {
-          continue;
-        }
-        table_cache[page_id] = pool_.get_block_address(table[page_id]);
-      }
-      if (!callback(offset + page_id, table_cache[page_id], argument)) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-StringBuilder &VectorImpl::write_to(StringBuilder &builder) const {
-  if (!builder) {
-    return builder;
-  }
-
-  builder << "{ pool = " << pool_.path()
-          << ", block_info = " << *block_info_
-          << ", header = " << *header_
-          << ", max_page_id = " << max_page_id_
-          << ", inter_thread_mutex = " << inter_thread_mutex_;
-  return builder << " }";
-}
-
-void VectorImpl::unlink(io::Pool pool,
-                        uint32_t block_id,
-                        uint64_t value_size,
-                        uint64_t page_size,
-                        uint64_t table_size,
-                        uint64_t secondary_table_size) try {
-  std::vector<uint32_t> block_ids;
-
-  {
-    std::unique_ptr<VectorImpl> vector = VectorImpl::open(
-        pool, block_id, value_size,
-        page_size, table_size, secondary_table_size, nullptr);
-    const VectorHeader * const header = vector->header_;
-
-    block_ids.push_back(block_id);
-
-    block_ids.push_back(header->first_table_block_id());
-    for (uint64_t i = 0; i < header->table_size(); ++i) {
-      if (vector->first_table_[i] != io::BLOCK_INVALID_ID) {
-        block_ids.push_back(vector->first_table_[i]);
-      }
-    }
-
-    if (header->secondary_table_block_id() != io::BLOCK_INVALID_ID) {
-      block_ids.push_back(header->secondary_table_block_id());
-      uint32_t * const secondary_table = static_cast<uint32_t *>(
-          pool.get_block_address(header->secondary_table_block_id()));
-      for (uint64_t i = 0; i < header->secondary_table_size(); ++i) {
-        if (secondary_table[i] != io::BLOCK_INVALID_ID) {
-          block_ids.push_back(secondary_table[i]);
-          uint32_t * const table = static_cast<uint32_t *>(
-              pool.get_block_address(secondary_table[i]));
-          for (uint64_t j = 0; j < header->table_size(); ++j) {
-            if (table[j] != io::BLOCK_INVALID_ID) {
-              block_ids.push_back(table[j]);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  for (size_t i = 0; i < block_ids.size(); ++i) {
-    pool.free_block(block_ids[i]);
-  }
-} catch (const std::exception &exception) {
-  GRNXX_ERROR() << exception;
-  GRNXX_THROW();
-}
-
-VectorImpl::VectorImpl()
-  : pool_(),
-    fill_page_(nullptr),
-    block_info_(nullptr),
-    header_(nullptr),
-    default_value_(nullptr),
-    table_size_bits_(0),
-    table_size_mask_(0),
-    max_page_id_(0),
-    first_table_(nullptr),
-    secondary_table_(nullptr),
-    secondary_table_cache_(),
-    first_table_cache_(),
-    tables_cache_(),
-    inter_thread_mutex_(MUTEX_UNLOCKED) {}
-
-void VectorImpl::create_vector(io::Pool pool,
-                               const void *default_value,
-                               uint64_t value_size,
-                               uint64_t page_size,
-                               uint64_t table_size,
-                               uint64_t secondary_table_size,
-                               FillPage fill_page) {
-  pool_ = pool;
-
-  std::unique_ptr<void *[]> first_table_cache(
-      new (std::nothrow) void *[table_size]);
-  if (!first_table_cache) {
-    GRNXX_ERROR() << "new void *[" << table_size << "] failed";
-    GRNXX_THROW();
-  }
-
-  uint64_t header_block_size = sizeof(VectorHeader);
-  if (default_value) {
-    header_block_size += value_size;
-  }
-  block_info_ = pool_.create_block(header_block_size);
-
-  const io::BlockInfo *first_table_block_info;
-  try {
-    first_table_block_info = pool_.create_block(sizeof(uint32_t) * table_size);
-  } catch (...) {
-    pool_.free_block(*block_info_);
-    throw;
-  }
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<VectorHeader *>(block_address);
-  *header_ = VectorHeader(default_value, value_size, page_size, table_size,
-                          secondary_table_size);
-  restore_from_header();
-
-  if (default_value_) {
-    std::memcpy(default_value_, default_value,
-                static_cast<size_t>(value_size));
-    fill_page_ = fill_page;
-  }
-
-  header_->set_first_table_block_id(first_table_block_info->id());
-  first_table_ = static_cast<uint32_t *>(
-      pool_.get_block_address(*first_table_block_info));
-  first_table_cache_ = std::move(first_table_cache);
-  for (uint64_t i = 0; i < header_->table_size(); ++i) {
-    first_table_[i] = io::BLOCK_INVALID_ID;
-    first_table_cache_[i] = nullptr;
-  }
-}
-
-void VectorImpl::open_vector(io::Pool pool,
-                             uint32_t block_id,
-                             uint64_t value_size,
-                             uint64_t page_size,
-                             uint64_t table_size,
-                             uint64_t secondary_table_size,
-                             FillPage fill_page) {
-  pool_ = pool;
-
-  block_info_ = pool_.get_block_info(block_id);
-  if (block_info_->size() < sizeof(VectorHeader)) {
-    GRNXX_ERROR() << "invalid argument: block_info = " << *block_info_
-                  << ", header_size = " << sizeof(VectorHeader);
-    GRNXX_THROW();
-  }
-
-  void * const block_address = pool_.get_block_address(*block_info_);
-  header_ = static_cast<VectorHeader *>(block_address);
-  restore_from_header();
-
-  if (default_value_) {
-    const uint64_t header_size = sizeof(VectorHeader) + value_size;
-    if (block_info_->size() < header_size) {
-      GRNXX_ERROR() << "invalid argument: block_info = " << *block_info_
-                    << ", header_size = " << header_size;
-      GRNXX_THROW();
-    }
-    fill_page_ = fill_page;
-  }
-
-  if (value_size != header_->value_size()) {
-    GRNXX_ERROR() << "invalid value size: actual = " << header_->value_size()
-                  << ", expected = " << value_size;
-    GRNXX_THROW();
-  }
-  if (page_size != header_->page_size()) {
-    GRNXX_ERROR() << "invalid page size: actual = " << header_->page_size()
-                  << ", expected = " << page_size;
-    GRNXX_THROW();
-  }
-  if (table_size != header_->table_size()) {
-    GRNXX_ERROR() << "invalid table size: actual = " << header_->table_size()
-                  << ", expected = " << table_size;
-    GRNXX_THROW();
-  }
-  if (secondary_table_size != header_->secondary_table_size()) {
-    GRNXX_ERROR() << "invalid secondary table size: actual = "
-                  << header_->secondary_table_size()
-                  << ", expected = " << secondary_table_size;
-    GRNXX_THROW();
-  }
-
-  first_table_ = static_cast<uint32_t *>(
-      pool_.get_block_address(header_->first_table_block_id()));
-
-  first_table_cache_.reset(new (std::nothrow) void *[header_->table_size()]);
-  if (!first_table_cache_) {
-    GRNXX_ERROR() << "new void *[" << header_->table_size() << "] failed";
-    GRNXX_THROW();
-  }
-  for (uint64_t i = 0; i < header_->table_size(); ++i) {
-    first_table_cache_[i] = nullptr;
-  }
-}
-
-void VectorImpl::restore_from_header() {
-  if (header_->has_default_value()) {
-    default_value_ = header_ + 1;
-  }
-  table_size_bits_ = bit_scan_reverse(header_->table_size());
-  table_size_mask_ = header_->table_size() - 1;
-  max_page_id_ = header_->table_size() * header_->secondary_table_size() - 1;
-}
-
-void *VectorImpl::get_page_address_on_failure(uint64_t page_id) {
-  if (page_id < header_->table_size()) {
-    if (!first_table_cache_[page_id]) {
-      if (first_table_[page_id] == io::BLOCK_INVALID_ID) {
-        initialize_page(&first_table_[page_id]);
-      }
-      first_table_cache_[page_id] =
-          pool_.get_block_address(first_table_[page_id]);
-    }
-    return first_table_cache_[page_id];
-  }
-
-  if (page_id <= max_page_id_) {
-    if (!tables_cache_) {
-      if (!secondary_table_cache_) {
-        if (!secondary_table_) {
-          if (header_->secondary_table_block_id() == io::BLOCK_INVALID_ID) {
-            initialize_secondary_table();
-          }
-          secondary_table_ = static_cast<uint32_t *>(
-              pool_.get_block_address(header_->secondary_table_block_id()));
-        }
-        initialize_secondary_table_cache();
-      }
-      initialize_tables_cache();
-    }
-
-    const uint64_t table_id = page_id >> table_size_bits_;
-    std::unique_ptr<void *[]> &table_cache = tables_cache_[table_id];
-    if (!table_cache) {
-      if (secondary_table_[table_id] == io::BLOCK_INVALID_ID) {
-        initialize_table(&secondary_table_[table_id]);
-      }
-      secondary_table_cache_[table_id] = static_cast<uint32_t *>(
-          pool_.get_block_address(secondary_table_[table_id]));
-      initialize_table_cache(&table_cache);
-    }
-
-    page_id &= table_size_mask_;
-    if (!table_cache[page_id]) {
-      uint32_t * const table = secondary_table_cache_[table_id];
-      if (table[page_id] == io::BLOCK_INVALID_ID) {
-        initialize_page(&table[page_id]);
-      }
-      table_cache[page_id] = pool_.get_block_address(table[page_id]);
-    }
-    return table_cache[page_id];
-  }
-
-  GRNXX_ERROR() << "invalid argument: page_id = " << page_id
-                << ": [0, " << max_page_id_ <<']';
-  GRNXX_THROW();
-}
-
-void VectorImpl::initialize_secondary_table() {
-  Lock lock(mutable_inter_process_mutex());
-  if (header_->secondary_table_block_id() == io::BLOCK_INVALID_ID) {
-    const auto block_info = pool_.create_block(
-        sizeof(uint32_t) * header_->secondary_table_size());
... truncated to 1.0MB




More information about the Groonga-commit mailing list
Back to archive index