[Groonga-commit] groonga/grnxx at 49a85c5 [master] Implement grnxx::map::DoubleArray::defrag().

Back to archive index

susumu.yata null+****@clear*****
Wed Aug 7 16:59:59 JST 2013


susumu.yata	2013-08-07 16:59:59 +0900 (Wed, 07 Aug 2013)

  New Revision: 49a85c5247e59cc5e416b3e5a02a9f0545fb3e11
  https://github.com/groonga/grnxx/commit/49a85c5247e59cc5e416b3e5a02a9f0545fb3e11

  Message:
    Implement grnxx::map::DoubleArray::defrag().

  Modified files:
    lib/grnxx/map/double_array.cpp

  Modified: lib/grnxx/map/double_array.cpp (+108 -9)
===================================================================
--- lib/grnxx/map/double_array.cpp    2013-08-07 16:09:21 +0900 (1b92d47)
+++ lib/grnxx/map/double_array.cpp    2013-08-07 16:59:59 +0900 (a73f307)
@@ -348,6 +348,8 @@ class DoubleArrayImpl {
   ~DoubleArrayImpl();
 
   static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id);
+  static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id,
+                                 DoubleArrayImpl *src_impl);
   static DoubleArrayImpl *open(Storage *storage, uint32_t storage_node_id);
 
   static void unlink(Storage *storage, uint32_t storage_node_id) {
@@ -378,8 +380,6 @@ class DoubleArrayImpl {
   bool remove(KeyArg key);
   bool replace(KeyArg src_key, KeyArg dest_key, int64_t *key_id = nullptr);
 
-  void defrag(double usage_rate_threshold);
-
   bool find_longest_prefix_match(KeyArg query,
                                  int64_t *key_id = nullptr,
                                  Key *key = nullptr);
@@ -404,8 +404,12 @@ class DoubleArrayImpl {
   Pool *pool_;
 
   void create_impl(Storage *storage, uint32_t storage_node_id);
+  void create_impl(Storage *storage, uint32_t storage_node_id,
+                   DoubleArrayImpl *src_impl);
   void open_impl(Storage *storage, uint32_t storage_node_id);
 
+  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);
@@ -450,6 +454,18 @@ DoubleArrayImpl *DoubleArrayImpl::create(Storage *storage,
   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) {
   std::unique_ptr<DoubleArrayImpl> impl(new (std::nothrow) DoubleArrayImpl);
@@ -586,11 +602,6 @@ bool DoubleArrayImpl::replace(KeyArg src_key, KeyArg dest_key,
   return true;
 }
 
-void DoubleArrayImpl::defrag(double usage_rate_threshold) {
-  // TODO
-  pool_->defrag(usage_rate_threshold);
-}
-
 bool DoubleArrayImpl::find_longest_prefix_match(KeyArg query,
                                                    int64_t *key_id,
                                                    Key *key) {
@@ -686,6 +697,19 @@ void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id) {
   }
 }
 
+void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id,
+                                  DoubleArrayImpl *src_impl) {
+  create_impl(storage, storage_node_id);
+  try {
+    // Build a double-array from "src_impl".
+    pool_ = src_impl->pool_;
+    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) {
   storage_ = storage;
   storage_node_id_ = storage_node_id;
@@ -722,6 +746,64 @@ bool DoubleArrayImpl::replace_key(int64_t key_id, KeyArg src_key,
   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[NODE_MAX_LABEL + 1];
+    uint64_t num_labels = 0;
+    uint64_t label = src_node.child();
+    while (label != NODE_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() != NODE_INVALID_LABEL)) {
+        labels[num_labels++] = label;
+      }
+      if (child_node.has_sibling()) {
+        label = src_impl->siblings_->get(child_node_id);
+      } else {
+        label = NODE_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 != NODE_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) : NODE_INVALID_LABEL;
+  }
+}
+
 bool DoubleArrayImpl::find_leaf(KeyArg key, Node **leaf_node,
                                 uint64_t *leaf_key_pos) {
   Node *node = &nodes_->get_value(ROOT_NODE_ID);
@@ -1222,8 +1304,25 @@ bool DoubleArray<Bytes>::replace(KeyArg src_key, KeyArg dest_key,
 }
 
 void DoubleArray<Bytes>::defrag(double usage_rate_threshold) {
-  // TODO
-  impl_->defrag(usage_rate_threshold);
+  refresh_impl();
+  if (max_key_id() == MAP_MIN_KEY_ID) {
+    // Nothing to do.
+    return;
+  }
+  // Create a new impl.
+  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;
+    old_impl_.swap(new_impl);
+    impl_.swap(old_impl_);
+    impl_id_ = header_->impl_id;
+  }
+  Impl::unlink(storage_, old_impl_->storage_node_id());
+  pool_->defrag(usage_rate_threshold);
 }
 
 void DoubleArray<Bytes>::truncate() {
-------------- next part --------------
HTML����������������������������...
Download 



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