/* Copyright (C) 2019 MariaDB Corporaton This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SMComm.h" #include "messageFormat.h" using namespace std; using namespace messageqcpp; namespace { idbdatafile::SMComm *instance = NULL; boost::mutex m; }; namespace idbdatafile { SMComm * SMComm::get() { if (instance) return instance; boost::mutex::scoped_lock sl(m); if (instance) return instance; instance = new SMComm(); return instance; } // timesavers #define common_exit(bs1, bs2, retCode) \ { \ buffers.returnByteStream(bs1); \ buffers.returnByteStream(bs2); \ return retCode; \ } // bs1 is the bytestream ptr with the command to SMComm. // bs2 is the bytestream pointer with the response from SMComm. // retCode is the var to store the return code in from the msg. // returns with the output pointer at the fcn-specific data #define check_for_error(bs1, bs2, retCode) \ { \ int l_errno; \ *bs2 >> retCode; \ if (retCode < 0) \ { \ *bs2 >> l_errno; \ errno = l_errno; \ common_exit(bs1, bs2, retCode); \ } \ } SMComm::SMComm() { } SMComm::~SMComm() { } int SMComm::open(const string &filename, const int mode, struct stat *statbuf) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::OPEN << filename << mode; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); memcpy(statbuf, response->buf(), sizeof(*statbuf)); common_exit(command, response, err); } ssize_t SMComm::pread(const string &filename, void *buf, const size_t count, const off_t offset) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::READ << filename << count << offset; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); memcpy(buf, response->buf(), err); common_exit(command, response, err); } ssize_t SMComm::pwrite(const string &filename, const void *buf, const size_t count, const off_t offset) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::WRITE << filename << count << offset; command->needAtLeast(count); uint8_t *cmdBuf = command->getInputPtr(); memcpy(cmdBuf, buf, count); command->advanceInputPtr(count); err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); common_exit(command, response, err); } ssize_t SMComm::append(const string &filename, const void *buf, const size_t count) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::APPEND << filename << count; command->needAtLeast(count); uint8_t *cmdBuf = command->getInputPtr(); memcpy(cmdBuf, buf, count); command->advanceInputPtr(count); err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); common_exit(command, response, err); } int SMComm::unlink(const string &filename) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::UNLINK << filename; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); common_exit(command, response, err); } int SMComm::stat(const string &filename, struct stat *statbuf) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::STAT << filename; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); memcpy(statbuf, response->buf(), sizeof(*statbuf)); common_exit(command, response, err); } int SMComm::truncate(const string &filename, const off64_t length) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::TRUNCATE << filename << length; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); common_exit(command, response, err); } int SMComm::listDirectory(const string &path, list *entries) { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::LIST_DIRECTORY << path; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); uint32_t numElements; string stmp; entries->clear(); *response >> numElements; while (numElements > 0) { *response >> stmp; entries->push_back(stmp); } common_exit(command, response, err); } int SMComm::ping() { ByteStream *command = buffers.getByteStream(); ByteStream *response = buffers.getByteStream(); int err; *command << (uint8_t) storagemanager::PING; err = sockets.send_recv(*command, response); if (err) common_exit(command, response, err); check_for_error(command, response, err); common_exit(command, response, err); } }