From 0b544bf55aea8a46e21cfe63f3e69b29f2a04256 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 16 Sep 2023 19:38:16 +0200 Subject: [PATCH] API: removed file size limitation --- src/log.h | 19 ++++++++--- src/p2p_server.cpp | 4 --- src/p2pool_api.cpp | 11 +++++- src/util.h | 8 ++--- tests/CMakeLists.txt | 1 + tests/src/log_tests.cpp | 76 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 tests/src/log_tests.cpp diff --git a/src/log.h b/src/log.h index c414216..a83f9bb 100644 --- a/src/log.h +++ b/src/log.h @@ -38,9 +38,18 @@ struct Stream enum params : int { BUF_SIZE = 1024 - 1 }; template - explicit FORCEINLINE Stream(char (&buf)[N]) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(N - 1) {} + explicit FORCEINLINE Stream(char (&buf)[N]) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(N - 1), m_spilled(0) {} - FORCEINLINE Stream(void* buf, size_t size) : m_pos(0), m_numberWidth(1), m_buf(reinterpret_cast(buf)), m_bufSize(static_cast(size) - 1) {} + FORCEINLINE Stream(void* buf, size_t size) { reset(buf, size); } + + FORCEINLINE void reset(void* buf, size_t size) + { + m_pos = 0; + m_numberWidth = 1; + m_buf = reinterpret_cast(buf); + m_bufSize = static_cast(size) - 1; + m_spilled = 0; + } template struct Entry @@ -70,9 +79,7 @@ struct Stream { static_assert(1 < base && base <= 64, "Invalid base"); - const T data_with_sign = data; - data = abs(data); - const bool negative = (data != data_with_sign); + const bool negative = is_negative(data); char buf[32]; size_t k = sizeof(buf); @@ -98,6 +105,7 @@ struct Stream const int n = static_cast(n0); const int pos = m_pos; if (pos + n > m_bufSize) { + m_spilled += n; return; } memcpy(m_buf + pos, buf, n); @@ -111,6 +119,7 @@ struct Stream int m_numberWidth; char* m_buf; int m_bufSize; + int m_spilled; }; struct Writer : public Stream diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 105500d..bb6f972 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -1348,10 +1348,6 @@ void P2PServer::api_update_local_stats() << static_cast(client->m_addrString) << '"'; - if (s.m_pos + 128 >= s.m_bufSize) { - break; - } - first = false; } } diff --git a/src/p2pool_api.cpp b/src/p2pool_api.cpp index c361a42..231c752 100644 --- a/src/p2pool_api.cpp +++ b/src/p2pool_api.cpp @@ -106,9 +106,18 @@ void p2pool_api::on_stop() void p2pool_api::dump_to_file_async_internal(Category category, const char* filename, Callback::Base&& callback) { - std::vector buf(16384); + std::vector buf(1024); log::Stream s(buf.data(), buf.size()); callback(s); + + // If the buffer was too small, try again with big enough buffer + if (s.m_spilled) { + // Assume that the second call will use no more than 2X bytes + buf.resize((static_cast(s.m_pos) + s.m_spilled) * 2 + 1); + s.reset(buf.data(), buf.size()); + callback(s); + } + buf.resize(s.m_pos); std::string path; diff --git a/src/util.h b/src/util.h index 3e92664..21fdbb0 100644 --- a/src/util.h +++ b/src/util.h @@ -91,11 +91,11 @@ static FORCEINLINE bool from_hex(char c, T& out_value) { return false; } -template struct abs_helper {}; -template struct abs_helper { static FORCEINLINE T value(T x) { return x; } }; -template struct abs_helper { static FORCEINLINE T value(T x) { return (x >= 0) ? x : -x; } }; +template struct is_negative_helper {}; +template struct is_negative_helper { static FORCEINLINE bool value(T) { return false; } }; +template struct is_negative_helper { static FORCEINLINE bool value(T x) { return (x < 0); } }; -template FORCEINLINE T abs(T x) { return abs_helper::value>::value(x); } +template FORCEINLINE bool is_negative(T x) { return is_negative_helper::value>::value(x); } template FORCEINLINE void writeVarint(T value, U&& callback) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5a0f720..41d7f54 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,6 +33,7 @@ set(SOURCES src/difficulty_type_tests.cpp src/hash_tests.cpp src/keccak_tests.cpp + src/log_tests.cpp src/main.cpp src/pool_block_tests.cpp src/util_tests.cpp diff --git a/tests/src/log_tests.cpp b/tests/src/log_tests.cpp new file mode 100644 index 0000000..3598699 --- /dev/null +++ b/tests/src/log_tests.cpp @@ -0,0 +1,76 @@ +/* + * This file is part of the Monero P2Pool + * Copyright (c) 2021-2023 SChernykh + * + * 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 3. + * + * 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, see . + */ + +#include "common.h" +#include "gtest/gtest.h" + +namespace p2pool { + +TEST(log, stream) +{ + constexpr int N = 63; + + char buf[N + 1] = {}; + log::Stream s(buf); + + for (int iter = 0; iter < 2; ++iter) { + ASSERT_EQ(s.m_bufSize, N); + + for (int i = 0; i < N; ++i) { + s << ' '; + + ASSERT_EQ(s.m_pos, i + 1); + ASSERT_EQ(s.m_spilled, 0); + } + + s << ' '; + + ASSERT_EQ(s.m_pos, N); + ASSERT_EQ(s.m_spilled, 1); + + for (int i = 0; i < N; ++i) { + ASSERT_EQ(buf[i], ' '); + } + + ASSERT_EQ(buf[N], '\0'); + + s.reset(buf, N + 1); + } +} + +TEST(log, pad_right) +{ + constexpr int N = 63; + + char buf[N + 1] = {}; + log::Stream s(buf); + + s << log::pad_right('1', N); + + ASSERT_EQ(s.m_pos, N); + ASSERT_EQ(s.m_spilled, 0); + + ASSERT_EQ(buf[0], '1'); + + for (int i = 1; i < N; ++i) { + ASSERT_EQ(buf[i], ' '); + } + + ASSERT_EQ(buf[N], '\0'); +} + +}