diff --git a/src/common/time_utils.cc b/src/common/time_utils.cc index 0822d1729..6059d7010 100644 --- a/src/common/time_utils.cc +++ b/src/common/time_utils.cc @@ -110,15 +110,24 @@ int64_t Timer::lap_s() { // Timeout implementation -Timeout::Timeout(std::chrono::nanoseconds timeout) : - timeout_(std::chrono::duration_cast(timeout)) { +Timeout::Timeout(std::chrono::nanoseconds timeout) { + if (timeout.count() < 0) { + infinite_ = true; + timeout_ = SteadyDuration(0); + } else { + infinite_ = false; + timeout_ = std::chrono::duration_cast(timeout); + } } SteadyTimePoint Timeout::deadline() const { + if (infinite_) { return SteadyTimePoint::max(); } return startTime() + timeout_; } SteadyDuration Timeout::remainingTime() const { + if (infinite_) { return SteadyDuration::max(); } + SteadyDuration elapsed = elapsedTime(); if (elapsed >= timeout_) { return SteadyDuration(0); @@ -128,21 +137,26 @@ SteadyDuration Timeout::remainingTime() const { } int64_t Timeout::remaining_ns() const { + if (infinite_) { return -1; } return duration_int64_cast(remainingTime()); } int64_t Timeout::remaining_us() const { + if (infinite_) { return -1; } return duration_int64_cast(remainingTime()); } int64_t Timeout::remaining_ms() const { + if (infinite_) { return -1; } return duration_int64_cast(remainingTime()); } int64_t Timeout::remaining_s() const { + if (infinite_) { return -1; } return duration_int64_cast>(remainingTime()); } bool Timeout::expired() const { + if (infinite_) { return false; } return remainingTime() == SteadyDuration(0); } diff --git a/src/common/time_utils.h b/src/common/time_utils.h index 523dde4d4..a4fcc2af5 100644 --- a/src/common/time_utils.h +++ b/src/common/time_utils.h @@ -96,4 +96,5 @@ class Timeout : public Timer { bool expired() const; private: SteadyDuration timeout_; + bool infinite_ = false; }; diff --git a/src/common/time_utils_unittest.cc b/src/common/time_utils_unittest.cc index 610f0b63d..84800fcfc 100644 --- a/src/common/time_utils_unittest.cc +++ b/src/common/time_utils_unittest.cc @@ -72,3 +72,21 @@ TEST(TimeUtilsTests, TimerAndTimeout) { EXPECT_EQ(0, timeout.remaining_ns()); EXPECT_TRUE(timeout.expired()); } + +TEST(TimeUtilsTests, InfiniteTimeout) { + Timeout timeout(std::chrono::milliseconds(-1)); + + EXPECT_FALSE(timeout.expired()); + EXPECT_EQ(timeout.remaining_ms(), -1); + EXPECT_EQ(timeout.remaining_us(), -1); + EXPECT_EQ(timeout.remaining_ns(), -1); + EXPECT_EQ(timeout.remaining_s(), -1); + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + EXPECT_FALSE(timeout.expired()); + EXPECT_EQ(timeout.remaining_ms(), -1); + EXPECT_EQ(timeout.remaining_us(), -1); + EXPECT_EQ(timeout.remaining_ns(), -1); + EXPECT_EQ(timeout.remaining_s(), -1); +} diff --git a/src/tools/append_file.cc b/src/tools/append_file.cc index 7099a2c56..5b9d12748 100644 --- a/src/tools/append_file.cc +++ b/src/tools/append_file.cc @@ -27,6 +27,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" #include "tools/tools_commands.h" @@ -41,15 +42,12 @@ static void append_file_usage() { } static int append_file(const char *fname, const char *afname) { - uint32_t cmd, leng, uid, gid; + uint32_t uid, gid; uint32_t msgid{0}; inode_t inode, ainode; + uint8_t status; - constexpr uint32_t kAppendFilePayload = - sizeof(msgid) + sizeof(inode) + sizeof(ainode) + sizeof(uid) + sizeof(gid); - constexpr uint32_t kReqBuffSize = sizeof(cmd) + sizeof(kAppendFilePayload) + kAppendFilePayload; - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; + MessageBuffer request, response; mode_t dmode, smode; int fd; @@ -74,73 +72,30 @@ static int append_file(const char *fname, const char *afname) { uid = getUId(); gid = getGId(); - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_APPEND); - put32bit(&wptr, kAppendFilePayload); - put32bit(&wptr, msgid); - putINode(&wptr, inode); - putINode(&wptr, ainode); - put32bit(&wptr, uid); - put32bit(&wptr, gid); - - // send the request - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } - - // read the first part of the answer - if (tcpread(fd, reqbuff, sizeof(cmd) + sizeof(leng)) != sizeof(cmd) + sizeof(leng)) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } - - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); + try { + serializeLegacyPacket(request, CLTOMA_FUSE_APPEND, msgid, inode, ainode, uid, gid); + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_APPEND, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); + deserializeAllLegacyPacketDataNoHeader(response, msgid, status); - if (cmd != MATOCL_FUSE_APPEND) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } + close_master_conn(0); - buff = (uint8_t *)malloc(leng); + if (msgid != 0) { + printf("%s: master query: wrong answer (msgid)\n", fname); + return -1; + } - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); + if (status != SAUNAFS_STATUS_OK) { + printf("%s: %s\n", fname, saunafs_error_string(status)); + return -1; + } + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); close_master_conn(1); return -1; } - close_master_conn(0); // not needed anymore - - // check the msgid - rptr = buff; - get32bit(&rptr, msgid); // queryid - if (msgid != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } - - if (leng - sizeof(msgid) != 1) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } - - if (*rptr != SAUNAFS_STATUS_OK) { - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } - - free(buff); - return 0; } diff --git a/src/tools/check_file.cc b/src/tools/check_file.cc index 5730583f5..eeaa62e1f 100644 --- a/src/tools/check_file.cc +++ b/src/tools/check_file.cc @@ -25,6 +25,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "tools/tools_commands.h" #include "tools/tools_common_functions.h" @@ -34,17 +35,11 @@ static void check_file_usage() { } static int check_file(const char *fname) { - uint32_t cmd, leng; uint32_t msgid{0}; inode_t inode; - uint8_t copies; - uint32_t chunks; + uint8_t status; - constexpr uint32_t kCheckFilePayload = sizeof(msgid) + sizeof(inode); - constexpr uint32_t kReqBuffSize = sizeof(cmd) + sizeof(kCheckFilePayload) + kCheckFilePayload; - - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; + MessageBuffer request, response; int fd; fd = open_master_conn(fname, &inode, nullptr, false); @@ -52,104 +47,76 @@ static int check_file(const char *fname) { return -1; } - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_CHECK); - put32bit(&wptr, kCheckFilePayload); - put32bit(&wptr, msgid); - putINode(&wptr, inode); - - // send request to master - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } - - // read the first part of the answer - if (tcpread(fd, reqbuff, sizeof(cmd) + sizeof(leng)) != sizeof(cmd) + sizeof(leng)) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } - - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); - - if (cmd != MATOCL_FUSE_CHECK) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } + try { + serializeLegacyPacket(request, CLTOMA_FUSE_CHECK, msgid, inode); + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_CHECK, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); - buff = (uint8_t *)malloc(leng); - - // read the rest of the answer into the buffer - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + close_master_conn(0); - close_master_conn(0); // not needed anymore + // Parse response buffer + const uint8_t *rptr = response.data(); + get32bit(&rptr, msgid); - rptr = buff; - get32bit(&rptr, msgid); // queryid + if (msgid != 0) { + printf("%s: master query: wrong answer (msgid)\n", fname); + return -1; + } - if (msgid != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } + uint32_t remaining = static_cast(response.size() - sizeof(msgid)); - if (leng - sizeof(msgid) == 1) { // an error code was returned - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } - - leng -= 4; + if (remaining == sizeof(status)) { + status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + return -1; + } - constexpr uint32_t kExpectedSize = + CHUNK_MATRIX_SIZE * sizeof(uint32_t); + constexpr uint32_t kExpectedSize = CHUNK_MATRIX_SIZE * sizeof(uint32_t); - if (leng % 3 != 0 && leng != kExpectedSize) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } + if (remaining % 3 != 0 && remaining != kExpectedSize) { + printf("%s: master query: wrong answer (leng)\n", fname); + return -1; + } - printf("%s:\n", fname); + printf("%s:\n", fname); - if (leng % 3 == 0) { - for (cmd = 0; cmd < leng; cmd += 3) { - copies = get8bit(&rptr); - chunks = get16bit(&rptr); - if (copies == 1) { - printf("1 copy:"); - } else { - printf("%" PRIu8 " copies:", copies); - } - print_number(" ", "\n", chunks, 1, 0, 1); - } - } else { - for (cmd = 0; cmd < CHUNK_MATRIX_SIZE; cmd++) { - get32bit(&rptr, chunks); - if (chunks > 0) { - if (cmd == 1) { - printf(" chunks with 1 copy: "); - } else if (cmd >= 10) { - printf(" chunks with 10+ copies:"); + // Legacy format: N * [copies:8, chunks:16] + if (remaining % 3 == 0) { + for (uint32_t offset = 0; offset < remaining; offset += 3) { + uint8_t copies = get8bit(&rptr); + uint16_t chunkCount16 = get16bit(&rptr); + uint32_t chunkCount = chunkCount16; + if (copies == 1) { + printf("1 copy:"); } else { - printf(" chunks with %u copies: ", cmd); + printf("%" PRIu8 " copies:", copies); + } + print_number(" ", "\n", chunkCount, 1, 0, 1); + } + } else { + // Modern format: CHUNK_MATRIX_SIZE * [chunks:32] + for (uint32_t copyIndex = 0; copyIndex < CHUNK_MATRIX_SIZE; ++copyIndex) { + uint32_t chunkCount = 0; + get32bit(&rptr, chunkCount); + if (chunkCount > 0) { + if (copyIndex == 1) { + printf(" chunks with 1 copy: "); + } else if (copyIndex >= 10) { + printf(" chunks with 10+ copies:"); + } else { + printf(" chunks with %u copies: ", copyIndex); + } + print_number(" ", "\n", chunkCount, 1, 0, 1); } - print_number(" ", "\n", chunks, 1, 0, 1); } } + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; } - free(buff); - return 0; } diff --git a/src/tools/dir_info.cc b/src/tools/dir_info.cc index 8794feda4..1321f7310 100644 --- a/src/tools/dir_info.cc +++ b/src/tools/dir_info.cc @@ -25,6 +25,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "common/type_defs.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" @@ -41,124 +42,95 @@ static void dir_info_usage() { } static int dir_info(const char *fname) { - uint32_t cmd, leng; uint32_t msgid = 0; - inode_t inode, inodes, dirs, files, links; - uint32_t chunks; - uint64_t length, size, realsize; - - constexpr uint8_t kDirStatsPayload = - sizeof(cmd) + sizeof(leng) + sizeof(msgid) + sizeof(inodes) + sizeof(dirs) + sizeof(files) + - sizeof(links) + sizeof(chunks) + sizeof(length) + sizeof(size) + sizeof(realsize); - constexpr uint8_t kDirStatsLegacyPayload = - sizeof(msgid) + sizeof(inodes) + sizeof(dirs) + sizeof(files) + sizeof(links) + - (4 * sizeof(uint32_t)) + sizeof(chunks) + sizeof(length) + sizeof(size) + sizeof(realsize); - - int fd; - fd = open_master_conn(fname, &inode, nullptr, false); - if (fd < 0) { - return -1; - } + inode_t inode; - constexpr uint32_t kDirInfoPayload = sizeof(msgid) + sizeof(inode); - constexpr uint32_t kReqBuffSize = sizeof(cmd) + sizeof(kDirInfoPayload) + kDirInfoPayload; + int fd = open_master_conn(fname, &inode, nullptr, false); + if (fd < 0) { return -1; } - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; + try { + MessageBuffer request, response; + serializeLegacyPacket(request, CLTOMA_FUSE_GETDIRSTATS, msgid, inode); + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_GETDIRSTATS, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_GETDIRSTATS); - put32bit(&wptr, kDirInfoPayload); - put32bit(&wptr, msgid); - putINode(&wptr, inode); + const uint8_t *rptr = response.data(); + get32bit(&rptr, msgid); - // send the request - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + close_master_conn(1); + return -1; + } - // read the first part of the answer (cmd and length) - if (tcpread(fd, reqbuff, sizeof(cmd) + sizeof(leng)) != sizeof(cmd) + sizeof(leng)) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } + uint32_t remaining = static_cast(response.size() - sizeof(msgid)); - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); + if (remaining == sizeof(uint8_t)) { + uint8_t status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + close_master_conn(0); + return (status == SAUNAFS_STATUS_OK) ? 0 : -1; + } - if (cmd != MATOCL_FUSE_GETDIRSTATS) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } + inode_t inodes, dirs, files, links; + uint32_t chunks = 0; + uint64_t length = 0, size = 0, realsize = 0; + + // Expected body sizes (after msgid) + const uint32_t expectedCurrentBody = sizeof(inodes) + sizeof(dirs) + sizeof(files) + + sizeof(links) + sizeof(chunks) + sizeof(length) + + sizeof(size) + sizeof(realsize); + + const uint32_t expectedLegacyBody = + sizeof(inodes) + sizeof(dirs) + sizeof(files) + sizeof(links) + + (4 * sizeof(uint32_t)) + // legacy fillers + sizeof(chunks) + sizeof(length) + sizeof(size) + sizeof(realsize); + + if (remaining != expectedCurrentBody && remaining != expectedLegacyBody) { + printf("%s: master query: wrong answer (leng) %u/(%u|%u)\n", fname, remaining, + expectedCurrentBody, expectedLegacyBody); + close_master_conn(1); + return -1; + } - buff = (uint8_t *)malloc(leng); + getINode(&rptr, inodes); + getINode(&rptr, dirs); + getINode(&rptr, files); + getINode(&rptr, links); - // read the rest of the answer into the buffer - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + const bool isLegacy = (remaining == expectedLegacyBody); + if (isLegacy) { + rptr += 2 * sizeof(uint32_t); // skip empty data (8 bytes) from legacy format + } - rptr = buff; - get32bit(&rptr, msgid); // queryid + get32bit(&rptr, chunks); - if (msgid != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + if (isLegacy) { + rptr += 2 * sizeof(uint32_t); // skip empty data (8 bytes) from legacy format + } - if (leng == sizeof(msgid) + sizeof(uint8_t)) { // status code - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - close_master_conn(1); - return -1; - } + length = get64bit(&rptr); + size = get64bit(&rptr); + realsize = get64bit(&rptr); - if (leng != kDirStatsLegacyPayload && leng != kDirStatsPayload) { - printf("%s: master query: wrong answer (leng) %u/(%u|%u)\n", fname, leng, kDirStatsPayload, - kDirStatsLegacyPayload); - free(buff); - close_master_conn(1); - return -1; - } + close_master_conn(0); - close_master_conn(0); + printf("%s:\n", fname); + print_number(" inodes: ", "\n", inodes, 0, 0, 1); + print_number(" directories: ", "\n", dirs, 0, 0, 1); + print_number(" files: ", "\n", files, 0, 0, 1); + print_number(" links: ", "\n", links, 0, 0, 1); + print_number(" chunks: ", "\n", chunks, 0, 0, 1); + print_number(" length: ", "\n", length, 0, 1, 1); + print_number(" size: ", "\n", size, 0, 1, 1); + print_number(" realsize: ", "\n", realsize, 0, 1, 1); - getINode(&rptr, inodes); - getINode(&rptr, dirs); - getINode(&rptr, files); - getINode(&rptr, links); - if (leng == kDirStatsLegacyPayload) { - rptr += 2 * sizeof(uint32_t); // skip empty data (8 bytes) from legacy format - } - get32bit(&rptr, chunks); - if (leng == kDirStatsLegacyPayload) { - rptr += 2 * sizeof(uint32_t); // skip empty data (8 bytes) from legacy format + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; } - length = get64bit(&rptr); - size = get64bit(&rptr); - realsize = get64bit(&rptr); - - free(buff); - - printf("%s:\n", fname); - print_number(" inodes: ", "\n", inodes, 0, 0, 1); - print_number(" directories: ", "\n", dirs, 0, 0, 1); - print_number(" files: ", "\n", files, 0, 0, 1); - print_number(" links: ", "\n", links, 0, 0, 1); - print_number(" chunks: ", "\n", chunks, 0, 0, 1); - print_number(" length: ", "\n", length, 0, 1, 1); - print_number(" size: ", "\n", size, 0, 1, 1); - print_number(" realsize: ", "\n", realsize, 0, 1, 1); return 0; } diff --git a/src/tools/file_info.cc b/src/tools/file_info.cc index 56f0e3e4b..2c9dcf3a1 100644 --- a/src/tools/file_info.cc +++ b/src/tools/file_info.cc @@ -23,6 +23,7 @@ #include #include "common/chunk_copies_calculator.h" +#include "common/server_connection.h" #include "common/type_defs.h" #include "protocol/cltoma.h" #include "protocol/matocl.h" @@ -50,100 +51,87 @@ static std::string chunkTypeToString(ChunkPartType type) { static int chunks_info(const char *file_name, int fd, inode_t inode) { static constexpr uint32_t kRequestSize = 100; std::vector chunks; - std::vector buffer; - uint32_t message_id, chunk_index; - - chunk_index = 0; - - do { - buffer.clear(); - cltoma::chunksInfo::serialize(buffer, (uint32_t)0, (uint32_t)0, (uint32_t)0, inode, chunk_index, kRequestSize); - if (tcpwrite(fd, buffer.data(), buffer.size()) != (int)buffer.size()) { - printf("%s [%" PRIu32 "]: master query: send error\n", file_name, chunk_index); - return -1; - } - - buffer.resize(PacketHeader::kSize); - if (tcptoread(fd, buffer.data(), PacketHeader::kSize, kInfiniteTimeout) != (int)PacketHeader::kSize) { - printf("%s [%" PRIu32 "]: master query: receive error\n", file_name, chunk_index); - return -1; - } - - PacketHeader header; - deserializePacketHeader(buffer, header); + uint32_t msgid{0}; + uint32_t chunkIndex{0}; - if (header.type != SAU_MATOCL_CHUNKS_INFO) { - printf("%s [%" PRIu32 "]: master query: wrong answer (type)\n", file_name, - chunk_index); - return -1; - } - - buffer.resize(header.length); - - if (tcptoread(fd, buffer.data(), header.length, kInfiniteTimeout) != (int)header.length) { - printf("%s [%" PRIu32 "]: master query: receive error\n", file_name, chunk_index); - return -1; - } - - PacketVersion version; - deserialize(buffer, version, message_id); + try { + do { + MessageBuffer request, response; + cltoma::chunksInfo::serialize(request, (uint32_t)0, (uint32_t)0, (uint32_t)0, inode, + chunkIndex, kRequestSize); + response = ServerConnection::sendAndReceive( + fd, request, SAU_MATOCL_CHUNKS_INFO, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kInfiniteTimeout); + + PacketVersion version; + deserialize(response, version, msgid); + + if (msgid != 0) { + printf("%s [%" PRIu32 "]: master query: wrong answer (queryid)\n", file_name, + chunkIndex); + return -1; + } - if (message_id != 0) { - printf("%s [%" PRIu32 "]: master query: wrong answer (queryid)\n", file_name, - chunk_index); - return -1; - } + uint8_t status = SAUNAFS_STATUS_OK; + if (version == matocl::chunksInfo::kStatusPacketVersion) { + matocl::chunksInfo::deserialize(response, msgid, status); + } else if (version != matocl::chunksInfo::kResponsePacketVersion) { + printf("%s [%" PRIu32 "]: master query: wrong answer (packet version)\n", file_name, + chunkIndex); + return -1; + } - uint8_t status = SAUNAFS_STATUS_OK; - if (version == matocl::chunksInfo::kStatusPacketVersion) { - matocl::chunksInfo::deserialize(buffer, message_id, status); - } else if (version != matocl::chunksInfo::kResponsePacketVersion) { - printf("%s [%" PRIu32 "]: master query: wrong answer (packet version)\n", file_name, - chunk_index); - return -1; - } - if (status != SAUNAFS_STATUS_OK) { - printf("%s [%" PRIu32 "]: %s\n", file_name, chunk_index, saunafs_error_string(status)); - return -1; - } + if (status != SAUNAFS_STATUS_OK) { + printf("%s [%" PRIu32 "]: %s\n", file_name, chunkIndex, + saunafs_error_string(status)); + return -1; + } - chunks.clear(); - matocl::chunksInfo::deserialize(buffer, message_id, chunks); - - for(auto &chunk : chunks) { - if (chunk.chunk_id == 0 && chunk.chunk_version == 0) { - printf("\tchunk %" PRIu32 ": empty\n", chunk_index); - } else { - printf("\tchunk %" PRIu32 ": %016" PRIX64 "_%08" PRIX32 "" - " / (id:%" PRIu64 " ver:%" PRIu32 ")\n", - chunk_index, chunk.chunk_id, chunk.chunk_version, chunk.chunk_id, chunk.chunk_version); - ChunkCopiesCalculator chunk_calculator; - for(const auto &part : chunk.chunk_parts) { - chunk_calculator.addPart(part.chunkType, MediaLabel::kWildcard); - } - chunk_calculator.evalRedundancyLevel(); - if (chunk.chunk_parts.size() > 0) { - std::sort(chunk.chunk_parts.begin(), chunk.chunk_parts.end()); - for (size_t i = 0; i < chunk.chunk_parts.size(); i++) { - printf("\t\tcopy %zu: %s:%s%s\n", i + 1, - chunk.chunk_parts[i].address.toString().c_str(), - chunk.chunk_parts[i].label.c_str(), - chunkTypeToString(chunk.chunk_parts[i].chunkType).c_str()); + chunks.clear(); + matocl::chunksInfo::deserialize(response, msgid, chunks); + + for (auto &chunk : chunks) { + if (chunk.chunk_id == 0 && chunk.chunk_version == 0) { + printf("\tchunk %" PRIu32 ": empty\n", chunkIndex); + } else { + printf("\tchunk %" PRIu32 ": %016" PRIX64 "_%08" PRIX32 " / (id:%" PRIu64 + " ver:%" PRIu32 ")\n", + chunkIndex, chunk.chunk_id, chunk.chunk_version, chunk.chunk_id, + chunk.chunk_version); + + ChunkCopiesCalculator chunk_calculator; + for (const auto &part : chunk.chunk_parts) { + chunk_calculator.addPart(part.chunkType, MediaLabel::kWildcard); } - } - if (chunk_calculator.getFullCopiesCount() == 0) { - if (chunk.chunk_parts.size() == 0) { - printf("\t\tno valid copies !!!\n"); - } else { - printf("\t\tnot enough parts available\n"); + chunk_calculator.evalRedundancyLevel(); + + if (!chunk.chunk_parts.empty()) { + std::sort(chunk.chunk_parts.begin(), chunk.chunk_parts.end()); + for (size_t i = 0; i < chunk.chunk_parts.size(); ++i) { + printf("\t\tcopy %zu: %s:%s%s\n", i + 1, + chunk.chunk_parts[i].address.toString().c_str(), + chunk.chunk_parts[i].label.c_str(), + chunkTypeToString(chunk.chunk_parts[i].chunkType).c_str()); + } + } + + if (chunk_calculator.getFullCopiesCount() == 0) { + if (chunk.chunk_parts.empty()) { + printf("\t\tno valid copies !!!\n"); + } else { + printf("\t\tnot enough parts available\n"); + } } } + ++chunkIndex; } - chunk_index++; - } - } while (chunks.size() >= kRequestSize); + } while (chunks.size() >= kRequestSize); - return 0; + return 0; + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + return -1; + } } static int file_info(const char *fileName) { diff --git a/src/tools/file_repair.cc b/src/tools/file_repair.cc index 6efbcfd41..fa2ff37e9 100644 --- a/src/tools/file_repair.cc +++ b/src/tools/file_repair.cc @@ -25,6 +25,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" #include "tools/tools_commands.h" @@ -41,9 +42,8 @@ static void file_repair_usage() { } static int file_repair(const char *fname, uint8_t correct_only_flag) { - uint32_t cmd, leng; - inode_t inode; uint32_t msgid{0}; + inode_t inode; uint32_t notchanged, erased, repaired; int fd; @@ -55,92 +55,58 @@ static int file_repair(const char *fname, uint8_t correct_only_flag) { uint32_t uid = getUId(); uint32_t gid = getGId(); - constexpr uint32_t kRepairPayload = - sizeof(msgid) + sizeof(inode) + sizeof(uid) + sizeof(gid) + sizeof(correct_only_flag); - constexpr uint32_t kReqBuffSize = sizeof(cmd) + sizeof(kRepairPayload) + kRepairPayload; - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; - - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_REPAIR); - put32bit(&wptr, kRepairPayload); - put32bit(&wptr, msgid); - putINode(&wptr, inode); - put32bit(&wptr, uid); - put32bit(&wptr, gid); - put8bit(&wptr, correct_only_flag); - - // send request to master - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } + try { + MessageBuffer request, response; + serializeLegacyPacket(request, CLTOMA_FUSE_REPAIR, msgid, inode, uid, gid, + correct_only_flag); - // read the first part of the answer - if (tcpread(fd, reqbuff, sizeof(cmd) + sizeof(leng)) != sizeof(cmd) + sizeof(leng)) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_REPAIR, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); + const uint8_t *rptr = response.data(); + get32bit(&rptr, msgid); - if (cmd != MATOCL_FUSE_REPAIR) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + close_master_conn(1); + return -1; + } - buff = (uint8_t *)malloc(leng); + uint32_t remaining = static_cast(response.size() - sizeof(msgid)); - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + if (remaining == sizeof(uint8_t)) { + uint8_t status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + close_master_conn(0); + return (status == SAUNAFS_STATUS_OK) ? 0 : -1; + } - rptr = buff; - get32bit(&rptr, msgid); // queryid + constexpr uint32_t kFileRepairPayload = + sizeof(notchanged) + sizeof(erased) + sizeof(repaired); + if (remaining != kFileRepairPayload) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); + return -1; + } - if (msgid != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + get32bit(&rptr, notchanged); + get32bit(&rptr, erased); + get32bit(&rptr, repaired); - if (leng - sizeof(msgid) == 1) { // an error code was returned - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - close_master_conn(1); - return -1; - } + close_master_conn(0); + + printf("%s:\n", fname); + print_number(" chunks not changed: ", "\n", notchanged, 1, 0, 1); + print_number(" chunks erased: ", "\n", erased, 1, 0, 1); + print_number(" chunks repaired: ", "\n", repaired, 1, 0, 1); - if (leng != sizeof(msgid) + 3 * sizeof(uint32_t)) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); + return 0; + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); close_master_conn(1); return -1; } - - close_master_conn(0); // not needed anymore - - get32bit(&rptr, notchanged); - get32bit(&rptr, erased); - get32bit(&rptr, repaired); - - free(buff); - - printf("%s:\n", fname); - print_number(" chunks not changed: ", "\n", notchanged, 1, 0, 1); - print_number(" chunks erased: ", "\n", erased, 1, 0, 1); - print_number(" chunks repaired: ", "\n", repaired, 1, 0, 1); - - return 0; } int file_repair_run(int argc, char **argv) { diff --git a/src/tools/get_eattr.cc b/src/tools/get_eattr.cc index 00fbabc69..23ae23a8e 100644 --- a/src/tools/get_eattr.cc +++ b/src/tools/get_eattr.cc @@ -25,6 +25,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" #include "tools/tools_commands.h" @@ -37,136 +38,141 @@ static void get_eattr_usage() { } static int get_eattr(const char *fname, uint8_t mode) { - uint32_t cmd, leng; + uint32_t msgid{0}; inode_t inode; - uint8_t fn, dn, i, j; - uint32_t fcnt[EATTR_BITS]; - uint32_t dcnt[EATTR_BITS]; uint8_t eattr; uint32_t cnt; - int fd; - fd = open_master_conn(fname, &inode, nullptr, false); - if (fd < 0) { - return -1; - } + uint8_t status; + uint8_t fileNodes, directoryNodes; - constexpr uint32_t kGetEAttrPayload = sizeof(uint32_t) + sizeof(inode) + sizeof(mode); - constexpr uint32_t kReqBuffSize = sizeof(cmd) + sizeof(kGetEAttrPayload) + kGetEAttrPayload; - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; - - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_GETEATTR); - put32bit(&wptr, kGetEAttrPayload); - put32bit(&wptr, 0); - putINode(&wptr, inode); - put8bit(&wptr, mode); - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } - if (tcpread(fd, reqbuff, 8) != 8) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); - if (cmd != MATOCL_FUSE_GETEATTR) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } - buff = (uint8_t *)malloc(leng); - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } - close_master_conn(0); - rptr = buff; - get32bit(&rptr, cmd); // queryid - if (cmd != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } - leng -= 4; - if (leng == 1) { - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } else if (leng % 5 != 2) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } else if (mode == GMODE_NORMAL && leng != 7) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } - if (mode == GMODE_NORMAL) { - fn = get8bit(&rptr); - dn = get8bit(&rptr); - eattr = get8bit(&rptr); - get32bit(&rptr, cnt); - if ((fn != 0 || dn != 1) && (fn != 1 || dn != 0)) { - printf("%s: master query: wrong answer (fn,dn)\n", fname); - free(buff); + MessageBuffer request, response; + + int fd = open_master_conn(fname, &inode, nullptr, false); + if (fd < 0) { return -1; } + + try { + serializeLegacyPacket(request, CLTOMA_FUSE_GETEATTR, msgid, inode, mode); + + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_GETEATTR, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); + + const uint8_t *rptr = response.data(); + + get32bit(&rptr, msgid); + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + close_master_conn(1); return -1; } - if (cnt != 1) { - printf("%s: master query: wrong answer (cnt)\n", fname); - free(buff); + + uint32_t bodySize = static_cast(response.size() - sizeof(msgid)); + + if (bodySize == sizeof(status)) { + status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + close_master_conn(0); + return (status == SAUNAFS_STATUS_OK) ? 0 : -1; + } + + if (bodySize < sizeof(fileNodes) + sizeof(directoryNodes)) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); return -1; } - printf("%s: ", fname); - if (eattr > 0) { - cnt = 0; - for (j = 0; j < EATTR_BITS; j++) { - if (eattr & (1 << j)) { - printf("%s%s", (cnt) ? "," : "", eattrtab[j]); - cnt = 1; + + fileNodes = get8bit(&rptr); + directoryNodes = get8bit(&rptr); + + bodySize -= (sizeof(fileNodes) + sizeof(directoryNodes)); + + // NORMAL MODE + if (mode == GMODE_NORMAL) { + const uint32_t expectedNormalBody = sizeof(eattr) + sizeof(cnt); + + if (bodySize != expectedNormalBody) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); + return -1; + } + + eattr = get8bit(&rptr); + get32bit(&rptr, cnt); + + if ((fileNodes != 0 || directoryNodes != 1) && + (fileNodes != 1 || directoryNodes != 0)) { + printf("%s: master query: wrong answer (fn,dn)\n", fname); + close_master_conn(1); + return -1; + } + + if (cnt != 1) { + printf("%s: master query: wrong answer (cnt)\n", fname); + close_master_conn(1); + return -1; + } + + close_master_conn(0); + + printf("%s: ", fname); + + if (eattr == 0) { + printf("-\n"); + return 0; + } + + bool first = true; + for (uint8_t j = 0; j < EATTR_BITS; ++j) { + if (eattr & (1u << j)) { + printf("%s%s", first ? "" : ",", eattrtab[j]); + first = false; } } printf("\n"); - } else { - printf("-\n"); + + return 0; } - // printf("%s: %" PRIX8 "\n",fname,eattr); - } else { - for (j = 0; j < EATTR_BITS; j++) { - fcnt[j] = 0; - dcnt[j] = 0; + + // AGGREGATED MODE + const uint32_t entrySize = sizeof(eattr) + sizeof(cnt); + const uint32_t expectedAggregatedBody = (fileNodes + directoryNodes) * entrySize; + + if (bodySize != expectedAggregatedBody) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); + return -1; } - fn = get8bit(&rptr); - dn = get8bit(&rptr); - for (i = 0; i < fn; i++) { + + uint32_t fcnt[EATTR_BITS] = {}; + uint32_t dcnt[EATTR_BITS] = {}; + + for (uint8_t i = 0; i < fileNodes; ++i) { eattr = get8bit(&rptr); get32bit(&rptr, cnt); - for (j = 0; j < EATTR_BITS; j++) { - if (eattr & (1 << j)) { - fcnt[j] += cnt; - } + + for (uint8_t j = 0; j < EATTR_BITS; ++j) { + if (eattr & (1u << j)) { fcnt[j] += cnt; } } } - for (i = 0; i < dn; i++) { + + for (uint8_t i = 0; i < directoryNodes; ++i) { eattr = get8bit(&rptr); get32bit(&rptr, cnt); - for (j = 0; j < EATTR_BITS; j++) { - if (eattr & (1 << j)) { - dcnt[j] += cnt; - } + + for (uint8_t j = 0; j < EATTR_BITS; ++j) { + if (eattr & (1u << j)) { dcnt[j] += cnt; } } } + + close_master_conn(0); + printf("%s:\n", fname); - for (j = 0; j < EATTR_BITS; j++) { + + for (uint8_t j = 0; j < EATTR_BITS; ++j) { if (eattrtab[j][0]) { printf(" not directory nodes with attribute %16s :", eattrtab[j]); print_number(" ", "\n", fcnt[j], 1, 0, 1); + printf(" directories with attribute %16s :", eattrtab[j]); print_number(" ", "\n", dcnt[j], 1, 0, 1); } else { @@ -180,8 +186,13 @@ static int get_eattr(const char *fname, uint8_t mode) { } } } + + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; } - free(buff); + return 0; } diff --git a/src/tools/get_trashtime.cc b/src/tools/get_trashtime.cc index f2c3ec5e8..c4e4cf915 100644 --- a/src/tools/get_trashtime.cc +++ b/src/tools/get_trashtime.cc @@ -26,6 +26,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" #include "tools/tools_commands.h" @@ -40,122 +41,135 @@ static void get_trashtime_usage() { } static int get_trashtime(const char *fname, uint8_t mode) { - uint32_t cmd, leng; + uint32_t msgid = 0; inode_t inode; - uint32_t fn, dn, i; + uint32_t fileNodes, directoryNodes, i; uint32_t trashtime; uint32_t cnt; - int fd; - fd = open_master_conn(fname, &inode, nullptr, false); - if (fd < 0) { - return -1; - } + uint8_t status; - constexpr uint32_t kGetTrashTimePayloadSize = sizeof(uint32_t) + sizeof(inode) + sizeof(mode); - constexpr uint32_t kReqBuffSize = - sizeof(cmd) + sizeof(kGetTrashTimePayloadSize) + kGetTrashTimePayloadSize; - uint8_t reqbuff[kReqBuffSize], *wptr, *buff; - const uint8_t *rptr; - - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_GETTRASHTIME); - put32bit(&wptr, kGetTrashTimePayloadSize); - put32bit(&wptr, 0); - putINode(&wptr, inode); - put8bit(&wptr, mode); - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } - if (tcpread(fd, reqbuff, 8) != 8) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); - if (cmd != MATOCL_FUSE_GETTRASHTIME) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } - buff = (uint8_t *)malloc(leng); - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } - close_master_conn(0); - rptr = buff; - get32bit(&rptr, cmd); // queryid - if (cmd != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } - leng -= 4; - if (leng == 1) { - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } else if (leng < 8 || leng % 8 != 0) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } else if (mode == GMODE_NORMAL && leng != 16) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } - if (mode == GMODE_NORMAL) { - get32bit(&rptr, fn); - get32bit(&rptr, dn); - get32bit(&rptr, trashtime); - get32bit(&rptr, cnt); - if ((fn != 0 || dn != 1) && (fn != 1 || dn != 0)) { - printf("%s: master query: wrong answer (fn,dn)\n", fname); - free(buff); + MessageBuffer request, response; + + int fd = open_master_conn(fname, &inode, nullptr, false); + if (fd < 0) { return -1; } + + try { + serializeLegacyPacket(request, CLTOMA_FUSE_GETTRASHTIME, msgid, inode, mode); + + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_GETTRASHTIME, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); + + const uint8_t *rptr = response.data(); + + get32bit(&rptr, msgid); + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + close_master_conn(1); return -1; } - if (cnt != 1) { - printf("%s: master query: wrong answer (cnt)\n", fname); - free(buff); + + uint32_t bodySize = static_cast(response.size() - sizeof(msgid)); + + if (bodySize == sizeof(status)) { + status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + close_master_conn(0); + return (status == SAUNAFS_STATUS_OK) ? 0 : -1; + } + + const uint32_t headerFieldsSize = sizeof(fileNodes) + sizeof(directoryNodes); + + if (bodySize < headerFieldsSize) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); + return -1; + } + + get32bit(&rptr, fileNodes); + get32bit(&rptr, directoryNodes); + + bodySize -= headerFieldsSize; + + if (mode == GMODE_NORMAL) { + const uint32_t expectedNormalBody = sizeof(trashtime) + sizeof(cnt); + if (bodySize != expectedNormalBody) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); + return -1; + } + + get32bit(&rptr, trashtime); + get32bit(&rptr, cnt); + + if ((fileNodes != 0 || directoryNodes != 1) && + (fileNodes != 1 || directoryNodes != 0)) { + printf("%s: master query: wrong answer (fn,dn)\n", fname); + close_master_conn(1); + return -1; + } + + if (cnt != 1) { + printf("%s: master query: wrong answer (cnt)\n", fname); + close_master_conn(1); + return -1; + } + + close_master_conn(0); + printf("%s: %" PRIu32 "\n", fname, trashtime); + return 0; + } + + const uint32_t entrySize = sizeof(trashtime) + sizeof(cnt); + const uint32_t expectedAggregatedBody = (fileNodes + directoryNodes) * entrySize; + + if (bodySize != expectedAggregatedBody) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(1); return -1; } - printf("%s: %" PRIu32 "\n", fname, trashtime); - } else { + std::vector> files; std::vector> dirs; - get32bit(&rptr, fn); - get32bit(&rptr, dn); - files.reserve(fn); - dirs.reserve(dn); - for (i = 0; i < fn; ++i) { + + files.reserve(fileNodes); + dirs.reserve(directoryNodes); + + for (i = 0; i < fileNodes; ++i) { get32bit(&rptr, trashtime); get32bit(&rptr, cnt); - files.push_back({trashtime, cnt}); + files.emplace_back(trashtime, cnt); } - for (i = 0; i < dn; ++i) { + + for (i = 0; i < directoryNodes; ++i) { get32bit(&rptr, trashtime); get32bit(&rptr, cnt); - dirs.push_back({trashtime, cnt}); + dirs.emplace_back(trashtime, cnt); } + + close_master_conn(0); + std::sort(files.begin(), files.end()); std::sort(dirs.begin(), dirs.end()); + printf("%s:\n", fname); + for (const auto &entry : files) { printf(" files with trashtime %10" PRIu32 " :", entry.first); print_number(" ", "\n", entry.second, 1, 0, 1); } + for (const auto &entry : dirs) { printf(" directories with trashtime %10" PRIu32 " :", entry.first); print_number(" ", "\n", entry.second, 1, 0, 1); } + + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; } - free(buff); + return 0; } diff --git a/src/tools/master_functions.cc b/src/tools/master_functions.cc index 8481d7fa6..8b01de9b8 100644 --- a/src/tools/master_functions.cc +++ b/src/tools/master_functions.cc @@ -61,44 +61,42 @@ static int kMaxMasterRetries = 5; #endif static int master_register(int rfd, uint32_t cuid) { - uint32_t i; - const uint8_t *rptr; - uint8_t *wptr, regbuff[8 + 73]; - - wptr = regbuff; - put32bit(&wptr, CLTOMA_FUSE_REGISTER); - put32bit(&wptr, 73); - memcpy(wptr, FUSE_REGISTER_BLOB_ACL, 64); - wptr += 64; - put8bit(&wptr, REGISTER_TOOLS); - put32bit(&wptr, cuid); - put16bit(&wptr, SAUNAFS_PACKAGE_VERSION_MAJOR); - put8bit(&wptr, SAUNAFS_PACKAGE_VERSION_MINOR); - put8bit(&wptr, SAUNAFS_PACKAGE_VERSION_MICRO); - if (tcpwrite(rfd, regbuff, 8 + 73) != 8 + 73) { - printf("register to master: send error\n"); - return -1; - } - if (tcpread(rfd, regbuff, 9) != 9) { - printf("register to master: receive error\n"); - return -1; - } - rptr = regbuff; - get32bit(&rptr, i); - if (i != MATOCL_FUSE_REGISTER) { - printf("register to master: wrong answer (type)\n"); - return -1; - } - get32bit(&rptr, i); - if (i != 1) { - printf("register to master: wrong answer (length)\n"); - return -1; - } - if (*rptr) { - printf("register to master: %s\n", saunafs_error_string(*rptr)); + MessageBuffer request, response; + + try { + uint8_t regTools = static_cast(REGISTER_TOOLS); + uint16_t majorVer = static_cast(SAUNAFS_PACKAGE_VERSION_MAJOR); + uint8_t minorVer = static_cast(SAUNAFS_PACKAGE_VERSION_MINOR); + uint8_t microVer = static_cast(SAUNAFS_PACKAGE_VERSION_MICRO); + constexpr char kBlobStr[] = FUSE_REGISTER_BLOB_ACL; + uint8_t blob[REGISTER_BLOB_SIZE] = {0}; + std::memcpy(blob, kBlobStr, + (sizeof(kBlobStr) < sizeof(blob)) ? sizeof(kBlobStr) : sizeof(blob)); + + serializeLegacyPacket(request, CLTOMA_FUSE_REGISTER, blob, regTools, cuid, majorVer, + minorVer, microVer); + + response = ServerConnection::sendAndReceive( + rfd, request, MATOCL_FUSE_REGISTER, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); + + if (response.size() != sizeof(uint8_t)) { + printf("register to master: wrong answer (length)\n"); + return -1; + } + + uint8_t status = response[0]; + + if (status != SAUNAFS_STATUS_OK) { + printf("register to master: %s\n", saunafs_error_string(status)); + return -1; + } + + return 0; + } catch (const Exception &e) { + fprintf(stderr, "register to master: %s\n", e.what()); return -1; } - return 0; } static int master_connect(const master_info_t *info) { diff --git a/src/tools/set_eattr.cc b/src/tools/set_eattr.cc index a980ca8b2..532495247 100644 --- a/src/tools/set_eattr.cc +++ b/src/tools/set_eattr.cc @@ -25,6 +25,7 @@ #include #include "common/datapack.h" +#include "common/server_connection.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" #include "tools/tools_commands.h" @@ -53,110 +54,77 @@ static void set_eattr_usage() { } static int set_eattr(const char *fname, uint8_t eattr, uint8_t mode) { - uint32_t cmd, leng, uid; - inode_t inode, changed, notchanged, notpermitted; uint32_t msgid{0}; + inode_t inode; - int fd; - fd = open_master_conn(fname, &inode, nullptr, true); - if (fd < 0) { - return -1; - } + MessageBuffer request, response; - uid = getUId(); - - constexpr uint32_t kSetEAttrPayload = - sizeof(msgid) + sizeof(inode) + sizeof(uid) + sizeof(eattr) + sizeof(mode); - constexpr uint32_t kSetEAttrFullSize = - sizeof(cmd) + sizeof(kSetEAttrPayload) + kSetEAttrPayload; - uint8_t reqbuff[kSetEAttrFullSize], *wptr, *buff; - const uint8_t *rptr; - - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_SETEATTR); - put32bit(&wptr, kSetEAttrPayload); - put32bit(&wptr, msgid); - putINode(&wptr, inode); - put32bit(&wptr, uid); - put8bit(&wptr, eattr); - put8bit(&wptr, mode); - - // send request to master - if (tcpwrite(fd, reqbuff, kSetEAttrFullSize) != kSetEAttrFullSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } + int fd = open_master_conn(fname, &inode, nullptr, true); + if (fd < 0) { return -1; } - // read the first part of the answer - if (tcpread(fd, reqbuff, sizeof(cmd) + sizeof(leng)) != sizeof(cmd) + sizeof(leng)) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } + try { + uint32_t uid = getUId(); - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); + serializeLegacyPacket(request, CLTOMA_FUSE_SETEATTR, msgid, inode, uid, eattr, mode); - if (cmd != MATOCL_FUSE_SETEATTR) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_SETEATTR, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kDefaultTimeoutMs); - buff = (uint8_t *)malloc(leng); + close_master_conn(0); - if (tcpread(fd, buff, leng) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } + const uint8_t *rptr = response.data(); - close_master_conn(0); // not needed anymore + get32bit(&rptr, msgid); + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + return -1; + } - rptr = buff; - get32bit(&rptr, msgid); // queryid + uint32_t bodySize = static_cast(response.size() - sizeof(msgid)); - if (msgid != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } + if (bodySize == sizeof(uint8_t)) { + uint8_t status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + return -1; + } - if (leng - sizeof(msgid) == 1) { // an error code was returned - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } + inode_t changed; + inode_t notchanged; + inode_t notpermitted; + constexpr uint32_t kExpectedSize = + sizeof(changed) + sizeof(notchanged) + sizeof(notpermitted); - if (leng != sizeof(msgid) + 3 * sizeof(inode_t)) { - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } + if (bodySize != kExpectedSize) { + printf("%s: master query: wrong answer (leng)\n", fname); + return -1; + } - getINode(&rptr, changed); - getINode(&rptr, notchanged); - getINode(&rptr, notpermitted); + getINode(&rptr, changed); + getINode(&rptr, notchanged); + getINode(&rptr, notpermitted); - if ((mode & SMODE_RMASK) == 0) { - if (changed) { - printf("%s: attribute(s) changed\n", fname); + if ((mode & SMODE_RMASK) == 0) { + if (changed) { + printf("%s: attribute(s) changed\n", fname); + } else { + printf("%s: attribute(s) not changed\n", fname); + } } else { - printf("%s: attribute(s) not changed\n", fname); + printf("%s:\n", fname); + print_number(" inodes with attributes changed: ", "\n", changed, kMode32, 0, 1); + print_number(" inodes with attributes not changed: ", "\n", notchanged, kMode32, 0, 1); + print_number(" inodes with permission denied: ", "\n", notpermitted, kMode32, 0, + 1); } - } else { - printf("%s:\n", fname); - print_number(" inodes with attributes changed: ", "\n", changed, kMode32, 0, 1); - print_number(" inodes with attributes not changed: ", "\n", notchanged, kMode32, 0, 1); - print_number(" inodes with permission denied: ", "\n", notpermitted, kMode32, 0, 1); - } - free(buff); + return 0; - return 0; + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; + } } static int gene_eattr_run(int argc, char **argv, uint8_t mode, void (*usage_func)(void)) { diff --git a/src/tools/set_trashtime.cc b/src/tools/set_trashtime.cc index 70af4e26c..2ffc36069 100644 --- a/src/tools/set_trashtime.cc +++ b/src/tools/set_trashtime.cc @@ -26,6 +26,7 @@ #include "common/datapack.h" #include "common/massert.h" +#include "common/server_connection.h" #include "common/type_defs.h" #include "errors/saunafs_error_codes.h" #include "errors/sfserr.h" @@ -46,96 +47,77 @@ static void set_trashtime_usage() { } static int set_trashtime(const char *fname, uint32_t trashtime, uint8_t mode) { - uint32_t cmd, leng, uid; + uint32_t uid; + uint32_t msgid{0}; + uint8_t status; inode_t inode, changed, notchanged, notpermitted; - constexpr uint32_t kPacketPayloadSize = - sizeof(uint32_t) + sizeof(inode) + sizeof(uid) + sizeof(trashtime) + sizeof(mode); - // CLTOMA_FUSE... kPacketPayloadSize - constexpr size_t kReqBuffSize = sizeof(uint32_t) + sizeof(uint32_t) + kPacketPayloadSize; - uint8_t reqbuff[kReqBuffSize]; - uint8_t *wptr; - uint8_t *buff; - const uint8_t *rptr; - int fd = open_master_conn(fname, &inode, nullptr, true); - if (fd < 0) { return -1; } uid = getUId(); - wptr = reqbuff; - put32bit(&wptr, CLTOMA_FUSE_SETTRASHTIME); - put32bit(&wptr, kPacketPayloadSize); - put32bit(&wptr, 0); - putINode(&wptr, inode); - put32bit(&wptr, uid); - put32bit(&wptr, trashtime); - put8bit(&wptr, mode); - - if (tcpwrite(fd, reqbuff, kReqBuffSize) != kReqBuffSize) { - printf("%s: master query: send error\n", fname); - close_master_conn(1); - return -1; - } - constexpr uint32_t kAnswerHeaderSize = sizeof(cmd) + sizeof(leng); - if (tcptoread(fd, reqbuff, kAnswerHeaderSize, kInfiniteTimeout) != kAnswerHeaderSize) { - printf("%s: master query: receive error\n", fname); - close_master_conn(1); - return -1; - } - rptr = reqbuff; - get32bit(&rptr, cmd); - get32bit(&rptr, leng); - if (cmd != MATOCL_FUSE_SETTRASHTIME) { - printf("%s: master query: wrong answer (type)\n", fname); - close_master_conn(1); - return -1; - } - buff = (uint8_t *)malloc(leng); - if (tcptoread(fd, buff, leng, kInfiniteTimeout) != (int32_t)leng) { - printf("%s: master query: receive error\n", fname); - free(buff); - close_master_conn(1); - return -1; - } - close_master_conn(0); - rptr = buff; - get32bit(&rptr, cmd); // queryid - if (cmd != 0) { - printf("%s: master query: wrong answer (queryid)\n", fname); - free(buff); - return -1; - } - leng -= sizeof(cmd); - if (leng == 1) { - printf("%s: %s\n", fname, saunafs_error_string(*rptr)); - free(buff); - return -1; - } else if (leng != 3 * kinode_t_size) { // changed, notchanged, notpermitted - printf("%s: master query: wrong answer (leng)\n", fname); - free(buff); - return -1; - } - getINode(&rptr, changed); - getINode(&rptr, notchanged); - getINode(&rptr, notpermitted); - if ((mode & SMODE_RMASK) == 0) { - if (changed || mode == SMODE_SET) { - printf("%s: %" PRIu32 "\n", fname, trashtime); + try { + MessageBuffer request, response; + + serializeLegacyPacket(request, CLTOMA_FUSE_SETTRASHTIME, msgid, inode, uid, trashtime, + mode); + + response = ServerConnection::sendAndReceive( + fd, request, MATOCL_FUSE_SETTRASHTIME, + ServerConnection::ReceiveMode::kReceiveFirstNonNopMessage, kInfiniteTimeout); + + const uint8_t *rptr = response.data(); + get32bit(&rptr, msgid); + + if (msgid != 0) { + printf("%s: master query: wrong answer (queryid)\n", fname); + close_master_conn(0); + return -1; + } + + uint32_t remaining = static_cast(response.size() - sizeof(msgid)); + + if (remaining == sizeof(status)) { + status = *rptr; + printf("%s: %s\n", fname, saunafs_error_string(status)); + close_master_conn(0); + return (status == SAUNAFS_STATUS_OK) ? 0 : -1; + } + + const uint32_t kExpectedSize = sizeof(changed) + sizeof(notchanged) + sizeof(notpermitted); + if (remaining != kExpectedSize) { + printf("%s: master query: wrong answer (leng)\n", fname); + close_master_conn(0); + return -1; + } + + getINode(&rptr, changed); + getINode(&rptr, notchanged); + getINode(&rptr, notpermitted); + + if ((mode & SMODE_RMASK) == 0) { + if (changed || mode == SMODE_SET) { + printf("%s: %" PRIu32 "\n", fname, trashtime); + } else { + printf("%s: trashtime not changed\n", fname); + } } else { - printf("%s: trashtime not changed\n", fname); + printf("%s:\n", fname); + print_number(" inodes with trashtime changed: ", "\n", changed, kMode32, 0, 1); + print_number(" inodes with trashtime not changed: ", "\n", notchanged, kMode32, 0, 1); + print_number(" inodes with permission denied: ", "\n", notpermitted, kMode32, 0, 1); } - } else { - printf("%s:\n", fname); - print_number(" inodes with trashtime changed: ", "\n", changed, kMode32, 0, 1); - print_number(" inodes with trashtime not changed: ", "\n", notchanged, kMode32, 0, 1); - print_number(" inodes with permission denied: ", "\n", notpermitted, kMode32, 0, 1); + + close_master_conn(0); + return 0; + } catch (const Exception &e) { + fprintf(stderr, "%s\n", e.what()); + close_master_conn(1); + return -1; } - free(buff); - return 0; } static int gene_set_trashtime_run(int argc, char **argv, int rflag) { diff --git a/src/tools/tools_common_functions.h b/src/tools/tools_common_functions.h index 9a3caed83..715c4ee2d 100644 --- a/src/tools/tools_common_functions.h +++ b/src/tools/tools_common_functions.h @@ -34,6 +34,8 @@ #include "common/type_defs.h" #include "protocol/SFSCommunication.h" +constexpr int kDefaultTimeoutMs = 10000; + #define tcpread(s, b, l) tcptoread(s, b, l, 10000) #define tcpwrite(s, b, l) tcptowrite(s, b, l, 10000)