#include "ReadTask.h" #include "messageFormat.h" #include using namespace std; namespace storagemanager { ReadTask::ReadTask(int sock, uint len) : PosixTask(sock, len) { } ReadTask::~ReadTask() { } #define check_error(msg, ret) \ if (!success) \ { \ handleError(msg, errno); \ return ret; \ } #define max(x, y) (x > y ? x : y) bool ReadTask::run() { uint8_t buf[1024] = {0}; // get the parameters if (getLength() > 1023) { handleError("ReadTask read", EFAULT); return true; } bool success; success = read(buf, getLength()); check_error("ReadTask read cmd", false); read_cmd *cmd = (read_cmd *) buf; #ifdef SM_TRACE cout << "read " << cmd->filename << " count " << cmd->count << " offset " << cmd->offset << endl; #endif // read from IOC, write to the socket vector outbuf; outbuf.resize(max(cmd->count, 4) + sizeof(sm_response)); sm_response *resp = (sm_response *) &outbuf[0]; resp->returnCode = 0; uint payloadLen = 0; // todo: do the reading and writing in chunks // todo: need to make this use O_DIRECT on the IOC side ioc->willRead(cmd->filename, cmd->offset, cmd->count); int err; while (resp->returnCode < cmd->count) { err = ioc->read(cmd->filename, &resp->payload[resp->returnCode], cmd->offset + resp->returnCode, cmd->count - resp->returnCode); if (err < 0) { if (resp->returnCode == 0) { resp->returnCode = err; payloadLen = 4; *((int32_t *) resp->payload) = errno; } break; } if (err == 0) break; resp->returnCode += err; } if (resp->returnCode >= 0) payloadLen = resp->returnCode; success = write(*resp, payloadLen); return success; } }