susumu.yata
null+****@clear*****
Mon Apr 29 19:46:58 JST 2013
susumu.yata 2013-04-29 19:46:58 +0900 (Mon, 29 Apr 2013) New Revision: 75e881c5dbe3bd13d114a662817db38ca7f8019c https://github.com/groonga/grnxx/commit/75e881c5dbe3bd13d114a662817db38ca7f8019c Message: Add exclusive access control. Modified files: lib/grnxx/storage.hpp lib/grnxx/storage/header.cpp lib/grnxx/storage/header.hpp lib/grnxx/storage/storage_impl.cpp lib/grnxx/storage/storage_impl.hpp Modified: lib/grnxx/storage.hpp (+2 -3) =================================================================== --- lib/grnxx/storage.hpp 2013-04-28 23:01:48 +0900 (54452a1) +++ lib/grnxx/storage.hpp 2013-04-29 19:46:58 +0900 (3d30255) @@ -160,7 +160,8 @@ class Storage { virtual bool unlink_node(uint32_t node_id) = 0; // Sweep marked nodes whose last modified time < (now - lifetime). - virtual bool sweep(Duration lifetime) = 0; + virtual bool sweep(Duration lifetime, + uint32_t root_node_id = STORAGE_ROOT_NODE_ID) = 0; // Return the storage path. // Note that an anonymous or temporary storage may return nullptr. @@ -173,8 +174,6 @@ class Storage { virtual uint16_t max_num_files() const = 0; // Return the total size. virtual uint64_t total_size() const = 0; - - // TODO: Member functions to get details, such as total size, #nodes, etc. }; } // namespace grnxx Modified: lib/grnxx/storage/header.cpp (+2 -2) =================================================================== --- lib/grnxx/storage/header.cpp 2013-04-28 23:01:48 +0900 (f3e9251) +++ lib/grnxx/storage/header.cpp 2013-04-29 19:46:58 +0900 (add40f9) @@ -44,8 +44,8 @@ Header::Header() latest_phantom_node_id(STORAGE_INVALID_NODE_ID), latest_unlinked_node_id(STORAGE_INVALID_NODE_ID), oldest_idle_node_ids(), - inter_process_data_mutex(MUTEX_UNLOCKED), - inter_process_file_mutex(MUTEX_UNLOCKED), + data_mutex(MUTEX_UNLOCKED), + file_mutex(MUTEX_UNLOCKED), reserved{} { std::memcpy(version, GRNXX_STORAGE_HEADER_VERSION, HEADER_VERSION_SIZE); for (size_t i = 0; i < NUM_IDLE_NODE_LISTS; ++i) { Modified: lib/grnxx/storage/header.hpp (+2 -2) =================================================================== --- lib/grnxx/storage/header.hpp 2013-04-28 23:01:48 +0900 (1988371) +++ lib/grnxx/storage/header.hpp 2013-04-29 19:46:58 +0900 (257c86e) @@ -60,9 +60,9 @@ struct Header { // The IDs of the oldest idle nodes. uint32_t oldest_idle_node_ids[NUM_IDLE_NODE_LISTS]; // A mutex object for exclusively updating data. - Mutex inter_process_data_mutex; + Mutex data_mutex; // A mutex object for exclusively update files. - Mutex inter_process_file_mutex; + Mutex file_mutex; uint8_t reserved[148]; // Initialize the members except "format". Modified: lib/grnxx/storage/storage_impl.cpp (+70 -21) =================================================================== --- lib/grnxx/storage/storage_impl.cpp 2013-04-28 23:01:48 +0900 (d790c82) +++ lib/grnxx/storage/storage_impl.cpp 2013-04-29 19:46:58 +0900 (ce6486a) @@ -18,6 +18,7 @@ #include "grnxx/storage/storage_impl.hpp" #include "grnxx/intrinsic.hpp" +#include "grnxx/lock.hpp" #include "grnxx/logger.hpp" #include "grnxx/slice.hpp" #include "grnxx/storage/chunk.hpp" @@ -67,6 +68,7 @@ StorageImpl::StorageImpl() header_chunk_(), node_header_chunks_(), node_body_chunks_(), + mutex_(MUTEX_UNLOCKED), clock_() {} StorageImpl::~StorageImpl() {} @@ -176,6 +178,7 @@ StorageNode StorageImpl::create_node(uint32_t parent_node_id, uint64_t size) { if (!parent_node_header) { return StorageNode(nullptr); } + Lock lock(&header_->data_mutex); NodeHeader * const node_header = create_active_node(size); if (!node_header) { return StorageNode(nullptr); @@ -220,9 +223,13 @@ bool StorageImpl::unlink_node(uint32_t node_id) { return true; } -bool StorageImpl::sweep(Duration lifetime) { - // TODO - return false; +bool StorageImpl::sweep(Duration lifetime, uint32_t root_node_id) { + Lock lock(&header_->data_mutex); + NodeHeader * const node_header = get_node_header(root_node_id); + if (!node_header) { + return false; + } + return sweep_subtree(clock_.now() - lifetime, node_header); } const char *StorageImpl::path() const { @@ -619,6 +626,27 @@ bool StorageImpl::associate_node_with_chunk(NodeHeader *node_header, return true; } +bool StorageImpl::sweep_subtree(Time threshold, NodeHeader *node_header) { + if (node_header->status == STORAGE_NODE_MARKED) { + if (node_header->modified_time <= threshold) { + // TODO: Unlink the node. + return true; + } + } + uint32_t node_id = node_header->child_node_id; + while (node_id != STORAGE_INVALID_NODE_ID) { + node_header = get_node_header(node_id); + if (!node_header) { + return false; + } + if (!sweep_subtree(threshold, node_header)) { + return false; + } + node_id = node_header->sibling_node_id; + } + return true; +} + ChunkIndex *StorageImpl::create_node_header_chunk( ChunkIndex **remainder_chunk_index) { if (header_->num_nodes > MAX_NODE_ID) { @@ -808,8 +836,11 @@ Chunk *StorageImpl::get_node_header_chunk(uint16_t chunk_id) { if (!node_header_chunks_[chunk_id]) { const ChunkIndex &chunk_index = node_header_chunk_indexes_[chunk_id]; if (flags_ & STORAGE_ANONYMOUS) { - node_header_chunks_[chunk_id].reset( - create_chunk(nullptr, chunk_index.offset, chunk_index.size)); + Lock lock(&mutex_); + if (!node_header_chunks_[chunk_id]) { + node_header_chunks_[chunk_id].reset( + create_chunk(nullptr, chunk_index.offset, chunk_index.size)); + } } else { File * const file = get_file(chunk_index.file_id); if (!file) { @@ -817,12 +848,18 @@ Chunk *StorageImpl::get_node_header_chunk(uint16_t chunk_id) { } const int64_t required_size = chunk_index.offset + chunk_index.size; if (file->size() < required_size) { - if (!file->resize(required_size)) { - return nullptr; + Lock file_lock(&header_->file_mutex); + if (file->size() < required_size) { + if (!file->resize(required_size)) { + return nullptr; + } } } - node_header_chunks_[chunk_id].reset( - create_chunk(file, chunk_index.offset, chunk_index.size)); + Lock lock(&mutex_); + if (!node_header_chunks_[chunk_id]) { + node_header_chunks_[chunk_id].reset( + create_chunk(file, chunk_index.offset, chunk_index.size)); + } } } return node_header_chunks_[chunk_id].get(); @@ -832,8 +869,11 @@ Chunk *StorageImpl::get_node_body_chunk(uint16_t chunk_id) { if (!node_body_chunks_[chunk_id]) { const ChunkIndex &chunk_index = node_body_chunk_indexes_[chunk_id]; if (flags_ & STORAGE_ANONYMOUS) { - node_body_chunks_[chunk_id].reset( - create_chunk(nullptr, chunk_index.offset, chunk_index.size)); + Lock lock(&mutex_); + if (!node_body_chunks_[chunk_id]) { + node_body_chunks_[chunk_id].reset( + create_chunk(nullptr, chunk_index.offset, chunk_index.size)); + } } else { File * const file = get_file(chunk_index.file_id); if (!file) { @@ -841,12 +881,18 @@ Chunk *StorageImpl::get_node_body_chunk(uint16_t chunk_id) { } const int64_t required_size = chunk_index.offset + chunk_index.size; if (file->size() < required_size) { - if (!file->resize(required_size)) { - return nullptr; + Lock file_lock(&header_->file_mutex); + if (file->size() < required_size) { + if (!file->resize(required_size)) { + return nullptr; + } } } - node_body_chunks_[chunk_id].reset( - create_chunk(file, chunk_index.offset, chunk_index.size)); + Lock lock(&mutex_); + if (!node_body_chunks_[chunk_id]) { + node_body_chunks_[chunk_id].reset( + create_chunk(file, chunk_index.offset, chunk_index.size)); + } } } return node_body_chunks_[chunk_id].get(); @@ -860,12 +906,15 @@ File *StorageImpl::get_file(uint16_t file_id) { 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)); + Lock file_lock(&header_->file_mutex); + if (!files_[file_id]) { + 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)); + } } } } Modified: lib/grnxx/storage/storage_impl.hpp (+5 -3) =================================================================== --- lib/grnxx/storage/storage_impl.hpp 2013-04-28 23:01:48 +0900 (8186144) +++ lib/grnxx/storage/storage_impl.hpp 2013-04-29 19:46:58 +0900 (d89819c) @@ -18,6 +18,7 @@ #ifndef GRNXX_STORAGE_STORAGE_IMPL_HPP #define GRNXX_STORAGE_STORAGE_IMPL_HPP +#include "grnxx/mutex.hpp" #include "grnxx/storage.hpp" #include "grnxx/time/periodic_clock.hpp" @@ -51,7 +52,7 @@ class StorageImpl : public Storage { bool unlink_node(uint32_t node_id); - bool sweep(Duration lifetime); + bool sweep(Duration lifetime, uint32_t root_node_id); const char *path() const; StorageFlags flags() const; @@ -59,8 +60,6 @@ class StorageImpl : public Storage { uint16_t max_num_files() const; uint64_t total_size() const; - // TODO: Member functions to get details, such as total size, #nodes, etc. - private: std::unique_ptr<char[]> path_; StorageFlags flags_; @@ -71,6 +70,7 @@ class StorageImpl : public Storage { std::unique_ptr<Chunk> header_chunk_; std::unique_ptr<std::unique_ptr<Chunk>[]> node_header_chunks_; std::unique_ptr<std::unique_ptr<Chunk>[]> node_body_chunks_; + Mutex mutex_; PeriodicClock clock_; bool create_file_backed_storage(const char *path, StorageFlags flags, @@ -99,6 +99,8 @@ class StorageImpl : public Storage { ChunkIndex **remainder_chunk_index); ChunkIndex *create_node_body_chunk(uint64_t size); + bool sweep_subtree(Time threshold, NodeHeader *node_header); + bool register_idle_node(NodeHeader *node_header); bool unregister_idle_node(NodeHeader *node_header); -------------- next part -------------- HTML����������������������������...Download