Skip to content
Open
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
88 changes: 88 additions & 0 deletions mooncake-store/include/tiered_cache/cache_tier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#pragma once

#include <string>
#include <vector>
#include <memory>
#include <optional>

#include "transfer_engine.h"

namespace mooncake {

struct DataSource;
enum class MemoryType;
class TieredBackend;
Comment on lines +12 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove redundant forward declarations.

DataSource and MemoryType are forward-declared but then fully defined in the same header (lines 20 and 37). These forward declarations are unnecessary. Additionally, forward-declaring an enum class before its definition in the same translation unit is non-standard.

 namespace mooncake {

-struct DataSource;
-enum class MemoryType;
 class TieredBackend;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
struct DataSource;
enum class MemoryType;
class TieredBackend;
class TieredBackend;
🤖 Prompt for AI Agents
In mooncake-store/include/tiered_cache/cache_tier.h around lines 12-14, remove
the redundant forward declarations of DataSource and MemoryType (and the forward
declaration of TieredBackend if it duplicates a later definition) because
DataSource and MemoryType are fully defined later in the same header (around
lines 20 and 37) and forward-declaring an enum class in the same translation
unit is non-standard; delete those forward-declaration lines and ensure any
references still compile (no other headers rely on them here) so the file uses
the later full definitions.


/**
* @enum MemoryType
* @brief Defines the physical storage medium type for a cache tier.
*/
enum class MemoryType { DRAM, NVME, UNKNOWN };

static inline std::string MemoryTypeToString(MemoryType type) {
switch (type) {
case MemoryType::DRAM:
return "DRAM";
case MemoryType::NVME:
return "NVME";
default:
return "UNKNOWN";
}
}

/**
* @struct DataSource
* @brief Describes a source of data for copy/write operations.
*/
struct DataSource {
uint64_t ptr; // Pointer to data (if in memory) / file descriptor
uint64_t offset; // Offset within the source (for files/SSDs)
size_t size; // Size in bytes
MemoryType type; // Source memory type
};

/**
* @class CacheTier
* @brief Abstract base class for a single tier (e.g., DRAM, SSD).
* * Update: Supports decoupled Allocation/Write/Bind operations to allow
* flexible placement strategies (Client-centric vs Master-centric).
*/
class CacheTier {
public:
virtual ~CacheTier() = default;

/**
* @brief Initializes the cache tier.
*/
virtual bool Init(TieredBackend* backend, TransferEngine* engine) = 0;

/**
* @brief Reserve Space (Allocation)
* Finds free space of `size` bytes. Does NOT copy data.
* * @param size Bytes to allocate.
* @param data DataSource struct to fill with allocation info.
* @return true if allocation succeeds.
*/
virtual bool Allocate(size_t size, DataSource& data) = 0;

/**
* @brief Free Space (Rollback/Cleanup)
* Releases space at offset. Used when writes fail or explicitly freeing
* anonymous blocks.
*/
virtual bool Free(DataSource data) = 0;

// --- Accessors & Metadata ---
virtual uint64_t GetTierId() const = 0;
virtual size_t GetCapacity() const = 0;
virtual size_t GetUsage() const = 0;
virtual MemoryType GetMemoryType() const = 0;
virtual const std::vector<std::string>& GetTags() const = 0;

protected:
// A pointer to the parent backend, allowing tiers to access shared services
// like the DataCopier.
TieredBackend* backend_ = nullptr;
};

} // namespace mooncake
86 changes: 86 additions & 0 deletions mooncake-store/include/tiered_cache/copier_registry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#pragma once

#include "tiered_cache/cache_tier.h"
#include "tiered_cache/data_copier.h"
#include <functional>
#include <map>
#include <string>
#include <vector>

namespace mooncake {

// Forward declaration from data_copier.h to avoid circular dependency
class DataCopierBuilder;

// Holds the registration information for a memory type.
struct MemoryTypeRegistration {
MemoryType type;
CopyFunction to_dram_func;
CopyFunction from_dram_func;
};

// Holds the registration for an optimized direct path.
struct DirectPathRegistration {
MemoryType src_type;
MemoryType dest_type;
CopyFunction func;
};

/**
* @brief A singleton registry for data copier functions.
*
* Modules can register their copy functions here during static initialization.
* The DataCopierBuilder will then use this registry to construct a DataCopier.
*/
class CopierRegistry {
public:
/**
* @brief Get the singleton instance of the registry.
*/
static CopierRegistry& GetInstance();

/**
* @brief Registers the to/from DRAM copy functions for a memory type.
*/
void RegisterMemoryType(MemoryType type, CopyFunction to_dram,
CopyFunction from_dram);

/**
* @brief Registers an optional, optimized direct copy path.
*/
void RegisterDirectPath(MemoryType src, MemoryType dest, CopyFunction func);

// These methods are used by the DataCopierBuilder to collect all
// registrations.
const std::vector<MemoryTypeRegistration>& GetMemoryTypeRegistrations()
const;
const std::vector<DirectPathRegistration>& GetDirectPathRegistrations()
const;

private:
friend class DataCopierBuilder;

CopierRegistry() = default;
~CopierRegistry() = default;
CopierRegistry(const CopierRegistry&) = delete;
CopierRegistry& operator=(const CopierRegistry&) = delete;

std::vector<MemoryTypeRegistration> memory_type_regs_;
std::vector<DirectPathRegistration> direct_path_regs_;
};

/**
* @brief A helper class to automatically register copiers at static
* initialization time.
*
* To register a new memory type, simply declare a static instance of this class
* in the corresponding .cpp file, providing the type and its to/from DRAM
* copiers.
*/
class CopierRegistrar {
public:
CopierRegistrar(MemoryType type, CopyFunction to_dram,
CopyFunction from_dram);
};

} // namespace mooncake
90 changes: 90 additions & 0 deletions mooncake-store/include/tiered_cache/data_copier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include "tiered_cache/cache_tier.h"
#include <functional>
#include <map>
#include <memory>
#include <glog/logging.h>
#include <stdexcept>
#include <vector>

namespace mooncake {

using CopyFunction =
std::function<bool(const DataSource& src, const DataSource& dst)>;

class DataCopier;

/**
* @brief A helper class to build a valid DataCopier.
*
* This builder enforces the rule that for any new memory type added,
* its copy functions to and from DRAM *must* be provided via the
* CopierRegistry.
*/
class DataCopierBuilder {
public:
/**
* @brief Constructs a builder. It automatically pulls all existing
* registrations from the global CopierRegistry.
*/
DataCopierBuilder();

/**
* @brief (Optional) Registers a highly optimized direct copy path.
* This will be used instead of the DRAM fallback. Can be used for testing
* or for paths that are not self-registered.
* @return A reference to the builder for chaining.
*/
DataCopierBuilder& AddDirectPath(MemoryType src_type, MemoryType dest_type,
CopyFunction func);

/**
* @brief Builds the final, immutable DataCopier object.
* It verifies that all memory types defined in the MemoryType enum
* have been registered via the registry before creating the object.
* @return A unique_ptr to the new DataCopier.
* @throws std::logic_error if a required to/from DRAM copier is missing.
*/
std::unique_ptr<DataCopier> Build() const;

private:
std::map<std::pair<MemoryType, MemoryType>, CopyFunction> copy_matrix_;
};

/**
* @brief A central utility for copying data between different memory types.
* It supports a fallback mechanism via DRAM for any copy paths that are not
* explicitly registered as a direct path.
*/
class DataCopier {
public:
// The constructor is private. Use DataCopierBuilder to create an instance.
~DataCopier() = default;
DataCopier(const DataCopier&) = delete;
DataCopier& operator=(const DataCopier&) = delete;

/**
* @brief Executes a copy from a source to a destination.
* It first attempts to find a direct copy function (e.g., VRAM -> VRAM).
* If not found, it automatically falls back to a two-step copy via a
* temporary DRAM buffer (e.g., VRAM -> DRAM -> SSD).
* @param src The data source descriptor.
* @param dest_type The memory type of the destination.
* @param dest_ptr A pointer to the destination (memory address, handle,
* etc.).
* @return True if the copy was successful, false otherwise.
*/
bool Copy(const DataSource& src, const DataSource& dst) const;

private:
friend class DataCopierBuilder; // Allow builder to access the constructor.
DataCopier(
std::map<std::pair<MemoryType, MemoryType>, CopyFunction> copy_matrix);

CopyFunction FindCopier(MemoryType src_type, MemoryType dest_type) const;
const std::map<std::pair<MemoryType, MemoryType>, CopyFunction>
copy_matrix_;
};

} // namespace mooncake
Loading
Loading