Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ucm/store/infra/file/ifile.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class IFile {
virtual Status MMap(void*& addr, size_t size, bool write, bool read, bool shared) = 0;
virtual void MUnmap(void* addr, size_t size) = 0;
virtual void ShmUnlink() = 0;
virtual Status UpdateTime() = 0;

private:
std::string path_;
Expand Down
12 changes: 12 additions & 0 deletions ucm/store/infra/file/posix_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <utime.h>
#include <unistd.h>
#include "logger/logger.h"

Expand Down Expand Up @@ -230,4 +231,15 @@ void PosixFile::ShmUnlink()
}
}

Status PosixFile::UpdateTime()
{
auto ret = utime(this->Path().c_str(), nullptr);
auto eno = errno;
if (ret != 0) {
UC_ERROR("Failed({},{}) to update time file({}).", ret, eno, this->Path());
return Status::OsApiError();
}
return Status::OK();
}

} // namespace UC
1 change: 1 addition & 0 deletions ucm/store/infra/file/posix_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class PosixFile : public IFile {
Status MMap(void*& addr, size_t size, bool write, bool read, bool shared) override;
void MUnmap(void* addr, size_t size) override;
void ShmUnlink() override;
Status UpdateTime() override;

private:
int32_t handle_;
Expand Down
93 changes: 93 additions & 0 deletions ucm/store/infra/template/timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* MIT License
*
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* */
#ifndef UNIFIEDCACHE_TIMER_H
#define UNIFIEDCACHE_TIMER_H

#include <chrono>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include "logger/logger.h"
#include "status/status.h"

namespace UC {

template <typename Callable>
class Timer {
public:
Timer(const std::chrono::seconds& interval, Callable&& callable)
: interval_(interval), callable_(callable), running_(false) {}
~Timer() {
{
std::lock_guard<std::mutex> lg(this->mutex_);
this->running_ = false;
}

this->cv_.notify_one();
if (this->thread_.joinable()) { this->thread_.join(); }
}
Status Start()
{
{
std::lock_guard<std::mutex> lg(this->mutex_);
if (this->running_) { return Status::OK(); }
}
try {
this->running_ = true;
this->thread_ = std::thread(&Timer::Runner, this);
return Status::OK();
} catch (const std::exception& e) {
UC_ERROR("Failed({}) to start timer.", e.what());
return Status::OutOfMemory();
}
}

private:
void Runner()
{
while (this->running_) {
try {
{
std::unique_lock<std::mutex> lg(this->mutex_);
this->cv_.wait_for(lg, this->interval_, [this] { return !this->running_; });
if (!this->running_) { break; }
}
this->callable_();
} catch (const std::exception& e) { UC_ERROR("Failed({}) to run timer.", e.what()); }
}
}

private:
std::chrono::seconds interval_;
Callable callable_;
std::thread thread_;
std::mutex mutex_;
std::condition_variable cv_;
std::atomic<bool> running_;
};

} // namespace UC

#endif
18 changes: 17 additions & 1 deletion ucm/store/nfsstore/cc/api/nfsstore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "logger/logger.h"
#include "space/space_manager.h"
#include "trans/trans_manager.h"
#include "hotness/hotness_manager.h"

namespace UC {

Expand All @@ -49,14 +50,26 @@ class NFSStoreImpl : public NFSStore {
return status.Underlying();
}
}
if (config.hotnessEnable) {
status = this->hotnessMgr_.Setup(config.hotnessInterval, this->spaceMgr_.GetSpaceLayout());
if (status.Failure()) {
UC_ERROR("Failed({}) to setup HotnessManager.", status);
return status.Underlying();
}
}
this->ShowConfig(config);
return Status::OK().Underlying();
}
int32_t Alloc(const std::string& block) override
{
return this->spaceMgr_.NewBlock(block).Underlying();
}
bool Lookup(const std::string& block) override { return this->spaceMgr_.LookupBlock(block); }
bool Lookup(const std::string& block) override
{
auto found = this->spaceMgr_.LookupBlock(block);
if (found) { this->hotnessMgr_.Visit(block); }
return found;
}
void Commit(const std::string& block, const bool success) override
{
this->spaceMgr_.CommitBlock(block, success);
Expand Down Expand Up @@ -105,11 +118,14 @@ class NFSStoreImpl : public NFSStore {
UC_INFO("Set UC::BufferNumber to {}.", config.transferBufferNumber);
UC_INFO("Set UC::TimeoutMs to {}.", config.transferTimeoutMs);
UC_INFO("Set UC::TempDumpDirEnable to {}.", config.tempDumpDirEnable);
UC_INFO("Set UC::HotnessInterval to {}.", config.hotnessInterval);
UC_INFO("Set UC::HotnessEnable to {}.", config.hotnessEnable);
}

private:
SpaceManager spaceMgr_;
TransManager transMgr_;
HotnessManager hotnessMgr_;
};

int32_t NFSStore::Setup(const Config& config)
Expand Down
4 changes: 3 additions & 1 deletion ucm/store/nfsstore/cc/api/nfsstore.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ class NFSStore : public CCStore {
size_t transferBufferNumber;
size_t transferTimeoutMs;
bool tempDumpDirEnable;
bool hotnessEnable;
size_t hotnessInterval;

Config(const std::vector<std::string>& storageBackends, const size_t kvcacheBlockSize,
const bool transferEnable)
: storageBackends{storageBackends}, kvcacheBlockSize{kvcacheBlockSize},
transferEnable{transferEnable}, transferDeviceId{-1}, transferStreamNumber{32},
transferIoSize{262144}, transferBufferNumber{512}, transferTimeoutMs{30000},
tempDumpDirEnable{false}
tempDumpDirEnable{false}, hotnessEnable{true}, hotnessInterval{60}
{
}
};
Expand Down
75 changes: 75 additions & 0 deletions ucm/store/nfsstore/cc/domain/hotness/hotness_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* MIT License
*
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* */

#ifndef UNIFIEDCACHE_HOTNESS_MANAGER_H
#define UNIFIEDCACHE_HOTNESS_MANAGER_H

#include <atomic>
#include <functional>
#include "hotness_set.h"
#include "hotness_timer.h"
#include "logger/logger.h"

namespace UC {

class HotnessManager {
public:
Status Setup(const size_t interval, const SpaceLayout* spaceLayout)
{
this->hotnessTimer_.SetInterval(interval);
this->layout_ = spaceLayout;
this->setupSuccess_ = true;
return Status::OK();
}

void Visit(const std::string& blockId)
{
if (!this->setupSuccess_) {
return;
}

this->hotnessSet_.Insert(blockId);
auto old = this->serviceRunning_.load(std::memory_order_acquire);
if (old) { return; }
if (this->serviceRunning_.compare_exchange_weak(old, true, std::memory_order_acq_rel)) {
auto updater = std::bind(&HotnessSet::UpdateHotness, &this->hotnessSet_, this->layout_);
if (this->hotnessTimer_.Start(std::move(updater)).Success()) {
UC_INFO("Space hotness service started.");
return;
}
this->serviceRunning_ = old;
}
}

private:
bool setupSuccess_{false};
std::atomic_bool serviceRunning_{false};
const SpaceLayout* layout_;
HotnessSet hotnessSet_;
HotnessTimer hotnessTimer_;
};

} // namespace UC

#endif
70 changes: 70 additions & 0 deletions ucm/store/nfsstore/cc/domain/hotness/hotness_set.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* MIT License
*
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* */

#include "hotness_set.h"
#include "logger/logger.h"
#include "file/file.h"
#include "template/singleton.h"
namespace UC {

void HotnessSet::Insert(const std::string& blockId)
{
std::lock_guard<std::mutex> lg(this->mutex_);
this->pendingBlocks_.insert(blockId);
}

void HotnessSet::UpdateHotness(const SpaceLayout* spaceLayout)
{
std::unordered_set<std::string> blocksToUpdate;
{
std::lock_guard<std::mutex> lg(this->mutex_);
if (this->pendingBlocks_.empty()) {
return;
}
blocksToUpdate.swap(this->pendingBlocks_);
}

size_t number = 0;
for (const std::string& blockId : blocksToUpdate) {
auto blockPath = spaceLayout->DataFilePath(blockId, false);
auto file = File::Make(blockPath);
if (!file) {
UC_WARN("Failed to make file({}), blockId({}).", blockPath, blockId);
continue;
}
auto status = file->UpdateTime();
if (status.Failure()) {
UC_WARN("Failed({}) to update time({}), blockId({}).", status, blockPath, blockId);
continue;
}
number++;
}
if (blocksToUpdate.size() == number) {
UC_INFO("All blocks are hotness.");
} else {
UC_WARN("{} of {} blocks are hotness.", blocksToUpdate.size() - number, blocksToUpdate.size());
}
}

} // namespace UC
Loading