diff --git a/src/chunkserver/datastore/chunkserver_chunkfile.cpp b/src/chunkserver/datastore/chunkserver_chunkfile.cpp index 5319d24b40..03e9b82432 100644 --- a/src/chunkserver/datastore/chunkserver_chunkfile.cpp +++ b/src/chunkserver/datastore/chunkserver_chunkfile.cpp @@ -265,7 +265,7 @@ CSErrorCode CSChunkFile::LoadSnapshot(SequenceNum sn) { } CSErrorCode CSChunkFile::Write(SequenceNum sn, - const char * buf, + const butil::IOBuf& buf, off_t offset, size_t length, uint32_t* cost) { diff --git a/src/chunkserver/datastore/chunkserver_chunkfile.h b/src/chunkserver/datastore/chunkserver_chunkfile.h index 7ffeb7ee10..b440575a40 100644 --- a/src/chunkserver/datastore/chunkserver_chunkfile.h +++ b/src/chunkserver/datastore/chunkserver_chunkfile.h @@ -23,6 +23,7 @@ #define SRC_CHUNKSERVER_DATASTORE_CHUNKSERVER_CHUNKFILE_H_ #include +#include #include #include #include @@ -147,7 +148,7 @@ class CSChunkFile { * @return: 返回错误码 */ CSErrorCode Write(SequenceNum sn, - const char * buf, + const butil::IOBuf& buf, off_t offset, size_t length, uint32_t* cost); @@ -289,6 +290,25 @@ class CSChunkFile { return rc; } + inline int writeData(const butil::IOBuf& buf, off_t offset, size_t length) { + int rc = lfs_->Write(fd_, buf, offset + pageSize_, length); + if (rc < 0) { + return rc; + } + // 如果是clone chunk,需要判断是否需要更改bitmap并更新metapage + if (isCloneChunk_) { + uint32_t beginIndex = offset / pageSize_; + uint32_t endIndex = (offset + length - 1) / pageSize_; + for (uint32_t i = beginIndex; i <= endIndex; ++i) { + // 记录dirty page + if (!metaPage_.bitmap->Test(i)) { + dirtyPages_.insert(i); + } + } + } + return rc; + } + inline bool CheckOffsetAndLength(off_t offset, size_t len) { // 检查offset+len是否越界 if (offset + len > size_) { diff --git a/src/chunkserver/datastore/chunkserver_datastore.cpp b/src/chunkserver/datastore/chunkserver_datastore.cpp index 70079d13e8..f97b614ba5 100644 --- a/src/chunkserver/datastore/chunkserver_datastore.cpp +++ b/src/chunkserver/datastore/chunkserver_datastore.cpp @@ -209,7 +209,7 @@ CSErrorCode CSDataStore::CreateChunkFile(const ChunkOptions & options, CSErrorCode CSDataStore::WriteChunk(ChunkID id, SequenceNum sn, - const char * buf, + const butil::IOBuf& buf, off_t offset, size_t length, uint32_t* cost, diff --git a/src/chunkserver/datastore/chunkserver_datastore.h b/src/chunkserver/datastore/chunkserver_datastore.h index fb469916f2..e26df7449a 100644 --- a/src/chunkserver/datastore/chunkserver_datastore.h +++ b/src/chunkserver/datastore/chunkserver_datastore.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,8 @@ using curve::fs::LocalFileSystem; using ::curve::common::Atomic; using CSChunkFilePtr = std::shared_ptr; +inline void TrivialDeleter(void* ptr) {} + /** * DataStore的配置参数 * baseDir:DataStore管理的目录路径 @@ -205,11 +208,24 @@ class CSDataStore { */ virtual CSErrorCode WriteChunk(ChunkID id, SequenceNum sn, - const char * buf, + const butil::IOBuf& buf, off_t offset, size_t length, uint32_t* cost, const std::string & cloneSourceLocation = ""); + + // Deprecated, only use for unit & integration test + virtual CSErrorCode WriteChunk( + ChunkID id, SequenceNum sn, const char* buf, off_t offset, + size_t length, uint32_t* cost, + const std::string& cloneSourceLocation = "") { + butil::IOBuf data; + data.append_user_data(const_cast(buf), length, TrivialDeleter); + + return WriteChunk(id, sn, data, offset, length, cost, + cloneSourceLocation); + } + /** * 创建克隆的Chunk,chunk中记录数据源位置信息 * 该接口需要保证幂等性,重复以相同参数进行创建返回成功 diff --git a/src/chunkserver/op_request.cpp b/src/chunkserver/op_request.cpp index fdf26a9085..9d2056b52a 100755 --- a/src/chunkserver/op_request.cpp +++ b/src/chunkserver/op_request.cpp @@ -448,7 +448,7 @@ void WriteChunkRequest::OnApply(uint64_t index, auto ret = datastore_->WriteChunk(request_->chunkid(), request_->sn(), - cntl_->request_attachment().to_string().c_str(), //NOLINT + cntl_->request_attachment(), request_->offset(), request_->size(), &cost, @@ -512,7 +512,7 @@ void WriteChunkRequest::OnApplyFromLog(std::shared_ptr datastore, auto ret = datastore->WriteChunk(request.chunkid(), request.sn(), - data.to_string().c_str(), + data, request.offset(), request.size(), &cost, diff --git a/src/fs/BUILD b/src/fs/BUILD index 224ba5ac76..f3e73f988d 100644 --- a/src/fs/BUILD +++ b/src/fs/BUILD @@ -28,7 +28,8 @@ cc_library( ]), deps = [ "//src/common:curve_common", - "//external:glog" + "//external:glog", + "//external:butil", ], visibility = ["//visibility:public"], ) diff --git a/src/fs/ext4_filesystem_impl.cpp b/src/fs/ext4_filesystem_impl.cpp index a91bf86920..8e62e4f633 100644 --- a/src/fs/ext4_filesystem_impl.cpp +++ b/src/fs/ext4_filesystem_impl.cpp @@ -329,6 +329,33 @@ int Ext4FileSystemImpl::Write(int fd, return length; } +int Ext4FileSystemImpl::Write(int fd, + butil::IOBuf buf, + uint64_t offset, + int length) { + int remainLength = length; + int relativeOffset = 0; + int retryTimes = 0; + + while (remainLength > 0) { + ssize_t ret = buf.pcut_into_file_descriptor(fd, offset, length); + if (ret < 0) { + if (errno == EINTR || retryTimes < MAX_RETYR_TIME) { + ++retryTimes; + continue; + } + LOG(ERROR) << "IOBuf::pcut_into_file_descriptor failed: " + << strerror(errno); + return -errno; + } + + remainLength -= ret; + offset += ret; + } + + return length; +} + int Ext4FileSystemImpl::Append(int fd, const char *buf, int length) { diff --git a/src/fs/ext4_filesystem_impl.h b/src/fs/ext4_filesystem_impl.h index be34539403..0adbddbb20 100644 --- a/src/fs/ext4_filesystem_impl.h +++ b/src/fs/ext4_filesystem_impl.h @@ -23,10 +23,12 @@ #ifndef SRC_FS_EXT4_FILESYSTEM_IMPL_H_ #define SRC_FS_EXT4_FILESYSTEM_IMPL_H_ +#include + +#include #include #include #include -#include #include "src/fs/local_filesystem.h" #include "src/fs/wrap_posix.h" @@ -52,6 +54,7 @@ class Ext4FileSystemImpl : public LocalFileSystem { int List(const string& dirPath, vector* names) override; int Read(int fd, char* buf, uint64_t offset, int length) override; int Write(int fd, const char* buf, uint64_t offset, int length) override; + int Write(int fd, butil::IOBuf buf, uint64_t offset, int length) override; int Append(int fd, const char* buf, int length) override; int Fallocate(int fd, int op, uint64_t offset, int length) override; diff --git a/src/fs/local_filesystem.h b/src/fs/local_filesystem.h index 37a94d8e3d..2def63500b 100644 --- a/src/fs/local_filesystem.h +++ b/src/fs/local_filesystem.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -159,6 +160,17 @@ class LocalFileSystem { */ virtual int Write(int fd, const char* buf, uint64_t offset, int length) = 0; + /** + * 向文件指定区域写入数据 + * @param fd:文件句柄id,通过Open接口获取 + * @param buf:待写入数据 + * @param offset:写入区域的起始偏移 + * @param length:写入数据的长度 + * @return 返回成功写入的数据长度,失败返回-1 + */ + virtual int Write(int fd, butil::IOBuf buf, uint64_t offset, + int length) = 0; + /** * 向文件末尾追加数据 * @param fd:文件句柄id,通过Open接口获取 @@ -218,4 +230,3 @@ class LocalFsFactory { } // namespace fs } // namespace curve #endif // SRC_FS_LOCAL_FILESYSTEM_H_ - diff --git a/test/chunkserver/conf_epoch_file_test.cpp b/test/chunkserver/conf_epoch_file_test.cpp index fddf8f569c..a6a1fc53b8 100644 --- a/test/chunkserver/conf_epoch_file_test.cpp +++ b/test/chunkserver/conf_epoch_file_test.cpp @@ -36,6 +36,7 @@ using ::testing::_; using ::testing::Invoke; using ::testing::Return; using ::testing::AnyNumber; +using ::testing::Matcher; using ::testing::DoAll; using ::testing::SetArgPointee; using ::testing::SetArrayArgument; @@ -188,7 +189,7 @@ TEST(ConfEpochFileTest, load_save) { CopysetID loadCopysetID; uint64_t loadEpoch; EXPECT_CALL(*fs, Open(_, _)).Times(1).WillOnce(Return(10)); - EXPECT_CALL(*fs, Write(_, _, _, _)).Times(1) + EXPECT_CALL(*fs, Write(_, Matcher(_), _, _)).Times(1) .WillOnce(Return(-1)); EXPECT_CALL(*fs, Close(_)).Times(1).WillOnce(Return(0)); ASSERT_EQ(-1, confEpochFile.Save(path, @@ -204,7 +205,7 @@ TEST(ConfEpochFileTest, load_save) { = std::make_shared(); ConfEpochFile confEpochFile(fs); EXPECT_CALL(*fs, Open(_, _)).Times(1).WillOnce(Return(10)); - EXPECT_CALL(*fs, Write(_, _, _, _)).Times(1) + EXPECT_CALL(*fs, Write(_, Matcher(_), _, _)).Times(1) .WillOnce(Return(jsonStr.size())); EXPECT_CALL(*fs, Close(_)).Times(1).WillOnce(Return(0)); EXPECT_CALL(*fs, Fsync(_)).Times(1).WillOnce(Return(-1)); diff --git a/test/chunkserver/copyset_node_test.cpp b/test/chunkserver/copyset_node_test.cpp index a020e34ac8..ec27e76adb 100644 --- a/test/chunkserver/copyset_node_test.cpp +++ b/test/chunkserver/copyset_node_test.cpp @@ -49,6 +49,7 @@ using ::testing::_; using ::testing::Invoke; using ::testing::Return; using ::testing::AnyNumber; +using ::testing::Matcher; using ::testing::DoAll; using ::testing::SetArgPointee; using ::testing::SetArgReferee; @@ -183,7 +184,7 @@ TEST_F(CopysetNodeTest, error_test) { copysetNode.SetLocalFileSystem(mockfs); copysetNode.SetConfEpochFile(std::move(epochFile)); EXPECT_CALL(*mockfs, Open(_, _)).Times(1).WillOnce(Return(10)); - EXPECT_CALL(*mockfs, Write(_, _, _, _)).Times(1) + EXPECT_CALL(*mockfs, Write(_, Matcher(_), _, _)).Times(1) .WillOnce(Return(jsonStr.size())); EXPECT_CALL(*mockfs, Fsync(_)).Times(1).WillOnce(Return(0)); EXPECT_CALL(*mockfs, Close(_)).Times(1).WillOnce(Return(0)); @@ -242,7 +243,7 @@ TEST_F(CopysetNodeTest, error_test) { copysetNode.SetLocalFileSystem(mockfs); copysetNode.SetConfEpochFile(std::move(epochFile)); EXPECT_CALL(*mockfs, Open(_, _)).Times(1).WillOnce(Return(10)); - EXPECT_CALL(*mockfs, Write(_, _, _, _)).Times(1) + EXPECT_CALL(*mockfs, Write(_, Matcher(_), _, _)).Times(1) .WillOnce(Return(jsonStr.size())); EXPECT_CALL(*mockfs, Fsync(_)).Times(1).WillOnce(Return(0)); EXPECT_CALL(*mockfs, Close(_)).Times(1).WillOnce(Return(0)); diff --git a/test/chunkserver/datastore/chunkfilepool_mock_unittest.cpp b/test/chunkserver/datastore/chunkfilepool_mock_unittest.cpp index b9d24dc801..80af5275c6 100644 --- a/test/chunkserver/datastore/chunkfilepool_mock_unittest.cpp +++ b/test/chunkserver/datastore/chunkfilepool_mock_unittest.cpp @@ -38,6 +38,7 @@ using ::testing::Ge; using ::testing::Gt; using ::testing::Return; using ::testing::NotNull; +using ::testing::Matcher; using ::testing::Mock; using ::testing::Truly; using ::testing::DoAll; @@ -161,7 +162,7 @@ TEST_F(CSChunkfilePoolMockTest, PersistEnCodeMetaInfoTest) { { EXPECT_CALL(*lfs_, Open(poolMetaPath, _)) .WillOnce(Return(-1)); - EXPECT_CALL(*lfs_, Write(_, _, _, _)) + EXPECT_CALL(*lfs_, Write(_, Matcher(_), _, _)) .Times(0); EXPECT_CALL(*lfs_, Close(_)) .Times(0); @@ -176,7 +177,7 @@ TEST_F(CSChunkfilePoolMockTest, PersistEnCodeMetaInfoTest) { { EXPECT_CALL(*lfs_, Open(poolMetaPath, _)) .WillOnce(Return(1)); - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, 4096)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, 4096)) .WillOnce(Return(-1)); EXPECT_CALL(*lfs_, Close(1)) .Times(1); @@ -191,7 +192,7 @@ TEST_F(CSChunkfilePoolMockTest, PersistEnCodeMetaInfoTest) { { EXPECT_CALL(*lfs_, Open(poolMetaPath, _)) .WillOnce(Return(1)); - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, 4096)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, 4096)) .WillOnce(Return(4096)); EXPECT_CALL(*lfs_, Close(1)) .Times(1); @@ -770,7 +771,8 @@ TEST_F(CSChunkfilePoolMockTest, GetChunkTest) { EXPECT_CALL(*lfs_, Fallocate(1, 0, 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(0)); - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, fileSize)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(NotNull()), 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(-1)); EXPECT_CALL(*lfs_, Close(1)) @@ -787,7 +789,8 @@ TEST_F(CSChunkfilePoolMockTest, GetChunkTest) { EXPECT_CALL(*lfs_, Fallocate(1, 0, 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(0)); - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, fileSize)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(NotNull()), 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(fileSize)); EXPECT_CALL(*lfs_, Fsync(1)) @@ -807,7 +810,8 @@ TEST_F(CSChunkfilePoolMockTest, GetChunkTest) { EXPECT_CALL(*lfs_, Fallocate(1, 0, 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(0)); - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, fileSize)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(NotNull()), 0, fileSize)) .Times(retryTimes) .WillRepeatedly(Return(fileSize)); EXPECT_CALL(*lfs_, Fsync(1)) diff --git a/test/chunkserver/datastore/datastore_mock_unittest.cpp b/test/chunkserver/datastore/datastore_mock_unittest.cpp index 357852e79a..fdee83b7ce 100644 --- a/test/chunkserver/datastore/datastore_mock_unittest.cpp +++ b/test/chunkserver/datastore/datastore_mock_unittest.cpp @@ -44,6 +44,7 @@ using ::testing::Ge; using ::testing::Gt; using ::testing::Return; using ::testing::NotNull; +using ::testing::Matcher; using ::testing::Mock; using ::testing::Truly; using ::testing::DoAll; @@ -207,7 +208,10 @@ class CSDataStore_test : public testing::Test { ON_CALL(*lfs_, Read(Ge(1), NotNull(), Ge(0), Gt(0))) .WillByDefault(ReturnArg<3>()); // fake Write - ON_CALL(*lfs_, Write(Ge(1), NotNull(), Ge(0), Gt(0))) + ON_CALL(*lfs_, + Write(Ge(1), Matcher(NotNull()), Ge(0), Gt(0))) + .WillByDefault(ReturnArg<3>()); + ON_CALL(*lfs_, Write(Ge(1), Matcher(_), Ge(0), Gt(0))) .WillByDefault(ReturnArg<3>()); // fake read chunk1 metapage FakeEncodeChunk(chunk1MetaPage, 0, 2); @@ -693,7 +697,8 @@ TEST_F(CSDataStore_test, WriteChunkTest1) { chunk3MetaPage + PAGE_SIZE), Return(PAGE_SIZE))); // will write data - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, @@ -853,8 +858,10 @@ TEST_F(CSDataStore_test, WriteChunkTest4) { memset(buf, 0, sizeof(buf)); // will write data - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(3, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); + EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, @@ -869,7 +876,7 @@ TEST_F(CSDataStore_test, WriteChunkTest4) { // return InvalidArgError if offset+length > CHUNK_SIZE offset = CHUNK_SIZE; - EXPECT_CALL(*lfs_, Write(3, NotNull(), _, __amd64)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), _, __amd64)) .Times(0); EXPECT_EQ(CSErrorCode::InvalidArgError, dataStore->WriteChunk(id, @@ -881,7 +888,7 @@ TEST_F(CSDataStore_test, WriteChunkTest4) { // return InvalidArgError if length not aligned offset = PAGE_SIZE; length = PAGE_SIZE - 1; - EXPECT_CALL(*lfs_, Write(3, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), _, _)) .Times(0); EXPECT_EQ(CSErrorCode::InvalidArgError, dataStore->WriteChunk(id, @@ -893,7 +900,7 @@ TEST_F(CSDataStore_test, WriteChunkTest4) { // return InvalidArgError if offset not aligned offset = PAGE_SIZE + 1; length = PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(3, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), _, _)) .Times(0); EXPECT_EQ(CSErrorCode::InvalidArgError, dataStore->WriteChunk(id, @@ -937,10 +944,11 @@ TEST_F(CSDataStore_test, WriteChunkTest6) { char buf[length]; // NOLINT memset(buf, 0, sizeof(buf)); // will update metapage - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(3, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1001,18 +1009,20 @@ TEST_F(CSDataStore_test, WriteChunkTest7) { metapage + PAGE_SIZE), Return(PAGE_SIZE))); // will update metapage - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will copy on write EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(3, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1028,7 +1038,8 @@ TEST_F(CSDataStore_test, WriteChunkTest7) { ASSERT_EQ(2, info.snapSn); // 再次写同一个page的数据,不再进行cow,而是直接写入数据 - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(3, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, @@ -1078,13 +1089,15 @@ TEST_F(CSDataStore_test, WriteChunkTest9) { // will copy on write EXPECT_CALL(*lfs_, Read(1, NotNull(), PAGE_SIZE + offset, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(2, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(2, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1132,11 +1145,12 @@ TEST_F(CSDataStore_test, WriteChunkTest10) { char buf[length]; // NOLINT memset(buf, 0, sizeof(buf)); // will update metapage - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will not cow // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1233,6 +1247,7 @@ TEST_F(CSDataStore_test, WriteChunkTest13) { CSChunkInfo info; // 创建 clone chunk { + LOG(INFO) << "case 1"; char chunk3MetaPage[PAGE_SIZE]; memset(chunk3MetaPage, 0, sizeof(chunk3MetaPage)); shared_ptr bitmap = @@ -1264,14 +1279,18 @@ TEST_F(CSDataStore_test, WriteChunkTest13) { // case1:chunk存在,且是clone chunk,写入区域之前未写过 { + LOG(INFO) << "case 2"; id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, @@ -1289,13 +1308,17 @@ TEST_F(CSDataStore_test, WriteChunkTest13) { // case2:chunk存在,且是clone chunk,写入区域之前已写过 { + LOG(INFO) << "case 3"; id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, @@ -1313,18 +1336,25 @@ TEST_F(CSDataStore_test, WriteChunkTest13) { // case3:chunk存在,且是clone chunk,部分区域已写过,部分未写过 { + LOG(INFO) << "case 4"; id = 3; // not exist offset = 0; length = 4 * PAGE_SIZE; + + std::unique_ptr buf(new char[length]); + // [2 * PAGE_SIZE, 4 * PAGE_SIZE)区域已写过,[0, PAGE_SIZE)为metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + offset + PAGE_SIZE, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, - buf, + buf.get(), offset, length, nullptr)); @@ -1338,18 +1368,25 @@ TEST_F(CSDataStore_test, WriteChunkTest13) { // case4:遍写整个chunk { + LOG(INFO) << "case 5"; id = 3; // not exist offset = 0; length = CHUNK_SIZE; + + std::unique_ptr buf(new char[length]); + // [PAGE_SIZE, 4 * PAGE_SIZE)区域已写过,[0, PAGE_SIZE)为metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + offset + PAGE_SIZE, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, - buf, + buf.get(), offset, length, nullptr)); @@ -1434,8 +1471,10 @@ TEST_F(CSDataStore_test, WriteChunkTest14) { // case1:clone chunk存在 { + LOG(INFO) << "case 1"; // sn == chunk.sn, sn < chunk.correctedSn sn = 2; + ASSERT_EQ(CSErrorCode::BackwardRequestError, dataStore->WriteChunk(id, sn, @@ -1457,15 +1496,19 @@ TEST_F(CSDataStore_test, WriteChunkTest14) { // case2:chunk存在,且是clone chunk, { + LOG(INFO) << "case 2"; id = 3; offset = PAGE_SIZE; length = 2 * PAGE_SIZE; sn = 3; // sn > chunk.sn;sn == correctedsn - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(2); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, @@ -1487,17 +1530,24 @@ TEST_F(CSDataStore_test, WriteChunkTest14) { // case3:chunk存在,且是clone chunk // sn > chunk.sn;sn == correctedsn { + LOG(INFO) << "case 3"; offset = 0; length = 4 * PAGE_SIZE; + + std::unique_ptr buf(new char[length]); + // [2 * PAGE_SIZE, 4 * PAGE_SIZE)区域已写过,[0, PAGE_SIZE)为metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + offset + PAGE_SIZE, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); + ASSERT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, - buf, + buf.get(), offset, length, nullptr)); @@ -1515,14 +1565,18 @@ TEST_F(CSDataStore_test, WriteChunkTest14) { // case3:chunk存在,且是clone chunk // sn > chunk.sn;sn > correctedsn { + LOG(INFO) << "case 4"; sn = 4; // 不会写数据 - EXPECT_CALL(*lfs_, Write(4, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), _, _)) .Times(0); + + std::unique_ptr buf(new char[length]); + ASSERT_EQ(CSErrorCode::StatusConflictError, dataStore->WriteChunk(id, sn, - buf, + buf.get(), offset, length, nullptr)); @@ -1583,10 +1637,11 @@ TEST_F(CSDataStore_test, WriteChunkTest15) { memset(buf, 0, sizeof(buf)); // will not create snapshot // will not copy on write - EXPECT_CALL(*lfs_, Write(2, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), _, _)) .Times(0); // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1641,13 +1696,14 @@ TEST_F(CSDataStore_test, WriteChunkTest16) { memset(buf, 0, sizeof(buf)); // will not create snapshot // will not copy on write - EXPECT_CALL(*lfs_, Write(2, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), _, _)) .Times(0); // will update sn - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -1690,6 +1746,7 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest1) { .WillOnce(Return(false)); EXPECT_CALL(*fpool_, GetChunk(snapPath, NotNull())) .WillOnce(Return(-UT_ERRNO)); + EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, sn, @@ -1785,8 +1842,9 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest2) { metapage + PAGE_SIZE), Return(PAGE_SIZE))); // write chunk metapage failed - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .WillOnce(Return(-UT_ERRNO)); + EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, sn, @@ -1846,11 +1904,14 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest3) { metapage + PAGE_SIZE), Return(PAGE_SIZE))); // will update metapage - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); + + LOG(INFO) << "case 1"; // copy data failed EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .WillOnce(Return(-UT_ERRNO)); + EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, sn, @@ -1863,11 +1924,13 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest3) { ASSERT_EQ(3, info.curSn); ASSERT_EQ(2, info.snapSn); + LOG(INFO) << "case 2"; // copy data success EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .Times(1); // write data to snapshot failed - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .WillOnce(Return(-UT_ERRNO)); EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, @@ -1880,14 +1943,16 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest3) { ASSERT_EQ(3, info.curSn); ASSERT_EQ(2, info.snapSn); + LOG(INFO) << "case 3"; // copy data success EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .Times(1); // write data to snapshot success - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); // update snapshot metapage failed - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .WillOnce(Return(-UT_ERRNO)); EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, @@ -1902,17 +1967,21 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest3) { // 再次写入仍会cow // will copy on write + LOG(INFO) << "case 4"; EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(3, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); + LOG(INFO) << "case 5"; EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, sn, @@ -1967,19 +2036,22 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest4) { metapage + PAGE_SIZE), Return(PAGE_SIZE))); // will update metapage - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will copy on write EXPECT_CALL(*lfs_, Read(3, NotNull(), PAGE_SIZE + offset, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // write chunk failed - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(3, Matcher(_), PAGE_SIZE + offset, length)) .WillOnce(Return(-UT_ERRNO)); + EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, sn, @@ -1989,7 +2061,8 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest4) { nullptr)); // 再次写入直接写chunk文件 // will write data - EXPECT_CALL(*lfs_, Write(3, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, + Write(3, Matcher(_), PAGE_SIZE + offset, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, @@ -2034,6 +2107,7 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest5) { .WillOnce(Return(false)); EXPECT_CALL(*fpool_, GetChunk(chunk3Path, NotNull())) .WillOnce(Return(-UT_ERRNO)); + EXPECT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, sn, buf, @@ -2194,10 +2268,12 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest6) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + PAGE_SIZE + offset, length)) .WillOnce(Return(-UT_ERRNO)); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); ASSERT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, @@ -2216,10 +2292,12 @@ TEST_F(CSDataStore_test, WriteChunkErrorTest6) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(_), + PAGE_SIZE + offset, length)) .Times(1); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .WillOnce(Return(-UT_ERRNO)); ASSERT_EQ(CSErrorCode::InternalError, dataStore->WriteChunk(id, @@ -2602,13 +2680,15 @@ TEST_F(CSDataStore_test, ReadSnapshotChunkTest3) { // data in [PAGE_SIZE, 2*PAGE_SIZE) will be cow EXPECT_CALL(*lfs_, Read(1, NotNull(), offset + PAGE_SIZE, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(2, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), + offset + PAGE_SIZE, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(2, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), offset + PAGE_SIZE, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, @@ -2706,13 +2786,15 @@ TEST_F(CSDataStore_test, ReadSnapshotChunkErrorTest1) { // data in [PAGE_SIZE, 2*PAGE_SIZE) will be cow EXPECT_CALL(*lfs_, Read(1, NotNull(), offset + PAGE_SIZE, length)) .Times(1); - EXPECT_CALL(*lfs_, Write(2, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), + offset + PAGE_SIZE, length)) .Times(1); // will update snapshot metapage - EXPECT_CALL(*lfs_, Write(2, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(2, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); // will write data - EXPECT_CALL(*lfs_, Write(1, NotNull(), offset + PAGE_SIZE, length)) + EXPECT_CALL(*lfs_, + Write(1, Matcher(_), offset + PAGE_SIZE, length)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->WriteChunk(id, @@ -3010,7 +3092,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest2) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .Times(1); // chunk's metapage should not be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3048,7 +3130,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest3) { EXPECT_CALL(*lfs_, Close(2)) .Times(0); // chunk's metapage should not be updated - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::BackwardRequestError, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3065,7 +3147,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest3) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .Times(1); // chunk's metapage should not be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3098,7 +3180,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest4) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .Times(1); // chunk's metapage will be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3125,7 +3207,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest5) { // fileSn > correctedSn SequenceNum fileSn = 2; // chunk's metapage should not be updated - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3154,7 +3236,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest6) { // fileSn > correctedSn SequenceNum fileSn = 4; // chunk's metapage will be updated - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3269,7 +3351,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest8) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .Times(0); // chunk's metapage should be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3320,7 +3402,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnTest9) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .Times(0); // chunk's metapage should not be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3349,13 +3431,13 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnErrorTest1) { SequenceNum fileSn = 3; // write chunk metapage failed - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .WillOnce(Return(-UT_ERRNO)); EXPECT_EQ(CSErrorCode::InternalError, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); // chunk's metapage will be updated - EXPECT_CALL(*lfs_, Write(3, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(3, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); EXPECT_EQ(CSErrorCode::Success, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3389,7 +3471,7 @@ TEST_F(CSDataStore_test, DeleteSnapshotChunkOrCorrectSnErrorTest2) { EXPECT_CALL(*fpool_, RecycleChunk(chunk1snap1Path)) .WillOnce(Return(-1)); // chunk's metapage will be updated - EXPECT_CALL(*lfs_, Write(1, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(1, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); EXPECT_EQ(CSErrorCode::InternalError, dataStore->DeleteSnapshotChunkOrCorrectSn(id, fileSn)); @@ -3732,7 +3814,7 @@ TEST_F(CSDataStore_test, PasteChunkTest1) { // case3:chunk存在,但不是clone chunk { - EXPECT_CALL(*lfs_, Write(_, NotNull(), _, _)) + EXPECT_CALL(*lfs_, Write(_, Matcher(NotNull()), _, _)) .Times(0); // 快照不存在 @@ -3760,10 +3842,12 @@ TEST_F(CSDataStore_test, PasteChunkTest1) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); ASSERT_EQ(CSErrorCode::Success, dataStore->PasteChunk(id, @@ -3783,9 +3867,11 @@ TEST_F(CSDataStore_test, PasteChunkTest1) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(0); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); ASSERT_EQ(CSErrorCode::Success, dataStore->PasteChunk(id, @@ -3805,11 +3891,14 @@ TEST_F(CSDataStore_test, PasteChunkTest1) { offset = 0; length = 4 * PAGE_SIZE; // [2 * PAGE_SIZE, 4 * PAGE_SIZE)区域已写过,[0, PAGE_SIZE)为metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), PAGE_SIZE, + PAGE_SIZE)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 4 * PAGE_SIZE, PAGE_SIZE)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + 4 * PAGE_SIZE, PAGE_SIZE)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); ASSERT_EQ(CSErrorCode::Success, dataStore->PasteChunk(id, @@ -3830,11 +3919,12 @@ TEST_F(CSDataStore_test, PasteChunkTest1) { length = CHUNK_SIZE; // [PAGE_SIZE, 4 * PAGE_SIZE)区域已写过,[0, PAGE_SIZE)为metapage EXPECT_CALL(*lfs_, Write(4, - NotNull(), + Matcher(NotNull()), 5 * PAGE_SIZE, CHUNK_SIZE - 4 * PAGE_SIZE)) .Times(1); - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(1); ASSERT_EQ(CSErrorCode::Success, dataStore->PasteChunk(id, @@ -3912,10 +4002,12 @@ TEST_F(CSDataStore_test, PasteChunkErrorTest1) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .WillOnce(Return(-UT_ERRNO)); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .Times(0); ASSERT_EQ(CSErrorCode::InternalError, dataStore->PasteChunk(id, @@ -3932,10 +4024,12 @@ TEST_F(CSDataStore_test, PasteChunkErrorTest1) { id = 3; // not exist offset = PAGE_SIZE; length = 2 * PAGE_SIZE; - EXPECT_CALL(*lfs_, Write(4, NotNull(), PAGE_SIZE + offset, length)) + EXPECT_CALL(*lfs_, Write(4, Matcher(NotNull()), + PAGE_SIZE + offset, length)) .Times(1); // update metapage - EXPECT_CALL(*lfs_, Write(4, NotNull(), 0, PAGE_SIZE)) + EXPECT_CALL(*lfs_, + Write(4, Matcher(NotNull()), 0, PAGE_SIZE)) .WillOnce(Return(-UT_ERRNO)); ASSERT_EQ(CSErrorCode::InternalError, dataStore->PasteChunk(id, diff --git a/test/chunkserver/fake_datastore.h b/test/chunkserver/fake_datastore.h index d806addf79..070b823105 100644 --- a/test/chunkserver/fake_datastore.h +++ b/test/chunkserver/fake_datastore.h @@ -130,7 +130,7 @@ class FakeCSDataStore : public CSDataStore { CSErrorCode WriteChunk(ChunkID id, SequenceNum sn, - const char *buf, + const butil::IOBuf& buf, off_t offset, size_t length, uint32_t *cost, @@ -139,7 +139,7 @@ class FakeCSDataStore : public CSDataStore { if (errorCode != CSErrorCode::Success) { return errorCode; } - ::memcpy(chunk_+offset, buf, length); + ::memcpy(chunk_+offset, buf.to_string().c_str(), length); *cost = length; chunkIds_.insert(id); sn_ = sn; diff --git a/test/chunkserver/metrics_test.cpp b/test/chunkserver/metrics_test.cpp index 8f19da4913..fd085ba9d3 100644 --- a/test/chunkserver/metrics_test.cpp +++ b/test/chunkserver/metrics_test.cpp @@ -468,8 +468,10 @@ TEST_F(CSMetricTest, CountTest) { char buf[PAGE_SIZE] = {0}; off_t offset = 0; size_t length = PAGE_SIZE; + butil::IOBuf dataBuf; + dataBuf.append(buf, PAGE_SIZE); ASSERT_EQ(CSErrorCode::Success, - datastore->WriteChunk(id, seq, buf, offset, length, nullptr)); + datastore->WriteChunk(id, seq, dataBuf, offset, length, nullptr)); ASSERT_EQ(1, copysetMetric->GetChunkCount()); ASSERT_EQ(0, copysetMetric->GetSnapshotCount()); ASSERT_EQ(0, copysetMetric->GetCloneChunkCount()); @@ -480,7 +482,7 @@ TEST_F(CSMetricTest, CountTest) { // 增加版本号,生成快照 seq = 2; ASSERT_EQ(CSErrorCode::Success, - datastore->WriteChunk(id, seq, buf, offset, length, nullptr)); + datastore->WriteChunk(id, seq, dataBuf, offset, length, nullptr)); ASSERT_EQ(1, copysetMetric->GetChunkCount()); ASSERT_EQ(1, copysetMetric->GetSnapshotCount()); ASSERT_EQ(0, copysetMetric->GetCloneChunkCount()); @@ -506,8 +508,10 @@ TEST_F(CSMetricTest, CountTest) { // clone chunk被覆盖写一遍,clone chun转成普通chunk char* buf2 = new char[CHUNK_SIZE]; + butil::IOBuf dataBuf2; + dataBuf.append(buf2, CHUNK_SIZE); ASSERT_EQ(CSErrorCode::Success, - datastore->WriteChunk(id2, 1, buf2, 0, CHUNK_SIZE, nullptr)); + datastore->WriteChunk(id2, 1, dataBuf, 0, CHUNK_SIZE, nullptr)); delete[] buf2; ASSERT_EQ(3, copysetMetric->GetChunkCount()); ASSERT_EQ(0, copysetMetric->GetSnapshotCount()); diff --git a/test/fs/ext4_filesystem_test.cpp b/test/fs/ext4_filesystem_test.cpp index 2deb679a3e..493f78df83 100644 --- a/test/fs/ext4_filesystem_test.cpp +++ b/test/fs/ext4_filesystem_test.cpp @@ -443,6 +443,55 @@ TEST_F(Ext4LocalFileSystemTest, WriteTest) { ASSERT_EQ(lfs->Write(666, buf, 0, 3), 3); } +TEST_F(Ext4LocalFileSystemTest, WriteIOBufTest) { + auto posixWrapper = std::make_shared(); + lfs->SetPosixWrapper(posixWrapper); + + { + // invalid fd + butil::IOBuf data; + data.resize(4096); + + ASSERT_LE(lfs->Write(1234567, data, 0, data.size()), 0); + } + + { + int fd = posixWrapper->open("/dev/null", O_WRONLY, 0644); + ASSERT_GE(fd, 0); + + butil::IOBuf data; + data.resize(4096); + + ASSERT_EQ(lfs->Write(fd, data, 0, 4096), 4096); + + posixWrapper->close(fd); + } + + { + const char* filename = "ext4_write_iobuf_test.data"; + + int fd = posixWrapper->open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); + ASSERT_GE(fd, 0) << strerror(errno); + + butil::IOBuf data; + data.resize(1024, 'a'); // a...a + data.resize(2048, 'b'); // a...ab...b + data.resize(4096, 'c'); // a...ab...bc......c + + std::string expectedData = data.to_string(); + + ASSERT_EQ(lfs->Write(fd, data, 512, 4096), 4096); + + char readBuffer[4096]; + ASSERT_EQ(lfs->Read(fd, readBuffer, 512, 4096), 4096); + + ASSERT_EQ(std::string(readBuffer, 4096), expectedData); + + posixWrapper->close(fd); + posixWrapper->remove(filename); + } +} + // test Fallocate TEST_F(Ext4LocalFileSystemTest, FallocateTest) { // success diff --git a/test/fs/mock_local_filesystem.h b/test/fs/mock_local_filesystem.h index 5f0235865b..f1d40a6f5e 100644 --- a/test/fs/mock_local_filesystem.h +++ b/test/fs/mock_local_filesystem.h @@ -47,6 +47,7 @@ class MockLocalFileSystem : public LocalFileSystem { MOCK_METHOD2(List, int(const string&, vector*)); MOCK_METHOD4(Read, int(int, char*, uint64_t, int)); MOCK_METHOD4(Write, int(int, const char*, uint64_t, int)); + MOCK_METHOD4(Write, int(int, butil::IOBuf, uint64_t, int)); MOCK_METHOD3(Append, int(int, const char*, int)); MOCK_METHOD4(Fallocate, int(int, int, uint64_t, int)); MOCK_METHOD2(Fstat, int(int, struct stat*)); diff --git a/test/integration/chunkserver/datastore/datastore_basic_test.cpp b/test/integration/chunkserver/datastore/datastore_basic_test.cpp index b212116171..0f91ad77c6 100644 --- a/test/integration/chunkserver/datastore/datastore_basic_test.cpp +++ b/test/integration/chunkserver/datastore/datastore_basic_test.cpp @@ -71,6 +71,7 @@ TEST_F(BasicTestSuit, BasicTest) { char buf1_1_1[PAGE_SIZE]; memset(buf1_1_1, 'a', length); + errorCode = dataStore_->WriteChunk(id, sn, buf1_1_1, @@ -109,6 +110,7 @@ TEST_F(BasicTestSuit, BasicTest) { // chunk 存在时,覆盖写 char buf1_1_2[PAGE_SIZE]; memset(buf1_1_2, 'b', length); + errorCode = dataStore_->WriteChunk(id, sn, buf1_1_2, @@ -132,6 +134,7 @@ TEST_F(BasicTestSuit, BasicTest) { memset(buf1_1_3, 'c', length); offset = PAGE_SIZE; length = PAGE_SIZE; + errorCode = dataStore_->WriteChunk(id, sn, buf1_1_3, @@ -156,9 +159,13 @@ TEST_F(BasicTestSuit, BasicTest) { memset(buf1_1_4, 'd', length); offset = PAGE_SIZE; length = 2 * PAGE_SIZE; + + butil::IOBuf iobuf1_1_4; + iobuf1_1_4.append(buf1_1_4, length); + errorCode = dataStore_->WriteChunk(id, sn, - buf1_1_4, + iobuf1_1_4, offset, length, nullptr); diff --git a/test/integration/chunkserver/datastore/datastore_restart_test.cpp b/test/integration/chunkserver/datastore/datastore_restart_test.cpp index 566d95f1d6..d91910fd21 100644 --- a/test/integration/chunkserver/datastore/datastore_restart_test.cpp +++ b/test/integration/chunkserver/datastore/datastore_restart_test.cpp @@ -150,9 +150,9 @@ class ExecWrite : public ExecStep { void Exec() override { char* buf = new char[data_.length]; memset(buf, data_.data, data_.length); + (*datastore_)->WriteChunk(id_, sn_, buf, data_.offset, data_.length, nullptr); - delete [] buf; } void Dump() override { diff --git a/test/integration/chunkserver/datastore/datastore_stress_test.cpp b/test/integration/chunkserver/datastore/datastore_stress_test.cpp index 4187017e8e..5f2af8086b 100644 --- a/test/integration/chunkserver/datastore/datastore_stress_test.cpp +++ b/test/integration/chunkserver/datastore/datastore_stress_test.cpp @@ -40,6 +40,7 @@ TEST_F(StressTestSuit, StressTest) { off_t offset = 0; size_t length = PAGE_SIZE; char buf[PAGE_SIZE] = {0}; + Atomic sn(1); static unsigned int seed = 1;