From 6d0afe69492a874e8ec35cbe1bdf9f2cfb5f4fd1 Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 7 Mar 2017 17:40:15 +0800 Subject: [PATCH 01/28] Add dir lock support (#527) --- src/nameserver/nameserver_impl.cc | 69 +++++++++++++++++++++++++++++++ src/nameserver/nameserver_impl.h | 19 +++++++++ src/nameserver/namespace.cc | 16 +++++++ src/nameserver/namespace.h | 4 ++ src/proto/nameserver.proto | 23 +++++++++++ src/proto/status_code.proto | 3 ++ 6 files changed, 134 insertions(+) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 9c2db1c5..fecb7b06 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -999,6 +999,58 @@ void NameServerImpl::ChangeReplicaNum(::google::protobuf::RpcController* control done->Run(); } +void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, + const LockDirRequest* request, + LockDirResponse* response, + ::google::protobuf::Closure* done) { + if (!is_leader_) { + response->set_status(kIsFollower); + done->Run(); + return; + } + std::string path = NameSpace::NormalizePath(request->dir_path()); + FileLockGuard lock_guard(new WriteLock(path)); + StatusCode status = namespace_->GetDirLockStatus(path); + if (status != kLocked) { + //TODO log remote? + if (status == kUnlock) { + namespace_->LockDir(path); + status = kOK; + } // else status maybe kCleaning or kBadParameter + response->set_status(status); + done->Run(); + } else { + //TODO log remote + namespace_->SetDirLockStatus(kCleaning, path); + WaitForBlockClosed(lock_guard, path, done); + } +} + +void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, + const UnlockDirRequest* request, + UnlockDirResponse* response, + ::google::protobuf::Closure* done) { + if (!is_leader_) { + response->set_status(kIsFollower); + done->Run(); + return; + } + std::string path = NameSpace::NormalizePath(request->dir_path()); + FileLockGuard lock_guard(new WriteLock(path)); + StatusCode status = namespace_->GetDirLockStatus(path); + if (status == kUnlock) { + response->set_status(kOK); + done->Run(); + } else if (status == kCleaning) { + response->set_status(kCleaning); + done->Run(); + } else { + //TODO log remote + namespace_->SetDirLockStatus(kCleaning, path); + WaitForBlockClosed(lock_guard, path, done); + } +} + void NameServerImpl::RebuildBlockMapCallback(const FileInfo& file_info) { for (int i = 0; i < file_info.blocks_size(); i++) { int64_t block_id = file_info.blocks(i); @@ -1590,6 +1642,23 @@ void NameServerImpl::SetActualFileSize(FileInfo* file) { file->set_size(file_size); } +void NameServerImpl::CheckBlockClosed(LockDirContext* context) { + //TODO log remote if success +} + +void NameServerImpl::WaitForBlockClosed(FileLockGuard lock_guard, + const std::string& path, ::google::protobuf::Closure* done) { + LockDirContext* context = + new LockDirContext(lock_guard, path, done); + std::vector all_blocks; + namespace_->ListAllBlocks(path, &all_blocks); + for (size_t i = 0; i < all_blocks.size(); i++) { + block_mapping_manager_->MarkIncomplete(all_blocks[i]); + } + work_thread_pool_->DelayTask(5000, + std::bind(&NameServerImpl::CheckBlockClosed, this, context)); +} + } // namespace bfs } // namespace baidu diff --git a/src/nameserver/nameserver_impl.h b/src/nameserver/nameserver_impl.h index afb6abaa..94cf9ac0 100644 --- a/src/nameserver/nameserver_impl.h +++ b/src/nameserver/nameserver_impl.h @@ -134,6 +134,14 @@ class NameServerImpl : public NameServer { const ChmodRequest* request, ChmodResponse* response, ::google::protobuf::Closure* done); + void LockDir(::google::protobuf::RpcController* controller, + const LockDirRequest* request, + LockDirResponse* response, + ::google::protobuf::Closure* done); + void UnlockDir(::google::protobuf::RpcController* controller, + const UnlockDirRequest* request, + UnlockDirResponse* response, + ::google::protobuf::Closure* done); bool WebService(const sofa::pbrpc::HTTPRequest&, sofa::pbrpc::HTTPResponse&); private: @@ -164,7 +172,18 @@ class NameServerImpl : public NameServer { const std::string& file_name, int64_t block_id); void SetActualFileSize(FileInfo* file); + struct LockDirContext; + void CheckBlockClosed(LockDirContext* lock_context); + void WaitForBlockClosed(FileLockGuard lock_guard, const std::string& path, + ::google::protobuf::Closure* done); private: + struct LockDirContext { + LockDirContext(FileLockGuard guard, const std::string& path, ::google::protobuf::Closure* d) : lock_guard(guard), dir_path(path), done(d) {} + FileLockGuard lock_guard; + std::string dir_path; + std::set blocks; + ::google::protobuf::Closure* done; + }; /// Global thread pool ThreadPool* read_thread_pool_; ThreadPool* work_thread_pool_; diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 33819585..a33e53d2 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -877,6 +877,22 @@ int64_t NameSpace::GetNewBlockId() { return next_block_id_++; } +StatusCode NameSpace::GetDirLockStatus(const std::string& path) { + return kOK; +} + +void NameSpace::SetDirLockStatus(StatusCode status, const std::string& path) { + +} + +void NameSpace::ListAllBlocks(const std::string& path, std::vector* result) { + +} + +void NameSpace::LockDir(const std::string& path) { + +} + } // namespace bfs } // namespace baidu /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index da0765fd..90df2fe8 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -68,6 +68,10 @@ class NameSpace { void TailSnapshot(int32_t ns_id, std::string* logstr); void EraseNamespace(); int64_t GetNewBlockId(); + StatusCode GetDirLockStatus(const std::string& path); + void SetDirLockStatus(StatusCode status, const std::string& path); + void ListAllBlocks(const std::string& path, std::vector* result); + void LockDir(const std::string& path); private: enum FileType { kDefault = 0, diff --git a/src/proto/nameserver.proto b/src/proto/nameserver.proto index 996cc499..430e1f12 100644 --- a/src/proto/nameserver.proto +++ b/src/proto/nameserver.proto @@ -338,6 +338,27 @@ message SymlinkResponse { optional StatusCode status = 2; } +message LockDirRequest { + optional int64 sequence_id = 1; + optional string dir_path = 2; + optional string uuid = 3; +}; + +message LockDirResponse { + optional int64 sequence_id = 1; + optional StatusCode status = 2; +}; + +message UnlockDirRequest { + optional int64 sequence_id = 1; + optional string dir_path = 2; +}; + +message UnlockDirResponse { + optional int64 sequence_id = 1; + optional StatusCode status = 2; +}; + service NameServer { rpc CreateFile(CreateFileRequest) returns(CreateFileResponse); rpc AddBlock(AddBlockRequest) returns(AddBlockResponse); @@ -363,5 +384,7 @@ service NameServer { rpc SysStat(SysStatRequest) returns(SysStatResponse); rpc Chmod(ChmodRequest) returns(ChmodResponse); rpc Symlink(SymlinkRequest) returns(SymlinkResponse); + rpc LockDir(LockDirRequest) returns(LockDirResponse); + rpc UnlockDir(UnlockDirRequest) returns(UnlockDirResponse); } diff --git a/src/proto/status_code.proto b/src/proto/status_code.proto index 908f3149..f1752a57 100644 --- a/src/proto/status_code.proto +++ b/src/proto/status_code.proto @@ -30,6 +30,9 @@ enum StatusCode { kSyncMetaFailed = 801; kSafeMode = 802; kServiceStop = 803; + kLocked = 804; + kUnlock = 805; + kCleaning = 806; } enum ChunkServerStatus { From 0c81542acf8909b6bd1018f08c8be2dd6a401b16 Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 8 Mar 2017 10:53:17 +0800 Subject: [PATCH 02/28] Add dir lock implementation (#527) --- src/nameserver/block_mapping_manager.cc | 4 +++ src/nameserver/block_mapping_manager.h | 1 + src/nameserver/nameserver_impl.cc | 43 ++++++++----------------- src/nameserver/nameserver_impl.h | 11 ------- src/nameserver/namespace.cc | 2 +- src/proto/nameserver.proto | 1 + src/sdk/bfs.h | 4 +++ src/sdk/fs_impl.cc | 29 +++++++++++++++++ src/sdk/fs_impl.h | 4 +++ 9 files changed, 58 insertions(+), 41 deletions(-) diff --git a/src/nameserver/block_mapping_manager.cc b/src/nameserver/block_mapping_manager.cc index 032685e5..ebe0e99d 100644 --- a/src/nameserver/block_mapping_manager.cc +++ b/src/nameserver/block_mapping_manager.cc @@ -159,5 +159,9 @@ void BlockMappingManager::MarkIncomplete(int64_t block_id) { block_mapping_[bucket_offset]->MarkIncomplete(block_id); } +bool BlockMappingManager::CheckBlocksClosed(const std::vector& blocks) { + return true; +} + } //namespace bfs } //namespace baidu diff --git a/src/nameserver/block_mapping_manager.h b/src/nameserver/block_mapping_manager.h index ec86bd4e..8049cd83 100644 --- a/src/nameserver/block_mapping_manager.h +++ b/src/nameserver/block_mapping_manager.h @@ -40,6 +40,7 @@ public : void GetRecoverNum(int32_t bucket_id, RecoverBlockNum* recover_num); void ListRecover(RecoverBlockSet* recover_blocks); void MarkIncomplete(int64_t block_id); + bool CheckBlocksClosed(const std::vector& blocks); private: int32_t GetBucketOffset(int64_t block_id); private: diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index fecb7b06..8068b028 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1017,13 +1017,13 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, namespace_->LockDir(path); status = kOK; } // else status maybe kCleaning or kBadParameter - response->set_status(status); - done->Run(); } else { //TODO log remote namespace_->SetDirLockStatus(kCleaning, path); - WaitForBlockClosed(lock_guard, path, done); + status = kCleaning; } + response->set_status(status); + done->Run(); } void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, @@ -1038,17 +1038,19 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); StatusCode status = namespace_->GetDirLockStatus(path); - if (status == kUnlock) { - response->set_status(kOK); - done->Run(); - } else if (status == kCleaning) { - response->set_status(kCleaning); - done->Run(); - } else { + if (status == kLocked) { //TODO log remote namespace_->SetDirLockStatus(kCleaning, path); - WaitForBlockClosed(lock_guard, path, done); + std::vector blocks; + namespace_->ListAllBlocks(path, &blocks);; + if (block_mapping_manager_->CheckBlocksClosed(blocks)) { + status = kUnlock; + } else { + status = kCleaning; + } } + response->set_status(status); + done->Run(); } void NameServerImpl::RebuildBlockMapCallback(const FileInfo& file_info) { @@ -1056,7 +1058,7 @@ void NameServerImpl::RebuildBlockMapCallback(const FileInfo& file_info) { int64_t block_id = file_info.blocks(i); int64_t version = file_info.version(); block_mapping_manager_->RebuildBlock(block_id, file_info.replicas(), - version, file_info.size()); + version, file_info.size()); } } @@ -1642,23 +1644,6 @@ void NameServerImpl::SetActualFileSize(FileInfo* file) { file->set_size(file_size); } -void NameServerImpl::CheckBlockClosed(LockDirContext* context) { - //TODO log remote if success -} - -void NameServerImpl::WaitForBlockClosed(FileLockGuard lock_guard, - const std::string& path, ::google::protobuf::Closure* done) { - LockDirContext* context = - new LockDirContext(lock_guard, path, done); - std::vector all_blocks; - namespace_->ListAllBlocks(path, &all_blocks); - for (size_t i = 0; i < all_blocks.size(); i++) { - block_mapping_manager_->MarkIncomplete(all_blocks[i]); - } - work_thread_pool_->DelayTask(5000, - std::bind(&NameServerImpl::CheckBlockClosed, this, context)); -} - } // namespace bfs } // namespace baidu diff --git a/src/nameserver/nameserver_impl.h b/src/nameserver/nameserver_impl.h index 94cf9ac0..4b2f3d79 100644 --- a/src/nameserver/nameserver_impl.h +++ b/src/nameserver/nameserver_impl.h @@ -172,18 +172,7 @@ class NameServerImpl : public NameServer { const std::string& file_name, int64_t block_id); void SetActualFileSize(FileInfo* file); - struct LockDirContext; - void CheckBlockClosed(LockDirContext* lock_context); - void WaitForBlockClosed(FileLockGuard lock_guard, const std::string& path, - ::google::protobuf::Closure* done); private: - struct LockDirContext { - LockDirContext(FileLockGuard guard, const std::string& path, ::google::protobuf::Closure* d) : lock_guard(guard), dir_path(path), done(d) {} - FileLockGuard lock_guard; - std::string dir_path; - std::set blocks; - ::google::protobuf::Closure* done; - }; /// Global thread pool ThreadPool* read_thread_pool_; ThreadPool* work_thread_pool_; diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index a33e53d2..01e85c3c 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -878,7 +878,7 @@ int64_t NameSpace::GetNewBlockId() { } StatusCode NameSpace::GetDirLockStatus(const std::string& path) { - return kOK; + return kUnlock; } void NameSpace::SetDirLockStatus(StatusCode status, const std::string& path) { diff --git a/src/proto/nameserver.proto b/src/proto/nameserver.proto index 430e1f12..b867d127 100644 --- a/src/proto/nameserver.proto +++ b/src/proto/nameserver.proto @@ -352,6 +352,7 @@ message LockDirResponse { message UnlockDirRequest { optional int64 sequence_id = 1; optional string dir_path = 2; + optional string uuid = 3; }; message UnlockDirResponse { diff --git a/src/sdk/bfs.h b/src/sdk/bfs.h index bfd9c72f..e8a534f9 100644 --- a/src/sdk/bfs.h +++ b/src/sdk/bfs.h @@ -98,6 +98,10 @@ class FS { virtual int32_t ListDirectory(const char* path, BfsFileInfo** filelist, int *num) = 0; /// Delete Directory virtual int32_t DeleteDirectory(const char* path, bool recursive) = 0; + /// Lock Directory + virtual int32_t LockDirectory(const char* path) = 0; + /// Unlock Directory + virtual int32_t UnlockDirectory(const char* path) = 0; /// Du virtual int32_t DiskUsage(const char* path, int64_t* du_size) = 0; /// Access diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index 4f1a0e23..384aa43c 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -410,6 +410,30 @@ int32_t FSImpl::DeleteFile(const char* path) { } return OK; } +int32_t FSImpl::LockDirectory(const char* path) { + LockDirRequest request; + LockDirResponse response; + request.set_dir_path(path); + request.set_uuid(GetUUID()); + bool ret = true; + while ((ret = nameserver_client_->SendRequest(&NameServer_Stub::LockDir, + &request, &response, 15, 1)) != kOK || + response.status() != kOK) { + sleep(5); + } + assert(response.status() == kOK); + return OK; +} +int32_t FSImpl::UnlockDirectory(const char* path) { + UnlockDirRequest request; + UnlockDirResponse response; + request.set_dir_path(path); + request.set_uuid(GetUUID()); + nameserver_client_->SendRequest(&NameServer_Stub::UnlockDir, + &request, &response, 15, 1); + //Don't care return value of rpc + return OK; +} int32_t FSImpl::Rename(const char* oldpath, const char* newpath) { RenameRequest request; RenameResponse response; @@ -560,5 +584,10 @@ bool FS::OpenFileSystem(const char* nameserver, FS** fs, const FSOptions&) { return true; } +const std::string& FSImpl::GetUUID() { + static std::string uuid; + return uuid; +} + } // namespace bfs } // namespace baidu diff --git a/src/sdk/fs_impl.h b/src/sdk/fs_impl.h index 00b91a4f..9eec0714 100644 --- a/src/sdk/fs_impl.h +++ b/src/sdk/fs_impl.h @@ -32,6 +32,8 @@ class FSImpl : public FS { int32_t CreateDirectory(const char* path); int32_t ListDirectory(const char* path, BfsFileInfo** filelist, int *num); int32_t DeleteDirectory(const char* path, bool recursive); + int32_t LockDirectory(const char* path); + int32_t UnlockDirectory(const char* path); int32_t DiskUsage(const char* path, int64_t* du_size); int32_t Access(const char* path, int32_t mode); int32_t Stat(const char* path, BfsFileInfo* fileinfo); @@ -53,6 +55,8 @@ class FSImpl : public FS { int32_t SysStat(const std::string& stat_name, std::string* result); int32_t ShutdownChunkServer(const std::vector& cs_addr); int32_t ShutdownChunkServerStat(); +private: + const std::string& GetUUID(); private: RpcClient* rpc_client_; NameServerClient* nameserver_client_; From 27bdeb732672ad56aeb198725edd993a7f3a9f8c Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 9 Mar 2017 10:58:18 +0800 Subject: [PATCH 03/28] Remove redudant interface (#527) --- src/nameserver/nameserver_impl.cc | 6 +++--- src/nameserver/namespace.cc | 7 ++----- src/nameserver/namespace.h | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 8068b028..29ef9c6f 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1014,12 +1014,12 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, if (status != kLocked) { //TODO log remote? if (status == kUnlock) { - namespace_->LockDir(path); + namespace_->SetDirLockStatus(path, kLocked, request->uuid()); status = kOK; } // else status maybe kCleaning or kBadParameter } else { //TODO log remote - namespace_->SetDirLockStatus(kCleaning, path); + namespace_->SetDirLockStatus(path, kCleaning); status = kCleaning; } response->set_status(status); @@ -1040,7 +1040,7 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, StatusCode status = namespace_->GetDirLockStatus(path); if (status == kLocked) { //TODO log remote - namespace_->SetDirLockStatus(kCleaning, path); + namespace_->SetDirLockStatus(path, kCleaning); std::vector blocks; namespace_->ListAllBlocks(path, &blocks);; if (block_mapping_manager_->CheckBlocksClosed(blocks)) { diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 01e85c3c..5bbb9be9 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -881,7 +881,8 @@ StatusCode NameSpace::GetDirLockStatus(const std::string& path) { return kUnlock; } -void NameSpace::SetDirLockStatus(StatusCode status, const std::string& path) { +void NameSpace::SetDirLockStatus(const std::string& path, StatusCode status, + const std::string& uuid) { } @@ -889,10 +890,6 @@ void NameSpace::ListAllBlocks(const std::string& path, std::vector* res } -void NameSpace::LockDir(const std::string& path) { - -} - } // namespace bfs } // namespace baidu /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 90df2fe8..42e46e87 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -69,9 +69,9 @@ class NameSpace { void EraseNamespace(); int64_t GetNewBlockId(); StatusCode GetDirLockStatus(const std::string& path); - void SetDirLockStatus(StatusCode status, const std::string& path); + void SetDirLockStatus(const std::string& path, StatusCode status, + const std::string& uuid = ""); void ListAllBlocks(const std::string& path, std::vector* result); - void LockDir(const std::string& path); private: enum FileType { kDefault = 0, From b60b659d2f3e2f9fce754f036f15fb9279d57758 Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 9 Mar 2017 11:04:07 +0800 Subject: [PATCH 04/28] Fix indent (#527) --- src/nameserver/nameserver_impl.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 29ef9c6f..3d0c8013 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1000,9 +1000,9 @@ void NameServerImpl::ChangeReplicaNum(::google::protobuf::RpcController* control } void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, - const LockDirRequest* request, - LockDirResponse* response, - ::google::protobuf::Closure* done) { + const LockDirRequest* request, + LockDirResponse* response, + ::google::protobuf::Closure* done) { if (!is_leader_) { response->set_status(kIsFollower); done->Run(); @@ -1027,9 +1027,9 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, } void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, - const UnlockDirRequest* request, - UnlockDirResponse* response, - ::google::protobuf::Closure* done) { + const UnlockDirRequest* request, + UnlockDirResponse* response, + ::google::protobuf::Closure* done) { if (!is_leader_) { response->set_status(kIsFollower); done->Run(); From d4920ab0707651fec26e4f4bb9a8b9c172746ed2 Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 10:01:45 +0800 Subject: [PATCH 05/28] Check whether blocks closed in LockDir (#527) --- src/nameserver/nameserver_impl.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 3d0c8013..fda52b61 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1016,7 +1016,15 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, if (status == kUnlock) { namespace_->SetDirLockStatus(path, kLocked, request->uuid()); status = kOK; - } // else status maybe kCleaning or kBadParameter + } else if (status == kCleaning) { + std::vector blocks; + namespace_->ListAllBlocks(path, &blocks); + if (block_mapping_manager_->CheckBlocksClosed(blocks)) { + //TODO log remote + namespace_->SetDirLockStatus(path, kUnlock); + status = kOK; + } + } // else status should be kBadParameter } else { //TODO log remote namespace_->SetDirLockStatus(path, kCleaning); From 528a3f1e47ae11ef6964e2b02d45a87cdd44971d Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 10:55:36 +0800 Subject: [PATCH 06/28] Rename status code (#527) --- src/nameserver/nameserver_impl.cc | 22 +++++++++++----------- src/nameserver/namespace.cc | 2 +- src/proto/status_code.proto | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index fda52b61..a3c7d863 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1011,24 +1011,24 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); StatusCode status = namespace_->GetDirLockStatus(path); - if (status != kLocked) { + if (status != kDirLocked) { //TODO log remote? - if (status == kUnlock) { - namespace_->SetDirLockStatus(path, kLocked, request->uuid()); + if (status == kDirUnlock) { + namespace_->SetDirLockStatus(path, kDirLocked, request->uuid()); status = kOK; - } else if (status == kCleaning) { + } else if (status == kDirLockCleaning) { std::vector blocks; namespace_->ListAllBlocks(path, &blocks); if (block_mapping_manager_->CheckBlocksClosed(blocks)) { //TODO log remote - namespace_->SetDirLockStatus(path, kUnlock); + namespace_->SetDirLockStatus(path, kDirUnlock); status = kOK; } } // else status should be kBadParameter } else { //TODO log remote - namespace_->SetDirLockStatus(path, kCleaning); - status = kCleaning; + namespace_->SetDirLockStatus(path, kDirLockCleaning); + status = kDirLockCleaning; } response->set_status(status); done->Run(); @@ -1046,15 +1046,15 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); StatusCode status = namespace_->GetDirLockStatus(path); - if (status == kLocked) { + if (status == kDirLocked) { //TODO log remote - namespace_->SetDirLockStatus(path, kCleaning); + namespace_->SetDirLockStatus(path, kDirLockCleaning); std::vector blocks; namespace_->ListAllBlocks(path, &blocks);; if (block_mapping_manager_->CheckBlocksClosed(blocks)) { - status = kUnlock; + status = kDirUnlock; } else { - status = kCleaning; + status = kDirLockCleaning; } } response->set_status(status); diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 5bbb9be9..76c3db04 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -878,7 +878,7 @@ int64_t NameSpace::GetNewBlockId() { } StatusCode NameSpace::GetDirLockStatus(const std::string& path) { - return kUnlock; + return kDirUnlock; } void NameSpace::SetDirLockStatus(const std::string& path, StatusCode status, diff --git a/src/proto/status_code.proto b/src/proto/status_code.proto index f1752a57..d92a9f95 100644 --- a/src/proto/status_code.proto +++ b/src/proto/status_code.proto @@ -30,9 +30,9 @@ enum StatusCode { kSyncMetaFailed = 801; kSafeMode = 802; kServiceStop = 803; - kLocked = 804; - kUnlock = 805; - kCleaning = 806; + kDirLocked = 804; + kDirUnlock = 805; + kDirLockCleaning = 806; } enum ChunkServerStatus { From ee44333b391da63e5b4eae0b439a6ffb87df41f5 Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 11:00:59 +0800 Subject: [PATCH 07/28] Smallfix (#527) --- src/sdk/fs_impl.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index 384aa43c..58e9c684 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -415,10 +415,8 @@ int32_t FSImpl::LockDirectory(const char* path) { LockDirResponse response; request.set_dir_path(path); request.set_uuid(GetUUID()); - bool ret = true; - while ((ret = nameserver_client_->SendRequest(&NameServer_Stub::LockDir, - &request, &response, 15, 1)) != kOK || - response.status() != kOK) { + while (!nameserver_client_->SendRequest(&NameServer_Stub::LockDir, + &request, &response, 15, 1) || response.status() != kOK) { sleep(5); } assert(response.status() == kOK); From a094b6288f2e48de7340f5018935a4ca90ce70a2 Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 09:53:16 +0800 Subject: [PATCH 08/28] Add ListAllBlocks for namespace (#527) --- src/nameserver/namespace.cc | 37 +++++++++++++++++++++++++ src/nameserver/namespace.h | 1 + src/nameserver/test/namespace_test.cc | 40 +++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 76c3db04..4a32dda5 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -887,7 +887,44 @@ void NameSpace::SetDirLockStatus(const std::string& path, StatusCode status, } void NameSpace::ListAllBlocks(const std::string& path, std::vector* result) { + //TODO modify return value + FileInfo info; + if (!LookUp(path, &info)) { + return; + } + if (GetFileType(info.type()) == kDefault) { + for (int i = 0; i < info.blocks_size(); i++) { + result->push_back(info.blocks(i)); + } + return; + } + ListAllBlocks(info.entry_id(), result); +} +void NameSpace::ListAllBlocks(int64_t entry_id, std::vector* result) { + std::string key_start, key_end; + EncodingStoreKey(entry_id, "", &key_start); + EncodingStoreKey(entry_id + 1, "", &key_end); + leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions()); + for (it->Seek(key_start); it->Valid(); it->Next()) { + leveldb::Slice key = it->key(); + if (key.compare(key_end)>=0) { + break; + } + FileInfo info; + bool ret = + info.ParseFromArray(it->value().data(), it->value().size()); + assert(ret); + FileType type = GetFileType(info.type()); + if (type == kDefault) { + for (int i = 0; i < info.blocks_size(); i++) { + result->push_back(info.blocks(i)); + } + } else if (type == kDir){ + ListAllBlocks(info.entry_id(), result); + } + } + delete it; } } // namespace bfs diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 42e46e87..8eaf93e0 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -101,6 +101,7 @@ class NameSpace { const std::string& key, const std::string& value); void InitBlockIdUpbound(NameServerLog* log); void UpdateBlockIdUpbound(NameServerLog* log); + void ListAllBlocks(int64_t entry_id, std::vector* result); private: leveldb::DB* db_; /// NameSpace storage leveldb::Cache* db_cache_; // block cache for leveldb diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 8efaa9e7..58e77d14 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -363,6 +363,46 @@ TEST_F(NameSpaceTest, GetNewBlockId) { system("rm -rf ./db"); } +TEST_F(NameSpaceTest, ListAllBlocks) { + system("rm -rf ./db"); + std::vector blocks_to_remove; + NameSpace ns; + ns.CreateFile("/abc", 0, 01755, -1, &blocks_to_remove); + ns.CreateFile("/abc/def", 0, 0, -1, &blocks_to_remove); + ns.CreateFile("/abc/ghi", 0, 0, -1, &blocks_to_remove); + FileInfo info; + ns.GetFileInfo("/abc/def", &info); + ASSERT_EQ(info.blocks_size(), 0); + info.add_blocks(ns.GetNewBlockId()); + ns.UpdateFileInfo(info, NULL); + ns.GetFileInfo("/abc/ghi", &info); + info.add_blocks(ns.GetNewBlockId()); + ns.UpdateFileInfo(info, NULL); + std::vector all_blocks; + ns.ListAllBlocks("/abc", &all_blocks); + ASSERT_EQ(all_blocks.size(), 2); + ns.CreateFile("/abc/jkl/mno", 0, 0, -1, &blocks_to_remove); + ns.GetFileInfo("abc/jkl/mno", &info); + info.add_blocks(ns.GetNewBlockId()); + ns.UpdateFileInfo(info, NULL); + all_blocks.clear(); + ns.ListAllBlocks("/abc", &all_blocks); + ASSERT_EQ(all_blocks.size(), 3); + all_blocks.clear(); + ns.ListAllBlocks("/", &all_blocks); + ASSERT_EQ(all_blocks.size(), 3); + all_blocks.clear(); + ns.ListAllBlocks("/abc/def", &all_blocks); + ASSERT_EQ(all_blocks.size(), 1); + all_blocks.clear(); + ns.GetFileInfo("/abc/def", &info); + info.add_blocks(ns.GetNewBlockId()); + ns.UpdateFileInfo(info, NULL); + ns.ListAllBlocks("/abc/def", &all_blocks); + ASSERT_EQ(all_blocks.size(), 2); + system("rm -rf ./db"); +} + } } From 526afbb5503a4c6a12514d035a2315537e06c587 Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 10:26:19 +0800 Subject: [PATCH 09/28] Add CheckBlocksClosed for BlockMapping (#527) --- src/nameserver/block_mapping.cc | 10 ++++++++++ src/nameserver/block_mapping.h | 1 + src/nameserver/block_mapping_manager.cc | 7 +++++++ 3 files changed, 18 insertions(+) diff --git a/src/nameserver/block_mapping.cc b/src/nameserver/block_mapping.cc index 1cdb9e1b..eb8e3ded 100644 --- a/src/nameserver/block_mapping.cc +++ b/src/nameserver/block_mapping.cc @@ -969,5 +969,15 @@ void BlockMapping::MarkIncomplete(int64_t block_id) { } } +RecoverStat BlockMapping::GetRecoverStat(int64_t block_id) { + MutexLock lock(&mu_); + NSBlock* block = NULL; + if (!GetBlockPtr(block_id, &block)) { + return kAny; + } else { + return block->recover_stat; + } +} + } // namespace bfs } // namespace baidu diff --git a/src/nameserver/block_mapping.h b/src/nameserver/block_mapping.h index b18a1de8..4083f391 100644 --- a/src/nameserver/block_mapping.h +++ b/src/nameserver/block_mapping.h @@ -81,6 +81,7 @@ class BlockMapping { void ListRecover(RecoverBlockSet* blocks); int32_t GetCheckNum(); void MarkIncomplete(int64_t block_id); + RecoverStat GetRecoverStat(int64_t block_id); private: void DealWithDeadBlockInternal(int32_t cs_id, int64_t block_id); typedef std::map > CheckList; diff --git a/src/nameserver/block_mapping_manager.cc b/src/nameserver/block_mapping_manager.cc index ebe0e99d..eecd521d 100644 --- a/src/nameserver/block_mapping_manager.cc +++ b/src/nameserver/block_mapping_manager.cc @@ -160,6 +160,13 @@ void BlockMappingManager::MarkIncomplete(int64_t block_id) { } bool BlockMappingManager::CheckBlocksClosed(const std::vector& blocks) { + for (auto it = blocks.begin(); it != blocks.end(); ++it) { + int32_t bucket_offset = GetBucketOffset(*it); + RecoverStat stat = block_mapping_[bucket_offset]->GetRecoverStat(*it); + if (stat == kBlockWriting || stat == kIncomplete) { + return false; + } + } return true; } From 90fb30e6524dcce90d210f8e0593d4709dd24bd3 Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 17:03:17 +0800 Subject: [PATCH 10/28] Add GetUUID and ut for CheckBlocksClosed (#527) --- Makefile | 13 ++++++++++++- src/nameserver/test/block_mapping_test.cc | 21 +++++++++++++++++++++ src/sdk/fs_impl.cc | 4 +++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 3b615798..0e1507f5 100644 --- a/Makefile +++ b/Makefile @@ -80,11 +80,13 @@ endif ifdef FUSE_LL_PATH BIN += bfs_ll_mount endif -TESTS = namespace_test block_mapping_test location_provider_test logdb_test \ +TESTS = namespace_test block_mapping_test \ + block_mapping_manager_test location_provider_test logdb_test \ file_lock_manager_test file_lock_test chunkserver_impl_test \ file_cache_test block_manager_test data_block_test TEST_OBJS = src/nameserver/test/namespace_test.o \ src/nameserver/test/block_mapping_test.o \ + src/nameserver/test/block_mapping_manager_test.o \ src/nameserver/test/logdb_test.o \ src/nameserver/test/location_provider_test.o \ src/nameserver/test/kv_client.o \ @@ -137,6 +139,15 @@ block_mapping_test: src/nameserver/test/block_mapping_test.o src/nameserver/bloc $(CXX) src/nameserver/block_mapping.o src/nameserver/test/block_mapping_test.o \ src/nameserver/block_mapping_manager.o $(OBJS) -o $@ $(LDFLAGS) +block_mapping_manager_test: src/nameserver/test/block_mapping_manager_test.o \ + src/nameserver/block_mapping_manager.o \ + src/nameserver/block_mapping.o + $(CXX) src/nameserver/block_mapping.o \ + src/nameserver/block_mapping_manager.o \ + src/nameserver/test/block_mapping_manager_test.o \ + $(OBJS) -o $@ $(LDFLAGS) + + logdb_test: src/nameserver/test/logdb_test.o src/nameserver/logdb.o $(CXX) src/nameserver/logdb.o src/nameserver/test/logdb_test.o $(OBJS) -o $@ $(LDFLAGS) diff --git a/src/nameserver/test/block_mapping_test.cc b/src/nameserver/test/block_mapping_test.cc index d2deda8f..77ef2432 100644 --- a/src/nameserver/test/block_mapping_test.cc +++ b/src/nameserver/test/block_mapping_test.cc @@ -126,6 +126,27 @@ TEST_F(BlockMappingTest, NotRecoverEmptyBlock) { ASSERT_TRUE(bm->lost_blocks_.empty()); } +TEST_F(BlockMappingTest, GetRecoverStat) { + int64_t block_id = 1; + int64_t block_version = 0; + int64_t block_size = 0; + int32_t replica = 3; + BlockMapping* bm = new BlockMapping(&thread_pool); + bm->RebuildBlock(block_id, replica, block_version, block_size); + int32_t cs1 = 23; + int32_t cs2 = 45; + int32_t cs3 = 67; + bool ret = + bm->UpdateBlockInfo(block_id, cs1, block_size, block_version) && + bm->UpdateBlockInfo(block_id, cs2, block_size, block_version); + ASSERT_TRUE(ret); + RecoverStat stat = bm->GetRecoverStat(block_id); + ASSERT_EQ(stat, kBlockWriting); + bm->UpdateBlockInfo(block_id, cs3, block_size, block_version); + stat = bm->GetRecoverStat(block_id); + ASSERT_EQ(stat, kNotInRecover); +} + } // namespace bfs } // namespace baidu diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index 58e9c684..12151311 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -583,7 +583,9 @@ bool FS::OpenFileSystem(const char* nameserver, FS** fs, const FSOptions&) { } const std::string& FSImpl::GetUUID() { - static std::string uuid; + static std::string uuid = common::util::GetLocalHostName() + ":" + + common::NumToString(getpid()) + ":" + + common::NumToString(common::timer::now_time()); return uuid; } From 638e070c43148e13a294554e0a951ed79eac52ce Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 13 Mar 2017 19:15:34 +0800 Subject: [PATCH 11/28] Add Get/SetDirLockStatus (#527) --- src/nameserver/namespace.cc | 46 ++++++++++++++++++++++++++++++++----- src/nameserver/namespace.h | 2 +- src/proto/file.proto | 3 +++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 4a32dda5..3a5d3c40 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -878,12 +878,46 @@ int64_t NameSpace::GetNewBlockId() { } StatusCode NameSpace::GetDirLockStatus(const std::string& path) { - return kDirUnlock; + FileInfo info; + if (!LookUp(path, &info)) { + return kNsNotFound; + } else if (GetFileType(info.type()) != kDir) { + return kBadParameter; + } else { + return info.dir_lock_stat(); + } } -void NameSpace::SetDirLockStatus(const std::string& path, StatusCode status, - const std::string& uuid) { - +StatusCode NameSpace::SetDirLockStatus(const std::string& path, + StatusCode status, + const std::string& uuid) { + std::vector paths; + common::util::SplitPath(path, &paths); + int64_t entry_id = kRootEntryid; + std::string file_key; + FileInfo info; + for (size_t i = 0; i < paths.size() - 1; i++) { + EncodingStoreKey(entry_id, paths[i], &file_key); + bool r = GetFromStore(file_key, &info); + if (!r) { + return kNsNotFound; + } + // all the parent directories should be clear + if (info.dir_lock_stat() != kDirLocked) { + return kNoPermission; + } + entry_id = info.entry_id(); + } + EncodingStoreKey(entry_id, paths[paths.size() - 1], &file_key); + bool r = GetFromStore(file_key, &info); + if (!r) { + return kNsNotFound; + } + info.set_dir_lock_stat(status); + std::string info_buf; + info.SerializeToString(&info_buf); + db_->Put(leveldb::WriteOptions(), file_key, info_buf); + return kOK; } void NameSpace::ListAllBlocks(const std::string& path, std::vector* result) { @@ -912,8 +946,8 @@ void NameSpace::ListAllBlocks(int64_t entry_id, std::vector* result) { break; } FileInfo info; - bool ret = - info.ParseFromArray(it->value().data(), it->value().size()); + bool ret = GetFromStore( + std::string(it->value().data(), it->value().size()), &info); assert(ret); FileType type = GetFileType(info.type()); if (type == kDefault) { diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 8eaf93e0..664fbb24 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -69,7 +69,7 @@ class NameSpace { void EraseNamespace(); int64_t GetNewBlockId(); StatusCode GetDirLockStatus(const std::string& path); - void SetDirLockStatus(const std::string& path, StatusCode status, + StatusCode SetDirLockStatus(const std::string& path, StatusCode status, const std::string& uuid = ""); void ListAllBlocks(const std::string& path, std::vector* result); private: diff --git a/src/proto/file.proto b/src/proto/file.proto index c8205358..8bd0afb7 100644 --- a/src/proto/file.proto +++ b/src/proto/file.proto @@ -1,3 +1,5 @@ +import "status_code.proto"; + package baidu.bfs; message FileInfo { @@ -13,5 +15,6 @@ message FileInfo { optional int32 owner = 10; repeated string cs_addrs = 11; optional string sym_link = 12; + optional StatusCode dir_lock_stat = 13 [default = kDirUnlock]; } From 4647fd127fce4e7387ec6c2f89ee5d630218deac Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 14 Mar 2017 17:09:16 +0800 Subject: [PATCH 12/28] Bugfix for ListAllBlocks & SetDirLockStatus (#527) --- src/nameserver/namespace.cc | 8 ++++---- src/nameserver/namespace.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 3a5d3c40..7d96dd81 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -903,7 +903,7 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, return kNsNotFound; } // all the parent directories should be clear - if (info.dir_lock_stat() != kDirLocked) { + if (info.dir_lock_stat() != kDirUnlock) { return kNoPermission; } entry_id = info.entry_id(); @@ -945,10 +945,10 @@ void NameSpace::ListAllBlocks(int64_t entry_id, std::vector* result) { if (key.compare(key_end)>=0) { break; } + std::string info_buf; + leveldb::Status s = db_->Get(leveldb::ReadOptions(), key, &info_buf); FileInfo info; - bool ret = GetFromStore( - std::string(it->value().data(), it->value().size()), &info); - assert(ret); + info.ParseFromString(info_buf); FileType type = GetFileType(info.type()); if (type == kDefault) { for (int i = 0; i < info.blocks_size(); i++) { diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 664fbb24..66412ed2 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -70,7 +70,7 @@ class NameSpace { int64_t GetNewBlockId(); StatusCode GetDirLockStatus(const std::string& path); StatusCode SetDirLockStatus(const std::string& path, StatusCode status, - const std::string& uuid = ""); + const std::string& uuid = ""); void ListAllBlocks(const std::string& path, std::vector* result); private: enum FileType { From d9f4e30b8724ae1ba29fa628e4797fde1d1b8b99 Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 14 Mar 2017 17:10:11 +0800 Subject: [PATCH 13/28] Add ut for Get/SetDirLockStatus (#527) --- src/nameserver/test/namespace_test.cc | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 58e77d14..164c296b 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -403,6 +403,38 @@ TEST_F(NameSpaceTest, ListAllBlocks) { system("rm -rf ./db"); } +TEST_F(NameSpaceTest, GetAndSetDirLockStatus) { + system("rm -rf ./db"); + NameSpace ns; + std::vector blocks_to_remove; + std::string path0("/abc"); + ns.CreateFile(path0, 0, 01755, -1, &blocks_to_remove); + StatusCode status = ns.GetDirLockStatus(path0); + ASSERT_EQ(status, kDirUnlock); + status = ns.SetDirLockStatus(path0, kDirLocked); + ASSERT_EQ(status, kOK); + status = ns.GetDirLockStatus(path0); + ASSERT_EQ(status, kDirLocked); + + std::string path1("/def"); + status = ns.GetDirLockStatus(path1); + ASSERT_EQ(status, kNsNotFound); + + std::string path2("/abc/ghi"); + ns.CreateFile(path2, 0, 01755, -1, &blocks_to_remove); + status = ns.GetDirLockStatus(path2); + ASSERT_EQ(status, kDirLocked); + status = ns.SetDirLockStatus(path2, kDirLocked); + ASSERT_EQ(status, kNoPermission); + + status = ns.SetDirLockStatus(path0, kDirLockCleaning); + ASSERT_EQ(status, kOK); + status = ns.GetDirLockStatus(path0); + ASSERT_EQ(status, kDirLockCleaning); + + system("rm -rf ./db"); +} + } } From 2109206a26343f097962cb2dab6d4e63e0cf6f89 Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 14 Mar 2017 17:35:39 +0800 Subject: [PATCH 14/28] Add log (#527) --- src/nameserver/nameserver_impl.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index a3c7d863..2e316bcf 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1011,17 +1011,23 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); StatusCode status = namespace_->GetDirLockStatus(path); + LOG(INFO, "%s try lock dir %s", request->uuid().c_str(), path.c_str()); if (status != kDirLocked) { //TODO log remote? if (status == kDirUnlock) { namespace_->SetDirLockStatus(path, kDirLocked, request->uuid()); + LOG(INFO, "%s lock dir %s", + request->uuid().c_str(), path.c_str()); status = kOK; } else if (status == kDirLockCleaning) { std::vector blocks; namespace_->ListAllBlocks(path, &blocks); if (block_mapping_manager_->CheckBlocksClosed(blocks)) { //TODO log remote - namespace_->SetDirLockStatus(path, kDirUnlock); + namespace_->SetDirLockStatus(path, kDirUnlock, + request->uuid()); + LOG(INFO, "%s lock dir %s", + request->uuid().c_str(), path.c_str()); status = kOK; } } // else status should be kBadParameter From b741c65c3b52c311106784d161b868c73a824d0f Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 14 Mar 2017 17:54:56 +0800 Subject: [PATCH 15/28] Use GetFromStore (#527) --- src/nameserver/namespace.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 7d96dd81..90be9bf8 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -945,10 +945,8 @@ void NameSpace::ListAllBlocks(int64_t entry_id, std::vector* result) { if (key.compare(key_end)>=0) { break; } - std::string info_buf; - leveldb::Status s = db_->Get(leveldb::ReadOptions(), key, &info_buf); FileInfo info; - info.ParseFromString(info_buf); + GetFromStore(std::string(key.data(), key.size()), &info); FileType type = GetFileType(info.type()); if (type == kDefault) { for (int i = 0; i < info.blocks_size(); i++) { From fcda9a2f4c0a395e0488a230c712325ed76ae669 Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 15 Mar 2017 10:11:47 +0800 Subject: [PATCH 16/28] Record lock holder in FileInfo (#527) --- src/nameserver/namespace.cc | 3 +++ src/proto/file.proto | 1 + 2 files changed, 4 insertions(+) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 90be9bf8..34da8e2a 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -914,6 +914,9 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, return kNsNotFound; } info.set_dir_lock_stat(status); + if (status == kDirLockCleaning) { + info.set_dir_lock_holder_uuid(""); + } std::string info_buf; info.SerializeToString(&info_buf); db_->Put(leveldb::WriteOptions(), file_key, info_buf); diff --git a/src/proto/file.proto b/src/proto/file.proto index 8bd0afb7..1f523d25 100644 --- a/src/proto/file.proto +++ b/src/proto/file.proto @@ -16,5 +16,6 @@ message FileInfo { repeated string cs_addrs = 11; optional string sym_link = 12; optional StatusCode dir_lock_stat = 13 [default = kDirUnlock]; + optional string dir_lock_holder_uuid = 14; } From 7f38c4e47b9ff9f609a50effa5fd340c9becf3b2 Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 15 Mar 2017 16:03:05 +0800 Subject: [PATCH 17/28] Check dir lock when create or delete file (#527) --- src/nameserver/nameserver_impl.cc | 12 ++-- src/nameserver/namespace.cc | 102 ++++++++++++++++++++++++++---- src/nameserver/namespace.h | 20 ++++-- 3 files changed, 114 insertions(+), 20 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 2e316bcf..c5853259 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -386,7 +386,9 @@ void NameServerImpl::CreateFile(::google::protobuf::RpcController* controller, NameServerLog log; std::vector blocks_to_remove; FileLockGuard file_lock(new WriteLock(path)); - StatusCode status = namespace_->CreateFile(path, flags, mode, replica_num, &blocks_to_remove, &log); + StatusCode status = + namespace_->CreateFile(path, flags, mode, + replica_num, &blocks_to_remove, "", &log); for (size_t i = 0; i < blocks_to_remove.size(); i++) { block_mapping_manager_->RemoveBlock(blocks_to_remove[i]); } @@ -781,7 +783,8 @@ void NameServerImpl::Rename(::google::protobuf::RpcController* controller, FileInfo remove_file; NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(oldpath, newpath)); - StatusCode status = namespace_->Rename(oldpath, newpath, &need_unlink, &remove_file, &log); + StatusCode status = namespace_->Rename(oldpath, newpath, &need_unlink, + &remove_file, "", &log); response->set_status(status); if (status != kOK) { done->Run(); @@ -846,7 +849,7 @@ void NameServerImpl::Unlink(::google::protobuf::RpcController* controller, FileInfo file_info; NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(path)); - StatusCode status = namespace_->RemoveFile(path, &file_info, &log); + StatusCode status = namespace_->RemoveFile(path, &file_info, "", &log); sofa::pbrpc::RpcController* ctl = reinterpret_cast(controller); LOG(INFO, "Sdk %s unlink file %s returns %s", ctl->RemoteAddress().c_str(), path.c_str(), StatusCode_Name(status).c_str()); @@ -907,7 +910,8 @@ void NameServerImpl::DeleteDirectory(::google::protobuf::RpcController* controll std::vector* removed = new std::vector; NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(path)); - StatusCode ret_status = namespace_->DeleteDirectory(path, recursive, removed, &log); + StatusCode ret_status = namespace_->DeleteDirectory(path, recursive, + removed, "", &log); sofa::pbrpc::RpcController* ctl = reinterpret_cast(controller); LOG(INFO, "Sdk %s delete directory %s returns %s", ctl->RemoteAddress().c_str(), path.c_str(), StatusCode_Name(ret_status).c_str()); diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 34da8e2a..ddfa56c0 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -251,7 +251,8 @@ bool NameSpace::GetFileInfo(const std::string& path, FileInfo* file_info) { return true; } -StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, std::string* fname, +StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, + std::string* fname, const std::string& uuid, NameServerLog* log) { std::vector paths; if (!common::util::SplitPath(path, &paths)) { @@ -281,6 +282,16 @@ StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, st if (GetFileType(file_info->type()) != kDir) { LOG(INFO, "Create path fail: %s is not a directory", paths[i].c_str()); return kBadParameter; + } else { + StatusCode lock_stat = file_info->dir_lock_stat(); + if (lock_stat == kDirLocked) { + if (uuid != file_info->dir_lock_holder_uuid()) { + LOG(INFO, "%s create path fail: %s is locked by %s", + uuid.c_str(), paths[i].c_str(), + file_info->dir_lock_holder_uuid().c_str()); + return kNoPermission; + } + } } } parent_id = file_info->entry_id(); @@ -289,14 +300,17 @@ StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, st return kOK; } -StatusCode NameSpace::CreateFile(const std::string& file_name, int flags, int mode, int replica_num, - std::vector* blocks_to_remove, NameServerLog* log) { +StatusCode NameSpace::CreateFile(const std::string& file_name, int flags, + int mode, int replica_num, + std::vector* blocks_to_remove, + const std::string& uuid, + NameServerLog* log) { if (file_name == "/") { return kBadParameter; } FileInfo file_info; std::string fname, info_value; - StatusCode status = BuildPath(file_name, &file_info, &fname, log); + StatusCode status = BuildPath(file_name, &file_info, &fname, uuid, log); if (status != kOK) { return status; } @@ -381,6 +395,7 @@ StatusCode NameSpace::Rename(const std::string& old_path, const std::string& new_path, bool* need_unlink, FileInfo* remove_file, + const std::string& uuid, NameServerLog* log) { *need_unlink = false; if (old_path == "/" || new_path == "/" || old_path == new_path) { @@ -410,6 +425,10 @@ StatusCode NameSpace::Rename(const std::string& old_path, old_path.c_str(), new_path.c_str(), new_paths[i].c_str()); return kBadParameter; } + if (path_file.dir_lock_stat() == kDirLocked && + path_file.dir_lock_holder_uuid() != uuid) { + return kNoPermission; + } if (path_file.entry_id() == old_file.entry_id()) { LOG(INFO, "Rename %s to %s fail: %s is the parent directory of %s", old_path.c_str(), new_path.c_str(), old_path.c_str(), @@ -426,7 +445,8 @@ StatusCode NameSpace::Rename(const std::string& old_path, FileInfo dst_file; if (LookUp(parent_id, dst_name, &dst_file)) { // if dst_file exists, type of both dst_file and old_file must be file - if ((GetFileType(dst_file.type()) == kDir) || (GetFileType(old_file.type()) == kDir)) { + if ((GetFileType(dst_file.type()) == kDir) || + (GetFileType(old_file.type()) == kDir)) { LOG(INFO, "Rename %s to %s, src %o or dst %o is not a file", old_path.c_str(), new_path.c_str(), old_file.type(), dst_file.type()); @@ -487,7 +507,7 @@ StatusCode NameSpace::Symlink(const std::string& src, const std::string& dst, Na } std::string fname, info_value; - StatusCode status = BuildPath(dst, &file_info, &fname, log); + StatusCode status = BuildPath(dst, &file_info, &fname, "", log); if (status != kOK) { return status; } @@ -516,16 +536,29 @@ StatusCode NameSpace::Symlink(const std::string& src, const std::string& dst, Na } } -StatusCode NameSpace::RemoveFile(const std::string& path, FileInfo* file_removed, NameServerLog* log) { +StatusCode NameSpace::RemoveFile(const std::string& path, + FileInfo* file_removed, + const std::string& uuid, + NameServerLog* log) { + if (path == "/") { + return kBadParameter; + } + std::string parent_path(path, 0, path.find_last_of("/") + 1); + FileInfo parent_info; + if (!CheckDirLockPermission(parent_path, uuid, &parent_info)) { + return kNoPermission; + } + std::string file_name(path, path.find_last_of("/") + 1, + path.size() - path.find_last_of("/") + 1); StatusCode ret_status = kOK; - if (LookUp(path, file_removed)) { + if (LookUp(parent_info.entry_id(), file_name, file_removed)) { // Only support file if (GetFileType(file_removed->type()) != kDir) { if (path == "/" || path.empty()) { LOG(INFO, "root type= %d", file_removed->type()); } std::string file_key; - EncodingStoreKey(file_removed->parent_entry_id(), file_removed->name(), &file_key); + EncodingStoreKey(parent_info.entry_id(), file_name, &file_key); if (DeleteFileInfo(file_key, log)) { LOG(INFO, "Unlink done: %s\n", path.c_str()); ret_status = kOK; @@ -593,7 +626,9 @@ StatusCode NameSpace::InternalComputeDiskUsage(const FileInfo& info, uint64_t* d } StatusCode NameSpace::DeleteDirectory(const std::string& path, bool recursive, - std::vector* files_removed, NameServerLog* log) { + std::vector* files_removed, + const std::string& uuid, + NameServerLog* log) { files_removed->clear(); FileInfo info; if (!LookUp(path, &info)) { @@ -602,6 +637,9 @@ StatusCode NameSpace::DeleteDirectory(const std::string& path, bool recursive, } else if (GetFileType(info.type()) != kDir) { LOG(INFO, "Delete Directory, %s %d is not a dir.", path.c_str(), info.type()); return kBadParameter; + } else if (info.dir_lock_stat() == kDirLocked && + info.dir_lock_holder_uuid() != uuid) { + return kNoPermission; } return InternalDeleteDirectory(info, recursive, files_removed, log); } @@ -903,7 +941,7 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, return kNsNotFound; } // all the parent directories should be clear - if (info.dir_lock_stat() != kDirUnlock) { + if (info.dir_lock_stat() == kDirLocked) { return kNoPermission; } entry_id = info.entry_id(); @@ -962,6 +1000,48 @@ void NameSpace::ListAllBlocks(int64_t entry_id, std::vector* result) { delete it; } +bool NameSpace::CheckDirLockPermission(const std::string& path, + const std::string& uuid, + FileInfo* info) { + if (path == "/") { + StatusCode status = root_path_.dir_lock_stat(); + if (status == kDirLocked && uuid != root_path_.dir_lock_holder_uuid()) { + return false; + } else if (status == kDirLockCleaning) { + return false; + } + *info = root_path_; + return true; + } + std::vector paths; + common::util::SplitPath(path, &paths); + int64_t entry_id = kRootEntryid; + for (size_t i = 0; i < paths.size(); i++) { + std::string file_key; + EncodingStoreKey(entry_id, paths[i], &file_key); + if(!GetFromStore(file_key, info)) { + return false; + } else { + if (GetFileType(info->type()) == kDir) { + StatusCode status = info->dir_lock_stat(); + if (status == kDirLocked && + info->dir_lock_holder_uuid() != uuid) { + LOG(INFO, "No permission, %s is lock by %s", + paths[i].c_str(), + info->dir_lock_holder_uuid().c_str()); + return false; + } else if (status == kDirLockCleaning) { + LOG(INFO, "No permission, %s dir lock is being cleaning", + paths[i].c_str()); + return false; + } + } + entry_id = info->entry_id(); + } + } + return true; +} + } // namespace bfs } // namespace baidu /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 66412ed2..6b18329b 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -32,19 +32,25 @@ class NameSpace { google::protobuf::RepeatedPtrField* outputs); /// Create file by name StatusCode CreateFile(const std::string& file_name, int flags, int mode, - int replica_num, std::vector* blocks_to_remove, + int replica_num, + std::vector* blocks_to_remove, + const std::string& uuid = "", NameServerLog* log = NULL); /// Remove file by name - StatusCode RemoveFile(const std::string& path, FileInfo* file_removed, NameServerLog* log = NULL); + StatusCode RemoveFile(const std::string& path, FileInfo* file_removed, + const std::string& uuid = "", NameServerLog* log = NULL); /// Remove director. StatusCode DeleteDirectory(const std::string& path, bool recursive, - std::vector* files_removed, NameServerLog* log = NULL); + std::vector* files_removed, + const std::string& uuid = "", + NameServerLog* log = NULL); StatusCode DiskUsage(const std::string& path, uint64_t* du_size); /// File rename StatusCode Rename(const std::string& old_path, const std::string& new_path, bool* need_unlink, FileInfo* remove_file, + const std::string& uuid = "", NameServerLog* log = NULL); /// Symlink: dst -> src StatusCode Symlink(const std::string& src, @@ -80,8 +86,9 @@ class NameSpace { }; FileType GetFileType(int type) const; bool GetLinkSrcPath(const FileInfo& info, FileInfo* src_info); - StatusCode BuildPath(const std::string& path, FileInfo* file_info, std::string* fname, - NameServerLog* log = NULL); + StatusCode BuildPath(const std::string& path, FileInfo* file_info, + std::string* fname, const std::string& uuid = "", + NameServerLog* log = NULL); static void EncodingStoreKey(int64_t entry_id, const std::string& path, std::string* key_str); @@ -102,6 +109,9 @@ class NameSpace { void InitBlockIdUpbound(NameServerLog* log); void UpdateBlockIdUpbound(NameServerLog* log); void ListAllBlocks(int64_t entry_id, std::vector* result); + bool CheckDirLockPermission(const std::string& path, + const std::string& uuid, + FileInfo* info); private: leveldb::DB* db_; /// NameSpace storage leveldb::Cache* db_cache_; // block cache for leveldb From 8a74dd0e81cec049086032263484fc4d6dd2f20b Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 15 Mar 2017 17:07:28 +0800 Subject: [PATCH 18/28] Add ut for Rename (#527) --- src/nameserver/namespace.cc | 11 ++++++++--- src/nameserver/test/namespace_test.cc | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index ddfa56c0..b464303e 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -283,9 +283,8 @@ StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, LOG(INFO, "Create path fail: %s is not a directory", paths[i].c_str()); return kBadParameter; } else { - StatusCode lock_stat = file_info->dir_lock_stat(); - if (lock_stat == kDirLocked) { - if (uuid != file_info->dir_lock_holder_uuid()) { + if (file_info->dir_lock_stat() == kDirLocked && + file_info->dir_lock_holder_uuid() != uuid) { LOG(INFO, "%s create path fail: %s is locked by %s", uuid.c_str(), paths[i].c_str(), file_info->dir_lock_holder_uuid().c_str()); @@ -406,6 +405,11 @@ StatusCode NameSpace::Rename(const std::string& old_path, LOG(INFO, "Rename not found: %s\n", old_path.c_str()); return kNsNotFound; } + if (GetFileType(old_file.type()) == kDir && + old_file.dir_lock_stat() == kDirLocked && + old_file.dir_lock_holder_uuid() != uuid) { + return kNoPermission; + } std::vector new_paths; if (!common::util::SplitPath(new_path, &new_paths) || new_paths.empty()) { @@ -465,6 +469,7 @@ StatusCode NameSpace::Rename(const std::string& old_path, std::string new_key; EncodingStoreKey(parent_id, dst_name, &new_key); std::string value; + // if dst is a directory, the dir lock info will be kept old_file.set_parent_entry_id(parent_id); old_file.set_name(dst_name); old_file.SerializeToString(&value); diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 164c296b..0657d077 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -228,6 +228,28 @@ TEST_F(NameSpaceTest, Rename) { ASSERT_EQ(kOK, ns.Rename("/file2", "/link", &need_unlink, &remove_file)); ASSERT_FALSE(need_unlink); + /// rename dir which parent protected by dir lock + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLocked, "uuid0")); + ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2", "/home/dir2_lock", + &need_unlink, &remove_file, "uuid1")); + ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2", "/home/dir2_lock", + &need_unlink, &remove_file, "uuid0")); + + /// rename dir after dir lock removed + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); + ASSERT_EQ(kOK, ns.Rename("/home/dir2", "/home/dir2_lock", + &need_unlink, &remove_file, "uuid1")); + + /// rename dir protected by dir lock + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLocked, "uuid0")); + ASSERT_EQ(kNoPermission, ns.Rename("/home", "/home1", + &need_unlink, &remove_file, "uuid1")); + ASSERT_EQ(kNoPermission, ns.Rename("/home", "/home1", + &need_unlink, &remove_file, "uuid0")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); + ASSERT_EQ(kOK, ns.Rename("/home", "/home1", + &need_unlink, &remove_file, "uuid0")); + ASSERT_EQ(kDirLockCleaning, ns.GetDirLockStatus("/home1")); } TEST_F(NameSpaceTest, RemoveFile) { From bd17d009a406f599e0e821867ff65237944c35dc Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 15 Mar 2017 20:01:01 +0800 Subject: [PATCH 19/28] Record uuid for dir lock & fix ut (#527) --- src/nameserver/namespace.cc | 3 ++- src/nameserver/test/namespace_test.cc | 28 +++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index b464303e..09b1f01f 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -289,7 +289,6 @@ StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, uuid.c_str(), paths[i].c_str(), file_info->dir_lock_holder_uuid().c_str()); return kNoPermission; - } } } } @@ -959,6 +958,8 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, info.set_dir_lock_stat(status); if (status == kDirLockCleaning) { info.set_dir_lock_holder_uuid(""); + } else if (status == kDirLocked) { + info.set_dir_lock_holder_uuid(uuid); } std::string info_buf; info.SerializeToString(&info_buf); diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 0657d077..18333fa6 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -133,6 +133,10 @@ TEST_F(NameSpaceTest, CreateFile) { ASSERT_EQ(kOK, ns.CreateFile("/dir1/subdir2/file3", 0, 01755, -1, &blocks_to_remove)); ASSERT_EQ(kBadParameter, ns.CreateFile("/", 0, 01755, -1, &blocks_to_remove)); ASSERT_EQ(kBadParameter, ns.CreateFile("/", 0, 0, -1, &blocks_to_remove)); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir1/subdir1", kDirLocked, "uuid0")); + /* ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove, "uuid1")); */ + ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove)); + system("rm -rf ./db"); } TEST_F(NameSpaceTest, List) { @@ -152,7 +156,10 @@ TEST_F(NameSpaceTest, List) { } TEST_F(NameSpaceTest, Symlink) { + FLAGS_namedb_path = "./db"; + system("rm -rf ./db"); NameSpace ns; + ASSERT_TRUE(CreateTree(&ns)); std::vector blocks_to_remove; /// link -> file ASSERT_EQ(kOK, ns.Symlink("/dir1/subdir1/file3", "/link3")); @@ -166,10 +173,14 @@ TEST_F(NameSpaceTest, Symlink) { ASSERT_EQ(kFileExists, ns.Symlink("/file1", "/file1")); /// none -> link ASSERT_EQ(kNsNotFound, ns.Symlink("/file000", "/link5")); + system("rm -rf ./db"); } TEST_F(NameSpaceTest, Rename) { + FLAGS_namedb_path = "./db"; + system("rm -rf ./db"); NameSpace ns; + ASSERT_TRUE(CreateTree(&ns)); bool need_unlink; FileInfo remove_file; /// self -> self @@ -222,7 +233,7 @@ TEST_F(NameSpaceTest, Rename) { /// link A -> link B - ASSERT_EQ(kOK, ns.Rename("/link4", "/link", &need_unlink, &remove_file)); + ASSERT_EQ(kOK, ns.Rename("/link2", "/link4", &need_unlink, &remove_file)); ASSERT_FALSE(need_unlink); /// fileA -> fileB, B is link ASSERT_EQ(kOK, ns.Rename("/file2", "/link", &need_unlink, &remove_file)); @@ -232,24 +243,25 @@ TEST_F(NameSpaceTest, Rename) { ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLocked, "uuid0")); ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2", "/home/dir2_lock", &need_unlink, &remove_file, "uuid1")); - ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2", "/home/dir2_lock", - &need_unlink, &remove_file, "uuid0")); + ASSERT_EQ(kOK, ns.Rename("/home/dir2", "/home/dir2_lock", + &need_unlink, &remove_file, "uuid0")); /// rename dir after dir lock removed ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); - ASSERT_EQ(kOK, ns.Rename("/home/dir2", "/home/dir2_lock", + ASSERT_EQ(kOK, ns.Rename("/home/dir2_lock", "/home/dir2", &need_unlink, &remove_file, "uuid1")); /// rename dir protected by dir lock ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLocked, "uuid0")); ASSERT_EQ(kNoPermission, ns.Rename("/home", "/home1", &need_unlink, &remove_file, "uuid1")); - ASSERT_EQ(kNoPermission, ns.Rename("/home", "/home1", - &need_unlink, &remove_file, "uuid0")); - ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); ASSERT_EQ(kOK, ns.Rename("/home", "/home1", &need_unlink, &remove_file, "uuid0")); - ASSERT_EQ(kDirLockCleaning, ns.GetDirLockStatus("/home1")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home1", kDirLockCleaning, "")); + ASSERT_EQ(kOK, ns.Rename("/home1", "/home", + &need_unlink, &remove_file, "uuid0")); + ASSERT_EQ(kDirLockCleaning, ns.GetDirLockStatus("/home")); + system("rm -rf ./db"); } TEST_F(NameSpaceTest, RemoveFile) { From fb22a4091a9577e7ad4c8907ad0abb81adef9491 Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 16 Mar 2017 10:06:38 +0800 Subject: [PATCH 20/28] Add CheckDirLockPermission & ut (#527) --- src/nameserver/namespace.cc | 33 +++++++++++++++------- src/nameserver/namespace.h | 1 + src/nameserver/test/namespace_test.cc | 40 +++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 09b1f01f..a9924887 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -282,14 +282,10 @@ StatusCode NameSpace::BuildPath(const std::string& path, FileInfo* file_info, if (GetFileType(file_info->type()) != kDir) { LOG(INFO, "Create path fail: %s is not a directory", paths[i].c_str()); return kBadParameter; - } else { - if (file_info->dir_lock_stat() == kDirLocked && - file_info->dir_lock_holder_uuid() != uuid) { - LOG(INFO, "%s create path fail: %s is locked by %s", - uuid.c_str(), paths[i].c_str(), - file_info->dir_lock_holder_uuid().c_str()); - return kNoPermission; - } + } else if (!CheckDirLockPermission(*file_info, uuid)) { + LOG(INFO, "Create path %s fail: have no permission on %s", + path.c_str(), paths[i].c_str()); + return kNoPermission; } } parent_id = file_info->entry_id(); @@ -428,8 +424,9 @@ StatusCode NameSpace::Rename(const std::string& old_path, old_path.c_str(), new_path.c_str(), new_paths[i].c_str()); return kBadParameter; } - if (path_file.dir_lock_stat() == kDirLocked && - path_file.dir_lock_holder_uuid() != uuid) { + if (!CheckDirLockPermission(path_file, uuid)) { + LOG(INFO, "Rename %s to %s fail: have no permission on %s", + old_path.c_str(), new_path.c_str(), new_paths[i].c_str()); return kNoPermission; } if (path_file.entry_id() == old_file.entry_id()) { @@ -1048,6 +1045,22 @@ bool NameSpace::CheckDirLockPermission(const std::string& path, return true; } +bool NameSpace::CheckDirLockPermission(const FileInfo& file_info, + const std::string& uuid) { + StatusCode status = file_info.dir_lock_stat(); + if (status == kDirLocked && file_info.dir_lock_holder_uuid() != uuid) { + LOG(INFO, "%s no permission, %s is locked by %s", + uuid.c_str(), file_info.name().c_str(), + file_info.dir_lock_holder_uuid().c_str()); + return false; + } else if (status == kDirLockCleaning) { + LOG(INFO, "%s no permission, %s dir lock is being cleaning", + uuid.c_str(), file_info.name().c_str()); + return false; + } + return true; +} + } // namespace bfs } // namespace baidu /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 6b18329b..933d908c 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -112,6 +112,7 @@ class NameSpace { bool CheckDirLockPermission(const std::string& path, const std::string& uuid, FileInfo* info); + bool CheckDirLockPermission(const FileInfo& info, const std::string& uuid); private: leveldb::DB* db_; /// NameSpace storage leveldb::Cache* db_cache_; // block cache for leveldb diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 18333fa6..09bdcb88 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -134,8 +134,12 @@ TEST_F(NameSpaceTest, CreateFile) { ASSERT_EQ(kBadParameter, ns.CreateFile("/", 0, 01755, -1, &blocks_to_remove)); ASSERT_EQ(kBadParameter, ns.CreateFile("/", 0, 0, -1, &blocks_to_remove)); ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir1/subdir1", kDirLocked, "uuid0")); - /* ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove, "uuid1")); */ - ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove)); + ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove, "uuid1")); + ASSERT_EQ(kOK, ns.CreateFile("/dir1/subdir1/file4", 0, 0, -1, &blocks_to_remove, "uuid0")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir1/subdir1", kDirLockCleaning, "")); + ASSERT_EQ(kNoPermission, ns.CreateFile("/dir1/subdir1/file5", 0, 0, -1, &blocks_to_remove, "uuid0")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir1/subdir1", kDirUnlock, "")); + ASSERT_EQ(kOK, ns.CreateFile("/dir1/subdir1/file5", 0, 0, -1, &blocks_to_remove, "uuid0")); system("rm -rf ./db"); } @@ -248,6 +252,9 @@ TEST_F(NameSpaceTest, Rename) { /// rename dir after dir lock removed ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); + ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2_lock", "/home/dir2", + &need_unlink, &remove_file, "uuid1")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirUnlock, "")); ASSERT_EQ(kOK, ns.Rename("/home/dir2_lock", "/home/dir2", &need_unlink, &remove_file, "uuid1")); @@ -284,6 +291,19 @@ TEST_F(NameSpaceTest, RemoveFile) { ASSERT_EQ(kOK, ns.RemoveFile("/link1", &file_removed)); ASSERT_EQ(11, file_removed.entry_id()); + /// rm file protected by dir lock + std::vector blocks_to_remove; + ASSERT_EQ(kOK, ns.CreateFile("/dir/subdir1/file3", 0, 0, -1, &blocks_to_remove)); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir/subdir1", kDirLocked, "uuid0")); + ASSERT_EQ(kNoPermission, ns.RemoveFile("/dir/subdir1/file3", &file_removed, "uuid1")); + ASSERT_EQ(kOK, ns.RemoveFile("/dir/subdir1/file3", &file_removed, "uuid0")); + ASSERT_EQ(kOK, ns.CreateFile("/dir/subdir1/file4", 0, 0, -1, &blocks_to_remove, "uuid0")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir/subdir1", kDirLockCleaning, "")); + ASSERT_EQ(kNoPermission, ns.RemoveFile("/dir/subdir1/file4", &file_removed, "uuid1")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/dir/subdir1", kDirUnlock, "")); + ASSERT_EQ(kOK, ns.RemoveFile("/dir/subdir1/file4", &file_removed, "uuid1")); + + system("rm -rf ./db"); } TEST_F(NameSpaceTest, DeleteDirectory) { @@ -329,6 +349,22 @@ TEST_F(NameSpaceTest, DeleteDirectory) { ASSERT_EQ(kOK, ns.DeleteDirectory("/", true, &files_removed)); ASSERT_EQ(kOK, ns.ListDirectory("/", &outputs)); ASSERT_EQ(0, outputs.size()); + + // Rmr dir with dir lock protected + std::vector blocks_to_remove; + ns.CreateFile("/tera", 0, 01755, -1, &blocks_to_remove); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/tera", kDirLocked, "uuid0")); + ASSERT_EQ(kNoPermission, ns.DeleteDirectory("/tera", true, &files_removed, "uuid1")); + ASSERT_EQ(kOK, ns.ListDirectory("/", &outputs)); + ASSERT_EQ(1, outputs.size()); + ASSERT_EQ(kOK, ns.DeleteDirectory("/tera", true, &files_removed, "uuid0")); + ASSERT_EQ(kOK, ns.ListDirectory("/", &outputs)); + ASSERT_EQ(0, outputs.size()); + ns.CreateFile("/tera", 0, 01755, -1, &blocks_to_remove); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/tera", kDirLocked, "uuid0")); + ASSERT_EQ(kNoPermission, ns.DeleteDirectory("/tera", true, &files_removed, "uuid1")); + ASSERT_EQ(kOK, ns.SetDirLockStatus("/tera", kDirLockCleaning, "")); + ASSERT_EQ(kOK, ns.DeleteDirectory("/tera", true, &files_removed, "uuid1")); } TEST_F(NameSpaceTest, DeleteDirectory2) { From f92ad06ef9b24a20dfae3c9c56a08154d1b0fda9 Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 16 Mar 2017 10:21:48 +0800 Subject: [PATCH 21/28] Add ut for CheckDirLockPermission (#527) --- src/nameserver/test/namespace_test.cc | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index 09bdcb88..d5350990 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -505,6 +505,38 @@ TEST_F(NameSpaceTest, GetAndSetDirLockStatus) { system("rm -rf ./db"); } +TEST_F(NameSpaceTest, CheckDirLockPermission) { + system("rm -rf ./db"); + NameSpace ns; + std::vector blocks_to_remove; + FileInfo info; + ns.CreateFile("/abc/def/ghi", 0, 01755, -1, &blocks_to_remove); + ASSERT_TRUE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid0", &info)); + ASSERT_TRUE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid1", &info)); + ns.SetDirLockStatus("/abc/def/ghi", kDirLocked, "uuid0"); + ASSERT_FALSE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid1", &info)); + ASSERT_TRUE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid0", &info)); + ns.SetDirLockStatus("/abc/def/ghi", kDirLockCleaning, ""); + ASSERT_FALSE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid1", &info)); + ASSERT_FALSE(ns.CheckDirLockPermission("/abc/def/ghi", "uuid0", &info)); + + ns.SetDirLockStatus("/abc/def/ghi", kDirUnlock, ""); + ASSERT_TRUE(ns.LookUp("/abc/def/ghi", &info)); + ASSERT_TRUE(ns.CheckDirLockPermission(info, "uuid0")); + ASSERT_TRUE(ns.CheckDirLockPermission(info, "uuid1")); + + ns.SetDirLockStatus("/abc/def/ghi", kDirLocked, "uuid0"); + ASSERT_TRUE(ns.LookUp("/abc/def/ghi", &info)); + ASSERT_TRUE(ns.CheckDirLockPermission(info, "uuid0")); + ASSERT_FALSE(ns.CheckDirLockPermission(info, "uuid1")); + + ns.SetDirLockStatus("/abc/def/ghi", kDirLockCleaning, "uuid0"); + ASSERT_TRUE(ns.LookUp("/abc/def/ghi", &info)); + ASSERT_FALSE(ns.CheckDirLockPermission(info, "uuid0")); + ASSERT_FALSE(ns.CheckDirLockPermission(info, "uuid1")); + system("rm -rf ./db"); +} + } } From 002a13f4d0338eff8ac6ff342b003627abd7b980 Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 16 Mar 2017 10:40:38 +0800 Subject: [PATCH 22/28] Add uuid in proto (#527) --- src/nameserver/nameserver_impl.cc | 13 +++++++------ src/proto/nameserver.proto | 4 ++++ src/sdk/fs_impl.cc | 4 ++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index c5853259..e02060c0 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -387,8 +387,8 @@ void NameServerImpl::CreateFile(::google::protobuf::RpcController* controller, std::vector blocks_to_remove; FileLockGuard file_lock(new WriteLock(path)); StatusCode status = - namespace_->CreateFile(path, flags, mode, - replica_num, &blocks_to_remove, "", &log); + namespace_->CreateFile(path, flags, mode, replica_num, + &blocks_to_remove, request->uuid(), &log); for (size_t i = 0; i < blocks_to_remove.size(); i++) { block_mapping_manager_->RemoveBlock(blocks_to_remove[i]); } @@ -784,7 +784,7 @@ void NameServerImpl::Rename(::google::protobuf::RpcController* controller, NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(oldpath, newpath)); StatusCode status = namespace_->Rename(oldpath, newpath, &need_unlink, - &remove_file, "", &log); + &remove_file, request->uuid(), &log); response->set_status(status); if (status != kOK) { done->Run(); @@ -849,7 +849,8 @@ void NameServerImpl::Unlink(::google::protobuf::RpcController* controller, FileInfo file_info; NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(path)); - StatusCode status = namespace_->RemoveFile(path, &file_info, "", &log); + StatusCode status = namespace_->RemoveFile(path, &file_info, + request->uuid(), &log); sofa::pbrpc::RpcController* ctl = reinterpret_cast(controller); LOG(INFO, "Sdk %s unlink file %s returns %s", ctl->RemoteAddress().c_str(), path.c_str(), StatusCode_Name(status).c_str()); @@ -910,8 +911,8 @@ void NameServerImpl::DeleteDirectory(::google::protobuf::RpcController* controll std::vector* removed = new std::vector; NameServerLog log; FileLockGuard file_lock_guard(new WriteLock(path)); - StatusCode ret_status = namespace_->DeleteDirectory(path, recursive, - removed, "", &log); + StatusCode ret_status = namespace_->DeleteDirectory(path, recursive, removed, + request->uuid(), &log); sofa::pbrpc::RpcController* ctl = reinterpret_cast(controller); LOG(INFO, "Sdk %s delete directory %s returns %s", ctl->RemoteAddress().c_str(), path.c_str(), StatusCode_Name(ret_status).c_str()); diff --git a/src/proto/nameserver.proto b/src/proto/nameserver.proto index b867d127..85ddb04f 100644 --- a/src/proto/nameserver.proto +++ b/src/proto/nameserver.proto @@ -42,6 +42,7 @@ message CreateFileRequest { optional int32 flags = 4; optional int32 replica_num = 5; optional string user = 7; + optional string uuid = 8; } message CreateFileResponse { @@ -94,6 +95,7 @@ message RenameRequest { optional int64 sequence_id = 1; optional string oldpath = 2; optional string newpath = 3; + optional string uuid = 4; } message RenameResponse { optional int64 sequence_id = 1; @@ -139,6 +141,7 @@ message FinishBlockResponse { message UnlinkRequest { optional int64 sequence_id = 1; optional string path = 2; + optional string uuid = 3; } message UnlinkResponse { optional int64 sequence_id = 1; @@ -149,6 +152,7 @@ message DeleteDirectoryRequest { optional int64 sequence_id = 1; optional string path = 2; optional bool recursive = 3; + optional string uuid = 4; } message DeleteDirectoryResponse { optional int64 sequence_id = 1; diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index 12151311..9dd1142e 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -100,6 +100,7 @@ int32_t FSImpl::CreateDirectory(const char* path) { request.set_file_name(path); request.set_mode(0755|(1<<9)); request.set_sequence_id(0); + request.set_uuid(GetUUID()); bool ret = nameserver_client_->SendRequest(&NameServer_Stub::CreateFile, &request, &response, 15, 3); if (!ret) { @@ -165,6 +166,7 @@ int32_t FSImpl::DeleteDirectory(const char* path, bool recursive) { request.set_sequence_id(0); request.set_path(path); request.set_recursive(recursive); + request.set_uuid(GetUUID()); bool ret = nameserver_client_->SendRequest(&NameServer_Stub::DeleteDirectory, &request, &response, 3600, 1); if (!ret) { @@ -397,6 +399,7 @@ int32_t FSImpl::DeleteFile(const char* path) { request.set_path(path); int64_t seq = common::timer::get_micros(); request.set_sequence_id(seq); + request.set_uuid(GetUUID()); // printf("Delete file: %s\n", path); bool ret = nameserver_client_->SendRequest(&NameServer_Stub::Unlink, &request, &response, 15, 1); @@ -438,6 +441,7 @@ int32_t FSImpl::Rename(const char* oldpath, const char* newpath) { request.set_oldpath(oldpath); request.set_newpath(newpath); request.set_sequence_id(0); + request.set_uuid(GetUUID()); bool ret = nameserver_client_->SendRequest(&NameServer_Stub::Rename, &request, &response, 15, 1); if (!ret) { From bfa0a829b15d1303101e7fced4d29246c3839005 Mon Sep 17 00:00:00 2001 From: yangce Date: Thu, 16 Mar 2017 11:33:21 +0800 Subject: [PATCH 23/28] Set uuid in OpenFile --- src/nameserver/nameserver_impl.cc | 17 +++++++++++++---- src/nameserver/namespace.cc | 6 +++++- src/nameserver/namespace.h | 3 ++- src/sdk/fs_impl.cc | 1 + 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index e02060c0..f01871f2 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1015,7 +1015,8 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, } std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); - StatusCode status = namespace_->GetDirLockStatus(path); + std::string holder; + StatusCode status = namespace_->GetDirLockStatus(path, &holder); LOG(INFO, "%s try lock dir %s", request->uuid().c_str(), path.c_str()); if (status != kDirLocked) { //TODO log remote? @@ -1038,8 +1039,15 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, } // else status should be kBadParameter } else { //TODO log remote - namespace_->SetDirLockStatus(path, kDirLockCleaning); - status = kDirLockCleaning; + if (holder != request->uuid()) { + namespace_->SetDirLockStatus(path, kDirLockCleaning); + status = kDirLockCleaning; + LOG(INFO, "%s try clean %s dir lock", + request->uuid().c_str(), path.c_str()); + } else { + // double lock by the same sdk, ignore it + status = kOK; + } } response->set_status(status); done->Run(); @@ -1626,7 +1634,8 @@ void NameServerImpl::CallMethod(const ::google::protobuf::MethodDescriptor* meth std::make_pair("PushBlockReport", work_thread_pool_), std::make_pair("SysStat", read_thread_pool_), std::make_pair("Chmod", work_thread_pool_), - std::make_pair("Symlink", work_thread_pool_) + std::make_pair("Symlink", work_thread_pool_), + std::make_pair("LockDir", work_thread_pool_) }; static int method_num = sizeof(ThreadPoolOfMethod) / diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index a9924887..50686d34 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -916,13 +916,17 @@ int64_t NameSpace::GetNewBlockId() { return next_block_id_++; } -StatusCode NameSpace::GetDirLockStatus(const std::string& path) { +StatusCode NameSpace::GetDirLockStatus(const std::string& path, + std::string* holder) { FileInfo info; if (!LookUp(path, &info)) { return kNsNotFound; } else if (GetFileType(info.type()) != kDir) { return kBadParameter; } else { + if (holder && info.dir_lock_stat() == kDirLocked) { + *holder = info.dir_lock_stat(); + } return info.dir_lock_stat(); } } diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 933d908c..7b93725f 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -74,7 +74,8 @@ class NameSpace { void TailSnapshot(int32_t ns_id, std::string* logstr); void EraseNamespace(); int64_t GetNewBlockId(); - StatusCode GetDirLockStatus(const std::string& path); + StatusCode GetDirLockStatus(const std::string& path, + std::string* holder = NULL); StatusCode SetDirLockStatus(const std::string& path, StatusCode status, const std::string& uuid = ""); void ListAllBlocks(const std::string& path, std::vector* result); diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index 9dd1142e..ccd0a19a 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -347,6 +347,7 @@ int32_t FSImpl::OpenFile(const char* path, int32_t flags, int32_t mode, request.set_flags(flags); request.set_mode(mode&0777); request.set_replica_num(write_option.replica); + request.set_uuid(GetUUID()); bool rpc_ret = nameserver_client_->SendRequest(&NameServer_Stub::CreateFile, &request, &response, 15, 1); if (!rpc_ret || response.status() != kOK) { From 8887470956b9daeecdb44b7a01b8e589c7ed4e8c Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 20 Mar 2017 10:18:27 +0800 Subject: [PATCH 24/28] Fix ut (#527) --- src/nameserver/nameserver_impl.cc | 19 ++++++++++++++++--- src/nameserver/namespace.cc | 7 ++++--- src/nameserver/namespace.h | 6 +++--- src/nameserver/test/namespace_test.cc | 8 ++++++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index f01871f2..271746a5 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1015,6 +1015,14 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, } std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); + std::string parent_path(path, 0, path.find_last_of("/")); + FileInfo info; + if (!namespace_->CheckDirLockPermission(parent_path, request->uuid(), &info)) { + LOG(INFO, "%s has no permission, parent is locked by %s", + request->uuid().c_str(), info.dir_lock_holder_uuid().c_str()); + response->set_status(kNoPermission); + done->Run(); + } std::string holder; StatusCode status = namespace_->GetDirLockStatus(path, &holder); LOG(INFO, "%s try lock dir %s", request->uuid().c_str(), path.c_str()); @@ -1022,8 +1030,7 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, //TODO log remote? if (status == kDirUnlock) { namespace_->SetDirLockStatus(path, kDirLocked, request->uuid()); - LOG(INFO, "%s lock dir %s", - request->uuid().c_str(), path.c_str()); + LOG(INFO, "%s lock dir %s", request->uuid().c_str(), path.c_str()); status = kOK; } else if (status == kDirLockCleaning) { std::vector blocks; @@ -1040,8 +1047,14 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, } else { //TODO log remote if (holder != request->uuid()) { - namespace_->SetDirLockStatus(path, kDirLockCleaning); + // must set dir lock stat to kDirLockCleaning before ListAllBlocks + namespace_->SetDirLockStatus(path, kDirLockCleaning, request->uuid()); status = kDirLockCleaning; + std::vector blocks; + namespace_->ListAllBlocks(path, &blocks); + for (auto it = blocks.begin(); it != blocks.end(); ++it) { + block_mapping_manager_->MarkIncomplete(*it); + } LOG(INFO, "%s try clean %s dir lock", request->uuid().c_str(), path.c_str()); } else { diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 50686d34..98524105 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -925,7 +925,7 @@ StatusCode NameSpace::GetDirLockStatus(const std::string& path, return kBadParameter; } else { if (holder && info.dir_lock_stat() == kDirLocked) { - *holder = info.dir_lock_stat(); + *holder = info.dir_lock_holder_uuid(); } return info.dir_lock_stat(); } @@ -957,7 +957,7 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, return kNsNotFound; } info.set_dir_lock_stat(status); - if (status == kDirLockCleaning) { + if (status == kDirUnlock) { info.set_dir_lock_holder_uuid(""); } else if (status == kDirLocked) { info.set_dir_lock_holder_uuid(uuid); @@ -1057,7 +1057,8 @@ bool NameSpace::CheckDirLockPermission(const FileInfo& file_info, uuid.c_str(), file_info.name().c_str(), file_info.dir_lock_holder_uuid().c_str()); return false; - } else if (status == kDirLockCleaning) { + } else if (status == kDirLockCleaning && + file_info.dir_lock_holder_uuid() == uuid) { LOG(INFO, "%s no permission, %s dir lock is being cleaning", uuid.c_str(), file_info.name().c_str()); return false; diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 7b93725f..15a1b00d 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -79,6 +79,9 @@ class NameSpace { StatusCode SetDirLockStatus(const std::string& path, StatusCode status, const std::string& uuid = ""); void ListAllBlocks(const std::string& path, std::vector* result); + bool CheckDirLockPermission(const std::string& path, + const std::string& uuid, + FileInfo* info); private: enum FileType { kDefault = 0, @@ -110,9 +113,6 @@ class NameSpace { void InitBlockIdUpbound(NameServerLog* log); void UpdateBlockIdUpbound(NameServerLog* log); void ListAllBlocks(int64_t entry_id, std::vector* result); - bool CheckDirLockPermission(const std::string& path, - const std::string& uuid, - FileInfo* info); bool CheckDirLockPermission(const FileInfo& info, const std::string& uuid); private: leveldb::DB* db_; /// NameSpace storage diff --git a/src/nameserver/test/namespace_test.cc b/src/nameserver/test/namespace_test.cc index d5350990..701ee193 100644 --- a/src/nameserver/test/namespace_test.cc +++ b/src/nameserver/test/namespace_test.cc @@ -252,10 +252,14 @@ TEST_F(NameSpaceTest, Rename) { /// rename dir after dir lock removed ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirLockCleaning, "")); + // not allow self's writing when cleaning dir lock ASSERT_EQ(kNoPermission, ns.Rename("/home/dir2_lock", "/home/dir2", + &need_unlink, &remove_file, "uuid0")); + // allow other's writing when cleaning dir lock + ASSERT_EQ(kOK, ns.Rename("/home/dir2_lock", "/home/dir2", &need_unlink, &remove_file, "uuid1")); ASSERT_EQ(kOK, ns.SetDirLockStatus("/home", kDirUnlock, "")); - ASSERT_EQ(kOK, ns.Rename("/home/dir2_lock", "/home/dir2", + ASSERT_EQ(kOK, ns.Rename("/home/dir2", "/home/dir2_lock", &need_unlink, &remove_file, "uuid1")); /// rename dir protected by dir lock @@ -533,7 +537,7 @@ TEST_F(NameSpaceTest, CheckDirLockPermission) { ns.SetDirLockStatus("/abc/def/ghi", kDirLockCleaning, "uuid0"); ASSERT_TRUE(ns.LookUp("/abc/def/ghi", &info)); ASSERT_FALSE(ns.CheckDirLockPermission(info, "uuid0")); - ASSERT_FALSE(ns.CheckDirLockPermission(info, "uuid1")); + ASSERT_TRUE(ns.CheckDirLockPermission(info, "uuid1")); system("rm -rf ./db"); } From 41a5bcd8e237c3ad9a7a8d320593a7631f2ca22a Mon Sep 17 00:00:00 2001 From: yangce Date: Mon, 20 Mar 2017 11:28:10 +0800 Subject: [PATCH 25/28] Sync dir lock to secondary nameservers (#527) --- src/nameserver/nameserver_impl.cc | 41 ++++++++++++++++++++++--------- src/nameserver/namespace.cc | 4 ++- src/nameserver/namespace.h | 3 ++- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 271746a5..24d79ee0 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1013,6 +1013,7 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, done->Run(); return; } + std::string path = NameSpace::NormalizePath(request->dir_path()); FileLockGuard lock_guard(new WriteLock(path)); std::string parent_path(path, 0, path.find_last_of("/")); @@ -1023,33 +1024,37 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, response->set_status(kNoPermission); done->Run(); } + std::string holder; StatusCode status = namespace_->GetDirLockStatus(path, &holder); LOG(INFO, "%s try lock dir %s", request->uuid().c_str(), path.c_str()); + bool need_log_remote = false; + NameServerLog log; if (status != kDirLocked) { - //TODO log remote? if (status == kDirUnlock) { - namespace_->SetDirLockStatus(path, kDirLocked, request->uuid()); + namespace_->SetDirLockStatus(path, kDirLocked, request->uuid(), &log); LOG(INFO, "%s lock dir %s", request->uuid().c_str(), path.c_str()); status = kOK; + need_log_remote = true; } else if (status == kDirLockCleaning) { std::vector blocks; namespace_->ListAllBlocks(path, &blocks); if (block_mapping_manager_->CheckBlocksClosed(blocks)) { - //TODO log remote namespace_->SetDirLockStatus(path, kDirUnlock, - request->uuid()); + request->uuid(), &log); LOG(INFO, "%s lock dir %s", request->uuid().c_str(), path.c_str()); status = kOK; + need_log_remote = true; } } // else status should be kBadParameter } else { - //TODO log remote if (holder != request->uuid()) { // must set dir lock stat to kDirLockCleaning before ListAllBlocks - namespace_->SetDirLockStatus(path, kDirLockCleaning, request->uuid()); + namespace_->SetDirLockStatus(path, kDirLockCleaning, + request->uuid(), &log); status = kDirLockCleaning; + need_log_remote = true; std::vector blocks; namespace_->ListAllBlocks(path, &blocks); for (auto it = blocks.begin(); it != blocks.end(); ++it) { @@ -1062,8 +1067,16 @@ void NameServerImpl::LockDir(::google::protobuf::RpcController* controller, status = kOK; } } + response->set_status(status); - done->Run(); + if (need_log_remote) { + LogRemote(log, std::bind(&NameServerImpl::SyncLogCallback, this, + controller, request, response, done, + (std::vector*)NULL, lock_guard, + std::placeholders::_1)); + } else { + done->Run(); + } } void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, @@ -1079,8 +1092,8 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, FileLockGuard lock_guard(new WriteLock(path)); StatusCode status = namespace_->GetDirLockStatus(path); if (status == kDirLocked) { - //TODO log remote - namespace_->SetDirLockStatus(path, kDirLockCleaning); + NameServerLog log; + namespace_->SetDirLockStatus(path, kDirLockCleaning, "", &log); std::vector blocks; namespace_->ListAllBlocks(path, &blocks);; if (block_mapping_manager_->CheckBlocksClosed(blocks)) { @@ -1088,9 +1101,15 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, } else { status = kDirLockCleaning; } + response->set_status(status); + LogRemote(log, std::bind(&NameServerImpl::SyncLogCallback, this, + controller, request, response, done, + (std::vector*)NULL, lock_guard, + std::placeholders::_1)); + } else { + response->set_status(status); + done->Run(); } - response->set_status(status); - done->Run(); } void NameServerImpl::RebuildBlockMapCallback(const FileInfo& file_info) { diff --git a/src/nameserver/namespace.cc b/src/nameserver/namespace.cc index 98524105..e1668115 100644 --- a/src/nameserver/namespace.cc +++ b/src/nameserver/namespace.cc @@ -933,7 +933,8 @@ StatusCode NameSpace::GetDirLockStatus(const std::string& path, StatusCode NameSpace::SetDirLockStatus(const std::string& path, StatusCode status, - const std::string& uuid) { + const std::string& uuid, + NameServerLog* log) { std::vector paths; common::util::SplitPath(path, &paths); int64_t entry_id = kRootEntryid; @@ -965,6 +966,7 @@ StatusCode NameSpace::SetDirLockStatus(const std::string& path, std::string info_buf; info.SerializeToString(&info_buf); db_->Put(leveldb::WriteOptions(), file_key, info_buf); + EncodeLog(log, kSyncWrite, file_key, info_buf); return kOK; } diff --git a/src/nameserver/namespace.h b/src/nameserver/namespace.h index 15a1b00d..c959f046 100644 --- a/src/nameserver/namespace.h +++ b/src/nameserver/namespace.h @@ -77,7 +77,8 @@ class NameSpace { StatusCode GetDirLockStatus(const std::string& path, std::string* holder = NULL); StatusCode SetDirLockStatus(const std::string& path, StatusCode status, - const std::string& uuid = ""); + const std::string& uuid = "", + NameServerLog* log = NULL); void ListAllBlocks(const std::string& path, std::vector* result); bool CheckDirLockPermission(const std::string& path, const std::string& uuid, From 8f999d8dc71db0f7b50e3d333d3ab1db5c06cbb4 Mon Sep 17 00:00:00 2001 From: yangce Date: Tue, 21 Mar 2017 13:50:54 +0800 Subject: [PATCH 26/28] Add block_mapping_manager_test.cc (#527) --- .../test/block_mapping_manager_test.cc | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/nameserver/test/block_mapping_manager_test.cc diff --git a/src/nameserver/test/block_mapping_manager_test.cc b/src/nameserver/test/block_mapping_manager_test.cc new file mode 100644 index 00000000..d2cda672 --- /dev/null +++ b/src/nameserver/test/block_mapping_manager_test.cc @@ -0,0 +1,59 @@ +// Copyright (c) 2017, Baidu.com, Inc. All Rights Reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#define private public +#include "nameserver/block_mapping_manager.h" + +#include + +namespace baidu { +namespace bfs { + +class BlockMappingManagerTest : public ::testing::Test { +public: + BlockMappingManagerTest() {} +protected: +}; + +TEST_F(BlockMappingManagerTest, CheckBlocksClosed) { + BlockMappingManager bm(5); + int64_t block_id1 = 1; + int64_t block_id2 = 2; + int64_t block_version = 0; + int64_t block_size = 0; + int32_t replica = 3; + bm.RebuildBlock(block_id1, replica, block_version, block_size); + bm.RebuildBlock(block_id2, replica, block_version, block_size); + std::vector blocks; + blocks.push_back(block_id1); + blocks.push_back(block_id2); + bool ret = bm.CheckBlocksClosed(blocks); + int32_t cs1 = 23; + int32_t cs2 = 45; + int32_t cs3 = 67; + ret = + bm.UpdateBlockInfo(block_id1, cs1, block_size, block_version) && + bm.UpdateBlockInfo(block_id1, cs2, block_size, block_version) && + bm.UpdateBlockInfo(block_id1, cs3, block_size, block_version); + ASSERT_EQ(ret, true); + ret = bm.CheckBlocksClosed(blocks); + ASSERT_EQ(ret, false); + ret = + bm.UpdateBlockInfo(block_id2, cs1, block_size, block_version) && + bm.UpdateBlockInfo(block_id2, cs2, block_size, block_version) && + bm.UpdateBlockInfo(block_id2, cs3, block_size, block_version); + ASSERT_EQ(ret, true); + ret = bm.CheckBlocksClosed(blocks); + ASSERT_EQ(ret, true); +} + +} // namespace bfs +} // namespace baidu + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + From bf6ea1ae63fedcfc3a59ed065727c742915ded5a Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 22 Mar 2017 09:41:57 +0800 Subject: [PATCH 27/28] Support timeout in LockDirectory (#527) --- src/sdk/bfs.h | 2 +- src/sdk/fs_impl.cc | 20 +++++++++++++++----- src/sdk/fs_impl.h | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/sdk/bfs.h b/src/sdk/bfs.h index e8a534f9..66333c0f 100644 --- a/src/sdk/bfs.h +++ b/src/sdk/bfs.h @@ -99,7 +99,7 @@ class FS { /// Delete Directory virtual int32_t DeleteDirectory(const char* path, bool recursive) = 0; /// Lock Directory - virtual int32_t LockDirectory(const char* path) = 0; + virtual int32_t LockDirectory(const char* path, int32_t timeout) = 0; /// Unlock Directory virtual int32_t UnlockDirectory(const char* path) = 0; /// Du diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index bf3ff053..bd6ca767 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -414,18 +414,28 @@ int32_t FSImpl::DeleteFile(const char* path) { } return OK; } -int32_t FSImpl::LockDirectory(const char* path) { - //TODO Support set timeout for LockDirectory +int32_t FSImpl::LockDirectory(const char* path, int32_t timeout) { LockDirRequest request; LockDirResponse response; request.set_dir_path(path); request.set_uuid(GetUUID()); + int32_t start_lock_time = common::timer::now_time(); + bool is_timeout = false; while (!nameserver_client_->SendRequest(&NameServer_Stub::LockDir, &request, &response, 15, 1) || response.status() != kOK) { - sleep(5); + if (common::timer::now_time() > timeout + start_lock_time) { + LOG(INFO, "Get %s dir lock timeout", path); + is_timeout = true; + break; + } else { + sleep(5); + } + } + if (is_timeout) { + return TIMEOUT; + } else { + return OK; } - assert(response.status() == kOK); - return OK; } int32_t FSImpl::UnlockDirectory(const char* path) { UnlockDirRequest request; diff --git a/src/sdk/fs_impl.h b/src/sdk/fs_impl.h index 9eec0714..48175a56 100644 --- a/src/sdk/fs_impl.h +++ b/src/sdk/fs_impl.h @@ -32,7 +32,7 @@ class FSImpl : public FS { int32_t CreateDirectory(const char* path); int32_t ListDirectory(const char* path, BfsFileInfo** filelist, int *num); int32_t DeleteDirectory(const char* path, bool recursive); - int32_t LockDirectory(const char* path); + int32_t LockDirectory(const char* path, int32_t timeout); int32_t UnlockDirectory(const char* path); int32_t DiskUsage(const char* path, int64_t* du_size); int32_t Access(const char* path, int32_t mode); From 2cd02135fa422927f0f329dc88db7d5652b7b93b Mon Sep 17 00:00:00 2001 From: yangce Date: Wed, 22 Mar 2017 11:35:14 +0800 Subject: [PATCH 28/28] Support force unlock dir (#527) --- src/client/bfs_client.cc | 15 +++++++++++++++ src/flags.cc | 1 + src/nameserver/nameserver_impl.cc | 15 ++++++++++----- src/proto/nameserver.proto | 1 + src/sdk/bfs.h | 4 ++-- src/sdk/fs_impl.cc | 3 ++- src/sdk/fs_impl.h | 2 +- 7 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/client/bfs_client.cc b/src/client/bfs_client.cc index 3df73cd3..6341f79b 100644 --- a/src/client/bfs_client.cc +++ b/src/client/bfs_client.cc @@ -23,6 +23,7 @@ DECLARE_string(flagfile); DECLARE_string(nameserver_nodes); +DECLARE_int32(sdk_dir_lock_timeout); void print_usage() { printf("Use:\nbfs_client path\n"); @@ -41,6 +42,8 @@ void print_usage() { printf("\t stat : list current stat of the file system\n"); printf("\t ln : create symlink\n"); printf("\t chmod : change file mode bits\n"); + printf("\t lockdir : lock the dir\n"); + printf("\t unlockdir : unlock the dir\n"); } int BfsTouchz(baidu::bfs::FS* fs, int argc, char* argv[]) { @@ -514,6 +517,14 @@ int BfsShutdownStat(baidu::bfs::FS* fs) { return 0; } +int BfsLockDir(baidu::bfs::FS* fs, int argc, char* argv[]) { + return fs->LockDirectory(argv[0], FLAGS_sdk_dir_lock_timeout); +} + +int BfsUnlockDir(baidu::bfs::FS* fs, int argc, char* argv[]) { + return fs->UnlockDirectory(argv[0], true); +} + /// bfs client main int main(int argc, char* argv[]) { FLAGS_flagfile = "./bfs.flag"; @@ -569,6 +580,10 @@ int main(int argc, char* argv[]) { ret = BfsShutdownStat(fs); } else if (strcmp(argv[1], "ln") == 0) { ret = BfsLink(fs, argc - 2, argv + 2); + } else if (strcmp(argv[1], "lockdir") == 0) { + ret = BfsLockDir(fs, argc - 2, argv + 2); + } else if (strcmp(argv[1], "unlockdir") == 0) { + ret = BfsUnlockDir(fs, argc - 2, argv + 2); } else { fprintf(stderr, "Unknown command: %s\n", argv[1]); } diff --git a/src/flags.cc b/src/flags.cc index 77d8102b..46ab476f 100644 --- a/src/flags.cc +++ b/src/flags.cc @@ -87,6 +87,7 @@ DEFINE_int32(sdk_thread_num, 10, "Sdk thread num"); DEFINE_int32(sdk_file_reada_len, 1024*1024, "Read ahead buffer len"); DEFINE_int32(sdk_createblock_retry, 5, "Create block retry times before fail"); DEFINE_int32(sdk_write_retry_times, 5, "Write retry times before fail"); +DEFINE_int32(sdk_dir_lock_timeout, 30, "Timeout for get dir lock"); /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ diff --git a/src/nameserver/nameserver_impl.cc b/src/nameserver/nameserver_impl.cc index 24d79ee0..2fc96da1 100644 --- a/src/nameserver/nameserver_impl.cc +++ b/src/nameserver/nameserver_impl.cc @@ -1093,13 +1093,18 @@ void NameServerImpl::UnlockDir(::google::protobuf::RpcController* controller, StatusCode status = namespace_->GetDirLockStatus(path); if (status == kDirLocked) { NameServerLog log; - namespace_->SetDirLockStatus(path, kDirLockCleaning, "", &log); - std::vector blocks; - namespace_->ListAllBlocks(path, &blocks);; - if (block_mapping_manager_->CheckBlocksClosed(blocks)) { + if (request->force_unlock()) { + namespace_->SetDirLockStatus(path, kDirUnlock, "", &log); status = kDirUnlock; } else { - status = kDirLockCleaning; + namespace_->SetDirLockStatus(path, kDirLockCleaning, "", &log); + std::vector blocks; + namespace_->ListAllBlocks(path, &blocks);; + if (block_mapping_manager_->CheckBlocksClosed(blocks)) { + status = kDirUnlock; + } else { + status = kDirLockCleaning; + } } response->set_status(status); LogRemote(log, std::bind(&NameServerImpl::SyncLogCallback, this, diff --git a/src/proto/nameserver.proto b/src/proto/nameserver.proto index 85ddb04f..9b32ca18 100644 --- a/src/proto/nameserver.proto +++ b/src/proto/nameserver.proto @@ -357,6 +357,7 @@ message UnlockDirRequest { optional int64 sequence_id = 1; optional string dir_path = 2; optional string uuid = 3; + optional bool force_unlock = 4 [default = false]; }; message UnlockDirResponse { diff --git a/src/sdk/bfs.h b/src/sdk/bfs.h index 66333c0f..07bbe7c2 100644 --- a/src/sdk/bfs.h +++ b/src/sdk/bfs.h @@ -99,9 +99,9 @@ class FS { /// Delete Directory virtual int32_t DeleteDirectory(const char* path, bool recursive) = 0; /// Lock Directory - virtual int32_t LockDirectory(const char* path, int32_t timeout) = 0; + virtual int32_t LockDirectory(const char* path, int32_t timeout = -1) = 0; /// Unlock Directory - virtual int32_t UnlockDirectory(const char* path) = 0; + virtual int32_t UnlockDirectory(const char* path, bool force_unloak = false) = 0; /// Du virtual int32_t DiskUsage(const char* path, int64_t* du_size) = 0; /// Access diff --git a/src/sdk/fs_impl.cc b/src/sdk/fs_impl.cc index bd6ca767..dce9c390 100644 --- a/src/sdk/fs_impl.cc +++ b/src/sdk/fs_impl.cc @@ -437,11 +437,12 @@ int32_t FSImpl::LockDirectory(const char* path, int32_t timeout) { return OK; } } -int32_t FSImpl::UnlockDirectory(const char* path) { +int32_t FSImpl::UnlockDirectory(const char* path, bool force_unloak) { UnlockDirRequest request; UnlockDirResponse response; request.set_dir_path(path); request.set_uuid(GetUUID()); + request.set_force_unlock(force_unloak); nameserver_client_->SendRequest(&NameServer_Stub::UnlockDir, &request, &response, 15, 1); //Don't care return value of rpc diff --git a/src/sdk/fs_impl.h b/src/sdk/fs_impl.h index 48175a56..b97006a8 100644 --- a/src/sdk/fs_impl.h +++ b/src/sdk/fs_impl.h @@ -33,7 +33,7 @@ class FSImpl : public FS { int32_t ListDirectory(const char* path, BfsFileInfo** filelist, int *num); int32_t DeleteDirectory(const char* path, bool recursive); int32_t LockDirectory(const char* path, int32_t timeout); - int32_t UnlockDirectory(const char* path); + int32_t UnlockDirectory(const char* path, bool force_unloak = false); int32_t DiskUsage(const char* path, int64_t* du_size); int32_t Access(const char* path, int32_t mode); int32_t Stat(const char* path, BfsFileInfo* fileinfo);