[Groonga-commit] groonga/grnxx [master] Implement reuse of empty pages. (grnxx::alpha::BlobVector)

アーカイブの一覧に戻る

susumu.yata null+****@clear*****
Wed Dec 5 11:46:48 JST 2012


susumu.yata	2012-12-05 11:46:48 +0900 (Wed, 05 Dec 2012)

  New Revision: 8c7ff5ecbee73b6b712f749b03ff1a21d8d4976c
  https://github.com/groonga/grnxx/commit/8c7ff5ecbee73b6b712f749b03ff1a21d8d4976c

  Log:
    Implement reuse of empty pages. (grnxx::alpha::BlobVector)

  Modified files:
    lib/alpha/blob_vector.cpp
    lib/alpha/blob_vector.hpp

  Modified: lib/alpha/blob_vector.cpp (+54 -1)
===================================================================
--- lib/alpha/blob_vector.cpp    2012-12-04 21:39:43 +0900 (8a62443)
+++ lib/alpha/blob_vector.cpp    2012-12-05 11:46:48 +0900 (dcce9b2)
@@ -33,6 +33,7 @@ BlobVectorHeader::BlobVectorHeader(uint32_t cells_block_id)
     page_infos_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_() {}
 
@@ -326,9 +327,22 @@ BlobVectorMediumValue BlobVectorImpl::create_medium_value(
   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.
   const uint64_t required_size =
       capacity + sizeof(BlobVectorMediumValueHeader);
   if (required_size > 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 (page_infos_[page_id].num_values() == 0) {
+        freeze_page(page_id);
+      }
+    }
+
+    // Unfreeze the oldest frozen page for reuse.
+    unfreeze_oldest_frozen_page();
+
     const uint32_t page_id = header_->next_page_id();
     offset = static_cast<uint64_t>(
         page_id << BLOB_VECTOR_VALUE_STORE_PAGE_SIZE_BITS);
@@ -382,7 +396,12 @@ void BlobVectorImpl::free_value(BlobVectorCell cell) {
       page_infos_[page_id].set_num_values(
           page_infos_[page_id].num_values() - 1);
       if (page_infos_[page_id].num_values() == 0) {
-        // TODO: Freeze.
+        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;
     }
@@ -435,6 +454,40 @@ void BlobVectorImpl::unregister_large_value(uint32_t block_id,
   }
 }
 
+void BlobVectorImpl::freeze_page(uint32_t page_id) {
+  BlobVectorPageInfo &page_info = page_infos_[page_id];
+  if (header_->latest_frozen_page_id() != BLOB_VECTOR_INVALID_PAGE_ID) {
+    BlobVectorPageInfo &latest_frozen_page_info =
+        page_infos_[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 =
+        page_infos_[header_->latest_frozen_page_id()];
+    const uint32_t oldest_frozen_page_id =
+        latest_frozen_page_info.next_page_id();
+    BlobVectorPageInfo &oldest_frozen_page_info =
+        page_infos_[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);
+      }
+    }
+  }
+}
+
 BlobVector::BlobVector(const BlobVectorCreate &, io::Pool pool)
   : impl_(BlobVectorImpl::create(pool)) {}
 

  Modified: lib/alpha/blob_vector.hpp (+10 -0)
===================================================================
--- lib/alpha/blob_vector.hpp    2012-12-04 21:39:43 +0900 (93e1c24)
+++ lib/alpha/blob_vector.hpp    2012-12-05 11:46:48 +0900 (4480a2b)
@@ -79,6 +79,9 @@ class BlobVectorHeader {
   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_;
   }
@@ -95,6 +98,9 @@ class BlobVectorHeader {
   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;
   }
@@ -111,6 +117,7 @@ class BlobVectorHeader {
   uint32_t page_infos_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_;
 };
@@ -435,6 +442,9 @@ class BlobVectorImpl {
   void unregister_large_value(uint32_t block_id,
                               BlobVectorLargeValueHeader *value_header);
 
+  void freeze_page(uint32_t page_id);
+  void unfreeze_oldest_frozen_page();
+
   Mutex *mutable_inter_thread_mutex() {
     return &inter_thread_mutex_;
   }
-------------- next part --------------
HTML����������������������������...
ダウンロード 



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