From 4f47ee1f96d6b007f83c255774b5ca0554057fb5 Mon Sep 17 00:00:00 2001 From: Patrick LeBlanc Date: Fri, 1 Feb 2019 13:05:29 -0600 Subject: [PATCH] Implemented the SM-side copy op & a couple minor changes. --- CMakeLists.txt | 1 + include/messageFormat.h | 25 +++++++++++++++-- src/AppendTask.cpp | 1 - src/CopyTask.cpp | 57 +++++++++++++++++++++++++++++++++++++++ src/CopyTask.h | 24 +++++++++++++++++ src/IOCoordinator.cpp | 23 +++++++++++++++- src/IOCoordinator.h | 1 + src/ListDirectoryTask.cpp | 1 - src/OpenTask.cpp | 1 - src/ProcessTask.cpp | 4 +++ src/ReadTask.cpp | 1 - src/StatTask.cpp | 1 - src/TruncateTask.cpp | 1 - src/UnlinkTask.cpp | 1 - src/unit_tests.cpp | 48 +++++++++++++++++++++++++++++++++ 15 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 src/CopyTask.cpp create mode 100644 src/CopyTask.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 358275837..91b8ed0b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(storagemanager_SRCS src/TruncateTask.cpp src/UnlinkTask.cpp src/WriteTask.cpp + src/CopyTask.cpp src/IOCoordinator.cpp src/SessionManager.cpp ) diff --git a/include/messageFormat.h b/include/messageFormat.h index 29ecf9725..d3e6928fc 100644 --- a/include/messageFormat.h +++ b/include/messageFormat.h @@ -60,7 +60,8 @@ enum Opcodes { APPEND, TRUNCATE, LIST_DIRECTORY, - PING + PING, + COPY }; /* @@ -74,7 +75,8 @@ enum Opcodes { On success, what follows is any output parameters from the call. - TBD: Require filenames to be NULL-terminated. Currently they are not. + Note: filenames and pathnames in the following parameters should + be absolute rather than relative. */ /* @@ -240,7 +242,26 @@ struct ping_cmd { uint8_t opcode; }; +/* + COPY + ---- + command format: + 1-byte opcode|4-byte filename1 length|filename2|4-byte filename2 length|filename2 + response format: +*/ + +struct f_name { + uint32_t flen; + char filename[]; +}; + +struct copy_cmd { + uint8_t opcode; + f_name file1; + // use f_name as an overlay at the end of file1 to get file2. +}; + #pragma pack(pop) } diff --git a/src/AppendTask.cpp b/src/AppendTask.cpp index 063999282..92df13ff1 100644 --- a/src/AppendTask.cpp +++ b/src/AppendTask.cpp @@ -1,7 +1,6 @@ #include "AppendTask.h" #include "messageFormat.h" -#include "IOCoordinator.h" #include using namespace std; diff --git a/src/CopyTask.cpp b/src/CopyTask.cpp new file mode 100644 index 000000000..a97f60c8b --- /dev/null +++ b/src/CopyTask.cpp @@ -0,0 +1,57 @@ + +#include "CopyTask.h" +#include +#include "messageFormat.h" + +using namespace std; + +namespace storagemanager +{ + +CopyTask::CopyTask(int sock, uint len) : PosixTask(sock, len) +{ +} + +CopyTask::~CopyTask() +{ +} + +#define check_error(msg) \ + if (!success) \ + { \ + handleError(msg, errno); \ + return; \ + } + +void CopyTask::run() +{ + bool success; + uint8_t buf[2048] = {0}; + + if (getLength() > 2047) + { + handleError("CopyTask read", ENAMETOOLONG); + return; + } + + success = read(buf, getLength()); + check_error("CopyTask read"); + copy_cmd *cmd = (copy_cmd *) buf; + string filename1(cmd->file1.filename, cmd->file1.flen); // need to copy this in case it's not null terminated + f_name *filename2 = (f_name *) &buf[sizeof(copy_cmd) + cmd->file1.flen]; + + int err = ioc->copyFile(filename1.c_str(), filename2->filename); + if (err) + { + handleError("CopyTask copy", errno); + return; + } + + sm_msg_resp *resp = (sm_msg_resp *) buf; + resp->type = SM_MSG_START; + resp->payloadLen = 4; + resp->returnCode = 0; + write(buf, sizeof(sm_msg_resp)); +} + +} diff --git a/src/CopyTask.h b/src/CopyTask.h new file mode 100644 index 000000000..80ba927e9 --- /dev/null +++ b/src/CopyTask.h @@ -0,0 +1,24 @@ + +#ifndef COPYTASK_H_ +#define COPYTASK_H_ + +#include "PosixTask.h" + +namespace storagemanager +{ + +class CopyTask : public PosixTask +{ + public: + CopyTask(int sock, uint length); + virtual ~CopyTask(); + + void run(); + + private: + CopyTask(); +}; + + +} +#endif diff --git a/src/IOCoordinator.cpp b/src/IOCoordinator.cpp index e1587dad8..cfcdb48ba 100644 --- a/src/IOCoordinator.cpp +++ b/src/IOCoordinator.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace std; @@ -54,7 +55,7 @@ struct scoped_closer { }; #define OPEN(name, mode) \ - fd = ::open(filename, mode, 0666); \ + fd = ::open(filename, mode, 0660); \ if (fd < 0) \ return fd; \ scoped_closer sc(fd); @@ -164,4 +165,24 @@ int IOCoordinator::unlink(const char *path) return ::unlink(path); } +int IOCoordinator::copyFile(const char *filename1, const char *filename2) +{ + int err = 0, l_errno; + try { + boost::filesystem::copy_file(filename1, filename2); + } + catch (boost::filesystem::filesystem_error &e) { + err = -1; + l_errno = EIO; // why not. + // eh, not going to translate all of boost's errors into our errors for this. + // log the error + cout << "IOCoordinator::copy(): got " << e.what() << endl; + } + catch (...) { + err = -1; + l_errno = EIO; + } + return err; +} + } diff --git a/src/IOCoordinator.h b/src/IOCoordinator.h index bb73aafba..a91716157 100644 --- a/src/IOCoordinator.h +++ b/src/IOCoordinator.h @@ -28,6 +28,7 @@ class IOCoordinator : public boost::noncopyable int stat(const char *path, struct stat *out); int truncate(const char *path, size_t newsize); int unlink(const char *path); + int copyFile(const char *filename1, const char *filename2); private: IOCoordinator(); diff --git a/src/ListDirectoryTask.cpp b/src/ListDirectoryTask.cpp index a6eb50ff7..b486cea1e 100644 --- a/src/ListDirectoryTask.cpp +++ b/src/ListDirectoryTask.cpp @@ -1,6 +1,5 @@ #include "ListDirectoryTask.h" -#include "IOCoordinator.h" #include "messageFormat.h" #include #include diff --git a/src/OpenTask.cpp b/src/OpenTask.cpp index e59f12ece..3329dc7e6 100644 --- a/src/OpenTask.cpp +++ b/src/OpenTask.cpp @@ -1,7 +1,6 @@ #include "OpenTask.h" -#include "IOCoordinator.h" #include "messageFormat.h" #include #include diff --git a/src/ProcessTask.cpp b/src/ProcessTask.cpp index bf47e2576..eb7263cb8 100644 --- a/src/ProcessTask.cpp +++ b/src/ProcessTask.cpp @@ -5,6 +5,7 @@ #include "messageFormat.h" #include "AppendTask.h" +#include "CopyTask.h" #include "ListDirectoryTask.h" #include "OpenTask.h" #include "PingTask.h" @@ -89,6 +90,9 @@ void ProcessTask::operator()() case PING: task = new PingTask(sock, length); break; + case COPY: + task = new CopyTask(sock, length); + break; default: throw runtime_error("ProcessTask: got an unknown opcode"); } diff --git a/src/ReadTask.cpp b/src/ReadTask.cpp index e6b291e99..3f86aa9e2 100644 --- a/src/ReadTask.cpp +++ b/src/ReadTask.cpp @@ -1,7 +1,6 @@ #include "ReadTask.h" #include "messageFormat.h" -#include "IOCoordinator.h" #include using namespace std; diff --git a/src/StatTask.cpp b/src/StatTask.cpp index a8724ef7c..40114afc5 100644 --- a/src/StatTask.cpp +++ b/src/StatTask.cpp @@ -1,7 +1,6 @@ #include "StatTask.h" #include "messageFormat.h" -#include "IOCoordinator.h" #include #include #include diff --git a/src/TruncateTask.cpp b/src/TruncateTask.cpp index c8077bf06..1e18dc8be 100644 --- a/src/TruncateTask.cpp +++ b/src/TruncateTask.cpp @@ -1,6 +1,5 @@ #include "TruncateTask.h" -#include "IOCoordinator.h" #include #include "messageFormat.h" diff --git a/src/UnlinkTask.cpp b/src/UnlinkTask.cpp index ff1446517..9b5484b52 100644 --- a/src/UnlinkTask.cpp +++ b/src/UnlinkTask.cpp @@ -1,6 +1,5 @@ #include "UnlinkTask.h" -#include "IOCoordinator.h" #include #include "messageFormat.h" diff --git a/src/unit_tests.cpp b/src/unit_tests.cpp index 575ec98ce..09899f3eb 100644 --- a/src/unit_tests.cpp +++ b/src/unit_tests.cpp @@ -6,6 +6,7 @@ #include "TruncateTask.h" #include "ListDirectoryTask.h" #include "PingTask.h" +#include "CopyTask.h" #include "messageFormat.h" #include #include @@ -398,6 +399,52 @@ bool pingtask() cout << "pingtask OK" << endl; } +bool copytask() +{ + /* + make a file + copy it + verify it exists + */ + const char *filename = "copytest1"; + ::unlink(filename); + int fd = ::open(filename, O_CREAT | O_RDWR, 0666); + assert(fd > 0); + scoped_closer f(fd); + int err = ::write(fd, "testjunk", 8); + assert(err == 8); + + uint8_t buf[1024]; + copy_cmd *cmd = (copy_cmd *) buf; + cmd->opcode = COPY; + cmd->file1.flen = strlen(filename); + strncpy(cmd->file1.filename, filename, cmd->file1.flen); + const char *filename2 = "copytest2"; + f_name *file2 = (f_name *) &cmd->file1.filename[cmd->file1.flen]; + file2->flen = strlen(filename2); + strncpy(file2->filename, filename2, file2->flen); + + uint len = (uint64_t) &file2->filename[file2->flen] - (uint64_t) buf; + ::write(sessionSock, buf, len); + CopyTask c(clientSock, len); + c.run(); + + // read the response + err = ::recv(sessionSock, buf, 1024, MSG_DONTWAIT); + sm_msg_resp *resp = (sm_msg_resp *) buf; + assert(err == sizeof(sm_msg_resp)); + assert(resp->type == SM_MSG_START); + assert(resp->payloadLen == 4); + assert(resp->returnCode == 0); + + // verify copytest2 is there + assert(boost::filesystem::exists(filename2)); + ::unlink(filename); + ::unlink(filename2); + cout << "copytask OK " << endl; + return true; +} + int main() { cout << "connecting" << endl; @@ -412,5 +459,6 @@ int main() truncatetask(); listdirtask(); pingtask(); + copytask(); return 0; }