Skip to content

Commit bcd6fe2

Browse files
author
lijiachen
committed
recycle
1 parent 2b1a5b6 commit bcd6fe2

File tree

15 files changed

+601
-7
lines changed

15 files changed

+601
-7
lines changed

ucm/store/infra/file/file.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ Status File::Access(const std::string& path, const int32_t mode)
5353
return FileImpl{path}.Access(mode);
5454
}
5555

56+
Status File::Stat(const std::string& path, IFile::FileStat& st)
57+
{
58+
FileImpl file{path};
59+
auto status = file.Open(IFile::OpenFlag::READ_ONLY);
60+
if (status.Failure()) { return status; }
61+
status = file.Stat(st);
62+
file.Close();
63+
return status;
64+
}
65+
5666
Status File::Read(const std::string& path, const size_t offset, const size_t length,
5767
uintptr_t address, const bool directIo)
5868
{

ucm/store/infra/file/file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class File {
3636
static Status RmDir(const std::string& path);
3737
static Status Rename(const std::string& path, const std::string& newName);
3838
static Status Access(const std::string& path, const int32_t mode);
39+
static Status Stat(const std::string& path, IFile::FileStat& st);
3940
static Status Read(const std::string& path, const size_t offset, const size_t length,
4041
uintptr_t address, const bool directIo = false);
4142
static Status Write(const std::string& path, const size_t offset, const size_t length,
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
* */
24+
25+
#ifndef UNIFIEDCACHE_TOP_N_HEAP_H
26+
#define UNIFIEDCACHE_TOP_N_HEAP_H
27+
28+
#include <algorithm>
29+
#include <cstdint>
30+
31+
namespace UC {
32+
33+
template <typename T, typename Compare = std::less<T>>
34+
class TopNHeap {
35+
public:
36+
using ValueType = T;
37+
using SizeType = uint32_t;
38+
using ConstRef = const T&;
39+
40+
private:
41+
using IndexType = uint32_t;
42+
std::vector<ValueType> val_{};
43+
std::vector<IndexType> idx_{};
44+
SizeType capacity_{0};
45+
SizeType size_{0};
46+
Compare cmp_{};
47+
48+
public:
49+
explicit TopNHeap(const SizeType capacity) noexcept(
50+
std::is_nothrow_default_constructible_v<Compare>)
51+
: capacity_{capacity} {
52+
val_.resize(capacity);
53+
idx_.resize(capacity);
54+
}
55+
TopNHeap(const TopNHeap&) = delete;
56+
TopNHeap(const TopNHeap&&) = delete;
57+
TopNHeap& operator=(const TopNHeap&) = delete;
58+
TopNHeap& operator=(const TopNHeap&&) = delete;
59+
~TopNHeap() { Clear(); }
60+
61+
SizeType Size() const noexcept { return size_; }
62+
SizeType Capacity() const noexcept { return capacity_; }
63+
bool Empty() const noexcept { return size_ == 0; }
64+
65+
void Push(ConstRef value) noexcept {
66+
if (size_ < capacity_) {
67+
val_[size_] = value;
68+
idx_[size_] = size_;
69+
SiftUp(size_);
70+
size_++;
71+
return;
72+
}
73+
if (cmp_(val_[idx_.front()], value)) {
74+
val_[idx_.front()] = value;
75+
SiftDown(0);
76+
}
77+
}
78+
ConstRef Top() const noexcept { return val_[idx_.front()]; }
79+
void Pop() noexcept {
80+
idx_[0] = idx_[--size_];
81+
if (size_) { SiftDown(0); }
82+
}
83+
void Clear() noexcept { size_ = 0; }
84+
private:
85+
static IndexType Parent(IndexType i) noexcept { return (i - 1) / 2; }
86+
static IndexType Left(IndexType i) noexcept { return 2 * i + 1; }
87+
static IndexType Right(IndexType i) noexcept { return 2 * i + 2; }
88+
void SiftUp(IndexType i) noexcept {
89+
auto pos = i;
90+
while (pos > 0) {
91+
auto p = Parent(pos);
92+
if (!cmp_(val_[idx_[pos]], val_[idx_[p]])) { break; }
93+
std::swap(idx_[pos], idx_[p]);
94+
pos = p;
95+
}
96+
}
97+
void SiftDown(IndexType i) noexcept {
98+
auto pos = i;
99+
for (;;) {
100+
auto l = Left(pos);
101+
auto r = Right(pos);
102+
auto best = pos;
103+
if (l < size_ && cmp_(val_[idx_[l]], val_[idx_[best]])) { best = l; }
104+
if (r < size_ && cmp_(val_[idx_[r]], val_[idx_[best]])) { best = r; }
105+
if (best == pos) { break; }
106+
std::swap(idx_[pos], idx_[best]);
107+
pos = best;
108+
}
109+
}
110+
};
111+
112+
template <typename T, size_t N, typename Compare = std::less<T>>
113+
class TopNFixedHeap : public TopNHeap<T, Compare> {
114+
public:
115+
TopNFixedHeap() : TopNHeap<T, Compare>{N} {}
116+
};
117+
118+
} // namespace UC
119+
120+
#endif

ucm/store/nfsstore/cc/api/nfsstore.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class NFSStoreImpl : public NFSStore {
3535
int32_t Setup(const Config& config)
3636
{
3737
auto status = this->spaceMgr_.Setup(config.storageBackends, config.kvcacheBlockSize,
38-
config.tempDumpDirEnable, config.storageCapacity);
38+
config.tempDumpDirEnable, config.storageCapacity,
39+
config.recycleEnable, config.recycleThresholdRatio);
3940
if (status.Failure()) {
4041
UC_ERROR("Failed({}) to setup SpaceManager.", status);
4142
return status.Underlying();
@@ -121,6 +122,8 @@ class NFSStoreImpl : public NFSStore {
121122
UC_INFO("Set UC::HotnessInterval to {}.", config.hotnessInterval);
122123
UC_INFO("Set UC::HotnessEnable to {}.", config.hotnessEnable);
123124
UC_INFO("Set UC::storageCapacity to {}.", config.storageCapacity);
125+
UC_INFO("Set UC::RecycleEnable to {}.", config.recycleEnable);
126+
UC_INFO("Set UC::RecycleThreshold to {}.", config.recycleThresholdRatio);
124127
}
125128

126129
private:

ucm/store/nfsstore/cc/api/nfsstore.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@ class NFSStore : public CCStore {
4444
bool hotnessEnable;
4545
size_t hotnessInterval;
4646
size_t storageCapacity;
47+
bool recycleEnable;
48+
float recycleThresholdRatio;
4749

4850
Config(const std::vector<std::string>& storageBackends, const size_t kvcacheBlockSize,
4951
const bool transferEnable)
5052
: storageBackends{storageBackends}, kvcacheBlockSize{kvcacheBlockSize},
5153
transferEnable{transferEnable}, transferDeviceId{-1}, transferStreamNumber{32},
5254
transferIoSize{262144}, transferBufferNumber{512}, transferTimeoutMs{30000},
5355
tempDumpDirEnable{false}, hotnessEnable{true}, hotnessInterval{60},
54-
storageCapacity{0}
56+
storageCapacity{0}, recycleEnable{true}, recycleThresholdRatio{0.7f}
5557
{
5658
}
5759
};

ucm/store/nfsstore/cc/domain/space/space_layout.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,24 @@
2424
#ifndef UNIFIEDCACHE_SPACE_LAYOUT_H
2525
#define UNIFIEDCACHE_SPACE_LAYOUT_H
2626

27+
#include <memory>
2728
#include <string>
2829
#include <vector>
2930
#include "status/status.h"
3031

3132
namespace UC {
3233

3334
class SpaceLayout {
35+
public:
36+
struct DataIterator;
3437
public:
3538
virtual ~SpaceLayout() = default;
3639
virtual Status Setup(const std::vector<std::string>& storageBackends) = 0;
3740
virtual std::string DataFileParent(const std::string& blockId, bool activated) const = 0;
3841
virtual std::string DataFilePath(const std::string& blockId, bool activated) const = 0;
3942
virtual std::string ClusterPropertyFilePath() const = 0;
43+
virtual std::shared_ptr<DataIterator> CreateFilePathIterator() const = 0;
44+
virtual std::string NextDataFilePath(std::shared_ptr<DataIterator> iter) const = 0;
4045
};
4146

4247
} // namespace UC

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ std::unique_ptr<SpaceLayout> MakeSpaceLayout(const bool tempDumpDirEnable)
4040
}
4141

4242
Status SpaceManager::Setup(const std::vector<std::string>& storageBackends, const size_t blockSize,
43-
const bool tempDumpDirEnable, const size_t storageCapacity)
43+
const bool tempDumpDirEnable, const size_t storageCapacity,
44+
const bool recycleEnable, const float recycleThresholdRatio)
4445
{
4546
if (blockSize == 0) {
4647
UC_ERROR("Invalid block size({}).", blockSize);
@@ -51,9 +52,18 @@ Status SpaceManager::Setup(const std::vector<std::string>& storageBackends, cons
5152
auto status = this->layout_->Setup(storageBackends);
5253
if (status.Failure()) { return status; }
5354
status = this->property_.Setup(this->layout_->ClusterPropertyFilePath());
55+
if (recycleEnable && storageCapacity > 0) {
56+
auto totalBlocks = storageCapacity / blockSize;
57+
status = this->recycle_.Setup(this->GetSpaceLayout(), totalBlocks, [this] {
58+
this->property_.DecreaseCapacity(this->blockSize_);
59+
});
60+
if (status.Failure()) { return status; }
61+
}
5462
if (status.Failure()) { return status; }
5563
this->blockSize_ = blockSize;
5664
this->capacity_ = storageCapacity;
65+
this->recycleEnable_ = recycleEnable;
66+
this->capacityRecycleThreshold_ = static_cast<size_t>(storageCapacity * recycleThresholdRatio);
5767
return Status::OK();
5868
}
5969

@@ -143,11 +153,14 @@ bool SpaceManager::LookupBlock(const std::string& blockId) const
143153

144154
const SpaceLayout* SpaceManager::GetSpaceLayout() const { return this->layout_.get(); }
145155

146-
Status SpaceManager::CapacityCheck() const
156+
Status SpaceManager::CapacityCheck()
147157
{
148158
if (this->capacity_ == 0) { return Status::OK(); }
149159

150160
const size_t used = this->property_.GetCapacity();
161+
if (this->recycleEnable_ && used >= this->capacityRecycleThreshold_) {
162+
this->recycle_.Trigger();
163+
}
151164
if (used > this->capacity_ - this->blockSize_) {
152165
UC_ERROR("Capacity is not enough, capacity: {}, current: {}, block size: {}.",
153166
this->capacity_, used, this->blockSize_);

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,30 @@
2828
#include "space_layout.h"
2929
#include "space_property.h"
3030
#include "status/status.h"
31+
#include "space_recycle.h"
3132

3233
namespace UC {
3334

3435
class SpaceManager {
3536
public:
3637
Status Setup(const std::vector<std::string>& storageBackends, const size_t blockSize,
37-
const bool tempDumpDirEnable, const size_t storageCapacity = 0);
38+
const bool tempDumpDirEnable, const size_t storageCapacity = 0,
39+
const bool recycleEnable = false, const float recycleThresholdRatio = 0.7f);
3840
Status NewBlock(const std::string& blockId);
3941
Status CommitBlock(const std::string& blockId, bool success = true);
4042
bool LookupBlock(const std::string& blockId) const;
4143
const SpaceLayout* GetSpaceLayout() const;
4244

4345
private:
44-
Status CapacityCheck() const;
46+
Status CapacityCheck();
4547
private:
4648
std::unique_ptr<SpaceLayout> layout_;
4749
SpaceProperty property_;
50+
SpaceRecycle recycle_;
4851
size_t blockSize_;
4952
size_t capacity_;
53+
bool recycleEnable_;
54+
size_t capacityRecycleThreshold_;
5055
};
5156

5257
} // namespace UC

0 commit comments

Comments
 (0)