diff --git a/include/messageFormat.h b/include/messageFormat.h index 3c1fe4d09..29ecf9725 100644 --- a/include/messageFormat.h +++ b/include/messageFormat.h @@ -181,17 +181,25 @@ struct stat_cmd { struct stat_resp { struct stat statbuf; -} +}; /* TRUNCATE -------- command format: - 1-byte opcode|off64_t length|4-byte filename length|filename + 1-byte opcode|off_t length|4-byte filename length|filename response format: - +*/ +struct truncate_cmd { + uint8_t opcode; // == TRUNCATE + off_t length; + uint32_t flen; + char filename[]; +}; + +/* LIST_DIRECTORY -------------- command format: @@ -200,15 +208,38 @@ struct stat_resp { response format: 4-byte num elements| (4-byte filename length|filename) * num elements - +*/ + +struct listdir_cmd { + uint8_t opcode; // == LIST_DIRECTORY + uint32_t plen; + char path[]; +}; + +struct listdir_resp_entry { + uint32_t flen; + char filename[]; +}; + +struct listdir_resp { + uint32_t elements; + listdir_resp_entry entries[]; + // followed by (elements * listdir_resp_entry) +}; + +/* PING ---- command format: 1-byte opcode - reponse format: - + response format: + nothing yet */ +struct ping_cmd { + uint8_t opcode; +}; + #pragma pack(pop) diff --git a/src/ListDirectoryTask.cpp b/src/ListDirectoryTask.cpp index c05af0c62..4c7a6aa5d 100644 --- a/src/ListDirectoryTask.cpp +++ b/src/ListDirectoryTask.cpp @@ -4,6 +4,7 @@ #include "messageFormat.h" #include #include +#include using namespace std; @@ -77,20 +78,24 @@ void ListDirectoryTask::run() success = read(buf, getLength()); check_error("ListDirectoryTask read"); - cmd_overlay *cmd = (cmd_overlay *) buf; + listdir_cmd *cmd = (listdir_cmd *) buf; vector listing; err = ioc->listDirectory(cmd->path, &listing); - uint payloadLen = 4 * listing.size(); + // be careful modifying the listdir return types... + uint payloadLen = sizeof(listdir_resp_entry) * listing.size(); for (uint i = 0; i < listing.size(); i++) payloadLen += listing.size(); - uint32_t *buf32 = (uint32_t *) buf; - buf32[0] = SM_MSG_START; - buf32[1] = payloadLen; + sm_msg_resp *resp = (sm_msg_resp *) buf; + resp->type = SM_MSG_START; + resp->payloadLen = payloadLen + sizeof(listdir_resp); + resp->returnCode = 0; + listdir_resp *r = (listdir_resp *) resp->payload; + r->elements = listing.size(); - int offset = SM_HEADER_LEN; + int offset = (uint64_t) r->entries - (uint64_t) buf; for (uint i = 0; i < listing.size(); i++) { success = writeString(buf, &offset, 1024, listing[i]); diff --git a/src/ListDirectoryTask.h b/src/ListDirectoryTask.h index 8a99ad755..42544bfe2 100644 --- a/src/ListDirectoryTask.h +++ b/src/ListDirectoryTask.h @@ -20,10 +20,6 @@ class ListDirectoryTask : public PosixTask ListDirectoryTask(); bool writeString(uint8_t *buf, int *offset, int size, const std::string &str); - struct cmd_overlay { - uint plen; - char path[]; - }; }; diff --git a/src/PingTask.cpp b/src/PingTask.cpp index a2cb6b4f7..2b11e5420 100644 --- a/src/PingTask.cpp +++ b/src/PingTask.cpp @@ -1,6 +1,7 @@ #include "PingTask.h" #include "messageFormat.h" +#include namespace storagemanager { @@ -16,8 +17,28 @@ PingTask::~PingTask() void PingTask::run() { // not much to check on for Milestone 1 - uint32_t buf[3] = { SM_MSG_START, 4, 0 }; // generic success response - write((uint8_t *) buf, 12); + + uint8_t buf; + + if (getLength() > 1) + { + handleError("PingTask", E2BIG); + return; + } + // consume the msg + bool success = read(&buf, getLength()); + if (!success) + { + handleError("PingTask", errno); + return; + } + + // send generic success response + sm_msg_resp ret; + ret.type = SM_MSG_START; + ret.payloadLen = 4; + ret.returnCode = 0; + write((uint8_t *) &ret, sizeof(ret)); } } diff --git a/src/StatTask.cpp b/src/StatTask.cpp index 4e949c25c..57d74a07f 100644 --- a/src/StatTask.cpp +++ b/src/StatTask.cpp @@ -42,19 +42,20 @@ void StatTask::run() success = read(buf, getLength()); check_error("StatTask read"); - cmd_overlay *cmd = (cmd_overlay *) buf; + stat_cmd *cmd = (stat_cmd *) buf; + sm_msg_resp *resp = (sm_msg_resp *) buf; - int err = ioc->stat(cmd->path, (struct stat *) &buf[SM_HEADER_LEN]); + int err = ioc->stat(cmd->filename, (struct stat *) resp->payload); if (err) { handleError("StatTask stat", errno); return; } - - uint32_t *buf32 = (uint32_t *) buf; - buf32[0] = SM_MSG_START; - buf32[1] = sizeof(struct stat); - write(buf, SM_HEADER_LEN + sizeof(struct stat)); + + resp->type = SM_MSG_START; + resp->payloadLen = sizeof(struct stat) + 4; + resp->returnCode = 0; + write(buf, sizeof(*resp) + sizeof(struct stat)); } } diff --git a/src/StatTask.h b/src/StatTask.h index 7e71edad6..00ed9a109 100644 --- a/src/StatTask.h +++ b/src/StatTask.h @@ -17,11 +17,6 @@ class StatTask : public PosixTask private: StatTask(); - - struct cmd_overlay { - uint plen; - char path[]; - }; }; diff --git a/src/TruncateTask.cpp b/src/TruncateTask.cpp index f1f7b778d..bbd43474a 100644 --- a/src/TruncateTask.cpp +++ b/src/TruncateTask.cpp @@ -38,20 +38,20 @@ void TruncateTask::run() success = read(buf, getLength()); check_error("TruncateTask read"); - cmd_overlay *cmd = (cmd_overlay *) buf; + truncate_cmd *cmd = (truncate_cmd *) buf; - int err = ioc->truncate(cmd->filename, cmd->newSize); + int err = ioc->truncate(cmd->filename, cmd->length); if (err) { handleError("TruncateTask truncate", errno); return; } - uint32_t *buf32 = (uint32_t *) buf; - buf32[0] = SM_MSG_START; - buf32[1] = 4; - buf32[2] = 0; - write(buf, 12); + 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/TruncateTask.h b/src/TruncateTask.h index 7a56df7d0..c4d9f6796 100644 --- a/src/TruncateTask.h +++ b/src/TruncateTask.h @@ -17,12 +17,6 @@ class TruncateTask : public PosixTask private: TruncateTask(); - - struct cmd_overlay { - off64_t newSize; - uint flen; - char filename[]; - }; }; diff --git a/src/unit_tests.cpp b/src/unit_tests.cpp index 737dfe5b3..4b4517692 100644 --- a/src/unit_tests.cpp +++ b/src/unit_tests.cpp @@ -2,6 +2,10 @@ #include "WriteTask.h" #include "AppendTask.h" #include "UnlinkTask.h" +#include "StatTask.h" +#include "TruncateTask.h" +#include "ListDirectoryTask.h" +#include "PingTask.h" #include "IOCoordinator.h" #include "messageFormat.h" #include @@ -254,6 +258,148 @@ bool unlinktask() cout << "unlink task OK" << endl; } +bool stattask() +{ + const char *filename = "stattest1"; + ::unlink(filename); + int fd = ::open(filename, O_CREAT | O_RDWR, 0666); + assert(fd > 0); + scoped_closer f(fd); + + uint8_t buf[1024]; + stat_cmd *cmd = (stat_cmd *) buf; + + cmd->opcode = STAT; + cmd->flen = strlen(filename); + strcpy((char *) cmd->filename, filename); + + ::write(sessionSock, cmd, sizeof(*cmd) + cmd->flen); + StatTask s(clientSock, sizeof(*cmd) + cmd->flen); + s.run(); + + // read the response + int err = ::recv(sessionSock, buf, 1024, MSG_DONTWAIT); + sm_msg_resp *resp = (sm_msg_resp *) buf; + assert(err == sizeof(struct stat) + sizeof(sm_msg_resp)); + assert(resp->type == SM_MSG_START); + assert(resp->payloadLen == sizeof(struct stat) + 4); + assert(resp->returnCode == 0); + struct stat *_stat = (struct stat *) resp->payload; + + // what can we verify about the stat... + assert(_stat->st_uid == getuid()); + assert(_stat->st_gid == getgid()); + assert(_stat->st_size == 0); + + ::unlink(filename); + cout << "stattask OK" << endl; + return true; +} + +bool truncatetask() +{ + const char *filename = "trunctest1"; + ::unlink(filename); + int fd = ::open(filename, O_CREAT | O_RDWR, 0666); + assert(fd > 0); + scoped_closer f(fd); + + uint8_t buf[1024]; + truncate_cmd *cmd = (truncate_cmd *) buf; + + cmd->opcode = TRUNCATE; + cmd->length = 1000; + cmd->flen = strlen(filename); + strcpy((char *) cmd->filename, filename); + + ::write(sessionSock, cmd, sizeof(*cmd) + cmd->flen); + TruncateTask t(clientSock, sizeof(*cmd) + cmd->flen); + t.run(); + + // read the response + int 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); + + struct stat statbuf; + ::stat(filename, &statbuf); + assert(statbuf.st_size == 1000); + ::unlink(filename); + cout << "truncate task OK" << endl; + return true; +} + +bool listdirtask() +{ + // make a file, make sure it's in the list returned. + const char *filename = "listdirtest1"; + ::unlink(filename); + int fd = ::open(filename, O_CREAT | O_RDWR, 0666); + assert(fd > 0); + scoped_closer f(fd); + + uint8_t buf[1024]; + listdir_cmd *cmd = (listdir_cmd *) buf; + + cmd->opcode = LIST_DIRECTORY; + cmd->plen = 1; + cmd->path[0] = '.'; + + ::write(sessionSock, cmd, sizeof(*cmd) + cmd->plen); + ListDirectoryTask l(clientSock, sizeof(*cmd) + cmd->plen); + l.run(); + + /* going to keep this simple. Don't run this in a big dir. */ + /* maybe later I'll make a dir, put a file in it, and etc. For now run it in a small dir. */ + int err = ::recv(sessionSock, buf, 1024, MSG_DONTWAIT); + sm_msg_resp *resp = (sm_msg_resp *) buf; + assert(err > 0); + assert(resp->type == SM_MSG_START); + assert(resp->returnCode == 0); + listdir_resp *r = (listdir_resp *) resp->payload; + //cout << "resp has " << r->elements << " elements" << endl; + int off = sizeof(sm_msg_resp) + sizeof(listdir_resp); + while (off < err) + { + listdir_resp_entry *e = (listdir_resp_entry *) &buf[off]; + //cout << "len = " << e->flen << endl; + assert(off + e->flen + sizeof(listdir_resp_entry) < 1024); + if (!strncmp(e->filename, filename, strlen(filename))) { + cout << "listdirtask OK" << endl; + return true; + } + //string name(e->filename, e->flen); + //cout << "name = " << name << endl; + off += e->flen + sizeof(listdir_resp_entry); + } + cout << "listdirtask(). Didn't find '" << filename << " in the listing. Dir too large for this test?" << endl; + assert(1); + return false; +} + +bool pingtask() +{ + uint8_t buf[1024]; + ping_cmd *cmd = (ping_cmd *) buf; + cmd->opcode = PING; + + ::write(sessionSock, cmd, sizeof(*cmd)); + PingTask p(clientSock, sizeof(*cmd)); + p.run(); + + // read the response + int 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); + cout << "pingtask OK" << endl; +} + int main() { ioc = new IOCoordinator(); @@ -265,5 +411,9 @@ int main() writetask(); appendtask(); unlinktask(); + stattask(); + truncatetask(); + listdirtask(); + pingtask(); return 0; }