susumu.yata
null+****@clear*****
Sun Apr 28 20:50:12 JST 2013
susumu.yata 2013-04-28 20:50:12 +0900 (Sun, 28 Apr 2013) New Revision: 3d38c48c07464e33f399861326be4ffd2616dafb https://github.com/groonga/grnxx/commit/3d38c48c07464e33f399861326be4ffd2616dafb Message: Implement open_or_create() and fix bugs. Modified files: lib/grnxx/storage.hpp lib/grnxx/storage/storage_impl.cpp Modified: lib/grnxx/storage.hpp (+5 -0) =================================================================== --- lib/grnxx/storage.hpp 2013-04-28 19:45:37 +0900 (0039030) +++ lib/grnxx/storage.hpp 2013-04-28 20:50:12 +0900 (f75ba47) @@ -92,10 +92,15 @@ StringBuilder &operator<<(StringBuilder &builder, class StorageNode { public: StorageNode() = default; + explicit StorageNode(std::nullptr_t) : header_(nullptr), body_(nullptr) {} StorageNode(StorageNodeHeader *header, void *body) : header_(header), body_(body) {} + // Return true iff "header_" != nullptr. + bool is_valid() const { + return header_ != nullptr; + } // Return the ID. uint32_t id() const; // Return the status. Modified: lib/grnxx/storage/storage_impl.cpp (+60 -12) =================================================================== --- lib/grnxx/storage/storage_impl.cpp 2013-04-28 19:45:37 +0900 (b03408e) +++ lib/grnxx/storage/storage_impl.cpp 2013-04-28 20:50:12 +0900 (32e2418) @@ -168,25 +168,25 @@ StorageNode StorageImpl::create_node(uint32_t parent_node_id, uint64_t size) { if (parent_node_id >= header_->num_nodes) { GRNXX_ERROR() << "invalid argument: parent_node_id = " << parent_node_id << ", num_nodes = " << header_->num_nodes; - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } else if (size > header_->max_file_size) { GRNXX_ERROR() << "invalid argument: size = " << size << ", max_file_size = " << header_->max_file_size; - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } NodeHeader * const parent_node_header = get_node_header(parent_node_id); if (!parent_node_header) { - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } NodeHeader * const node_header = create_active_node(size); if (!node_header) { - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } node_header->sibling_node_id = parent_node_header->child_node_id; parent_node_header->child_node_id = node_header->id; void * const body = get_node_body(node_header); if (!body) { - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } return StorageNode(node_header, body); } @@ -194,11 +194,11 @@ StorageNode StorageImpl::create_node(uint32_t parent_node_id, uint64_t size) { StorageNode StorageImpl::open_node(uint32_t node_id) { NodeHeader * const node_header = get_node_header(node_id); if (!node_header) { - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } void * const body = get_node_body(node_header); if (!body) { - return StorageNode(nullptr, nullptr); + return StorageNode(nullptr); } return StorageNode(node_header, body); } @@ -355,8 +355,55 @@ bool StorageImpl::open_or_create_storage(const char *path, StorageFlags flags, if (flags & STORAGE_HUGE_TLB) { flags_ |= STORAGE_HUGE_TLB; } - // TODO - return false; + std::unique_ptr<File> header_file(File::open(path)); + if (header_file) { + // Open an existing storage. + // TODO: If another thread or process is creating the storage? + std::unique_ptr<Chunk> header_chunk( + create_chunk(header_file.get(), 0, HEADER_CHUNK_SIZE)); + if (!header_chunk) { + return false; + } + header_ = static_cast<Header *>(header_chunk->address()); + if (!header_->is_valid()) { + return false; + } + if (!prepare_pointers()) { + return false; + } + files_[0] = std::move(header_file); + header_chunk_ = std::move(header_chunk); + } else { + // Create a storage. + header_file.reset(File::create(path)); + if (!header_file) { + return false; + } + if (!header_file->resize(HEADER_CHUNK_SIZE)) { + return false; + } + std::unique_ptr<Chunk> header_chunk( + create_chunk(header_file.get(), 0, HEADER_CHUNK_SIZE)); + if (!header_chunk) { + return false; + } + header_ = static_cast<Header *>(header_chunk->address()); + *header_ = Header(); + header_->max_file_size = options.max_file_size & ~(CHUNK_UNIT_SIZE - 1); + header_->max_num_files = options.max_num_files; + header_->total_size = HEADER_CHUNK_SIZE; + if (!prepare_pointers()) { + return false; + } + prepare_indexes(); + files_[0] = std::move(header_file); + header_chunk_ = std::move(header_chunk); + if (!create_active_node(options.root_size)) { + return false; + } + header_->validate(); + } + return true; } bool StorageImpl::prepare_pointers() { @@ -465,15 +512,16 @@ bool StorageImpl::divide_idle_node(NodeHeader *node_header, uint64_t size) { if (!second_node_header) { return false; } + if (!unregister_idle_node(node_header)) { + return false; + } + header_->latest_phantom_node_id = second_node_header->next_phantom_node_id; second_node_header->status = STORAGE_NODE_IDLE; second_node_header->chunk_id = node_header->chunk_id; second_node_header->offset = node_header->offset + size; second_node_header->size = node_header->size - size; second_node_header->prev_node_id = node_header->id; second_node_header->modified_time = clock_.now(); - if (!unregister_idle_node(node_header)) { - return false; - } node_header->size = size; node_header->next_node_id = second_node_header->id; second_node_header->modified_time = clock_.now(); -------------- next part -------------- HTML����������������������������...Download