Skip to content

Commit b0412d8

Browse files
Lijiachen1018lijiachen
andauthored
[feat] Re-use active block (#334)
reuse act Co-authored-by: lijiachen <lijiachen19@huawei.com>
1 parent 29be755 commit b0412d8

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

ucm/store/nfsstore/cc/domain/space/space_manager.cc

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#include "file/file.h"
2626
#include "logger/logger.h"
2727
#include "space_shard_temp_layout.h"
28+
#include <chrono>
29+
30+
constexpr auto MIN_REUSE_BLOCK_AGE = 300; // 5 minutes
2831

2932
namespace UC {
3033

@@ -96,9 +99,28 @@ Status SpaceManager::NewBlock(const std::string& blockId)
9699
if (status.Failure()) {
97100
if (status != Status::DuplicateKey()) {
98101
UC_ERROR("Failed({}) to new block({}).", status, blockId);
102+
return status;
103+
}
104+
// Reuse the active block if it is not accessed within the last 5 minutes
105+
status = file->Open(IFile::OpenFlag::READ_WRITE);
106+
if (status.Failure()) {
107+
UC_ERROR("Failed({}) to open file({}).", status, file->Path());
108+
return status;
109+
}
110+
IFile::FileStat st{};
111+
status = file->Stat(st);
112+
if (status.Failure()) {
113+
UC_ERROR("Failed({}) to stat file({}).", status, file->Path());
114+
return status;
115+
}
116+
const auto now = std::chrono::system_clock::now();
117+
const auto lastAccess = std::chrono::system_clock::from_time_t(st.st_atime);
118+
if (now - lastAccess <= std::chrono::seconds(MIN_REUSE_BLOCK_AGE)) {
119+
UC_ERROR("Block({}) is active, cannot reuse it.", blockId);
120+
return Status::DuplicateKey();
99121
}
100-
return status;
101122
}
123+
102124
status = file->Truncate(this->blockSize_);
103125
if (status.Failure()) {
104126
UC_ERROR("Failed({}) to new block({}).", status, blockId);

ucm/store/test/case/nfsstore/space_manager_test.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2222
* SOFTWARE.
2323
* */
24+
#include <utime.h>
2425
#include "cmn/path_base.h"
2526
#include "space/space_manager.h"
27+
#include "file/file.h"
2628

2729
class UCSpaceManagerTest : public UC::PathBase {};
2830

@@ -88,4 +90,36 @@ TEST_F(UCSpaceManagerTest, IterAllBlockFile)
8890
count = 0;
8991
while (!layout->NextDataFilePath(iter).empty()) { count++; }
9092
ASSERT_EQ(count, 3);
93+
}
94+
95+
TEST_F(UCSpaceManagerTest, NewBlockReuseIfActiveAccessedLongAgo)
96+
{
97+
UC::SpaceManager spaceMgr;
98+
constexpr size_t blockSize = 1024 * 1024;
99+
constexpr size_t capacity = blockSize * 1024;
100+
ASSERT_EQ(spaceMgr.Setup({this->Path()}, blockSize, false, capacity), UC::Status::OK());
101+
const auto* layout = spaceMgr.GetSpaceLayout();
102+
ASSERT_NE(layout, nullptr);
103+
104+
const std::string block1 = "a1b2c3d4e5f6789012345678901234ab";
105+
auto parent = UC::File::Make(layout->DataFileParent(block1, /*activated=*/true));
106+
ASSERT_NE(parent, nullptr);
107+
ASSERT_EQ(parent->MkDir(), UC::Status::OK());
108+
109+
const auto activePath = layout->DataFilePath(block1, /*activated=*/true);
110+
auto activeFile = UC::File::Make(activePath);
111+
ASSERT_NE(activeFile, nullptr);
112+
ASSERT_EQ(activeFile->Open(UC::IFile::OpenFlag::CREATE | UC::IFile::OpenFlag::READ_WRITE), UC::Status::OK());
113+
activeFile->Close();
114+
115+
// NewBlock should return DuplicateKey because the file is recent
116+
ASSERT_EQ(spaceMgr.NewBlock(block1), UC::Status::DuplicateKey());
117+
118+
// Set atime to 10 minutes ago so it is not considered recent
119+
struct utimbuf newTime;
120+
auto tp = time(nullptr) - 600;
121+
newTime.modtime = tp;
122+
newTime.actime = tp;
123+
utime(activePath.c_str(), &newTime);
124+
ASSERT_EQ(spaceMgr.NewBlock(block1), UC::Status::OK());
91125
}

0 commit comments

Comments
 (0)