-
Notifications
You must be signed in to change notification settings - Fork 415
[TransferEngine] Introduce generic NVMeoF transport implementation (#780) #793
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…talling Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
561c299 to
ab2a023
Compare
Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
Signed-off-by: Jinlong Chen <[email protected]>
ab2a023 to
8ada073
Compare
Signed-off-by: Jinlong Chen <[email protected]>
|
Hello, I'm very happy to see the code support for NVMe over Fabrics as a transport. However, I have a small question to ask. Will adding NVMe segments here conflict with the currently implemented tiered caching mechanism #578 , Mooncake+3FS, or are the two compatible? |
Hello, the two should be compatible by design. Although not recommended, NVMe segments can be used with 3FS, just like memory segments. |
| local_buffer_size, protocol, | ||
| rdma_devices, master_server_addr); | ||
| }) | ||
| .def("setup_with_files", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add more parameters in setup or use environment variables to complete the file setup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can.
The only difference between setup_with_files and setup is that setup_with_files takes a files argument instead of the global_segment_size argument. We can add the files argument as the last argument of setup for compatibility. Do you think this is better than adding setup_with_files?
|
Currently working on releasing 0.3.5 and will review this PR ASAP. @nickyc975 |
Signed-off-by: Jinlong Chen <[email protected]>
|
1.请问一下通过NVMeoF实现传输,是client持久化的逻辑吗? |
NVMeoF传输与当前的client持久化逻辑是相互独立的,暂时还不能替换现有的持久化逻辑。 |
mooncake-store/include/allocator.h
Outdated
| std::string segment_name, FileBufferID file_id, | ||
| void* buffer_ptr, std::size_t size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid add a new parameter. Could we combine FileBufferID and buffer_ptr as a union or an optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the file_id parameter can be removed according to #883 . I am working on it.
| std::vector<BufferDesc> buffers; | ||
| // this is for nvmeof. | ||
| std::vector<NVMeoFBufferDesc> nvmeof_buffers; | ||
| // Generic file buffers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be #ifdef USE_NVMEOF_GENERIC here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logically we can have other transports than support file buffers. Therefore, file buffer components are intended to be separated from NVMeoF components.
|
Could you resolve the conflicts? thx. @nickyc975 |
Done. |
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a generic NVMeoF transport implementation, which is a significant and well-structured feature addition. The changes are extensive, touching documentation, CMake build files, C++ source code for both the store and transfer engine, and Python bindings. The overall implementation looks solid. I've identified a few areas for improvement, primarily related to maintainability and documentation clarity. Specifically, I've pointed out a typo in the documentation, suggested refactoring a couple of functions that use goto to improve readability, and recommended adding more detailed comments to explain a workaround for CacheLib's memory allocation.
doc/en/nvmeof_generic_transport.md
Outdated
| ```bash | ||
| ./build/mooncake-transfer-engine/example/transfer_engine_nvmeof_generic_bench \ | ||
| --local_server_name=127.0.0.1:8081 \ | ||
| --metadata_server=http://127.0.0.0.0:8080/metadata \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There appears to be a typo in the IP address for the metadata server. It's written as 127.0.0.0.0, but it should likely be 127.0.0.1 to match the other examples and standard loopback usage.
| --metadata_server=http://127.0.0.0.0:8080/metadata \ | |
| --metadata_server=http://127.0.0.1:8080/metadata \ |
mooncake-store/src/allocator.cpp
Outdated
| // Add a padding to base to support zero-based buffers. | ||
| auto padded_base = base + facebook::cachelib::Slab::kSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment "Add a padding to base to support zero-based buffers" is a bit brief. To improve maintainability, could you add a more detailed explanation for why this padding is necessary for CacheLib? For example, explaining if CacheLib has issues with zero addresses or if this is to avoid some other specific behavior would be very helpful for future developers who might need to work with this code.
| static size_t getFileSize(const std::string& file) { | ||
| size_t size = 0; | ||
| struct stat st; | ||
| int rc; | ||
|
|
||
| int fd = open(file.c_str(), O_RDONLY); | ||
| if (fd < 0) { | ||
| LOG(ERROR) << "Failed to open file " << file << ", errno=" << errno; | ||
| goto out; | ||
| } | ||
|
|
||
| rc = fstat(fd, &st); | ||
| if (rc < 0) { | ||
| LOG(ERROR) << "Failed fstat on file " << file << ", errno=" << errno; | ||
| goto close_file; | ||
| } | ||
|
|
||
| if (S_ISLNK(st.st_mode)) { | ||
| LOG(ERROR) << "File " << file << " is a symbolic link"; | ||
| goto close_file; | ||
| } | ||
|
|
||
| if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { | ||
| rc = ioctl(fd, BLKGETSIZE64, &size); | ||
| if (rc < 0) { | ||
| LOG(ERROR) << "Failed ioctl on file " << file | ||
| << ", errno=" << errno; | ||
| size = 0; | ||
| } | ||
| } else if (S_ISREG(st.st_mode)) { | ||
| size = st.st_size; | ||
| } | ||
|
|
||
| close_file: | ||
| close(fd); | ||
| out: | ||
| return size; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getFileSize function uses goto statements for flow control. While functional, this can make the code harder to read and maintain. Consider refactoring to avoid goto, for example by using early returns. This will improve code clarity and align with modern C++ best practices.
static size_t getFileSize(const std::string& file) {
size_t size = 0;
int fd = open(file.c_str(), O_RDONLY);
if (fd < 0) {
LOG(ERROR) << "Failed to open file " << file << ", errno=" << errno;
return 0;
}
struct stat st;
if (fstat(fd, &st) < 0) {
LOG(ERROR) << "Failed fstat on file " << file << ", errno=" << errno;
close(fd);
return 0;
}
if (S_ISLNK(st.st_mode)) {
LOG(ERROR) << "File " << file << " is a symbolic link";
close(fd);
return 0;
}
if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
LOG(ERROR) << "Failed ioctl on file " << file
<< ", errno=" << errno;
size = 0;
}
} else if (S_ISREG(st.st_mode)) {
size = st.st_size;
}
close(fd);
return size;
}| static size_t getFileSize(const std::string &file) { | ||
| size_t size = 0; | ||
| struct stat st; | ||
|
|
||
| int fd = open(file.c_str(), O_RDONLY); | ||
| if (fd < 0) { | ||
| goto err_out; | ||
| } | ||
|
|
||
| if (fstat(fd, &st) != 0) { | ||
| goto err_close_file; | ||
| } | ||
|
|
||
| if (S_ISLNK(st.st_mode)) { | ||
| goto err_close_file; | ||
| } | ||
|
|
||
| if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { | ||
| ioctl(fd, BLKGETSIZE64, &size); | ||
| } else if (S_ISREG(st.st_mode)) { | ||
| size = st.st_size; | ||
| } | ||
|
|
||
| err_close_file: | ||
| close(fd); | ||
| err_out: | ||
| return size; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This getFileSize function uses goto for error handling. To improve code readability and maintainability, consider refactoring it to use early returns instead. This makes the control flow more straightforward and is generally considered a better practice in modern C++.
static size_t getFileSize(const std::string &file) {
size_t size = 0;
struct stat st;
int fd = open(file.c_str(), O_RDONLY);
if (fd < 0) {
return 0;
}
if (fstat(fd, &st) != 0) {
close(fd);
return 0;
}
if (S_ISLNK(st.st_mode)) {
close(fd);
return 0;
}
if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
ioctl(fd, BLKGETSIZE64, &size);
} else if (S_ISREG(st.st_mode)) {
size = st.st_size;
}
close(fd);
return size;
}52d7c85 to
41cdb49
Compare
This pull request adds support for file segments to Transfer Engine and Mooncake Store, then introduces a generic NVMeoF transport implementation to Transfer Engine.
Please read the RFC (#780) and the documents in this PR for more information.