[Groonga-commit] groonga/grnxx at 0b9b18b [master] Refactor grnxx::map::Pool.

Back to archive index

susumu.yata null+****@clear*****
Thu Aug 15 16:43:18 JST 2013


susumu.yata	2013-08-15 16:43:18 +0900 (Thu, 15 Aug 2013)

  New Revision: 0b9b18b4972bf6cca53144135778e0758e715675
  https://github.com/groonga/grnxx/commit/0b9b18b4972bf6cca53144135778e0758e715675

  Message:
    Refactor grnxx::map::Pool.

  Modified files:
    lib/grnxx/map/pool.cpp
    lib/grnxx/map/pool.hpp

  Modified: lib/grnxx/map/pool.cpp (+137 -106)
===================================================================
--- lib/grnxx/map/pool.cpp    2013-08-14 23:49:13 +0900 (01ad878)
+++ lib/grnxx/map/pool.cpp    2013-08-15 16:43:18 +0900 (1ec5d7d)
@@ -19,6 +19,7 @@
 
 #include <cstring>
 #include <exception>
+#include <limits>
 
 #include "grnxx/exception.hpp"
 #include "grnxx/geo_point.hpp"
@@ -32,7 +33,7 @@ namespace grnxx {
 namespace map {
 namespace {
 
-constexpr uint64_t INVALID_UNIT_ID = ~0ULL;
+constexpr uint64_t INVALID_UNIT_ID = std::numeric_limits<uint64_t>::max();
 
 }  // namespace
 
@@ -96,6 +97,9 @@ void Pool<T>::unlink(Storage *storage, uint32_t storage_node_id) {
 
 template <typename T>
 void Pool<T>::unset(int64_t key_id) {
+  if (size_ != header_->size) {
+    refresh();
+  }
   void * const page = get_page(key_id);
   const uint64_t local_key_id = key_id % PAGE_SIZE;
   const uint64_t unit_id = local_key_id / UNIT_SIZE;
@@ -115,6 +119,9 @@ void Pool<T>::unset(int64_t key_id) {
 
 template <typename T>
 void Pool<T>::reset(int64_t key_id, KeyArg dest_key) {
+  if (size_ != header_->size) {
+    refresh();
+  }
   void * const page = get_page(key_id);
   const uint64_t local_key_id = key_id % PAGE_SIZE;
   const Unit * const unit =
@@ -128,6 +135,9 @@ void Pool<T>::reset(int64_t key_id, KeyArg dest_key) {
 
 template <typename T>
 int64_t Pool<T>::add(KeyArg key) {
+  if (size_ != header_->size) {
+    refresh();
+  }
   if (header_->latest_available_unit_id == INVALID_UNIT_ID) {
     // Use a new unit.
     const int64_t next_key_id = header_->max_key_id + 1;
@@ -208,19 +218,20 @@ void *Pool<T>::open_page(int64_t key_id) {
                   << ", size = " << header_->size;
     throw LogicError();
   }
-  Lock lock(&header_->mutex);
-  refresh_pool();
   const uint64_t page_id = key_id / PAGE_SIZE;
   if (!pages_[page_id]) {
-    // Open an existing full-size page.
-    // Note that a small-size page is opened in refresh_pool().
-    if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
-      GRNXX_ERROR() << "not found: page_id = " << page_id;
-      throw LogicError();
+    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);
     }
-    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];
 }
@@ -228,7 +239,7 @@ void *Pool<T>::open_page(int64_t key_id) {
 template <typename T>
 void *Pool<T>::reserve_page(int64_t key_id) {
   if (static_cast<uint64_t>(key_id) >= header_->size) {
-    expand_pool();
+    expand();
   }
   const uint64_t page_id = key_id / PAGE_SIZE;
   if (!pages_[page_id]) {
@@ -237,7 +248,7 @@ void *Pool<T>::reserve_page(int64_t key_id) {
       void *page;
       if (table_[page_id] == STORAGE_INVALID_NODE_ID) {
         // Create a full-size page.
-        // Note that a small-size page is created in expand_pool().
+        // 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 =
@@ -246,7 +257,7 @@ void *Pool<T>::reserve_page(int64_t key_id) {
         page = page_node.body();
       } else {
         // Open an existing full-size page.
-        // Note that a small-size page is opened in refresh_pool().
+        // Note that a small-size page is opened in refresh_page().
         StorageNode page_node = storage_->open_node(table_[page_id]);
         page = page_node.body();
       }
@@ -257,115 +268,135 @@ void *Pool<T>::reserve_page(int64_t key_id) {
 }
 
 template <typename T>
-void Pool<T>::expand_pool() {
+void Pool<T>::expand() {
   Lock lock(&header_->mutex);
-  refresh_pool();
-  uint64_t new_size = (size_ == 0) ? MIN_PAGE_SIZE : (size_ * 2);
-  if (new_size <= PAGE_SIZE) {
-    // Create a small-size page.
-    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();
+  if (size_ < PAGE_SIZE) {
+    // Create a small-size page or the first full-size page.
+    header_->size = expand_page();
+    refresh_page();
   } else {
     // Create a 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);
-    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_->size = expand_table();
+    refresh_table();
+  }
+}
+
+template <typename T>
+uint64_t 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_->table_storage_node_id = table_node.id();
   }
-  header_->size = new_size;
-  refresh_pool();
+  header_->page_storage_node_id = page_node.id();
+  return new_size;
 }
 
 template <typename T>
-void Pool<T>::refresh_pool() {
-  if (size_ == header_->size) {
-    // Nothing to do.
-    return;
+uint64_t 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];
+    }
   }
-  if (header_->size <= PAGE_SIZE) {
-    // Reopen a page because it is old.
-    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);
+  for ( ; i < new_table_size; ++i) {
+    new_table[i] = STORAGE_INVALID_NODE_ID;
+  }
+  header_->table_storage_node_id = table_node.id();
+  return 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 {
-      pages_[0] =
-          static_cast<Unit *>(page_node.body()) + (header_->size / UNIT_SIZE);
+      // Reopen a table because it is old.
+      refresh_table();
     }
-  } else {
-    // Reopen a table because it is old.
-    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]);
+    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 = " << new_table_size;
+      GRNXX_ERROR() << "new void *[] failed: size = " << 1;
       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;
-    }
+    new_pages[0] =
+        static_cast<Unit *>(page_node.body()) + (header_->size / UNIT_SIZE);
     pages_.swap(new_pages);
-    // Keep an old cache table because another thread may read it.
-    if (new_pages) {
-      try {
-        // TODO: Time must be added.
-        queue_.push(std::move(new_pages));
-      } catch (const std::exception &exception) {
-        GRNXX_ERROR() << "std::queue::push() failed";
-        throw StandardError(exception);
-      }
+  } 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 {
+      // TODO: Time must be added.
+      queue_.push(std::move(new_pages));
+    } catch (const std::exception &exception) {
+      GRNXX_ERROR() << "std::queue::push() failed";
+      throw StandardError(exception);
     }
-    table_ = new_table;
   }
-  size_ = header_->size;
+  table_ = new_table;
 }
 
 template class Pool<int8_t>;

  Modified: lib/grnxx/map/pool.hpp (+16 -5)
===================================================================
--- lib/grnxx/map/pool.hpp    2013-08-14 23:49:13 +0900 (b4e6a20)
+++ lib/grnxx/map/pool.hpp    2013-08-15 16:43:18 +0900 (be80571)
@@ -100,6 +100,9 @@ class Pool {
   }
 
   bool get(int64_t key_id, Key *key) {
+    if (size_ != header_->size) {
+      refresh();
+    }
     const void * const page = get_page(key_id);
     const uint64_t local_key_id = key_id % PAGE_SIZE;
     const Unit * const unit =
@@ -113,11 +116,17 @@ class Pool {
   }
 
   Key get_key(int64_t key_id) {
+    if (size_ != header_->size) {
+      refresh();
+    }
     const void * const page = get_page(key_id);
     return static_cast<const T *>(page)[key_id % PAGE_SIZE];
   }
 
   bool get_bit(int64_t key_id) {
+    if (size_ != header_->size) {
+      refresh();
+    }
     const void * const page = get_page(key_id);
     const uint64_t local_key_id = key_id % PAGE_SIZE;
     const Unit * const unit =
@@ -146,9 +155,6 @@ class Pool {
   void open_pool(Storage *storage, uint32_t storage_node_id);
 
   void *get_page(int64_t key_id) {
-    if (size_ != header_->size) {
-      return open_page(key_id);
-    }
     void * const page = pages_[key_id / PAGE_SIZE];
     if (!page) {
       return open_page(key_id);
@@ -159,8 +165,13 @@ class Pool {
 
   void *reserve_page(int64_t key_id);
 
-  void expand_pool();
-  void refresh_pool();
+  void expand();
+  uint64_t expand_page();
+  uint64_t expand_table();
+
+  void refresh();
+  void refresh_page();
+  void refresh_table();
 };
 
 }  // namespace map
-------------- next part --------------
HTML����������������������������...
Download 



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