[Groonga-commit] groonga/grnxx at 16f53f5 [master] Reimplement grnxx::map::DoubleArray::truncate().

Back to archive index

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


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

  New Revision: 16f53f56f74814f6eab746c3b5bf91267561eeec
  https://github.com/groonga/grnxx/commit/16f53f56f74814f6eab746c3b5bf91267561eeec

  Message:
    Reimplement grnxx::map::DoubleArray::truncate().

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

  Modified: lib/grnxx/map/double_array.cpp (+60 -25)
===================================================================
--- lib/grnxx/map/double_array.cpp    2013-08-07 15:37:15 +0900 (7ad6f97)
+++ lib/grnxx/map/double_array.cpp    2013-08-07 16:09:21 +0900 (1b92d47)
@@ -23,10 +23,12 @@
 #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/key_pool.hpp"
+#include "grnxx/mutex.hpp"
 #include "grnxx/storage.hpp"
 
 namespace grnxx {
@@ -345,10 +347,13 @@ class DoubleArrayImpl {
   DoubleArrayImpl();
   ~DoubleArrayImpl();
 
-  static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id,
-                                 const MapOptions &options);
+  static DoubleArrayImpl *create(Storage *storage, uint32_t storage_node_id);
   static DoubleArrayImpl *open(Storage *storage, uint32_t storage_node_id);
 
+  static void unlink(Storage *storage, uint32_t storage_node_id) {
+    storage->unlink_node(storage_node_id);
+  }
+
   void set_pool(Pool *pool) {
     pool_ = pool;
   }
@@ -375,8 +380,6 @@ class DoubleArrayImpl {
 
   void defrag(double usage_rate_threshold);
 
-  void truncate();
-
   bool find_longest_prefix_match(KeyArg query,
                                  int64_t *key_id = nullptr,
                                  Key *key = nullptr);
@@ -400,8 +403,7 @@ class DoubleArrayImpl {
   std::unique_ptr<BlockArray> blocks_;
   Pool *pool_;
 
-  void create_impl(Storage *storage, uint32_t storage_node_id,
-                   const MapOptions &options);
+  void create_impl(Storage *storage, uint32_t storage_node_id);
   void open_impl(Storage *storage, uint32_t storage_node_id);
 
   bool replace_key(int64_t key_id, KeyArg src_key, KeyArg dest_key);
@@ -438,14 +440,13 @@ DoubleArrayImpl::DoubleArrayImpl()
 DoubleArrayImpl::~DoubleArrayImpl() {}
 
 DoubleArrayImpl *DoubleArrayImpl::create(Storage *storage,
-                                         uint32_t storage_node_id,
-                                         const MapOptions &options) {
+                                         uint32_t storage_node_id) {
   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, options);
+  impl->create_impl(storage, storage_node_id);
   return impl.release();
 }
 
@@ -590,14 +591,6 @@ void DoubleArrayImpl::defrag(double usage_rate_threshold) {
   pool_->defrag(usage_rate_threshold);
 }
 
-void DoubleArrayImpl::truncate() {
-  // TODO: How to recycle nodes.
-  Node * const node = &nodes_->get_value(ROOT_NODE_ID);
-  node->set_child(NODE_INVALID_LABEL);
-  node->set_offset(NODE_INVALID_OFFSET);
-  pool_->truncate();
-}
-
 bool DoubleArrayImpl::find_longest_prefix_match(KeyArg query,
                                                    int64_t *key_id,
                                                    Key *key) {
@@ -668,8 +661,7 @@ bool DoubleArrayImpl::find_longest_prefix_match(KeyArg query,
   return found;
 }
 
-void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id,
-                                  const MapOptions &) {
+void DoubleArrayImpl::create_impl(Storage *storage, uint32_t storage_node_id) {
   storage_ = storage;
   StorageNode storage_node =
       storage->create_node(storage_node_id, sizeof(Header));
@@ -1100,8 +1092,10 @@ void DoubleArrayImpl::unset_block_level(uint64_t block_id, Block *block) {
 
 struct DoubleArrayHeader {
   CommonHeader common_header;
+  uint64_t impl_id;
   uint32_t impl_storage_node_id;
   uint32_t pool_storage_node_id;
+  Mutex mutex;
 
   // Initialize the member variables.
   DoubleArrayHeader();
@@ -1112,8 +1106,10 @@ struct DoubleArrayHeader {
 
 DoubleArrayHeader::DoubleArrayHeader()
     : common_header(FORMAT_STRING, MAP_DOUBLE_ARRAY),
+      impl_id(0),
       impl_storage_node_id(STORAGE_INVALID_NODE_ID),
-      pool_storage_node_id(STORAGE_INVALID_NODE_ID) {}
+      pool_storage_node_id(STORAGE_INVALID_NODE_ID),
+      mutex() {}
 
 DoubleArrayHeader::operator bool() const {
   return common_header.format() == FORMAT_STRING;
@@ -1147,7 +1143,9 @@ DoubleArray<Bytes>::DoubleArray()
       storage_node_id_(STORAGE_INVALID_NODE_ID),
       header_(nullptr),
       impl_(),
-      pool_() {}
+      old_impl_(),
+      pool_(),
+      impl_id_(0) {}
 
 DoubleArray<Bytes>::~DoubleArray() {}
 
@@ -1229,8 +1227,30 @@ void DoubleArray<Bytes>::defrag(double usage_rate_threshold) {
 }
 
 void DoubleArray<Bytes>::truncate() {
-  // TODO
-  impl_->truncate();
+  refresh_impl();
+  if (max_key_id() == MAP_MIN_KEY_ID) {
+    // Nothing to do.
+    return;
+  }
+  // Create an empty impl.
+  std::unique_ptr<Impl> new_impl(Impl::create(storage_, storage_node_id_));
+  try {
+    pool_->truncate();
+    new_impl->set_pool(pool_.get());
+  } catch (...) {
+    Impl::unlink(storage_, new_impl->storage_node_id());
+    throw;
+  }
+  {
+    // 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());
 }
 
 bool DoubleArray<Bytes>::find_longest_prefix_match(KeyArg query,
@@ -1258,7 +1278,7 @@ bool DoubleArray<Bytes>::find_longest_prefix_match(KeyArg query,
 //}
 
 void DoubleArray<Bytes>::create_map(Storage *storage, uint32_t storage_node_id,
-                                    const MapOptions &options) {
+                                    const MapOptions &) {
   storage_ = storage;
   StorageNode storage_node =
       storage->create_node(storage_node_id, sizeof(Header));
@@ -1266,7 +1286,7 @@ void DoubleArray<Bytes>::create_map(Storage *storage, uint32_t storage_node_id,
   try {
     header_ = static_cast<Header *>(storage_node.body());
     *header_ = Header();
-    impl_.reset(Impl::create(storage, storage_node_id_, options));
+    impl_.reset(Impl::create(storage, storage_node_id_));
     pool_.reset(Pool::create(storage, storage_node_id_));
     impl_->set_pool(pool_.get());
     header_->impl_storage_node_id = impl_->storage_node_id();
@@ -1292,9 +1312,24 @@ void DoubleArray<Bytes>::open_map(Storage *storage, uint32_t storage_node_id) {
                   << ", actual = " << header_->common_header.format();
     throw LogicError();
   }
+  Lock lock(&header_->mutex);
   impl_.reset(Impl::open(storage, header_->impl_storage_node_id));
   pool_.reset(Pool::open(storage, header_->pool_storage_node_id));
   impl_->set_pool(pool_.get());
+  impl_id_ = header_->impl_id;
+}
+
+void DoubleArray<Bytes>::refresh_impl() {
+  if (impl_id_ != header_->impl_id) {
+    Lock lock(&header_->mutex);
+    if (impl_id_ != header_->impl_id) {
+      std::unique_ptr<Impl> new_impl(
+          Impl::open(storage_, header_->impl_storage_node_id));
+      old_impl_.swap(new_impl);
+      impl_.swap(old_impl_);
+      impl_id_ = header_->impl_id;
+    }
+  }
 }
 
 }  // namespace map

  Modified: lib/grnxx/map/double_array.hpp (+4 -0)
===================================================================
--- lib/grnxx/map/double_array.hpp    2013-08-07 15:37:15 +0900 (fa679c0)
+++ lib/grnxx/map/double_array.hpp    2013-08-07 16:09:21 +0900 (020ee8f)
@@ -103,11 +103,15 @@ class DoubleArray<Bytes> : public Map<Bytes> {
   uint32_t storage_node_id_;
   Header *header_;
   std::unique_ptr<Impl> impl_;
+  std::unique_ptr<Impl> old_impl_;
   std::unique_ptr<Pool> pool_;
+  uint64_t impl_id_;
 
   void create_map(Storage *storage, uint32_t storage_node_id,
                   const MapOptions &options);
   void open_map(Storage *storage, uint32_t storage_node_id);
+
+  void refresh_impl();
 };
 
 }  // namespace map
-------------- next part --------------
HTML����������������������������...
Download 



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