From ca179b8caf8090ee624208e2635b4277b1cb6f1a Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Fri, 1 Nov 2024 18:47:05 +0200 Subject: [PATCH 01/21] Add seqnum and offset input args, add composite sequence number support Signed-off-by: Aleksandr Ivanov --- .../bmqstoragetool/bmqstoragetool.m.cpp | 26 +- ...bmqstoragetool_compositesequencenumber.cpp | 115 ++++++ ...m_bmqstoragetool_compositesequencenumber.h | 184 ++++++++++ ...qstoragetool_compositesequencenumber.t.cpp | 338 ++++++++++++++++++ .../m_bmqstoragetool_parameters.cpp | 92 ++++- .../m_bmqstoragetool_parameters.h | 32 +- .../bmqstoragetool/package/bmqstoragetool.mem | 1 + 7 files changed, 770 insertions(+), 18 deletions(-) create mode 100644 src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp create mode 100644 src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h create mode 100644 src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp diff --git a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp index 2fe44db4f..364e5fdcc 100644 --- a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp +++ b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp @@ -31,7 +31,7 @@ using namespace BloombergLP; using namespace m_bmqstoragetool; static bool -parseArgs(CommandLineArguments& arguments, int argc, const char* argv[]) +parseArgs(CommandLineArguments& arguments, int argc, const char* argv[], bslma::Allocator* allocator) { bool showHelp = false; @@ -82,6 +82,26 @@ parseArgs(CommandLineArguments& arguments, int argc, const char* argv[]) "higher timestamp bound", balcl::TypeInfo(&arguments.d_timestampLt), balcl::OccurrenceInfo::e_OPTIONAL}, + {"seqnum-gt", + "record composite sequence number greater than", + "lower record sequence number bound", + balcl::TypeInfo(&arguments.d_seqNumGt), + balcl::OccurrenceInfo::e_OPTIONAL}, + {"seqnum-lt", + "record composite sequence number less than", + "higher sequence number bound", + balcl::TypeInfo(&arguments.d_seqNumLt), + balcl::OccurrenceInfo::e_OPTIONAL}, + {"offset-gt", + "record offset greater than", + "lower record offset bound", + balcl::TypeInfo(&arguments.d_offsetGt), + balcl::OccurrenceInfo::e_OPTIONAL}, + {"offset-lt", + "record offset less than", + "higher record offset bound", + balcl::TypeInfo(&arguments.d_offsetLt), + balcl::OccurrenceInfo::e_OPTIONAL}, {"outstanding", "only outstanding", "show only outstanding (not deleted) messages", @@ -130,7 +150,7 @@ parseArgs(CommandLineArguments& arguments, int argc, const char* argv[]) } bsl::string error; - if (!arguments.validate(&error)) { + if (!arguments.validate(&error, allocator)) { bsl::cerr << "Arguments validation failed:\n" << error; return false; // RETURN } @@ -157,7 +177,7 @@ int main(int argc, const char* argv[]) // Arguments parsing CommandLineArguments arguments(allocator); - if (!parseArgs(arguments, argc, argv)) { + if (!parseArgs(arguments, argc, argv, allocator)) { return rc_ARGUMENTS_PARSING_FAILED; // RETURN } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp new file mode 100644 index 000000000..2a431134c --- /dev/null +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -0,0 +1,115 @@ +// Copyright 2014-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// bmqstoragetool +#include + +// BDE +#include +#include + +namespace BloombergLP { +namespace m_bmqstoragetool { + +// ============================= +// class CompositeSequenceNumber +// ============================= + +CompositeSequenceNumber::CompositeSequenceNumber() +: d_leaseId(0) +, d_seqNumber(0) +, d_isUnset(true) +{ + // NOTHING +} + +CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString) +{ + d_isUnset = true; + + if (seqNumString.empty()) { + errorDescription << "Invalid input: empty string."; + return *this; // RETURN + } + + // Find the position of the separator + const size_t separatorPos = seqNumString.find('-'); + if (separatorPos == bsl::string::npos) { + errorDescription << "Invalid format: no '-' separator found."; + return *this; // RETURN + } + + // Extract parts + // TODO: use allocator! + bsl::string firstPart = seqNumString.substr(0, separatorPos); + bsl::string secondPart = seqNumString.substr(separatorPos + 1); + + // Convert parts to numbers + try { + size_t posFirst, posSecond; + + unsigned long uLong = bsl::stoul(firstPart, &posFirst); + d_seqNumber = bsl::stoul(secondPart, &posSecond); + + if (posFirst != firstPart.size() || posSecond != secondPart.size()) { + throw bsl::invalid_argument(""); + } + + d_leaseId = static_cast(uLong); + if (uLong != d_leaseId) { + throw bsl::out_of_range(""); + } + + if (d_leaseId == 0 || d_seqNumber == 0) { + errorDescription << "Invalid input: zero values encountered."; + return *this; // RETURN + } + + d_isUnset = false; + + } catch (const bsl::invalid_argument& e) { + errorDescription << "Invalid input: non-numeric values encountered."; + } catch (const bsl::out_of_range& e) { + errorDescription << "Invalid input: number out of range."; + } + + return *this; +} + +bsl::ostream& +CompositeSequenceNumber::print(bsl::ostream& stream, int level, int spacesPerLevel) const +{ + if (stream.bad()) { + return stream; // RETURN + } + + bdlb::Print::indent(stream, level, spacesPerLevel); + + if (isUnset()) { + stream << "** UNSET **"; + } + else { + stream << "leaseId: " << leaseId() << ", sequenceNumber: " << sequenceNumber(); + } + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +} // close package namespace +} // close enterprise namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h new file mode 100644 index 000000000..b6ee0560f --- /dev/null +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -0,0 +1,184 @@ +// Copyright 2014-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER +#define INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER + +//@PURPOSE: Provide value-semantic type to represent composite sequence number, which is used for message filtering. +// +//@CLASSES: +// m_bmqstoragetool::CompositeSequenceNumber: Value-semantic type to represent composite sequence number. +// +//@DESCRIPTION: 'CompositeSequenceNumber' provides value-semantic type to represent sequence number. +// There could be sequence numbers collision inside journal file for different lease Ids, +// so need to handle composite sequence number taking into account Primary Lease Id too. + +// BDE +#include +#include +#include + +namespace BloombergLP { +namespace m_bmqstoragetool { + +// ============================= +// class CompositeSequenceNumber +// ============================= + +class CompositeSequenceNumber { + private: + // DATA + unsigned int d_leaseId; + // Primary Lease Id + bsls::Types::Uint64 d_seqNumber; + // Sequence Number + bool d_isUnset; + + public: + // CREATORS + + /// Create an un-initialized CompositeSequenceNumber. Note that `isUnset()` would + /// return true. + CompositeSequenceNumber(); + + // MANIPULATORS + + /// Initialize this CompositeSequenceNumber from the specified `seqNumString` representation in format `-`. + /// Return a reference offering modifiable access to this object. If convertion is successfull, `isUnset()` would return `true`. + /// Otherwise, `isUnset()` would return `false` and specified `errorDescription` is filled with error description. + CompositeSequenceNumber& fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString); + + // ACCESSORS + + /// Return `true` if the value of this object is not set. + bool isUnset() const; + + /// Return Primary Lease Id value. + unsigned int leaseId() const; + + /// Return Sequence Number value. + bsls::Types::Uint64 sequenceNumber() const; + + /// Write the value of this object to the specified output `stream` in a + /// human-readable format, and return a reference to `stream`. + /// Optionally specify an initial indentation `level`. If `level` is + /// specified, optionally specify `spacesPerLevel`, whose absolute value + /// indicates the number of spaces per indentation level for this + /// object. If `level` is negative, suppress indentation of the first + /// line. If `spacesPerLevel` is negative, format the entire output on + /// one line, suppressing all but the initial indentation (as governed + /// by `level`). If `stream` is not valid on entry, this operation has + /// no effect. Note that this human-readable format is not fully + /// specified, and can change without notice. + bsl::ostream& + print(bsl::ostream& stream, int level = 0, int spacesPerLevel = 4) const; +}; + +// FREE OPERATORS + +// ----------------- +// class MessageGUID +// ----------------- + +/// Write the value of the specified `rhs` object to the specified output +/// `stream` in a human-readable format, and return a reference to `stream`. +/// Note that this human-readable format is not fully specified, and can +/// change without notice. +bsl::ostream& operator<<(bsl::ostream& stream, const CompositeSequenceNumber& rhs); + +/// Return true if the specified `lhs` instance is less than the +/// specified `rhs` instance, false otherwise. +bool operator<(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); + +/// Return true if the specified `lhs` instance is less or equal to the +/// specified `rhs` instance, false otherwise. +bool operator<=(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); + +// ============================================================================ +// INLINE DEFINITIONS +// ============================================================================ + +// ============================= +// class CompositeSequenceNumber +// ============================= + +// ACCESSORS + +inline bool CompositeSequenceNumber::isUnset() const +{ + return d_isUnset; +} + +inline unsigned int CompositeSequenceNumber::leaseId() const +{ + return d_leaseId; +} + +inline bsls::Types::Uint64 CompositeSequenceNumber::sequenceNumber() const +{ + return d_seqNumber; +} + +} // close package namespace + +// ============================= +// class CompositeSequenceNumber +// ============================= + +// FREE OPERATORS + +inline bsl::ostream& m_bmqstoragetool::operator<<(bsl::ostream& stream, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) +{ + // PRECONDITIONS + BSLS_ASSERT(!rhs.isUnset()); + + return rhs.print(stream, 0, -1); +} + +inline bool m_bmqstoragetool::operator<(const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) +{ + // PRECONDITIONS + BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + + // Check leaseId first + if (lhs.leaseId() < rhs.leaseId()) { + return true; // RETURN + } else if (lhs.leaseId() == rhs.leaseId()) { + if (lhs.sequenceNumber() < rhs.sequenceNumber()) { + return true; // RETURN + } + } + + return false; +} + +inline bool m_bmqstoragetool::operator<=(const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) +{ + // PRECONDITIONS + BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + + if (lhs.leaseId() == rhs.leaseId() && lhs.sequenceNumber() == rhs.sequenceNumber()) { + return true; + } + + return lhs < rhs; +} + +} // close enterprise namespace + +#endif diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp new file mode 100644 index 000000000..73e04fa5d --- /dev/null +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -0,0 +1,338 @@ +// Copyright 2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// bmqstoragetool +#include + +// BMQ +#include + +// BDE +#include + +// TEST DRIVER +#include + +// CONVENIENCE +using namespace BloombergLP; +using namespace m_bmqstoragetool; +using namespace bsl; + +// ============================================================================ +// TESTS +// ---------------------------------------------------------------------------- + +static void test1_breathingTest() +// ------------------------------------------------------------------------ +// BREATHING TEST +// +// Concerns: +// Exercise the basic functionality of the component. +// +// Testing: +// Basic functionality +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("BREATHING TEST"); + + CompositeSequenceNumber compositeSeqNum; + + ASSERT(compositeSeqNum.isUnset()); +} + +static void test2_fromStringTest() +// ------------------------------------------------------------------------ +// FROM STRING TEST +// +// Concerns: +// Exercise the functionality to initialize component from string representation. +// +// Testing: +// fromString method +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("FROM STRING TEST"); + + bmqu::MemOutStream errorDescription(s_allocator_p); + + // Valid string + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("123-456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), false); + ASSERT_EQ(compositeSeqNum.leaseId(), 123u); + ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); + ASSERT(errorDescription.str().empty()); + } + + // Valid string with leading zeros + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("00123-000456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), false); + ASSERT_EQ(compositeSeqNum.leaseId(), 123u); + ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); + ASSERT(errorDescription.str().empty()); + } + + // Empty string + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: empty string."); + } + + // Invalid string with missed separator + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("123456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); + } + + // Invalid string with wrong separator + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("123_456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); + } + + // Invalid string with non-numeric value in first part + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("1a23-456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); + } + + // Invalid string with non-numeric value in second part + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("123-45a6", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); + } + + // Invalid string with zero value in first part + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("0-456", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); + } + + // Invalid string with zero value in second part + { + CompositeSequenceNumber compositeSeqNum; + + bsl::string inputString("123-0", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); + } + + // Invalid string with out of range value in first part + { + CompositeSequenceNumber compositeSeqNum; + + // Simulate unsigned int overflow + bsl::string inputString("11111111111-123", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); + } + + // Invalid string with out of range value in second part + { + CompositeSequenceNumber compositeSeqNum; + + // Simulate bsls::Types::Uint64 overflow + bsl::string inputString("123-111111111111111111111", s_allocator_p); + errorDescription.reset(); + + compositeSeqNum.fromString(errorDescription, inputString); + ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT(!errorDescription.str().empty()); + ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); + } +} + +static void test3_comparisonTest() +// ------------------------------------------------------------------------ +// COMPARISON TEST +// +// Concerns: +// Exercise the functionality to compare objects. +// +// Testing: +// operator<() and operator<=() methods +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("COMPARISON TEST"); + + bmqu::MemOutStream errorDescription(s_allocator_p); + + // leaseId is less, seqNumber is greater + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("2-1", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT(lhs < rhs); + } + + // leaseId is less, seqNumber is less + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("2-2", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT(lhs < rhs); + } + + // leaseId is greater, seqNumber is greater + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("3-2", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("2-1", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT_EQ((lhs < rhs), false); + } + + // leaseId is greater, seqNumber is less + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("3-1", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("2-2", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT_EQ((lhs < rhs), false); + } + + // leaseId is equal, seqNumber is less + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT(lhs < rhs); + } + + // leaseId is equal, seqNumber is greater + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT_EQ((lhs < rhs), false); + } + + // Compare for equality using '<=': leaseId is equal, seqNumber is equal + { + CompositeSequenceNumber lhs; + lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + + CompositeSequenceNumber rhs; + rhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + + ASSERT(!lhs.isUnset() && !rhs.isUnset()); + ASSERT_EQ((lhs <= rhs), true); + } +} + +// ============================================================================ +// MAIN PROGRAM +// ---------------------------------------------------------------------------- + +int main(int argc, char* argv[]) +{ + TEST_PROLOG(bmqtst::TestHelper::e_DEFAULT); + + switch (_testCase) { + case 0: + case 1: test1_breathingTest(); break; + case 2: test2_fromStringTest(); break; + case 3: test3_comparisonTest(); break; + default: { + cerr << "WARNING: CASE '" << _testCase << "' NOT FOUND." << endl; + s_testStatus = -1; + } break; + } + + TEST_EPILOG(bmqtst::TestHelper::e_CHECK_DEF_GBL_ALLOC); +} diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 79c7e3028..58149337c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -77,11 +77,16 @@ bool isValidQueueKeyHexRepresentation(const char* queueKeyBuf) CommandLineArguments::CommandLineArguments(bslma::Allocator* allocator) : d_timestampGt(0) , d_timestampLt(0) +, d_seqNumGt(allocator) +, d_seqNumLt(allocator) +, d_offsetGt(0) +, d_offsetLt(0) , d_journalPath(allocator) , d_journalFile(allocator) , d_dataFile(allocator) , d_cslFile(allocator) , d_guid(allocator) +, d_seqNum(allocator) , d_queueKey(allocator) , d_queueName(allocator) , d_dumpLimit(0) @@ -94,9 +99,9 @@ CommandLineArguments::CommandLineArguments(bslma::Allocator* allocator) { } -bool CommandLineArguments::validate(bsl::string* error) +bool CommandLineArguments::validate(bsl::string* error, bslma::Allocator* allocator) { - bmqu::MemOutStream ss; + bmqu::MemOutStream ss(allocator); if (d_journalPath.empty() && d_journalFile.empty()) { ss << "Neither journal path nor journal file are specified\n"; @@ -162,18 +167,69 @@ bool CommandLineArguments::validate(bsl::string* error) if (d_cslFile.empty() && !d_queueName.empty()) { ss << "Can't search by queue name, because csl file is not " "specified\n"; - } + } if (d_timestampLt < 0 || d_timestampGt < 0 || (d_timestampLt > 0 && d_timestampGt >= d_timestampLt)) { ss << "Invalid timestamp range specified\n"; } + if (!d_seqNumLt.empty() || !d_seqNumGt.empty()) { + bmqu::MemOutStream errorDescr(allocator); + CompositeSequenceNumber seqNumLt, seqNumGt; + if (!d_seqNumLt.empty()) { + seqNumLt.fromString(errorDescr, d_seqNumLt); + if(seqNumLt.isUnset()) { + ss << "--seqnum-lt: " << errorDescr.str() << "\n"; + errorDescr.reset(); + } + } + if (!d_seqNumGt.empty()) { + seqNumGt.fromString(errorDescr, d_seqNumGt); + if(seqNumGt.isUnset()) { + ss << "--seqnum-gt: " << errorDescr.str() << "\n"; + } + } + + if (!seqNumLt.isUnset() && !seqNumGt.isUnset()) { + if (seqNumLt <= seqNumGt) { + ss << "Invalid sequence number range specified\n"; + } + } + } + if (d_offsetLt < 0 || d_offsetGt < 0 || + (d_offsetLt > 0 && d_offsetGt >= d_offsetLt)) { + ss << "Invalid offset range specified\n"; + } + // Check that only one range type can be selected + bsl::size_t rangesCnt = 0; + if (d_timestampLt || d_timestampGt) { + rangesCnt++; + } + if (!d_seqNumLt.empty() || !d_seqNumGt.empty()) { + rangesCnt++; + } + if (d_offsetLt || d_offsetGt) { + rangesCnt++; + } + if (rangesCnt > 1) { + ss << "Only one range type can be selected: timestamp, seqnum or offset\n"; + } + if (!d_guid.empty() && - (!d_queueKey.empty() || !d_queueName.empty() || d_outstanding || - d_confirmed || d_partiallyConfirmed || d_timestampGt > 0 || - d_timestampLt > 0 || d_summary)) { + (!d_queueKey.empty() || !d_queueName.empty() || !d_seqNum.empty() || d_outstanding || + d_confirmed || d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { ss << "Giud filter can't be combined with any other filters, as it is " "specific enough to find a particular message\n"; } + + if (!d_seqNum.empty() && + (!d_queueKey.empty() || !d_queueName.empty() || !d_guid.empty()|| d_outstanding || + d_confirmed || d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { + ss << "secnum filter can't be combined with any other filters, as it is " + "specific enough to find a particular message\n"; + } + + // TODO: offset check too + if (d_summary && (d_outstanding || d_confirmed || d_partiallyConfirmed || d_details)) { ss << "'--summary' can't be combined with '--outstanding', " @@ -211,8 +267,9 @@ bool CommandLineArguments::validate(bsl::string* error) Parameters::Parameters(bslma::Allocator* allocator) : d_queueMap(allocator) -, d_timestampGt(0) -, d_timestampLt(0) +, d_valueType(e_NONE) +, d_valueGt(0) +, d_valueLt(0) , d_guid(allocator) , d_queueKey(allocator) , d_queueName(allocator) @@ -229,8 +286,9 @@ Parameters::Parameters(bslma::Allocator* allocator) Parameters::Parameters(const CommandLineArguments& arguments, bslma::Allocator* allocator) : d_queueMap(allocator) -, d_timestampGt(arguments.d_timestampGt) -, d_timestampLt(arguments.d_timestampLt) +, d_valueType(e_NONE) +, d_valueGt(0) +, d_valueLt(0) , d_guid(arguments.d_guid, allocator) , d_queueKey(arguments.d_queueKey, allocator) , d_queueName(arguments.d_queueName, allocator) @@ -242,6 +300,20 @@ Parameters::Parameters(const CommandLineArguments& arguments, , d_confirmed(arguments.d_confirmed) , d_partiallyConfirmed(arguments.d_partiallyConfirmed) { + // Set search range type and values if present + if (arguments.d_timestampLt || arguments.d_timestampGt) { + d_valueType = e_TIMESTAMP; + d_valueLt = static_cast(arguments.d_timestampLt); + d_valueGt = static_cast(arguments.d_timestampGt); + } else if (!arguments.d_seqNumLt.empty() || arguments.d_seqNumGt.empty()) { + d_valueType = e_SEQUENCE_NUM; + // d_valueLt = static_cast(arguments.d_seqNumLt); + // d_valueGt = static_cast(arguments.d_seqNumGt); + } else { + d_valueType = e_OFFSET; + d_valueLt = static_cast(arguments.d_offsetLt); + d_valueGt = static_cast(arguments.d_offsetGt); + } } void Parameters::validateQueueNames(bslma::Allocator* allocator) const diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h index 25ba703c0..17a86a247 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h @@ -26,6 +26,7 @@ // command-line parameters for the 'bmqtool' program. // bmqstoragetool +#include #include // MQB @@ -57,6 +58,14 @@ struct CommandLineArguments { // Filter messages by minimum timestamp bsls::Types::Int64 d_timestampLt; // Filter messages by maximum timestamp + bsl::string d_seqNumGt; + // Filter messages by minimum record composite sequence number + bsl::string d_seqNumLt; + // Filter messages by maximum record composite sequence number + bsls::Types::Int64 d_offsetGt; + // Filter messages by minimum record offset + bsls::Types::Int64 d_offsetLt; + // Filter messages by maximum record offset bsl::string d_journalPath; // Path to find all files from bsl::string d_journalFile; @@ -67,6 +76,8 @@ struct CommandLineArguments { // Path to read CSL files from bsl::vector d_guid; // Filter messages by message guids + bsl::vector d_seqNum; + // Filter messages by message composite sequence numbers bsl::vector d_queueKey; // Filter messages by queue keys bsl::vector d_queueName; @@ -91,19 +102,30 @@ struct CommandLineArguments { // MANIPULATORS /// Validate the consistency of all settings. - bool validate(bsl::string* error); + bool validate(bsl::string* error, bslma::Allocator* allocator = 0); }; struct Parameters { + // PUBLIC TYPES + enum SearchValueType { e_NONE = 0, e_TIMESTAMP = 1, e_SEQUENCE_NUM = 2, e_OFFSET = 3 }; + // PUBLIC DATA QueueMap d_queueMap; // Queue map containing uri to key and key to info mappings - bsls::Types::Int64 d_timestampGt; - // Filter messages by minimum timestamp - bsls::Types::Int64 d_timestampLt; - // Filter messages by maximum timestamp + SearchValueType d_valueType; + // Search value type for message filtering + bsls::Types::Uint64 d_valueGt; + // Filter messages greater than value + bsls::Types::Uint64 d_valueLt; + // Filter messages less than value + CompositeSequenceNumber d_seqNumGt; + // Filter messages greater than sequence number + CompositeSequenceNumber d_seqNumLt; + // Filter messages less than sequence number bsl::vector d_guid; // Filter messages by message guids + bsl::vector d_seqNum; + // Filter messages by message sequence number bsl::vector d_queueKey; // Filter messages by queue keys bsl::vector d_queueName; diff --git a/src/applications/bmqstoragetool/package/bmqstoragetool.mem b/src/applications/bmqstoragetool/package/bmqstoragetool.mem index 497ae4f23..b6ed97056 100644 --- a/src/applications/bmqstoragetool/package/bmqstoragetool.mem +++ b/src/applications/bmqstoragetool/package/bmqstoragetool.mem @@ -1,5 +1,6 @@ m_bmqstoragetool_commandprocessor m_bmqstoragetool_commandprocessorfactory +m_bmqstoragetool_compositesequencenumber m_bmqstoragetool_filemanager m_bmqstoragetool_filemanagermock m_bmqstoragetool_filters From f36e2f6f3daa38531e68a8284266cb46ffeb1884 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Thu, 7 Nov 2024 18:00:19 +0200 Subject: [PATCH 02/21] Debug binary search for all range types Signed-off-by: Aleksandr Ivanov --- ...bmqstoragetool_compositesequencenumber.cpp | 8 + ...m_bmqstoragetool_compositesequencenumber.h | 3 + ...qstoragetool_compositesequencenumber.t.cpp | 15 +- .../m_bmqstoragetool_filters.cpp | 50 ++- .../bmqstoragetool/m_bmqstoragetool_filters.h | 18 +- .../m_bmqstoragetool_journalfile.cpp | 142 +++++++ .../m_bmqstoragetool_journalfile.h | 5 + .../m_bmqstoragetool_journalfileprocessor.cpp | 395 +++++++++++++++++- .../m_bmqstoragetool_journalfileprocessor.h | 9 +- ..._bmqstoragetool_journalfileprocessor.t.cpp | 128 +++++- .../m_bmqstoragetool_parameters.cpp | 38 +- .../m_bmqstoragetool_searchresultfactory.cpp | 5 +- 12 files changed, 770 insertions(+), 46 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index 2a431134c..21191fa8d 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -35,6 +35,14 @@ CompositeSequenceNumber::CompositeSequenceNumber() // NOTHING } +CompositeSequenceNumber::CompositeSequenceNumber(const unsigned int leaseId, const bsls::Types::Uint64 sequenceNumber) +: d_leaseId(leaseId) +, d_seqNumber(sequenceNumber) +{ + BSLS_ASSERT(d_leaseId > 0 && d_seqNumber > 0); + d_isUnset = !(d_leaseId > 0 && d_seqNumber > 0); +} + CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString) { d_isUnset = true; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index b6ee0560f..8c9f68c4d 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -53,6 +53,9 @@ class CompositeSequenceNumber { /// return true. CompositeSequenceNumber(); + /// Create CompositeSequenceNumber from the specified `leaseId` and `sequenceNumber` + CompositeSequenceNumber(const unsigned int leaseId, const bsls::Types::Uint64 sequenceNumber); + // MANIPULATORS /// Initialize this CompositeSequenceNumber from the specified `seqNumString` representation in format `-`. diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index 73e04fa5d..bc0eea5e7 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -19,9 +19,6 @@ // BMQ #include -// BDE -#include - // TEST DRIVER #include @@ -47,9 +44,17 @@ static void test1_breathingTest() { bmqtst::TestHelper::printTestName("BREATHING TEST"); - CompositeSequenceNumber compositeSeqNum; + { + CompositeSequenceNumber compositeSeqNum; + ASSERT(compositeSeqNum.isUnset()); + } - ASSERT(compositeSeqNum.isUnset()); + { + CompositeSequenceNumber compositeSeqNum(1, 2); + ASSERT(!compositeSeqNum.isUnset()); + ASSERT_EQ(compositeSeqNum.leaseId(), 1ul); + ASSERT_EQ(compositeSeqNum.sequenceNumber(), 2ul); + } } static void test2_fromStringTest() diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp index 578cc86fb..9e21a87dc 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +// bmqstoragetool #include namespace BloombergLP { @@ -25,12 +26,18 @@ namespace m_bmqstoragetool { Filters::Filters(const bsl::vector& queueKeys, const bsl::vector& queueUris, const QueueMap& queueMap, - const bsls::Types::Int64 timestampGt, - const bsls::Types::Int64 timestampLt, + const Parameters::SearchValueType valueType, + const bsls::Types::Uint64 valueGt, + const bsls::Types::Uint64 valueLt, + const CompositeSequenceNumber seqNumGt, + const CompositeSequenceNumber seqNumLt, bslma::Allocator* allocator) : d_queueKeys(allocator) -, d_timestampGt(static_cast(timestampGt)) -, d_timestampLt(static_cast(timestampLt)) +, d_valueType(valueType) +, d_valueGt(valueGt) +, d_valueLt(valueLt) +, d_seqNumGt(seqNumGt) +, d_seqNumLt(seqNumLt) { // Fill internal structures if (!queueKeys.empty()) { @@ -52,8 +59,9 @@ Filters::Filters(const bsl::vector& queueKeys, } } -bool Filters::apply(const mqbs::MessageRecord& record) +bool Filters::apply(const mqbs::MessageRecord& record, bsls::Types::Uint64 offset) const { + // Apply `queue key` filter if (!d_queueKeys.empty()) { // Match by queueKey bsl::unordered_set::const_iterator it = bsl::find( @@ -65,10 +73,34 @@ bool Filters::apply(const mqbs::MessageRecord& record) return false; // RETURN } } - const bsls::Types::Uint64& ts = record.header().timestamp(); - if ((d_timestampGt > 0 && ts <= d_timestampGt) || - (d_timestampLt > 0 && ts >= d_timestampLt)) { - // Match by timestamp + + // Apply `range` filter + bsls::Types::Uint64 value; + switch(d_valueType) { + case Parameters::e_TIMESTAMP: + value = record.header().timestamp(); + break; + case Parameters::e_SEQUENCE_NUM: + { + CompositeSequenceNumber seqNum(record.header().primaryLeaseId(), record.header().sequenceNumber()); + if ((!d_seqNumGt.isUnset() && seqNum <= d_seqNumGt) || + (!d_seqNumLt.isUnset() && d_seqNumLt <= seqNum)) { + // Not inside range + return false; // RETURN + } + } + break; + case Parameters::e_OFFSET: + value = offset; + break; + default: + // No range filter defined + return true; // RETURN + + } + if ((d_valueGt > 0 && value <= d_valueGt) || + (d_valueLt > 0 && value >= d_valueLt)) { + // Not inside range return false; // RETURN } return true; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h index c637ff993..631299a30 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h @@ -43,8 +43,11 @@ class Filters { private: // DATA bsl::unordered_set d_queueKeys; - const bsls::Types::Uint64 d_timestampGt; - const bsls::Types::Uint64 d_timestampLt; + const Parameters::SearchValueType d_valueType; + const bsls::Types::Uint64 d_valueGt; + const bsls::Types::Uint64 d_valueLt; + const CompositeSequenceNumber d_seqNumGt; + const CompositeSequenceNumber d_seqNumLt; public: // CREATORS @@ -53,15 +56,18 @@ class Filters { explicit Filters(const bsl::vector& queueKeys, const bsl::vector& queueUris, const QueueMap& queueMap, - const bsls::Types::Int64 timestampGt, - const bsls::Types::Int64 timestampLt, + const Parameters::SearchValueType valueType, + const bsls::Types::Uint64 valueGt, + const bsls::Types::Uint64 valueLt, + const CompositeSequenceNumber seqNumGt, + const CompositeSequenceNumber seqNumLt, bslma::Allocator* allocator); - // MANIPULATORS + // ACCESSORS /// Apply filters at specified 'record' and return true if all filters /// are matched, false otherwise. - bool apply(const mqbs::MessageRecord& record); + bool apply(const mqbs::MessageRecord& record, bsls::Types::Uint64 offset) const; }; } // close package namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp index aef61e6d1..2549ee113 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp @@ -602,6 +602,148 @@ void JournalFile::addJournalRecordsWithConfirmedMessagesWithDifferentOrder( } } +void JournalFile::addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, size_t leaseCount) +{ + // PRECONDITIONS + BSLS_ASSERT(records); + + unsigned int leaseId = 0; + bsls::Types::Uint64 seqNumber = 1; + + for (unsigned int i = 1; i <= d_numRecords; ++i) { + unsigned int remainder = i % 4; + if (i % leaseCount == 1) { + leaseId++; + seqNumber = 1; + } + if (0 == remainder) { + bmqt::MessageGUID guid; + mqbu::MessageGUIDUtil::generateGUID(&guid); + OffsetPtr rec(d_block, d_currPos); + new (rec.get()) MessageRecord(); + rec->header() + .setPrimaryLeaseId(leaseId) + .setSequenceNumber(seqNumber++) + .setTimestamp(i * d_timestampIncrement); + rec->setRefCount(i % FileStoreProtocol::k_MAX_MSG_REF_COUNT_HARD) + .setQueueKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "abcde")) + .setFileKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "12345")) + .setMessageOffsetDwords(i) + .setMessageGUID(guid) + .setCrc32c(i) + .setCompressionAlgorithmType( + bmqt::CompressionAlgorithmType::e_NONE) + .setMagic(RecordHeader::k_MAGIC); + + RecordBufferType buf; + bsl::memcpy(buf.buffer(), + rec.get(), + FileStoreProtocol::k_JOURNAL_RECORD_SIZE); + records->push_back(bsl::make_pair(RecordType::e_MESSAGE, buf)); + } + else if (1 == remainder) { + // ConfRec + bmqt::MessageGUID guid; + mqbu::MessageGUIDUtil::generateGUID(&guid); + OffsetPtr rec(d_block, d_currPos); + new (rec.get()) ConfirmRecord(); + rec->header() + .setPrimaryLeaseId(leaseId) + .setSequenceNumber(seqNumber++) + .setTimestamp(i * d_timestampIncrement); + rec->setReason(ConfirmReason::e_REJECTED) + .setQueueKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "abcde")) + .setAppKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "appid")) + .setMessageGUID(guid) + .setMagic(RecordHeader::k_MAGIC); + + RecordBufferType buf; + bsl::memcpy(buf.buffer(), + rec.get(), + FileStoreProtocol::k_JOURNAL_RECORD_SIZE); + records->push_back(bsl::make_pair(RecordType::e_CONFIRM, buf)); + } + else if (2 == remainder) { + // DelRec + bmqt::MessageGUID guid; + mqbu::MessageGUIDUtil::generateGUID(&guid); + OffsetPtr rec(d_block, d_currPos); + new (rec.get()) DeletionRecord(); + rec->header() + .setPrimaryLeaseId(leaseId) + .setSequenceNumber(seqNumber++) + .setTimestamp(i * d_timestampIncrement); + rec->setDeletionRecordFlag(DeletionRecordFlag::e_IMPLICIT_CONFIRM) + .setQueueKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "abcde")) + .setMessageGUID(guid) + .setMagic(RecordHeader::k_MAGIC); + + RecordBufferType buf; + bsl::memcpy(buf.buffer(), + rec.get(), + FileStoreProtocol::k_JOURNAL_RECORD_SIZE); + records->push_back(bsl::make_pair(RecordType::e_DELETION, buf)); + } + else if (3 == remainder) { + // QueueOpRec + OffsetPtr rec(d_block, d_currPos); + new (rec.get()) QueueOpRecord(); + rec->header() + .setPrimaryLeaseId(leaseId) + .setSequenceNumber(seqNumber++) + .setTimestamp(i * d_timestampIncrement); + rec->setFlags(3) + .setQueueKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "abcde")) + .setAppKey( + mqbu::StorageKey(mqbu::StorageKey::BinaryRepresentation(), + "appid")) + .setType(QueueOpType::e_PURGE) + .setMagic(RecordHeader::k_MAGIC); + + RecordBufferType buf; + bsl::memcpy(buf.buffer(), + rec.get(), + FileStoreProtocol::k_JOURNAL_RECORD_SIZE); + records->push_back(bsl::make_pair(RecordType::e_QUEUE_OP, buf)); + } + // else { + // OffsetPtr rec(d_block, d_currPos); + // new (rec.get()) JournalOpRecord(JournalOpType::e_SYNCPOINT, + // SyncPointType::e_REGULAR, + // 1234567, // seqNum + // 25, // leaderTerm + // 121, // leaderNodeId + // 8800, // dataFilePosition + // 100, // qlistFilePosition + // RecordHeader::k_MAGIC); + + // rec->header() + // .setPrimaryLeaseId(100) + // .setSequenceNumber(i) + // .setTimestamp(i * d_timestampIncrement); + // RecordBufferType buf; + // bsl::memcpy(buf.buffer(), + // rec.get(), + // FileStoreProtocol::k_JOURNAL_RECORD_SIZE); + // records->push_back(bsl::make_pair(RecordType::e_JOURNAL_OP, buf)); + // } + + d_currPos += FileStoreProtocol::k_JOURNAL_RECORD_SIZE; + } +} + } // close package namespace } // close enterprise namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h index 1a6b42efe..2b24865ab 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h @@ -157,6 +157,11 @@ class JournalFile { GuidVectorType* expectedGUIDs, size_t numMessages, bsl::vector& messageOffsets); + + /// Generate sequence of all types of records. Increase Primary Lease Id after the specified `leaseCount` records. + /// Store list of created records in the specified `records`. + void addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, size_t leaseCount); + }; // ============================================================================ diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index efdd5c4af..c7a6bb4f5 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -14,6 +14,8 @@ // limitations under the License. // bmqstoragetool +#include "m_bmqstoragetool_compositesequencenumber.h" +#include "m_bmqstoragetool_parameters.h" #include // BDE @@ -36,14 +38,48 @@ namespace BloombergLP { namespace m_bmqstoragetool { +namespace { + +bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || valueType == Parameters::e_OFFSET); + + return (valueType == Parameters::e_TIMESTAMP) ? jit->recordHeader().timestamp() : jit->recordOffset(); +} + +template +T getValue_1(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || valueType == Parameters::e_OFFSET); + + return (valueType == Parameters::e_TIMESTAMP) ? jit->recordHeader().timestamp() : jit->recordOffset(); +} + +template<> +CompositeSequenceNumber getValue_1(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + BSLS_ASSERT(valueType != Parameters::e_NONE); + + return CompositeSequenceNumber(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); +} + +} // close unnamed namespace + /// Move the journal iterator pointed by the specified 'jit' to the first -/// message whose timestamp is more then the specified 'timestamp'. Return '1' +/// record whose value (timestamp or offset) is more then the specified 'valueGt'. Return '1' /// on success, '0' if there are no such records or negative value if an error /// was encountered. Note that if this method returns < 0, the specified 'jit' /// is invalidated. Behavior is undefined unless last call to `nextRecord` or /// 'advance' returned '1' and the iterator points to a valid record. int moveToLowerBound(mqbs::JournalFileIterator* jit, - const bsls::Types::Uint64& timestamp) + const Parameters::SearchValueType valueType, + const bsls::Types::Uint64& valueGt) { // PRECONDITIONS BSLS_ASSERT(jit); @@ -57,7 +93,7 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, bsls::Types::Uint64 left = 0; bsls::Types::Uint64 right = recordsNumber; while (right > left + 1) { - const bool goBackwards = jit->recordHeader().timestamp() > timestamp; + const bool goBackwards = getValue(jit, valueType) > valueGt; if (goBackwards != jit->isReverseMode()) { jit->flipDirection(); } @@ -81,7 +117,7 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, if (jit->isReverseMode()) { jit->flipDirection(); } - if (jit->recordHeader().timestamp() <= timestamp) { + if (getValue(jit, valueType) <= valueGt) { if (jit->recordIndex() < recordsNumber) { rc = jit->nextRecord(); } @@ -95,6 +131,327 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, return rc; // RETURN } +template +int moveToLower(mqbs::JournalFileIterator* jit, + const Parameters::SearchValueType valueType, + const T& valueGt) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + + int rc = 1; + const unsigned int recordSize = jit->header().recordWords() * + bmqp::Protocol::k_WORD_SIZE; + const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - + jit->firstRecordPosition()) / + recordSize; + bsls::Types::Uint64 left = 0; + bsls::Types::Uint64 right = recordsNumber; + while (right > left + 1) { + const bool goBackwards = valueGt < getValue_1(jit, valueType); + if (goBackwards != jit->isReverseMode()) { + jit->flipDirection(); + } + if (goBackwards) { + if (jit->recordIndex() == 0) { + break; // BREAK + } + right = jit->recordIndex(); + } + else { + if (jit->recordIndex() == recordsNumber) { + break; // BREAK + } + left = jit->recordIndex(); + } + rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); + if (rc != 1) { + return rc; // RETURN + } + } + if (jit->isReverseMode()) { + jit->flipDirection(); + } + if (getValue_1(jit, valueType) <= valueGt) { + if (jit->recordIndex() < recordsNumber) { + rc = jit->nextRecord(); + } + else { + // It's the last record, so there are no messages with timestamp + // greater than the specified 'timestamp' in the file. + rc = 0; + } + } + + return rc; // RETURN +} + +int moveToLowerSeqNumber(mqbs::JournalFileIterator* jit, + const CompositeSequenceNumber& seqNumGt) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + BSLS_ASSERT(!seqNumGt.isUnset()); + + int rc = 1; + const unsigned int recordSize = jit->header().recordWords() * + bmqp::Protocol::k_WORD_SIZE; + const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - + jit->firstRecordPosition()) / + recordSize; + bsls::Types::Uint64 left = 0; + bsls::Types::Uint64 right = recordsNumber; + while (right > left + 1) { + CompositeSequenceNumber seqNum(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); + const bool goBackwards = seqNumGt < seqNum; + if (goBackwards != jit->isReverseMode()) { + jit->flipDirection(); + } + if (goBackwards) { + if (jit->recordIndex() == 0) { + break; // BREAK + } + right = jit->recordIndex(); + } + else { + if (jit->recordIndex() == recordsNumber) { + break; // BREAK + } + left = jit->recordIndex(); + } + rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); + if (rc != 1) { + return rc; // RETURN + } + } + if (jit->isReverseMode()) { + jit->flipDirection(); + } + CompositeSequenceNumber seqNum(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); + if (seqNum <= seqNumGt) { + if (jit->recordIndex() < recordsNumber) { + rc = jit->nextRecord(); + } + else { + // It's the last record, so there are no messages with timestamp + // greater than the specified 'timestamp' in the file. + rc = 0; + } + } + + return rc; // RETURN +} + +int moveToLowerSeqNumber_2(mqbs::JournalFileIterator* jit, + const CompositeSequenceNumber& seqNumGt) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + + int rc = 1; + const unsigned int recordSize = jit->header().recordWords() * + bmqp::Protocol::k_WORD_SIZE; + const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - + jit->firstRecordPosition()) / + recordSize; + bsls::Types::Uint64 left = 0; + bsls::Types::Uint64 right = recordsNumber; + + bsl::cout << "right_1: " << right << "\n"; + + // First, find required leaseId range + + // Check edge condition to skip search left edge + if (seqNumGt.leaseId() == 1) { + right = left; + } + unsigned int leftLeaseId = bsl::max(seqNumGt.leaseId() - 1, 1u); + // unsigned int rightLeaseId = seqNumGt.leaseId() + 1; + + //////////////////////////////////////////////////////////////////////// + // Find left position + while (right > left + 1) { + // const bool goBackwards = jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId(); + const bool goBackwards = jit->recordHeader().primaryLeaseId() > leftLeaseId; + bsl::cout << "goBackwards: " << jit->recordHeader().primaryLeaseId() << " : " << seqNumGt.leaseId() << "\n"; + + if (goBackwards != jit->isReverseMode()) { + jit->flipDirection(); + } + if (goBackwards) { + if (jit->recordIndex() == 0) { + break; // BREAK + } + right = jit->recordIndex(); + bsl::cout << "right: " << right << "\n"; + } + else { + if (jit->recordIndex() == recordsNumber) { + break; // BREAK + } + left = jit->recordIndex(); + bsl::cout << "left: " << left << "\n"; + } + rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); + if (rc != 1) { + return rc; // RETURN + } + } + + bsl::cout << "Found Left index: " << jit->recordIndex() << "\n"; + bsl::cout << jit->recordHeader() << '\n'; + + if (jit->isReverseMode()) { + jit->flipDirection(); + } + + // Move inside range + if (jit->recordHeader().primaryLeaseId() < seqNumGt.leaseId()) { + if (jit->recordIndex() < recordsNumber) { + rc = jit->nextRecord(); + if (rc != 1) { + return rc; // RETURN + } + } + else { + // TODO + return 0; // RETURN + } + } + + left = jit->recordIndex(); + + bsls::Types::Uint64 foundLeft = left; + right = recordsNumber; + + //////////////////////////////////////////////////////////////////////// + // Search right + while (right > left + 1) { + const bool goBackwards = jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId(); + // const bool goBackwards = jit->recordHeader().primaryLeaseId() > leftLeaseId; + bsl::cout << "goBackwards: " << jit->recordHeader().primaryLeaseId() << " : " << seqNumGt.leaseId() << "\n"; + + if (goBackwards != jit->isReverseMode()) { + jit->flipDirection(); + } + if (goBackwards) { + if (jit->recordIndex() == 0) { + break; // BREAK + } + right = jit->recordIndex(); + bsl::cout << "right: " << right << "\n"; + } + else { + if (jit->recordIndex() == recordsNumber) { + break; // BREAK + } + left = jit->recordIndex(); + bsl::cout << "left: " << left << "\n"; + } + rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); + if (rc != 1) { + return rc; // RETURN + } + } + + bsl::cout << "Found Right index: " << jit->recordIndex() << "\n"; + bsl::cout << jit->recordHeader() << '\n'; + + // Move inside range + if (jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId()) { + + if (jit->recordIndex() != 0) { + if (!jit->isReverseMode()) { + jit->flipDirection(); + } + rc = jit->nextRecord(); + if (rc != 1) { + return rc; // RETURN + } + } + else { + // TODO + return 0; // RETURN + } + } + + bsl::cout << "Final Right: " << jit->recordHeader() << '\n'; + + if (jit->isReverseMode()) { + jit->flipDirection(); + } + + // Check edge case (right position) + if (jit->recordHeader().sequenceNumber() == seqNumGt.sequenceNumber()) + { + // Move to next record + if (jit->recordIndex() < recordsNumber) { + // if (!jit->isReverseMode()) { + // jit->flipDirection(); + // } + rc = jit->nextRecord(); + bsl::cout << "Edge case Right: " << jit->recordHeader() << '\n'; + return rc; // RETURN + } + else { + // TODO + return 0; // RETURN + } + } + + //////////////////////////////////////////////////////////////////////// + // Search inside leaqseId + left = foundLeft; + right = jit->recordIndex(); + while (right > left + 1) { + const bool goBackwards = jit->recordHeader().sequenceNumber() > seqNumGt.sequenceNumber(); + bsl::cout << "goBackwards: " << jit->recordHeader().sequenceNumber() << " : " << seqNumGt.sequenceNumber() << "\n"; + + if (goBackwards != jit->isReverseMode()) { + jit->flipDirection(); + } + if (goBackwards) { + if (jit->recordIndex() == 0) { + break; // BREAK + } + right = jit->recordIndex(); + bsl::cout << "right: " << right << "\n"; + } + else { + if (jit->recordIndex() == recordsNumber) { + break; // BREAK + } + left = jit->recordIndex(); + bsl::cout << "left: " << left << "\n"; + } + rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); + if (rc != 1) { + return rc; // RETURN + } + } + + bsl::cout << "Found index: " << jit->recordIndex() << "\n"; + bsl::cout << jit->recordHeader() << '\n'; + + if (jit->isReverseMode()) { + jit->flipDirection(); + } + if (jit->recordHeader().sequenceNumber() <= seqNumGt.sequenceNumber()) { + // if (getValue(jit, valueType) <= valueGt) { + if (jit->recordIndex() < recordsNumber) { + rc = jit->nextRecord(); + } + else { + // It's the last record, so there are no messages with timestamp + // greater than the specified 'timestamp' in the file. + rc = 0; + } + } + + return rc; +} + + // ========================== // class JournalFileProcessor // ========================== @@ -121,12 +478,15 @@ void JournalFileProcessor::process() Filters filters(d_parameters->d_queueKey, d_parameters->d_queueName, d_parameters->d_queueMap, - d_parameters->d_timestampGt, - d_parameters->d_timestampLt, + d_parameters->d_valueType, + d_parameters->d_valueGt, + d_parameters->d_valueLt, + d_parameters->d_seqNumGt, + d_parameters->d_seqNumLt, d_allocator_p); bool stopSearch = false; - bool needTimestampSearch = d_parameters->d_timestampGt > 0; + bool needMoveToLowerBound = d_parameters->d_valueGt > 0 || !d_parameters->d_seqNumGt.isUnset(); // Iterate through all Journal file records mqbs::JournalFileIterator* iter = d_fileManager->journalFileIterator(); @@ -140,8 +500,14 @@ void JournalFileProcessor::process() d_ostream << "Iteration aborted (exit status " << rc << ")."; return; // RETURN } - if (needTimestampSearch) { - rc = moveToLowerBound(iter, d_parameters->d_timestampGt); + + if (needMoveToLowerBound) { + // rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_valueGt); + if (d_parameters->d_valueType == Parameters::e_SEQUENCE_NUM) { + rc = moveToLower(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); + } else { + rc = moveToLower(iter, d_parameters->d_valueType, d_parameters->d_valueGt); + } if (rc == 0) { stopSearch = true; continue; // CONTINUE @@ -151,13 +517,18 @@ void JournalFileProcessor::process() << rc << ")."; return; // RETURN } - needTimestampSearch = false; + needMoveToLowerBound = false; } + + bsl::cout << iter->recordHeader() << '\n'; + // continue; + // MessageRecord if (iter->recordType() == mqbs::RecordType::e_MESSAGE) { const mqbs::MessageRecord& record = iter->asMessageRecord(); + // Apply filters - if (filters.apply(record)) { + if (filters.apply(record, iter->recordOffset())) { stopSearch = d_searchResult_p->processMessageRecord( record, iter->recordIndex(), @@ -167,6 +538,7 @@ void JournalFileProcessor::process() // ConfirmRecord else if (iter->recordType() == mqbs::RecordType::e_CONFIRM) { const mqbs::ConfirmRecord& record = iter->asConfirmRecord(); + stopSearch = d_searchResult_p->processConfirmRecord( record, iter->recordIndex(), @@ -175,6 +547,7 @@ void JournalFileProcessor::process() // DeletionRecord else if (iter->recordType() == mqbs::RecordType::e_DELETION) { const mqbs::DeletionRecord& record = iter->asDeletionRecord(); + stopSearch = d_searchResult_p->processDeletionRecord( record, iter->recordIndex(), diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h index 08876adec..bbcb30b8e 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h @@ -41,7 +41,14 @@ namespace BloombergLP { namespace m_bmqstoragetool { int moveToLowerBound(mqbs::JournalFileIterator* jit, - const bsls::Types::Uint64& timestamp); + const Parameters::SearchValueType valueType, + const bsls::Types::Uint64& value); +int moveToLowerSeqNumber(mqbs::JournalFileIterator* jit, + const CompositeSequenceNumber& seqNumGt); +template +int moveToLower(mqbs::JournalFileIterator* jit, + const Parameters::SearchValueType valueType, + const T& value); // ========================== // class JournalFileProcessor diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index d05da9b5a..fbd421480 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -14,6 +14,7 @@ // limitations under the License. // bmqstoragetool +#include "m_bmqstoragetool_parameters.h" #include #include #include @@ -822,8 +823,9 @@ static void test11_searchMessagesByTimestamp() // Configure parameters to search messages by timestamps Parameters params(s_allocator_p); - params.d_timestampGt = ts1; - params.d_timestampLt = ts2; + params.d_valueGt = ts1; + params.d_valueLt = ts2; + params.d_valueType = Parameters::e_TIMESTAMP; // Prepare file manager bslma::ManagedPtr fileManager( new (*s_allocator_p) FileManagerMock(journalFile), @@ -1173,7 +1175,8 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); ResultChecker::check(journalFileIt, ts); } @@ -1193,13 +1196,15 @@ static void test15_timestampSearchTest() // Find record with lower timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts1), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts2), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); ResultChecker::check(journalFileIt, ts2); // Find record with lower timestamp than the record pointed by the @@ -1207,7 +1212,8 @@ static void test15_timestampSearchTest() ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts1), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the @@ -1215,7 +1221,8 @@ static void test15_timestampSearchTest() ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts2), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); ResultChecker::check(journalFileIt, ts2); } @@ -1229,7 +1236,8 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts), 0); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); ASSERT_EQ(journalFileIt.recordIndex(), k_NUM_RECORDS - 1); ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); @@ -1244,13 +1252,114 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, ts), 1); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); ASSERT_EQ(journalFileIt.recordIndex(), 0U); ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); } } +static void test16_sequenceNumSearchTest() +// ------------------------------------------------------------------------ +// TIMESTAMP SEARCH TEST +// +// Concerns: +// Find the first message in journal file with timestamp more than the +// specified 'ts' and move the specified JournalFileIterator to it. +// +// Testing: +// m_bmqstoragetool::moveToLowerBound() +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("TIMESTAMP SEARCH TEST"); + + struct Test { + int d_line; + size_t d_numRecords; + size_t d_numRecordsWithSameLeaseId; + unsigned int d_leaseIdGt; + bsls::Types::Uint64 d_seqNumberGt; + } k_DATA[] = {{L_, 32, 4, 3, 2}, + {L_, 300, 10, 3, 2}, + {L_, 320, 11, 3, 2}, + {L_, 320, 11, 3, 1}, // edge case (first seqNum edge inside leaseId) + {L_, 320, 11, 3, 11}, // edge case (last seqNum edge inside leaseId) + {L_, 300, 11, 1, 1}, // edge case (left seqNum edge inside first leaseId) + {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum edge inside last leaseId) + {L_, 3, 2, 1, 2}, + {L_, 30, 29, 1, 29}, + {L_, 30, 29, 1, 28}, + {L_, 300, 9, 1, 9}, + {L_, 300, 9, 1, 8}, + {L_, 300, 9, 1, 7}, + {L_, 300, 9, 1, 6}, + {L_, 300, 9, 1, 5}, + {L_, 300, 9, 1, 4}, + {L_, 300, 9, 1, 3}, + {L_, 300, 9, 1, 2}, + {L_, 300, 9, 1, 1}, + {L_, 300, 9, 2, 9}, + {L_, 300, 9, 2, 8}, + {L_, 300, 9, 2, 7}, + {L_, 300, 9, 2, 6}, + {L_, 300, 9, 2, 5}, + {L_, 300, 9, 2, 4}, + {L_, 300, 9, 2, 3}, + {L_, 300, 9, 2, 2}, + {L_, 300, 9, 2, 1}, + + }; + + const size_t k_NUM_DATA = sizeof(k_DATA) / sizeof(*k_DATA); + + for (size_t idx = 0; idx < k_NUM_DATA; ++idx) { + const Test& test = k_DATA[idx]; + + // Simulate journal file + JournalFile::RecordsListType records(s_allocator_p); + JournalFile journalFile(test.d_numRecords, s_allocator_p); + journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, test.d_numRecordsWithSameLeaseId); + + mqbs::JournalFileIterator journalFileIt( + &journalFile.mappedFileDescriptor(), + journalFile.fileHeader(), + false); + + CompositeSequenceNumber seqNumGt(test.d_leaseIdGt, test.d_seqNumberGt); + unsigned int expectedLeaseId = test.d_leaseIdGt + (test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId ? 1 : 0); + bsls::Types::Uint64 expectedSeqNumber = test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId ? 1 : (test.d_seqNumberGt + 1); + + // Move the iterator to the beginning of the file + ASSERT_EQ(journalFileIt.nextRecord(), 1); + // ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLowerSeqNumber(&journalFileIt, seqNumGt), 1); + ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 1); + ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().primaryLeaseId(), expectedLeaseId); + ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().sequenceNumber(), expectedSeqNumber); + } + + // Edge case: not in the range (greater then the last record) + { + const size_t k_NUM_RECORDS = 300; + JournalFile::RecordsListType records(s_allocator_p); + JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, k_NUM_RECORDS); + + mqbs::JournalFileIterator journalFileIt( + &journalFile.mappedFileDescriptor(), + journalFile.fileHeader(), + false); + + // Move the iterator to the beginning of the file + ASSERT_EQ(journalFileIt.nextRecord(), 1); + CompositeSequenceNumber seqNumGt(1, k_NUM_RECORDS); + // ASSERT_EQ(m_bmqstoragetool::moveToLowerSeqNumber(&journalFileIt, seqNumGt), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 0); + ASSERT_EQ(journalFileIt.recordHeader().primaryLeaseId(), 1u); + ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), k_NUM_RECORDS); + } +} + // ============================================================================ // MAIN PROGRAM // ---------------------------------------------------------------------------- @@ -1276,6 +1385,7 @@ int main(int argc, char* argv[]) case 13: test13_searchMessagesWithPayloadDumpTest(); break; case 14: test14_summaryTest(); break; case 15: test15_timestampSearchTest(); break; + case 16: test16_sequenceNumSearchTest(); break; default: { cerr << "WARNING: CASE '" << _testCase << "' NOT FOUND." << endl; s_testStatus = -1; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 58149337c..8fc6b1b73 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -227,6 +227,19 @@ bool CommandLineArguments::validate(bsl::string* error, bslma::Allocator* alloca ss << "secnum filter can't be combined with any other filters, as it is " "specific enough to find a particular message\n"; } + if (!d_seqNum.empty()) { + + // TODO: move to method + + CompositeSequenceNumber seqNum; + bmqu::MemOutStream errorDescr(allocator); + for (bsl::vector::const_iterator cit = d_seqNum.begin(); cit != d_seqNum.end(); ++cit) { + seqNum.fromString(errorDescr, *cit); + if(seqNum.isUnset()) { + ss << "--seqnum: " << errorDescr.str() << "\n"; + } + } + } // TODO: offset check too @@ -281,6 +294,7 @@ Parameters::Parameters(bslma::Allocator* allocator) , d_confirmed(false) , d_partiallyConfirmed(false) { + // NOTHING } Parameters::Parameters(const CommandLineArguments& arguments, @@ -290,6 +304,7 @@ Parameters::Parameters(const CommandLineArguments& arguments, , d_valueGt(0) , d_valueLt(0) , d_guid(arguments.d_guid, allocator) +, d_seqNum(allocator) , d_queueKey(arguments.d_queueKey, allocator) , d_queueName(arguments.d_queueName, allocator) , d_dumpLimit(arguments.d_dumpLimit) @@ -305,15 +320,32 @@ Parameters::Parameters(const CommandLineArguments& arguments, d_valueType = e_TIMESTAMP; d_valueLt = static_cast(arguments.d_timestampLt); d_valueGt = static_cast(arguments.d_timestampGt); - } else if (!arguments.d_seqNumLt.empty() || arguments.d_seqNumGt.empty()) { + } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { + bsl::cout << "INSIDE!!!!" << arguments.d_seqNumGt << "\n"; d_valueType = e_SEQUENCE_NUM; - // d_valueLt = static_cast(arguments.d_seqNumLt); - // d_valueGt = static_cast(arguments.d_seqNumGt); + CompositeSequenceNumber seqNum; + bmqu::MemOutStream errorDescr(allocator); + if (!arguments.d_seqNumLt.empty()) { + d_seqNumLt.fromString(errorDescr, arguments.d_seqNumLt); + } + if (!arguments.d_seqNumGt.empty()) { + d_seqNumGt.fromString(errorDescr, arguments.d_seqNumGt); + // bsl::cout << "INSIDE _1 !!!!" << arguments.d_seqNumGt << "\n"; + } } else { d_valueType = e_OFFSET; d_valueLt = static_cast(arguments.d_offsetLt); d_valueGt = static_cast(arguments.d_offsetGt); } + + if (!arguments.d_seqNum.empty()) { + CompositeSequenceNumber seqNum; + bmqu::MemOutStream errorDescr(allocator); + for (bsl::vector::const_iterator cit = arguments.d_seqNum.begin(); cit != arguments.d_seqNum.end(); ++cit) { + seqNum.fromString(errorDescr, *cit); + d_seqNum.push_back(seqNum); + } + } } void Parameters::validateQueueNames(bslma::Allocator* allocator) const diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp index 04fe3127e..47501084f 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp @@ -14,6 +14,7 @@ // limitations under the License. // bmqstoragetool +#include "m_bmqstoragetool_parameters.h" #include namespace BloombergLP { @@ -123,10 +124,10 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( } // Add TimestampDecorator if 'timestampLt' is given. - if (params->d_timestampLt > 0) { + if (params->d_valueType == Parameters::e_TIMESTAMP && params->d_valueLt > 0) { searchResult.reset( new (*alloc) SearchResultTimestampDecorator(searchResult, - params->d_timestampLt, + params->d_valueLt, alloc), alloc); } From 2ed441f19bdfbc66465c54195d7f8f59a3629f78 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Thu, 7 Nov 2024 18:28:34 +0200 Subject: [PATCH 03/21] Reemove debug Signed-off-by: Aleksandr Ivanov --- .../m_bmqstoragetool_journalfileprocessor.cpp | 351 +----------------- .../m_bmqstoragetool_journalfileprocessor.h | 7 +- ..._bmqstoragetool_journalfileprocessor.t.cpp | 30 +- 3 files changed, 23 insertions(+), 365 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index c7a6bb4f5..8aa7af125 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -39,18 +39,8 @@ namespace BloombergLP { namespace m_bmqstoragetool { namespace { - -bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || valueType == Parameters::e_OFFSET); - - return (valueType == Parameters::e_TIMESTAMP) ? jit->recordHeader().timestamp() : jit->recordOffset(); -} - template -T getValue_1(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +T getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); @@ -60,11 +50,11 @@ T getValue_1(const mqbs::JournalFileIterator* jit, const Parameters::SearchValue } template<> -CompositeSequenceNumber getValue_1(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); - BSLS_ASSERT(valueType != Parameters::e_NONE); + BSLS_ASSERT(valueType == Parameters::e_SEQUENCE_NUM); return CompositeSequenceNumber(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); } @@ -72,67 +62,13 @@ CompositeSequenceNumber getValue_1(const mqbs::JournalF } // close unnamed namespace /// Move the journal iterator pointed by the specified 'jit' to the first -/// record whose value (timestamp or offset) is more then the specified 'valueGt'. Return '1' +/// record whose value `T` is more then the specified 'valueGt'. Return '1' /// on success, '0' if there are no such records or negative value if an error /// was encountered. Note that if this method returns < 0, the specified 'jit' /// is invalidated. Behavior is undefined unless last call to `nextRecord` or /// 'advance' returned '1' and the iterator points to a valid record. -int moveToLowerBound(mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType, - const bsls::Types::Uint64& valueGt) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - - int rc = 1; - const unsigned int recordSize = jit->header().recordWords() * - bmqp::Protocol::k_WORD_SIZE; - const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - - jit->firstRecordPosition()) / - recordSize; - bsls::Types::Uint64 left = 0; - bsls::Types::Uint64 right = recordsNumber; - while (right > left + 1) { - const bool goBackwards = getValue(jit, valueType) > valueGt; - if (goBackwards != jit->isReverseMode()) { - jit->flipDirection(); - } - if (goBackwards) { - if (jit->recordIndex() == 0) { - break; // BREAK - } - right = jit->recordIndex(); - } - else { - if (jit->recordIndex() == recordsNumber) { - break; // BREAK - } - left = jit->recordIndex(); - } - rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); - if (rc != 1) { - return rc; // RETURN - } - } - if (jit->isReverseMode()) { - jit->flipDirection(); - } - if (getValue(jit, valueType) <= valueGt) { - if (jit->recordIndex() < recordsNumber) { - rc = jit->nextRecord(); - } - else { - // It's the last record, so there are no messages with timestamp - // greater than the specified 'timestamp' in the file. - rc = 0; - } - } - - return rc; // RETURN -} - template -int moveToLower(mqbs::JournalFileIterator* jit, +int moveToLowerBound(mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType, const T& valueGt) { @@ -148,7 +84,7 @@ int moveToLower(mqbs::JournalFileIterator* jit, bsls::Types::Uint64 left = 0; bsls::Types::Uint64 right = recordsNumber; while (right > left + 1) { - const bool goBackwards = valueGt < getValue_1(jit, valueType); + const bool goBackwards = valueGt < getValue(jit, valueType); if (goBackwards != jit->isReverseMode()) { jit->flipDirection(); } @@ -172,7 +108,7 @@ int moveToLower(mqbs::JournalFileIterator* jit, if (jit->isReverseMode()) { jit->flipDirection(); } - if (getValue_1(jit, valueType) <= valueGt) { + if (getValue(jit, valueType) <= valueGt) { if (jit->recordIndex() < recordsNumber) { rc = jit->nextRecord(); } @@ -186,272 +122,6 @@ int moveToLower(mqbs::JournalFileIterator* jit, return rc; // RETURN } -int moveToLowerSeqNumber(mqbs::JournalFileIterator* jit, - const CompositeSequenceNumber& seqNumGt) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - BSLS_ASSERT(!seqNumGt.isUnset()); - - int rc = 1; - const unsigned int recordSize = jit->header().recordWords() * - bmqp::Protocol::k_WORD_SIZE; - const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - - jit->firstRecordPosition()) / - recordSize; - bsls::Types::Uint64 left = 0; - bsls::Types::Uint64 right = recordsNumber; - while (right > left + 1) { - CompositeSequenceNumber seqNum(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); - const bool goBackwards = seqNumGt < seqNum; - if (goBackwards != jit->isReverseMode()) { - jit->flipDirection(); - } - if (goBackwards) { - if (jit->recordIndex() == 0) { - break; // BREAK - } - right = jit->recordIndex(); - } - else { - if (jit->recordIndex() == recordsNumber) { - break; // BREAK - } - left = jit->recordIndex(); - } - rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); - if (rc != 1) { - return rc; // RETURN - } - } - if (jit->isReverseMode()) { - jit->flipDirection(); - } - CompositeSequenceNumber seqNum(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); - if (seqNum <= seqNumGt) { - if (jit->recordIndex() < recordsNumber) { - rc = jit->nextRecord(); - } - else { - // It's the last record, so there are no messages with timestamp - // greater than the specified 'timestamp' in the file. - rc = 0; - } - } - - return rc; // RETURN -} - -int moveToLowerSeqNumber_2(mqbs::JournalFileIterator* jit, - const CompositeSequenceNumber& seqNumGt) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - - int rc = 1; - const unsigned int recordSize = jit->header().recordWords() * - bmqp::Protocol::k_WORD_SIZE; - const bsls::Types::Uint64 recordsNumber = (jit->lastRecordPosition() - - jit->firstRecordPosition()) / - recordSize; - bsls::Types::Uint64 left = 0; - bsls::Types::Uint64 right = recordsNumber; - - bsl::cout << "right_1: " << right << "\n"; - - // First, find required leaseId range - - // Check edge condition to skip search left edge - if (seqNumGt.leaseId() == 1) { - right = left; - } - unsigned int leftLeaseId = bsl::max(seqNumGt.leaseId() - 1, 1u); - // unsigned int rightLeaseId = seqNumGt.leaseId() + 1; - - //////////////////////////////////////////////////////////////////////// - // Find left position - while (right > left + 1) { - // const bool goBackwards = jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId(); - const bool goBackwards = jit->recordHeader().primaryLeaseId() > leftLeaseId; - bsl::cout << "goBackwards: " << jit->recordHeader().primaryLeaseId() << " : " << seqNumGt.leaseId() << "\n"; - - if (goBackwards != jit->isReverseMode()) { - jit->flipDirection(); - } - if (goBackwards) { - if (jit->recordIndex() == 0) { - break; // BREAK - } - right = jit->recordIndex(); - bsl::cout << "right: " << right << "\n"; - } - else { - if (jit->recordIndex() == recordsNumber) { - break; // BREAK - } - left = jit->recordIndex(); - bsl::cout << "left: " << left << "\n"; - } - rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); - if (rc != 1) { - return rc; // RETURN - } - } - - bsl::cout << "Found Left index: " << jit->recordIndex() << "\n"; - bsl::cout << jit->recordHeader() << '\n'; - - if (jit->isReverseMode()) { - jit->flipDirection(); - } - - // Move inside range - if (jit->recordHeader().primaryLeaseId() < seqNumGt.leaseId()) { - if (jit->recordIndex() < recordsNumber) { - rc = jit->nextRecord(); - if (rc != 1) { - return rc; // RETURN - } - } - else { - // TODO - return 0; // RETURN - } - } - - left = jit->recordIndex(); - - bsls::Types::Uint64 foundLeft = left; - right = recordsNumber; - - //////////////////////////////////////////////////////////////////////// - // Search right - while (right > left + 1) { - const bool goBackwards = jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId(); - // const bool goBackwards = jit->recordHeader().primaryLeaseId() > leftLeaseId; - bsl::cout << "goBackwards: " << jit->recordHeader().primaryLeaseId() << " : " << seqNumGt.leaseId() << "\n"; - - if (goBackwards != jit->isReverseMode()) { - jit->flipDirection(); - } - if (goBackwards) { - if (jit->recordIndex() == 0) { - break; // BREAK - } - right = jit->recordIndex(); - bsl::cout << "right: " << right << "\n"; - } - else { - if (jit->recordIndex() == recordsNumber) { - break; // BREAK - } - left = jit->recordIndex(); - bsl::cout << "left: " << left << "\n"; - } - rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); - if (rc != 1) { - return rc; // RETURN - } - } - - bsl::cout << "Found Right index: " << jit->recordIndex() << "\n"; - bsl::cout << jit->recordHeader() << '\n'; - - // Move inside range - if (jit->recordHeader().primaryLeaseId() > seqNumGt.leaseId()) { - - if (jit->recordIndex() != 0) { - if (!jit->isReverseMode()) { - jit->flipDirection(); - } - rc = jit->nextRecord(); - if (rc != 1) { - return rc; // RETURN - } - } - else { - // TODO - return 0; // RETURN - } - } - - bsl::cout << "Final Right: " << jit->recordHeader() << '\n'; - - if (jit->isReverseMode()) { - jit->flipDirection(); - } - - // Check edge case (right position) - if (jit->recordHeader().sequenceNumber() == seqNumGt.sequenceNumber()) - { - // Move to next record - if (jit->recordIndex() < recordsNumber) { - // if (!jit->isReverseMode()) { - // jit->flipDirection(); - // } - rc = jit->nextRecord(); - bsl::cout << "Edge case Right: " << jit->recordHeader() << '\n'; - return rc; // RETURN - } - else { - // TODO - return 0; // RETURN - } - } - - //////////////////////////////////////////////////////////////////////// - // Search inside leaqseId - left = foundLeft; - right = jit->recordIndex(); - while (right > left + 1) { - const bool goBackwards = jit->recordHeader().sequenceNumber() > seqNumGt.sequenceNumber(); - bsl::cout << "goBackwards: " << jit->recordHeader().sequenceNumber() << " : " << seqNumGt.sequenceNumber() << "\n"; - - if (goBackwards != jit->isReverseMode()) { - jit->flipDirection(); - } - if (goBackwards) { - if (jit->recordIndex() == 0) { - break; // BREAK - } - right = jit->recordIndex(); - bsl::cout << "right: " << right << "\n"; - } - else { - if (jit->recordIndex() == recordsNumber) { - break; // BREAK - } - left = jit->recordIndex(); - bsl::cout << "left: " << left << "\n"; - } - rc = jit->advance(bsl::max((right - left) / 2, 1ULL)); - if (rc != 1) { - return rc; // RETURN - } - } - - bsl::cout << "Found index: " << jit->recordIndex() << "\n"; - bsl::cout << jit->recordHeader() << '\n'; - - if (jit->isReverseMode()) { - jit->flipDirection(); - } - if (jit->recordHeader().sequenceNumber() <= seqNumGt.sequenceNumber()) { - // if (getValue(jit, valueType) <= valueGt) { - if (jit->recordIndex() < recordsNumber) { - rc = jit->nextRecord(); - } - else { - // It's the last record, so there are no messages with timestamp - // greater than the specified 'timestamp' in the file. - rc = 0; - } - } - - return rc; -} - - // ========================== // class JournalFileProcessor // ========================== @@ -502,18 +172,17 @@ void JournalFileProcessor::process() } if (needMoveToLowerBound) { - // rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_valueGt); if (d_parameters->d_valueType == Parameters::e_SEQUENCE_NUM) { - rc = moveToLower(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); + rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); } else { - rc = moveToLower(iter, d_parameters->d_valueType, d_parameters->d_valueGt); + rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_valueGt); } if (rc == 0) { stopSearch = true; continue; // CONTINUE } else if (rc < 0) { - d_ostream << "Binary search by timesamp aborted (exit status " + d_ostream << "Binary search aborted (exit status " << rc << ")."; return; // RETURN } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h index bbcb30b8e..6181ecfdd 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h @@ -40,13 +40,8 @@ namespace BloombergLP { namespace m_bmqstoragetool { -int moveToLowerBound(mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType, - const bsls::Types::Uint64& value); -int moveToLowerSeqNumber(mqbs::JournalFileIterator* jit, - const CompositeSequenceNumber& seqNumGt); template -int moveToLower(mqbs::JournalFileIterator* jit, +int moveToLowerBound(mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType, const T& value); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index fbd421480..cbca6821c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -1175,8 +1175,7 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); ResultChecker::check(journalFileIt, ts); } @@ -1196,15 +1195,13 @@ static void test15_timestampSearchTest() // Find record with lower timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); ResultChecker::check(journalFileIt, ts2); // Find record with lower timestamp than the record pointed by the @@ -1212,8 +1209,7 @@ static void test15_timestampSearchTest() ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the @@ -1221,8 +1217,7 @@ static void test15_timestampSearchTest() ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); ResultChecker::check(journalFileIt, ts2); } @@ -1236,8 +1231,7 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); ASSERT_EQ(journalFileIt.recordIndex(), k_NUM_RECORDS - 1); ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); @@ -1252,8 +1246,7 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); ASSERT_EQ(journalFileIt.recordIndex(), 0U); ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); @@ -1332,8 +1325,7 @@ static void test16_sequenceNumSearchTest() // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - // ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLowerSeqNumber(&journalFileIt, seqNumGt), 1); - ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 1); + ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 1); ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().primaryLeaseId(), expectedLeaseId); ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().sequenceNumber(), expectedSeqNumber); } @@ -1353,11 +1345,13 @@ static void test16_sequenceNumSearchTest() // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); CompositeSequenceNumber seqNumGt(1, k_NUM_RECORDS); - // ASSERT_EQ(m_bmqstoragetool::moveToLowerSeqNumber(&journalFileIt, seqNumGt), 0); - ASSERT_EQ(m_bmqstoragetool::moveToLower(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 0); ASSERT_EQ(journalFileIt.recordHeader().primaryLeaseId(), 1u); ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), k_NUM_RECORDS); } + + // TODO: less than first record in the file + } // ============================================================================ From 23ca939aa4865e5d25751b20ad4a47f89e2f53f3 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Fri, 8 Nov 2024 09:53:45 +0200 Subject: [PATCH 04/21] Simplify getValue template Signed-off-by: Aleksandr Ivanov --- .../m_bmqstoragetool_journalfileprocessor.cpp | 7 +++++-- .../m_bmqstoragetool_journalfileprocessor.t.cpp | 3 --- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index 8aa7af125..9650d5006 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -40,7 +40,10 @@ namespace m_bmqstoragetool { namespace { template -T getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +T getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType); + +template<> +bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); @@ -50,7 +53,7 @@ T getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueTy } template<> -CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index cbca6821c..476c4fc04 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -1349,9 +1349,6 @@ static void test16_sequenceNumSearchTest() ASSERT_EQ(journalFileIt.recordHeader().primaryLeaseId(), 1u); ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), k_NUM_RECORDS); } - - // TODO: less than first record in the file - } // ============================================================================ From 33d990ea351e4fc4d1392e1020c0518489560df7 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Fri, 8 Nov 2024 19:17:07 +0200 Subject: [PATCH 05/21] Add search result decorators for seq.number and offset, add UTs Signed-off-by: Aleksandr Ivanov --- .../m_bmqstoragetool_journalfileprocessor.cpp | 9 +- ..._bmqstoragetool_journalfileprocessor.t.cpp | 153 ++++++++++++++++-- .../m_bmqstoragetool_searchresult.cpp | 108 ++++++++++++- .../m_bmqstoragetool_searchresult.h | 101 +++++++++++- .../m_bmqstoragetool_searchresultfactory.cpp | 32 +++- 5 files changed, 375 insertions(+), 28 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index 9650d5006..11df5beea 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -175,10 +175,10 @@ void JournalFileProcessor::process() } if (needMoveToLowerBound) { - if (d_parameters->d_valueType == Parameters::e_SEQUENCE_NUM) { - rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); - } else { + if (d_parameters->d_valueGt > 0) { rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_valueGt); + } else { + rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); } if (rc == 0) { stopSearch = true; @@ -191,9 +191,6 @@ void JournalFileProcessor::process() } needMoveToLowerBound = false; } - - bsl::cout << iter->recordHeader() << '\n'; - // continue; // MessageRecord if (iter->recordType() == mqbs::RecordType::e_MESSAGE) { diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index 476c4fc04..174547996 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -14,6 +14,7 @@ // limitations under the License. // bmqstoragetool +#include "m_bmqstoragetool_compositesequencenumber.h" #include "m_bmqstoragetool_parameters.h" #include #include @@ -1253,19 +1254,19 @@ static void test15_timestampSearchTest() } } -static void test16_sequenceNumSearchTest() +static void test16_sequenceNumberLowerBoundTest() // ------------------------------------------------------------------------ -// TIMESTAMP SEARCH TEST +// MOVE TO SEQUENCE NUMBER LOWER BOUND TEST // // Concerns: -// Find the first message in journal file with timestamp more than the -// specified 'ts' and move the specified JournalFileIterator to it. +// Find the first message in journal file with sequence number more than the +// specified 'valueGt' and move the specified JournalFileIterator to it. // // Testing: // m_bmqstoragetool::moveToLowerBound() // ------------------------------------------------------------------------ { - bmqtst::TestHelper::printTestName("TIMESTAMP SEARCH TEST"); + bmqtst::TestHelper::printTestName("MOVE TO SEQUENCE NUMBER LOWER BOUND TEST"); struct Test { int d_line; @@ -1275,11 +1276,11 @@ static void test16_sequenceNumSearchTest() bsls::Types::Uint64 d_seqNumberGt; } k_DATA[] = {{L_, 32, 4, 3, 2}, {L_, 300, 10, 3, 2}, - {L_, 320, 11, 3, 2}, - {L_, 320, 11, 3, 1}, // edge case (first seqNum edge inside leaseId) - {L_, 320, 11, 3, 11}, // edge case (last seqNum edge inside leaseId) + {L_, 300, 11, 3, 2}, + {L_, 300, 11, 3, 1}, // edge case (first seqNum inside leaseId) + {L_, 300, 11, 3, 11}, // edge case (last seqNum inside leaseId) {L_, 300, 11, 1, 1}, // edge case (left seqNum edge inside first leaseId) - {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum edge inside last leaseId) + {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum inside last leaseId) {L_, 3, 2, 1, 2}, {L_, 30, 29, 1, 29}, {L_, 30, 29, 1, 28}, @@ -1301,7 +1302,6 @@ static void test16_sequenceNumSearchTest() {L_, 300, 9, 2, 3}, {L_, 300, 9, 2, 2}, {L_, 300, 9, 2, 1}, - }; const size_t k_NUM_DATA = sizeof(k_DATA) / sizeof(*k_DATA); @@ -1351,6 +1351,135 @@ static void test16_sequenceNumSearchTest() } } +static void test17_searchMessagesBySequenceNumbersRange() +// ------------------------------------------------------------------------ +// SEARCH MESSAGES BY SEQUENCE NUMBERS RANGE TEST +// +// Concerns: +// Search messages by sequence number in journal file and output GUIDs. +// +// Testing: +// JournalFileProcessor::process() +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("SEARCH MESSAGES BY SEQUENCE NUMBERS RANGE TEST"); + + // Simulate journal file + const size_t k_NUM_RECORDS = 100; + JournalFile::RecordsListType records(s_allocator_p); + JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, 10); + const CompositeSequenceNumber seqNumGt(3, 3); + const CompositeSequenceNumber seqNumLt(4, 6); + + // Configure parameters to search messages by sequence number range + Parameters params(s_allocator_p); + params.d_seqNumGt = seqNumGt; + params.d_seqNumLt = seqNumLt; + params.d_valueType = Parameters::e_SEQUENCE_NUM; + // Prepare file manager + bslma::ManagedPtr fileManager( + new (*s_allocator_p) FileManagerMock(journalFile), + s_allocator_p); + + // Get GUIDs of messages inside sequence nums range and prepare expected + // output + bmqu::MemOutStream expectedStream(s_allocator_p); + + bsl::list::const_iterator recordIter = + records.begin(); + bsl::size_t msgCnt = 0; + for (; recordIter != records.end(); ++recordIter) { + RecordType::Enum rtype = recordIter->first; + if (rtype == RecordType::e_MESSAGE) { + const MessageRecord& msg = *reinterpret_cast( + recordIter->second.buffer()); + const CompositeSequenceNumber seqNum(msg.header().primaryLeaseId(), msg.header().sequenceNumber()); + if (seqNumGt < seqNum && seqNum < seqNumLt) { + outputGuidString(expectedStream, msg.messageGUID()); + msgCnt++; + } + } + } + expectedStream << msgCnt << " message GUID(s) found." << bsl::endl; + + // Run search + bmqu::MemOutStream resultStream(s_allocator_p); + bslma::ManagedPtr searchProcessor = + CommandProcessorFactory::createCommandProcessor(¶ms, + fileManager, + resultStream, + s_allocator_p); + searchProcessor->process(); + + ASSERT_EQ(resultStream.str(), expectedStream.str()); +} + +static void test18_searchMessagesByOffsetsRange() +// ------------------------------------------------------------------------ +// SEARCH MESSAGES BY OFFSETS RANGE TEST +// +// Concerns: +// Search messages by offsets range in journal file and output GUIDs. +// +// Testing: +// JournalFileProcessor::process() +// ------------------------------------------------------------------------ +{ + bmqtst::TestHelper::printTestName("SEARCH MESSAGES BY OFFSETS RANGE TEST"); + + // Simulate journal file + const size_t k_NUM_RECORDS = 50; + JournalFile::RecordsListType records(s_allocator_p); + JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + journalFile.addAllTypesRecords(&records); + const size_t k_HEADER_SIZE = sizeof(mqbs::FileHeader) + sizeof(mqbs::JournalFileHeader); + const bsls::Types::Uint64 offsetGt = mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 15 + k_HEADER_SIZE; + const bsls::Types::Uint64 offsetLt = mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 35 + k_HEADER_SIZE; + + // Configure parameters to search messages by timestamps + Parameters params(s_allocator_p); + params.d_valueGt = offsetGt; + params.d_valueLt = offsetLt; + params.d_valueType = Parameters::e_OFFSET; + // Prepare file manager + bslma::ManagedPtr fileManager( + new (*s_allocator_p) FileManagerMock(journalFile), + s_allocator_p); + + // Get GUIDs of messages within offsets range and prepare expected + // output + bmqu::MemOutStream expectedStream(s_allocator_p); + + bsl::list::const_iterator recordIter = + records.begin(); + bsl::size_t msgCnt = 0; + for (; recordIter != records.end(); ++recordIter) { + RecordType::Enum rtype = recordIter->first; + if (rtype == RecordType::e_MESSAGE) { + const MessageRecord& msg = *reinterpret_cast( + recordIter->second.buffer()); + const bsls::Types::Uint64& offset = msg.header().sequenceNumber() * mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE; + if (offset > offsetGt && offset < offsetLt) { + outputGuidString(expectedStream, msg.messageGUID()); + msgCnt++; + } + } + } + expectedStream << msgCnt << " message GUID(s) found." << bsl::endl; + + // Run search + bmqu::MemOutStream resultStream(s_allocator_p); + bslma::ManagedPtr searchProcessor = + CommandProcessorFactory::createCommandProcessor(¶ms, + fileManager, + resultStream, + s_allocator_p); + searchProcessor->process(); + + ASSERT_EQ(resultStream.str(), expectedStream.str()); +} + // ============================================================================ // MAIN PROGRAM // ---------------------------------------------------------------------------- @@ -1376,7 +1505,9 @@ int main(int argc, char* argv[]) case 13: test13_searchMessagesWithPayloadDumpTest(); break; case 14: test14_summaryTest(); break; case 15: test15_timestampSearchTest(); break; - case 16: test16_sequenceNumSearchTest(); break; + case 16: test16_sequenceNumberLowerBoundTest(); break; + case 17: test17_searchMessagesBySequenceNumbersRange(); break; + case 18: test18_searchMessagesByOffsetsRange(); break; default: { cerr << "WARNING: CASE '" << _testCase << "' NOT FOUND." << endl; s_testStatus = -1; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp index ce7b98bac..c9cf2b7ee 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp @@ -245,14 +245,14 @@ void SearchResultDecorator::outputResult(const GuidsList& guidFilter) // class SearchResultTimestampDecorator // ==================================== -bool SearchResultTimestampDecorator::stop(bsls::Types::Uint64 timestamp) const +bool SearchResultTimestampDecorator::stop(const bsls::Types::Uint64 timestamp) const { return timestamp >= d_timestampLt && !SearchResultDecorator::hasCache(); } SearchResultTimestampDecorator::SearchResultTimestampDecorator( const bsl::shared_ptr& component, - bsls::Types::Uint64 timestampLt, + const bsls::Types::Uint64 timestampLt, bslma::Allocator* allocator) : SearchResultDecorator(component, allocator) , d_timestampLt(timestampLt) @@ -292,6 +292,110 @@ bool SearchResultTimestampDecorator::processDeletionRecord( stop(record.header().timestamp()); } +// ================================= +// class SearchResultOffsetDecorator +// ================================= + +bool SearchResultOffsetDecorator::stop(const bsls::Types::Uint64 offset) const +{ + return offset >= d_offsetLt && !SearchResultDecorator::hasCache(); +} + +SearchResultOffsetDecorator::SearchResultOffsetDecorator( + const bsl::shared_ptr& component, + const bsls::Types::Uint64 offsetLt, + bslma::Allocator* allocator) +: SearchResultDecorator(component, allocator) +, d_offsetLt(offsetLt) +{ + // NOTHING +} + +bool SearchResultOffsetDecorator::processMessageRecord( + const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processMessageRecord(record, + recordIndex, + recordOffset) || + stop(recordOffset); +} + +bool SearchResultOffsetDecorator::processConfirmRecord( + const mqbs::ConfirmRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processConfirmRecord(record, + recordIndex, + recordOffset) || + stop(recordOffset); +} + +bool SearchResultOffsetDecorator::processDeletionRecord( + const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processDeletionRecord(record, + recordIndex, + recordOffset) || + stop(recordOffset); +} + +// ========================================= +// class SearchResultSequenceNumberDecorator +// ========================================= + +bool SearchResultSequenceNumberDecorator::stop(const CompositeSequenceNumber& sequenceNumber) const +{ + return sequenceNumberLt <= sequenceNumber && !SearchResultDecorator::hasCache(); +} + +SearchResultSequenceNumberDecorator::SearchResultSequenceNumberDecorator( + const bsl::shared_ptr& component, + const CompositeSequenceNumber& sequenceNumberLt, + bslma::Allocator* allocator) +: SearchResultDecorator(component, allocator) +, sequenceNumberLt(sequenceNumberLt) +{ + // NOTHING +} + +bool SearchResultSequenceNumberDecorator::processMessageRecord( + const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processMessageRecord(record, + recordIndex, + recordOffset) || + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); +} + +bool SearchResultSequenceNumberDecorator::processConfirmRecord( + const mqbs::ConfirmRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processConfirmRecord(record, + recordIndex, + recordOffset) || + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); +} + +bool SearchResultSequenceNumberDecorator::processDeletionRecord( + const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + return SearchResultDecorator::processDeletionRecord(record, + recordIndex, + recordOffset) || + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); +} + // ======================= // class SearchShortResult // ======================= diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 123241799..9015625a6 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -43,6 +43,7 @@ // a logic of search and output results. // bmqstoragetool +#include "m_bmqstoragetool_compositesequencenumber.h" #include #include #include @@ -367,8 +368,8 @@ class SearchResultTimestampDecorator : public SearchResultDecorator { // ACCESSORS - bool stop(bsls::Types::Uint64 timestamp) const; - // Return 'true' if the specified 'timestamp' is greated than + bool stop(const bsls::Types::Uint64 timestamp) const; + // Return 'true' if the specified 'timestamp' is greater than // 'd_timestampLt' and internal cache is empty. public: @@ -403,6 +404,102 @@ class SearchResultTimestampDecorator : public SearchResultDecorator { BSLS_KEYWORD_OVERRIDE; }; +// ================================= +// class SearchResultOffsetDecorator +// ================================= + +/// This class provides decorator to handle offsets. +class SearchResultOffsetDecorator : public SearchResultDecorator { + private: + const bsls::Types::Uint64 d_offsetLt; + // Higher bound offset. + + // ACCESSORS + + bool stop(const bsls::Types::Uint64 offset) const; + // Return 'true' if the specified 'offset' is greater than + // 'd_offsetLt' and internal cache is empty. + + public: + // CREATORS + + /// Constructor using the specified `component`, `offsetLt` and + /// `allocator`. + SearchResultOffsetDecorator( + const bsl::shared_ptr& component, + const bsls::Types::Uint64 offsetLt, + bslma::Allocator* allocator); + + // MANIPULATORS + + /// Process `message` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processMessageRecord(const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `confirm` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processConfirmRecord(const mqbs::ConfirmRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `deletion` record with the specified `record`, `recordIndex` + /// and `recordOffset`. + bool processDeletionRecord(const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; +}; + +// ========================================= +// class SearchResultSequenceNumberDecorator +// ========================================= + +/// This class provides decorator to handle offsets. +class SearchResultSequenceNumberDecorator : public SearchResultDecorator { + private: + const CompositeSequenceNumber sequenceNumberLt; + // Higher bound sequence number. + + // ACCESSORS + + bool stop(const CompositeSequenceNumber& sequenceNumber) const; + // Return 'true' if the specified 'sequenceNumber' is greater than + // 'sequenceNumberLt' and internal cache is empty. + + public: + // CREATORS + + /// Constructor using the specified `component`, `offsetLt` and + /// `allocator`. + SearchResultSequenceNumberDecorator( + const bsl::shared_ptr& component, + const CompositeSequenceNumber& seqNumberLt, + bslma::Allocator* allocator); + + // MANIPULATORS + + /// Process `message` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processMessageRecord(const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `confirm` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processConfirmRecord(const mqbs::ConfirmRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `deletion` record with the specified `record`, `recordIndex` + /// and `recordOffset`. + bool processDeletionRecord(const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; +}; + // ======================== // class SearchAllDecorator // ======================== diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp index 47501084f..f806cd019 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp @@ -123,13 +123,31 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( alloc); } - // Add TimestampDecorator if 'timestampLt' is given. - if (params->d_valueType == Parameters::e_TIMESTAMP && params->d_valueLt > 0) { - searchResult.reset( - new (*alloc) SearchResultTimestampDecorator(searchResult, - params->d_valueLt, - alloc), - alloc); + if (params->d_valueLt > 0) { + // Add TimestampDecorator if 'valueLt' is given and value type is `e_TIMESTAMP`. + if (params->d_valueType == Parameters::e_TIMESTAMP) { + searchResult.reset( + new (*alloc) SearchResultTimestampDecorator(searchResult, + params->d_valueLt, + alloc), + alloc); + } else if (params->d_valueType == Parameters::e_OFFSET) { + // Add OffsetDecorator if 'valueLt' is given and value type is `e_OFFSET`. + searchResult.reset( + new (*alloc) SearchResultOffsetDecorator(searchResult, + params->d_valueLt, + alloc), + alloc); + } + } + + // Add SequenceNumberDecorator if 'seqNumLt' is given value type is `e_SEQUENCE_NUM`. + if (params->d_valueType == Parameters::e_SEQUENCE_NUM && !params->d_seqNumLt.isUnset()) { + searchResult.reset( + new (*alloc) SearchResultSequenceNumberDecorator(searchResult, + params->d_seqNumLt, + alloc), + alloc); } BSLS_ASSERT(searchResult); From 1bcf85395aae491a045f762951ff7ad2e1a13feb Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Mon, 11 Nov 2024 15:06:22 +0200 Subject: [PATCH 06/21] Fix hasCache() call Signed-off-by: Aleksandr Ivanov --- .../m_bmqstoragetool_searchresult.cpp | 5 ++ .../m_bmqstoragetool_searchresult.h | 46 +++++++++++-------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp index c9cf2b7ee..5423bd1a0 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp @@ -241,6 +241,11 @@ void SearchResultDecorator::outputResult(const GuidsList& guidFilter) d_searchResult->outputResult(guidFilter); } +bool SearchResultDecorator::hasCache() const +{ + return d_searchResult->hasCache(); +} + // ==================================== // class SearchResultTimestampDecorator // ==================================== diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 9015625a6..742383b19 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -78,11 +78,6 @@ class SearchResult { GuidsMap; // Hash map of message guids to iterators of GuidsList. - virtual bool hasCache() const { return false; } - // Return `false` if all required data is processed, e.g. all given GUIDs - // are output and search could be stopped. Return `true` to indicate that - // there is incomplete data. - public: // CREATORS @@ -110,6 +105,11 @@ class SearchResult { virtual void outputResult() = 0; /// Output result of a search filtered by the specified GUIDs filter. virtual void outputResult(const GuidsList& guidFilter) = 0; + + virtual bool hasCache() const { return false; } + /// Return `false` if all required data is processed, e.g. all given GUIDs + /// are output and search could be stopped. Return `true` to indicate that + /// there is incomplete data. }; // ======================= @@ -162,13 +162,6 @@ class SearchShortResult : public SearchResult { void outputGuidData(const GuidData& guidData); // Output result in short format (only GUIDs). - // PRIVATE ACCESSORS - - bool hasCache() const BSLS_KEYWORD_OVERRIDE; - // Return 'false' if all required data is processed, e.g. all given GUIDs - // are output and search could be stopped. Return 'true' to indicate that - // there is incomplete data. - public: // CREATORS @@ -205,6 +198,13 @@ class SearchShortResult : public SearchResult { void outputResult() BSLS_KEYWORD_OVERRIDE; /// Output result of a search filtered by the specified GUIDs filter. void outputResult(const GuidsList& guidFilter) BSLS_KEYWORD_OVERRIDE; + + // ACCESSORS + + /// Return 'false' if all required data is processed, e.g. all given GUIDs + /// are output and search could be stopped. Return 'true' to indicate that + /// there is incomplete data. + bool hasCache() const BSLS_KEYWORD_OVERRIDE; }; // ======================== @@ -264,13 +264,6 @@ class SearchDetailResult : public SearchResult { void outputMessageDetails(const MessageDetails& messageDetails); // Output message details with the specified 'messageDetails'. - // PRIVATE ACCESSORS - - bool hasCache() const BSLS_KEYWORD_OVERRIDE; - // Return 'false' if all required data is processed, e.g. all given GUIDs - // are output and search could be stopped. Return 'true' to indicate that - // there is incomplete data. - public: // CREATORS @@ -308,6 +301,13 @@ class SearchDetailResult : public SearchResult { void outputResult() BSLS_KEYWORD_OVERRIDE; /// Output result of a search filtered by the specified GUIDs filter. void outputResult(const GuidsList& guidFilter) BSLS_KEYWORD_OVERRIDE; + + // ACCESSORS + + /// Return 'false' if all required data is processed, e.g. all given GUIDs + /// are output and search could be stopped. Return 'true' to indicate that + /// there is incomplete data. + bool hasCache() const BSLS_KEYWORD_OVERRIDE; }; // =========================== @@ -354,6 +354,14 @@ class SearchResultDecorator : public SearchResult { void outputResult() BSLS_KEYWORD_OVERRIDE; /// Output result of a search filtered by the specified GUIDs filter. void outputResult(const GuidsList& guidFilter) BSLS_KEYWORD_OVERRIDE; + + // ACCESSORS + + bool hasCache() const BSLS_KEYWORD_OVERRIDE; + // Return 'false' if all required data is processed, e.g. all given GUIDs + // are output and search could be stopped. Return 'true' to indicate that + // there is incomplete data. + }; // ==================================== From 25a805a6f7199e09bf3cfc6ccf3277c7b9763ca9 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Mon, 11 Nov 2024 15:23:35 +0200 Subject: [PATCH 07/21] Fix code style Signed-off-by: Aleksandr Ivanov --- .../bmqstoragetool/bmqstoragetool.m.cpp | 6 +- ...bmqstoragetool_compositesequencenumber.cpp | 29 ++- ...m_bmqstoragetool_compositesequencenumber.h | 66 +++--- ...qstoragetool_compositesequencenumber.t.cpp | 27 ++- .../m_bmqstoragetool_filters.cpp | 55 +++-- .../bmqstoragetool/m_bmqstoragetool_filters.h | 19 +- .../m_bmqstoragetool_journalfile.cpp | 9 +- .../m_bmqstoragetool_journalfile.h | 9 +- .../m_bmqstoragetool_journalfileprocessor.cpp | 55 +++-- .../m_bmqstoragetool_journalfileprocessor.h | 6 +- ..._bmqstoragetool_journalfileprocessor.t.cpp | 193 +++++++++++------- .../m_bmqstoragetool_parameters.cpp | 59 +++--- .../m_bmqstoragetool_parameters.h | 11 +- .../m_bmqstoragetool_searchresult.cpp | 22 +- .../m_bmqstoragetool_searchresult.h | 8 +- .../m_bmqstoragetool_searchresultfactory.cpp | 29 +-- 16 files changed, 363 insertions(+), 240 deletions(-) diff --git a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp index 364e5fdcc..cf36cb0f9 100644 --- a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp +++ b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp @@ -30,8 +30,10 @@ using namespace BloombergLP; using namespace m_bmqstoragetool; -static bool -parseArgs(CommandLineArguments& arguments, int argc, const char* argv[], bslma::Allocator* allocator) +static bool parseArgs(CommandLineArguments& arguments, + int argc, + const char* argv[], + bslma::Allocator* allocator) { bool showHelp = false; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index 21191fa8d..b64cfd5d8 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -35,7 +35,9 @@ CompositeSequenceNumber::CompositeSequenceNumber() // NOTHING } -CompositeSequenceNumber::CompositeSequenceNumber(const unsigned int leaseId, const bsls::Types::Uint64 sequenceNumber) +CompositeSequenceNumber::CompositeSequenceNumber( + const unsigned int leaseId, + const bsls::Types::Uint64 sequenceNumber) : d_leaseId(leaseId) , d_seqNumber(sequenceNumber) { @@ -43,7 +45,9 @@ CompositeSequenceNumber::CompositeSequenceNumber(const unsigned int leaseId, con d_isUnset = !(d_leaseId > 0 && d_seqNumber > 0); } -CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString) +CompositeSequenceNumber& +CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, + const bsl::string& seqNumString) { d_isUnset = true; @@ -57,11 +61,11 @@ CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& error if (separatorPos == bsl::string::npos) { errorDescription << "Invalid format: no '-' separator found."; return *this; // RETURN - } + } // Extract parts // TODO: use allocator! - bsl::string firstPart = seqNumString.substr(0, separatorPos); + bsl::string firstPart = seqNumString.substr(0, separatorPos); bsl::string secondPart = seqNumString.substr(separatorPos + 1); // Convert parts to numbers @@ -69,7 +73,7 @@ CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& error size_t posFirst, posSecond; unsigned long uLong = bsl::stoul(firstPart, &posFirst); - d_seqNumber = bsl::stoul(secondPart, &posSecond); + d_seqNumber = bsl::stoul(secondPart, &posSecond); if (posFirst != firstPart.size() || posSecond != secondPart.size()) { throw bsl::invalid_argument(""); @@ -86,18 +90,20 @@ CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& error } d_isUnset = false; - - } catch (const bsl::invalid_argument& e) { + } + catch (const bsl::invalid_argument& e) { errorDescription << "Invalid input: non-numeric values encountered."; - } catch (const bsl::out_of_range& e) { + } + catch (const bsl::out_of_range& e) { errorDescription << "Invalid input: number out of range."; } return *this; } -bsl::ostream& -CompositeSequenceNumber::print(bsl::ostream& stream, int level, int spacesPerLevel) const +bsl::ostream& CompositeSequenceNumber::print(bsl::ostream& stream, + int level, + int spacesPerLevel) const { if (stream.bad()) { return stream; // RETURN @@ -109,7 +115,8 @@ CompositeSequenceNumber::print(bsl::ostream& stream, int level, int spacesPerLev stream << "** UNSET **"; } else { - stream << "leaseId: " << leaseId() << ", sequenceNumber: " << sequenceNumber(); + stream << "leaseId: " << leaseId() + << ", sequenceNumber: " << sequenceNumber(); } if (spacesPerLevel >= 0) { diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index 8c9f68c4d..24a03e90e 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -16,14 +16,18 @@ #ifndef INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER #define INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER -//@PURPOSE: Provide value-semantic type to represent composite sequence number, which is used for message filtering. +//@PURPOSE: Provide value-semantic type to represent composite sequence number, +//which is used for message filtering. // //@CLASSES: -// m_bmqstoragetool::CompositeSequenceNumber: Value-semantic type to represent composite sequence number. +// m_bmqstoragetool::CompositeSequenceNumber: Value-semantic type to represent +// composite sequence number. // -//@DESCRIPTION: 'CompositeSequenceNumber' provides value-semantic type to represent sequence number. -// There could be sequence numbers collision inside journal file for different lease Ids, -// so need to handle composite sequence number taking into account Primary Lease Id too. +//@DESCRIPTION: 'CompositeSequenceNumber' provides value-semantic type to +//represent sequence number. +// There could be sequence numbers collision inside journal file for different +// lease Ids, so need to handle composite sequence number taking into account +// Primary Lease Id too. // BDE #include @@ -49,19 +53,25 @@ class CompositeSequenceNumber { public: // CREATORS - /// Create an un-initialized CompositeSequenceNumber. Note that `isUnset()` would - /// return true. + /// Create an un-initialized CompositeSequenceNumber. Note that + /// `isUnset()` would return true. CompositeSequenceNumber(); - /// Create CompositeSequenceNumber from the specified `leaseId` and `sequenceNumber` - CompositeSequenceNumber(const unsigned int leaseId, const bsls::Types::Uint64 sequenceNumber); + /// Create CompositeSequenceNumber from the specified `leaseId` and + /// `sequenceNumber` + CompositeSequenceNumber(const unsigned int leaseId, + const bsls::Types::Uint64 sequenceNumber); // MANIPULATORS - /// Initialize this CompositeSequenceNumber from the specified `seqNumString` representation in format `-`. - /// Return a reference offering modifiable access to this object. If convertion is successfull, `isUnset()` would return `true`. - /// Otherwise, `isUnset()` would return `false` and specified `errorDescription` is filled with error description. - CompositeSequenceNumber& fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString); + /// Initialize this CompositeSequenceNumber from the specified + /// `seqNumString` representation in format `-`. + /// Return a reference offering modifiable access to this object. If + /// convertion is successfull, `isUnset()` would return `true`. Otherwise, + /// `isUnset()` would return `false` and specified `errorDescription` is + /// filled with error description. + CompositeSequenceNumber& fromString(bsl::ostream& errorDescription, + const bsl::string& seqNumString); // ACCESSORS @@ -99,15 +109,18 @@ class CompositeSequenceNumber { /// `stream` in a human-readable format, and return a reference to `stream`. /// Note that this human-readable format is not fully specified, and can /// change without notice. -bsl::ostream& operator<<(bsl::ostream& stream, const CompositeSequenceNumber& rhs); +bsl::ostream& operator<<(bsl::ostream& stream, + const CompositeSequenceNumber& rhs); /// Return true if the specified `lhs` instance is less than the /// specified `rhs` instance, false otherwise. -bool operator<(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); +bool operator<(const CompositeSequenceNumber& lhs, + const CompositeSequenceNumber& rhs); /// Return true if the specified `lhs` instance is less or equal to the /// specified `rhs` instance, false otherwise. -bool operator<=(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); +bool operator<=(const CompositeSequenceNumber& lhs, + const CompositeSequenceNumber& rhs); // ============================================================================ // INLINE DEFINITIONS @@ -142,8 +155,9 @@ inline bsls::Types::Uint64 CompositeSequenceNumber::sequenceNumber() const // FREE OPERATORS -inline bsl::ostream& m_bmqstoragetool::operator<<(bsl::ostream& stream, - const m_bmqstoragetool::CompositeSequenceNumber& rhs) +inline bsl::ostream& m_bmqstoragetool::operator<<( + bsl::ostream& stream, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS BSLS_ASSERT(!rhs.isUnset()); @@ -151,8 +165,9 @@ inline bsl::ostream& m_bmqstoragetool::operator<<(bsl::ostream& strea return rhs.print(stream, 0, -1); } -inline bool m_bmqstoragetool::operator<(const m_bmqstoragetool::CompositeSequenceNumber& lhs, - const m_bmqstoragetool::CompositeSequenceNumber& rhs) +inline bool m_bmqstoragetool::operator<( + const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); @@ -160,7 +175,8 @@ inline bool m_bmqstoragetool::operator<(const m_bmqstoragetool::CompositeSequenc // Check leaseId first if (lhs.leaseId() < rhs.leaseId()) { return true; // RETURN - } else if (lhs.leaseId() == rhs.leaseId()) { + } + else if (lhs.leaseId() == rhs.leaseId()) { if (lhs.sequenceNumber() < rhs.sequenceNumber()) { return true; // RETURN } @@ -169,13 +185,15 @@ inline bool m_bmqstoragetool::operator<(const m_bmqstoragetool::CompositeSequenc return false; } -inline bool m_bmqstoragetool::operator<=(const m_bmqstoragetool::CompositeSequenceNumber& lhs, - const m_bmqstoragetool::CompositeSequenceNumber& rhs) +inline bool m_bmqstoragetool::operator<=( + const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); - if (lhs.leaseId() == rhs.leaseId() && lhs.sequenceNumber() == rhs.sequenceNumber()) { + if (lhs.leaseId() == rhs.leaseId() && + lhs.sequenceNumber() == rhs.sequenceNumber()) { return true; } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index bc0eea5e7..c8d81320b 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -62,7 +62,8 @@ static void test2_fromStringTest() // FROM STRING TEST // // Concerns: -// Exercise the functionality to initialize component from string representation. +// Exercise the functionality to initialize component from string +// representation. // // Testing: // fromString method @@ -123,7 +124,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); + ASSERT_EQ(errorDescription.str(), + "Invalid format: no '-' separator found."); } // Invalid string with wrong separator @@ -136,7 +138,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); + ASSERT_EQ(errorDescription.str(), + "Invalid format: no '-' separator found."); } // Invalid string with non-numeric value in first part @@ -149,7 +152,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: non-numeric values encountered."); } // Invalid string with non-numeric value in second part @@ -162,7 +166,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: non-numeric values encountered."); } // Invalid string with zero value in first part @@ -175,7 +180,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: zero values encountered."); } // Invalid string with zero value in second part @@ -188,7 +194,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: zero values encountered."); } // Invalid string with out of range value in first part @@ -202,7 +209,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: number out of range."); } // Invalid string with out of range value in second part @@ -216,7 +224,8 @@ static void test2_fromStringTest() compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); + ASSERT_EQ(errorDescription.str(), + "Invalid input: number out of range."); } } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp index 9e21a87dc..3e3a64f22 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp @@ -23,15 +23,15 @@ namespace m_bmqstoragetool { // class Filters // ============= -Filters::Filters(const bsl::vector& queueKeys, - const bsl::vector& queueUris, - const QueueMap& queueMap, +Filters::Filters(const bsl::vector& queueKeys, + const bsl::vector& queueUris, + const QueueMap& queueMap, const Parameters::SearchValueType valueType, - const bsls::Types::Uint64 valueGt, - const bsls::Types::Uint64 valueLt, - const CompositeSequenceNumber seqNumGt, - const CompositeSequenceNumber seqNumLt, - bslma::Allocator* allocator) + const bsls::Types::Uint64 valueGt, + const bsls::Types::Uint64 valueLt, + const CompositeSequenceNumber seqNumGt, + const CompositeSequenceNumber seqNumLt, + bslma::Allocator* allocator) : d_queueKeys(allocator) , d_valueType(valueType) , d_valueGt(valueGt) @@ -59,7 +59,8 @@ Filters::Filters(const bsl::vector& queueKeys, } } -bool Filters::apply(const mqbs::MessageRecord& record, bsls::Types::Uint64 offset) const +bool Filters::apply(const mqbs::MessageRecord& record, + bsls::Types::Uint64 offset) const { // Apply `queue key` filter if (!d_queueKeys.empty()) { @@ -76,27 +77,21 @@ bool Filters::apply(const mqbs::MessageRecord& record, bsls::Types::Uint64 offse // Apply `range` filter bsls::Types::Uint64 value; - switch(d_valueType) { - case Parameters::e_TIMESTAMP: - value = record.header().timestamp(); - break; - case Parameters::e_SEQUENCE_NUM: - { - CompositeSequenceNumber seqNum(record.header().primaryLeaseId(), record.header().sequenceNumber()); - if ((!d_seqNumGt.isUnset() && seqNum <= d_seqNumGt) || - (!d_seqNumLt.isUnset() && d_seqNumLt <= seqNum)) { - // Not inside range - return false; // RETURN - } - } - break; - case Parameters::e_OFFSET: - value = offset; - break; - default: - // No range filter defined - return true; // RETURN - + switch (d_valueType) { + case Parameters::e_TIMESTAMP: value = record.header().timestamp(); break; + case Parameters::e_SEQUENCE_NUM: { + CompositeSequenceNumber seqNum(record.header().primaryLeaseId(), + record.header().sequenceNumber()); + if ((!d_seqNumGt.isUnset() && seqNum <= d_seqNumGt) || + (!d_seqNumLt.isUnset() && d_seqNumLt <= seqNum)) { + // Not inside range + return false; // RETURN + } + } break; + case Parameters::e_OFFSET: value = offset; break; + default: + // No range filter defined + return true; // RETURN } if ((d_valueGt > 0 && value <= d_valueGt) || (d_valueLt > 0 && value >= d_valueLt)) { diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h index 631299a30..b74c7b571 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h @@ -53,21 +53,22 @@ class Filters { // CREATORS /// Constructor using the specified arguments. - explicit Filters(const bsl::vector& queueKeys, - const bsl::vector& queueUris, - const QueueMap& queueMap, + explicit Filters(const bsl::vector& queueKeys, + const bsl::vector& queueUris, + const QueueMap& queueMap, const Parameters::SearchValueType valueType, - const bsls::Types::Uint64 valueGt, - const bsls::Types::Uint64 valueLt, - const CompositeSequenceNumber seqNumGt, - const CompositeSequenceNumber seqNumLt, - bslma::Allocator* allocator); + const bsls::Types::Uint64 valueGt, + const bsls::Types::Uint64 valueLt, + const CompositeSequenceNumber seqNumGt, + const CompositeSequenceNumber seqNumLt, + bslma::Allocator* allocator); // ACCESSORS /// Apply filters at specified 'record' and return true if all filters /// are matched, false otherwise. - bool apply(const mqbs::MessageRecord& record, bsls::Types::Uint64 offset) const; + bool apply(const mqbs::MessageRecord& record, + bsls::Types::Uint64 offset) const; }; } // close package namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp index 2549ee113..d820a9efb 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp @@ -602,12 +602,14 @@ void JournalFile::addJournalRecordsWithConfirmedMessagesWithDifferentOrder( } } -void JournalFile::addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, size_t leaseCount) +void JournalFile::addAllTypesRecordsWithMultipleLeaseId( + RecordsListType* records, + size_t leaseCount) { // PRECONDITIONS BSLS_ASSERT(records); - unsigned int leaseId = 0; + unsigned int leaseId = 0; bsls::Types::Uint64 seqNumber = 1; for (unsigned int i = 1; i <= d_numRecords; ++i) { @@ -737,7 +739,8 @@ void JournalFile::addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records // bsl::memcpy(buf.buffer(), // rec.get(), // FileStoreProtocol::k_JOURNAL_RECORD_SIZE); - // records->push_back(bsl::make_pair(RecordType::e_JOURNAL_OP, buf)); + // records->push_back(bsl::make_pair(RecordType::e_JOURNAL_OP, + // buf)); // } d_currPos += FileStoreProtocol::k_JOURNAL_RECORD_SIZE; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h index 2b24865ab..c34840738 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h @@ -158,10 +158,11 @@ class JournalFile { size_t numMessages, bsl::vector& messageOffsets); - /// Generate sequence of all types of records. Increase Primary Lease Id after the specified `leaseCount` records. - /// Store list of created records in the specified `records`. - void addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, size_t leaseCount); - + /// Generate sequence of all types of records. Increase Primary Lease Id + /// after the specified `leaseCount` records. Store list of created records + /// in the specified `records`. + void addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, + size_t leaseCount); }; // ============================================================================ diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index 11df5beea..e27a3bdee 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -39,27 +39,34 @@ namespace BloombergLP { namespace m_bmqstoragetool { namespace { -template -T getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType); +template +T getValue(const mqbs::JournalFileIterator* jit, + const Parameters::SearchValueType valueType); -template<> -bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +template <> +bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, + const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); - BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || valueType == Parameters::e_OFFSET); + BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || + valueType == Parameters::e_OFFSET); - return (valueType == Parameters::e_TIMESTAMP) ? jit->recordHeader().timestamp() : jit->recordOffset(); + return (valueType == Parameters::e_TIMESTAMP) + ? jit->recordHeader().timestamp() + : jit->recordOffset(); } -template<> -CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType) +template <> +CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, + const Parameters::SearchValueType valueType) { // PRECONDITIONS BSLS_ASSERT(jit); BSLS_ASSERT(valueType == Parameters::e_SEQUENCE_NUM); - return CompositeSequenceNumber(jit->recordHeader().primaryLeaseId(), jit->recordHeader().sequenceNumber()); + return CompositeSequenceNumber(jit->recordHeader().primaryLeaseId(), + jit->recordHeader().sequenceNumber()); } } // close unnamed namespace @@ -70,10 +77,10 @@ CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, const Par /// was encountered. Note that if this method returns < 0, the specified 'jit' /// is invalidated. Behavior is undefined unless last call to `nextRecord` or /// 'advance' returned '1' and the iterator points to a valid record. -template -int moveToLowerBound(mqbs::JournalFileIterator* jit, +template +int moveToLowerBound(mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType, - const T& valueGt) + const T& valueGt) { // PRECONDITIONS BSLS_ASSERT(jit); @@ -158,8 +165,9 @@ void JournalFileProcessor::process() d_parameters->d_seqNumLt, d_allocator_p); - bool stopSearch = false; - bool needMoveToLowerBound = d_parameters->d_valueGt > 0 || !d_parameters->d_seqNumGt.isUnset(); + bool stopSearch = false; + bool needMoveToLowerBound = d_parameters->d_valueGt > 0 || + !d_parameters->d_seqNumGt.isUnset(); // Iterate through all Journal file records mqbs::JournalFileIterator* iter = d_fileManager->journalFileIterator(); @@ -176,22 +184,29 @@ void JournalFileProcessor::process() if (needMoveToLowerBound) { if (d_parameters->d_valueGt > 0) { - rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_valueGt); - } else { - rc = moveToLowerBound(iter, d_parameters->d_valueType, d_parameters->d_seqNumGt); + rc = moveToLowerBound( + iter, + d_parameters->d_valueType, + d_parameters->d_valueGt); + } + else { + rc = moveToLowerBound( + iter, + d_parameters->d_valueType, + d_parameters->d_seqNumGt); } if (rc == 0) { stopSearch = true; continue; // CONTINUE } else if (rc < 0) { - d_ostream << "Binary search aborted (exit status " - << rc << ")."; + d_ostream << "Binary search aborted (exit status " << rc + << ")."; return; // RETURN } needMoveToLowerBound = false; } - + // MessageRecord if (iter->recordType() == mqbs::RecordType::e_MESSAGE) { const mqbs::MessageRecord& record = iter->asMessageRecord(); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h index 6181ecfdd..1b7c81751 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h @@ -40,10 +40,10 @@ namespace BloombergLP { namespace m_bmqstoragetool { -template -int moveToLowerBound(mqbs::JournalFileIterator* jit, +template +int moveToLowerBound(mqbs::JournalFileIterator* jit, const Parameters::SearchValueType valueType, - const T& value); + const T& value); // ========================== // class JournalFileProcessor diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index 174547996..ef3977d69 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -824,8 +824,8 @@ static void test11_searchMessagesByTimestamp() // Configure parameters to search messages by timestamps Parameters params(s_allocator_p); - params.d_valueGt = ts1; - params.d_valueLt = ts2; + params.d_valueGt = ts1; + params.d_valueLt = ts2; params.d_valueType = Parameters::e_TIMESTAMP; // Prepare file manager bslma::ManagedPtr fileManager( @@ -1176,7 +1176,11 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts), + 1); ResultChecker::check(journalFileIt, ts); } @@ -1196,13 +1200,21 @@ static void test15_timestampSearchTest() // Find record with lower timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts1), + 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts2), + 1); ResultChecker::check(journalFileIt, ts2); // Find record with lower timestamp than the record pointed by the @@ -1210,7 +1222,11 @@ static void test15_timestampSearchTest() ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts1), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts1), + 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the @@ -1218,7 +1234,11 @@ static void test15_timestampSearchTest() ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts2), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts2), + 1); ResultChecker::check(journalFileIt, ts2); } @@ -1232,7 +1252,11 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts), + 0); ASSERT_EQ(journalFileIt.recordIndex(), k_NUM_RECORDS - 1); ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); @@ -1247,7 +1271,11 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_TIMESTAMP, ts), 1); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_TIMESTAMP, + ts), + 1); ASSERT_EQ(journalFileIt.recordIndex(), 0U); ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts); ASSERT(!journalFileIt.isReverseMode()); @@ -1266,43 +1294,31 @@ static void test16_sequenceNumberLowerBoundTest() // m_bmqstoragetool::moveToLowerBound() // ------------------------------------------------------------------------ { - bmqtst::TestHelper::printTestName("MOVE TO SEQUENCE NUMBER LOWER BOUND TEST"); + bmqtst::TestHelper::printTestName( + "MOVE TO SEQUENCE NUMBER LOWER BOUND TEST"); struct Test { - int d_line; - size_t d_numRecords; - size_t d_numRecordsWithSameLeaseId; - unsigned int d_leaseIdGt; - bsls::Types::Uint64 d_seqNumberGt; - } k_DATA[] = {{L_, 32, 4, 3, 2}, - {L_, 300, 10, 3, 2}, - {L_, 300, 11, 3, 2}, - {L_, 300, 11, 3, 1}, // edge case (first seqNum inside leaseId) - {L_, 300, 11, 3, 11}, // edge case (last seqNum inside leaseId) - {L_, 300, 11, 1, 1}, // edge case (left seqNum edge inside first leaseId) - {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum inside last leaseId) - {L_, 3, 2, 1, 2}, - {L_, 30, 29, 1, 29}, - {L_, 30, 29, 1, 28}, - {L_, 300, 9, 1, 9}, - {L_, 300, 9, 1, 8}, - {L_, 300, 9, 1, 7}, - {L_, 300, 9, 1, 6}, - {L_, 300, 9, 1, 5}, - {L_, 300, 9, 1, 4}, - {L_, 300, 9, 1, 3}, - {L_, 300, 9, 1, 2}, - {L_, 300, 9, 1, 1}, - {L_, 300, 9, 2, 9}, - {L_, 300, 9, 2, 8}, - {L_, 300, 9, 2, 7}, - {L_, 300, 9, 2, 6}, - {L_, 300, 9, 2, 5}, - {L_, 300, 9, 2, 4}, - {L_, 300, 9, 2, 3}, - {L_, 300, 9, 2, 2}, - {L_, 300, 9, 2, 1}, - }; + int d_line; + size_t d_numRecords; + size_t d_numRecordsWithSameLeaseId; + unsigned int d_leaseIdGt; + bsls::Types::Uint64 d_seqNumberGt; + } k_DATA[] = { + {L_, 32, 4, 3, 2}, {L_, 300, 10, 3, 2}, {L_, 300, 11, 3, 2}, + {L_, 300, 11, 3, 1}, // edge case (first seqNum inside leaseId) + {L_, 300, 11, 3, 11}, // edge case (last seqNum inside leaseId) + {L_, 300, 11, 1, 1}, // edge case (left seqNum edge inside first + // leaseId) + {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum inside + // last leaseId) + {L_, 3, 2, 1, 2}, {L_, 30, 29, 1, 29}, {L_, 30, 29, 1, 28}, + {L_, 300, 9, 1, 9}, {L_, 300, 9, 1, 8}, {L_, 300, 9, 1, 7}, + {L_, 300, 9, 1, 6}, {L_, 300, 9, 1, 5}, {L_, 300, 9, 1, 4}, + {L_, 300, 9, 1, 3}, {L_, 300, 9, 1, 2}, {L_, 300, 9, 1, 1}, + {L_, 300, 9, 2, 9}, {L_, 300, 9, 2, 8}, {L_, 300, 9, 2, 7}, + {L_, 300, 9, 2, 6}, {L_, 300, 9, 2, 5}, {L_, 300, 9, 2, 4}, + {L_, 300, 9, 2, 3}, {L_, 300, 9, 2, 2}, {L_, 300, 9, 2, 1}, + }; const size_t k_NUM_DATA = sizeof(k_DATA) / sizeof(*k_DATA); @@ -1311,43 +1327,66 @@ static void test16_sequenceNumberLowerBoundTest() // Simulate journal file JournalFile::RecordsListType records(s_allocator_p); - JournalFile journalFile(test.d_numRecords, s_allocator_p); - journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, test.d_numRecordsWithSameLeaseId); + JournalFile journalFile(test.d_numRecords, s_allocator_p); + journalFile.addAllTypesRecordsWithMultipleLeaseId( + &records, + test.d_numRecordsWithSameLeaseId); mqbs::JournalFileIterator journalFileIt( - &journalFile.mappedFileDescriptor(), - journalFile.fileHeader(), - false); - + &journalFile.mappedFileDescriptor(), + journalFile.fileHeader(), + false); + CompositeSequenceNumber seqNumGt(test.d_leaseIdGt, test.d_seqNumberGt); - unsigned int expectedLeaseId = test.d_leaseIdGt + (test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId ? 1 : 0); - bsls::Types::Uint64 expectedSeqNumber = test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId ? 1 : (test.d_seqNumberGt + 1); + unsigned int expectedLeaseId = + test.d_leaseIdGt + + (test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId ? 1 : 0); + bsls::Types::Uint64 expectedSeqNumber = + test.d_seqNumberGt == test.d_numRecordsWithSameLeaseId + ? 1 + : (test.d_seqNumberGt + 1); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ_D(test.d_line, m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 1); - ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().primaryLeaseId(), expectedLeaseId); - ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().sequenceNumber(), expectedSeqNumber); + ASSERT_EQ_D( + test.d_line, + m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_SEQUENCE_NUM, + seqNumGt), + 1); + ASSERT_EQ_D(test.d_line, + journalFileIt.recordHeader().primaryLeaseId(), + expectedLeaseId); + ASSERT_EQ_D(test.d_line, + journalFileIt.recordHeader().sequenceNumber(), + expectedSeqNumber); } // Edge case: not in the range (greater then the last record) { - const size_t k_NUM_RECORDS = 300; + const size_t k_NUM_RECORDS = 300; JournalFile::RecordsListType records(s_allocator_p); JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); - journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, k_NUM_RECORDS); + journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, + k_NUM_RECORDS); mqbs::JournalFileIterator journalFileIt( - &journalFile.mappedFileDescriptor(), - journalFile.fileHeader(), - false); - + &journalFile.mappedFileDescriptor(), + journalFile.fileHeader(), + false); + // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); CompositeSequenceNumber seqNumGt(1, k_NUM_RECORDS); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, Parameters::e_SEQUENCE_NUM, seqNumGt), 0); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( + &journalFileIt, + Parameters::e_SEQUENCE_NUM, + seqNumGt), + 0); ASSERT_EQ(journalFileIt.recordHeader().primaryLeaseId(), 1u); - ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), k_NUM_RECORDS); + ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), + k_NUM_RECORDS); } } @@ -1362,7 +1401,8 @@ static void test17_searchMessagesBySequenceNumbersRange() // JournalFileProcessor::process() // ------------------------------------------------------------------------ { - bmqtst::TestHelper::printTestName("SEARCH MESSAGES BY SEQUENCE NUMBERS RANGE TEST"); + bmqtst::TestHelper::printTestName( + "SEARCH MESSAGES BY SEQUENCE NUMBERS RANGE TEST"); // Simulate journal file const size_t k_NUM_RECORDS = 100; @@ -1374,8 +1414,8 @@ static void test17_searchMessagesBySequenceNumbersRange() // Configure parameters to search messages by sequence number range Parameters params(s_allocator_p); - params.d_seqNumGt = seqNumGt; - params.d_seqNumLt = seqNumLt; + params.d_seqNumGt = seqNumGt; + params.d_seqNumLt = seqNumLt; params.d_valueType = Parameters::e_SEQUENCE_NUM; // Prepare file manager bslma::ManagedPtr fileManager( @@ -1394,7 +1434,9 @@ static void test17_searchMessagesBySequenceNumbersRange() if (rtype == RecordType::e_MESSAGE) { const MessageRecord& msg = *reinterpret_cast( recordIter->second.buffer()); - const CompositeSequenceNumber seqNum(msg.header().primaryLeaseId(), msg.header().sequenceNumber()); + const CompositeSequenceNumber seqNum( + msg.header().primaryLeaseId(), + msg.header().sequenceNumber()); if (seqNumGt < seqNum && seqNum < seqNumLt) { outputGuidString(expectedStream, msg.messageGUID()); msgCnt++; @@ -1433,14 +1475,17 @@ static void test18_searchMessagesByOffsetsRange() JournalFile::RecordsListType records(s_allocator_p); JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); journalFile.addAllTypesRecords(&records); - const size_t k_HEADER_SIZE = sizeof(mqbs::FileHeader) + sizeof(mqbs::JournalFileHeader); - const bsls::Types::Uint64 offsetGt = mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 15 + k_HEADER_SIZE; - const bsls::Types::Uint64 offsetLt = mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 35 + k_HEADER_SIZE; + const size_t k_HEADER_SIZE = sizeof(mqbs::FileHeader) + + sizeof(mqbs::JournalFileHeader); + const bsls::Types::Uint64 offsetGt = + mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 15 + k_HEADER_SIZE; + const bsls::Types::Uint64 offsetLt = + mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 35 + k_HEADER_SIZE; // Configure parameters to search messages by timestamps Parameters params(s_allocator_p); - params.d_valueGt = offsetGt; - params.d_valueLt = offsetLt; + params.d_valueGt = offsetGt; + params.d_valueLt = offsetLt; params.d_valueType = Parameters::e_OFFSET; // Prepare file manager bslma::ManagedPtr fileManager( @@ -1459,7 +1504,9 @@ static void test18_searchMessagesByOffsetsRange() if (rtype == RecordType::e_MESSAGE) { const MessageRecord& msg = *reinterpret_cast( recordIter->second.buffer()); - const bsls::Types::Uint64& offset = msg.header().sequenceNumber() * mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE; + const bsls::Types::Uint64& offset = + msg.header().sequenceNumber() * + mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE; if (offset > offsetGt && offset < offsetLt) { outputGuidString(expectedStream, msg.messageGUID()); msgCnt++; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 8fc6b1b73..3f6ce4ff0 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -99,7 +99,8 @@ CommandLineArguments::CommandLineArguments(bslma::Allocator* allocator) { } -bool CommandLineArguments::validate(bsl::string* error, bslma::Allocator* allocator) +bool CommandLineArguments::validate(bsl::string* error, + bslma::Allocator* allocator) { bmqu::MemOutStream ss(allocator); @@ -167,24 +168,24 @@ bool CommandLineArguments::validate(bsl::string* error, bslma::Allocator* alloca if (d_cslFile.empty() && !d_queueName.empty()) { ss << "Can't search by queue name, because csl file is not " "specified\n"; - } + } if (d_timestampLt < 0 || d_timestampGt < 0 || (d_timestampLt > 0 && d_timestampGt >= d_timestampLt)) { ss << "Invalid timestamp range specified\n"; } if (!d_seqNumLt.empty() || !d_seqNumGt.empty()) { - bmqu::MemOutStream errorDescr(allocator); + bmqu::MemOutStream errorDescr(allocator); CompositeSequenceNumber seqNumLt, seqNumGt; if (!d_seqNumLt.empty()) { seqNumLt.fromString(errorDescr, d_seqNumLt); - if(seqNumLt.isUnset()) { + if (seqNumLt.isUnset()) { ss << "--seqnum-lt: " << errorDescr.str() << "\n"; errorDescr.reset(); } } if (!d_seqNumGt.empty()) { seqNumGt.fromString(errorDescr, d_seqNumGt); - if(seqNumGt.isUnset()) { + if (seqNumGt.isUnset()) { ss << "--seqnum-gt: " << errorDescr.str() << "\n"; } } @@ -211,31 +212,36 @@ bool CommandLineArguments::validate(bsl::string* error, bslma::Allocator* alloca rangesCnt++; } if (rangesCnt > 1) { - ss << "Only one range type can be selected: timestamp, seqnum or offset\n"; + ss << "Only one range type can be selected: timestamp, seqnum or " + "offset\n"; } if (!d_guid.empty() && - (!d_queueKey.empty() || !d_queueName.empty() || !d_seqNum.empty() || d_outstanding || - d_confirmed || d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { + (!d_queueKey.empty() || !d_queueName.empty() || !d_seqNum.empty() || + d_outstanding || d_confirmed || d_partiallyConfirmed || + rangesCnt > 0 || d_summary)) { ss << "Giud filter can't be combined with any other filters, as it is " "specific enough to find a particular message\n"; } - if (!d_seqNum.empty() && - (!d_queueKey.empty() || !d_queueName.empty() || !d_guid.empty()|| d_outstanding || - d_confirmed || d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { - ss << "secnum filter can't be combined with any other filters, as it is " + if (!d_seqNum.empty() && + (!d_queueKey.empty() || !d_queueName.empty() || !d_guid.empty() || + d_outstanding || d_confirmed || d_partiallyConfirmed || + rangesCnt > 0 || d_summary)) { + ss << "secnum filter can't be combined with any other filters, as it " + "is " "specific enough to find a particular message\n"; } if (!d_seqNum.empty()) { - // TODO: move to method CompositeSequenceNumber seqNum; - bmqu::MemOutStream errorDescr(allocator); - for (bsl::vector::const_iterator cit = d_seqNum.begin(); cit != d_seqNum.end(); ++cit) { + bmqu::MemOutStream errorDescr(allocator); + for (bsl::vector::const_iterator cit = d_seqNum.begin(); + cit != d_seqNum.end(); + ++cit) { seqNum.fromString(errorDescr, *cit); - if(seqNum.isUnset()) { + if (seqNum.isUnset()) { ss << "--seqnum: " << errorDescr.str() << "\n"; } } @@ -316,15 +322,16 @@ Parameters::Parameters(const CommandLineArguments& arguments, , d_partiallyConfirmed(arguments.d_partiallyConfirmed) { // Set search range type and values if present - if (arguments.d_timestampLt || arguments.d_timestampGt) { + if (arguments.d_timestampLt || arguments.d_timestampGt) { d_valueType = e_TIMESTAMP; d_valueLt = static_cast(arguments.d_timestampLt); d_valueGt = static_cast(arguments.d_timestampGt); - } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { + } + else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { bsl::cout << "INSIDE!!!!" << arguments.d_seqNumGt << "\n"; d_valueType = e_SEQUENCE_NUM; CompositeSequenceNumber seqNum; - bmqu::MemOutStream errorDescr(allocator); + bmqu::MemOutStream errorDescr(allocator); if (!arguments.d_seqNumLt.empty()) { d_seqNumLt.fromString(errorDescr, arguments.d_seqNumLt); } @@ -332,16 +339,20 @@ Parameters::Parameters(const CommandLineArguments& arguments, d_seqNumGt.fromString(errorDescr, arguments.d_seqNumGt); // bsl::cout << "INSIDE _1 !!!!" << arguments.d_seqNumGt << "\n"; } - } else { + } + else { d_valueType = e_OFFSET; - d_valueLt = static_cast(arguments.d_offsetLt); - d_valueGt = static_cast(arguments.d_offsetGt); + d_valueLt = static_cast(arguments.d_offsetLt); + d_valueGt = static_cast(arguments.d_offsetGt); } if (!arguments.d_seqNum.empty()) { CompositeSequenceNumber seqNum; - bmqu::MemOutStream errorDescr(allocator); - for (bsl::vector::const_iterator cit = arguments.d_seqNum.begin(); cit != arguments.d_seqNum.end(); ++cit) { + bmqu::MemOutStream errorDescr(allocator); + for (bsl::vector::const_iterator cit = + arguments.d_seqNum.begin(); + cit != arguments.d_seqNum.end(); + ++cit) { seqNum.fromString(errorDescr, *cit); d_seqNum.push_back(seqNum); } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h index 17a86a247..721c5ca9c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h @@ -58,9 +58,9 @@ struct CommandLineArguments { // Filter messages by minimum timestamp bsls::Types::Int64 d_timestampLt; // Filter messages by maximum timestamp - bsl::string d_seqNumGt; + bsl::string d_seqNumGt; // Filter messages by minimum record composite sequence number - bsl::string d_seqNumLt; + bsl::string d_seqNumLt; // Filter messages by maximum record composite sequence number bsls::Types::Int64 d_offsetGt; // Filter messages by minimum record offset @@ -107,7 +107,12 @@ struct CommandLineArguments { struct Parameters { // PUBLIC TYPES - enum SearchValueType { e_NONE = 0, e_TIMESTAMP = 1, e_SEQUENCE_NUM = 2, e_OFFSET = 3 }; + enum SearchValueType { + e_NONE = 0, + e_TIMESTAMP = 1, + e_SEQUENCE_NUM = 2, + e_OFFSET = 3 + }; // PUBLIC DATA QueueMap d_queueMap; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp index 5423bd1a0..9100c262d 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp @@ -250,14 +250,15 @@ bool SearchResultDecorator::hasCache() const // class SearchResultTimestampDecorator // ==================================== -bool SearchResultTimestampDecorator::stop(const bsls::Types::Uint64 timestamp) const +bool SearchResultTimestampDecorator::stop( + const bsls::Types::Uint64 timestamp) const { return timestamp >= d_timestampLt && !SearchResultDecorator::hasCache(); } SearchResultTimestampDecorator::SearchResultTimestampDecorator( const bsl::shared_ptr& component, - const bsls::Types::Uint64 timestampLt, + const bsls::Types::Uint64 timestampLt, bslma::Allocator* allocator) : SearchResultDecorator(component, allocator) , d_timestampLt(timestampLt) @@ -353,14 +354,16 @@ bool SearchResultOffsetDecorator::processDeletionRecord( // class SearchResultSequenceNumberDecorator // ========================================= -bool SearchResultSequenceNumberDecorator::stop(const CompositeSequenceNumber& sequenceNumber) const +bool SearchResultSequenceNumberDecorator::stop( + const CompositeSequenceNumber& sequenceNumber) const { - return sequenceNumberLt <= sequenceNumber && !SearchResultDecorator::hasCache(); + return sequenceNumberLt <= sequenceNumber && + !SearchResultDecorator::hasCache(); } SearchResultSequenceNumberDecorator::SearchResultSequenceNumberDecorator( const bsl::shared_ptr& component, - const CompositeSequenceNumber& sequenceNumberLt, + const CompositeSequenceNumber& sequenceNumberLt, bslma::Allocator* allocator) : SearchResultDecorator(component, allocator) , sequenceNumberLt(sequenceNumberLt) @@ -376,7 +379,8 @@ bool SearchResultSequenceNumberDecorator::processMessageRecord( return SearchResultDecorator::processMessageRecord(record, recordIndex, recordOffset) || - stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), + record.header().sequenceNumber())); } bool SearchResultSequenceNumberDecorator::processConfirmRecord( @@ -387,7 +391,8 @@ bool SearchResultSequenceNumberDecorator::processConfirmRecord( return SearchResultDecorator::processConfirmRecord(record, recordIndex, recordOffset) || - stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), + record.header().sequenceNumber())); } bool SearchResultSequenceNumberDecorator::processDeletionRecord( @@ -398,7 +403,8 @@ bool SearchResultSequenceNumberDecorator::processDeletionRecord( return SearchResultDecorator::processDeletionRecord(record, recordIndex, recordOffset) || - stop(CompositeSequenceNumber(record.header().primaryLeaseId(), record.header().sequenceNumber())); + stop(CompositeSequenceNumber(record.header().primaryLeaseId(), + record.header().sequenceNumber())); } // ======================= diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 742383b19..03cf1b3fe 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -361,7 +361,6 @@ class SearchResultDecorator : public SearchResult { // Return 'false' if all required data is processed, e.g. all given GUIDs // are output and search could be stopped. Return 'true' to indicate that // there is incomplete data. - }; // ==================================== @@ -433,10 +432,9 @@ class SearchResultOffsetDecorator : public SearchResultDecorator { /// Constructor using the specified `component`, `offsetLt` and /// `allocator`. - SearchResultOffsetDecorator( - const bsl::shared_ptr& component, - const bsls::Types::Uint64 offsetLt, - bslma::Allocator* allocator); + SearchResultOffsetDecorator(const bsl::shared_ptr& component, + const bsls::Types::Uint64 offsetLt, + bslma::Allocator* allocator); // MANIPULATORS diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp index f806cd019..e9665479c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp @@ -124,30 +124,35 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( } if (params->d_valueLt > 0) { - // Add TimestampDecorator if 'valueLt' is given and value type is `e_TIMESTAMP`. + // Add TimestampDecorator if 'valueLt' is given and value type is + // `e_TIMESTAMP`. if (params->d_valueType == Parameters::e_TIMESTAMP) { searchResult.reset( new (*alloc) SearchResultTimestampDecorator(searchResult, params->d_valueLt, alloc), alloc); - } else if (params->d_valueType == Parameters::e_OFFSET) { - // Add OffsetDecorator if 'valueLt' is given and value type is `e_OFFSET`. + } + else if (params->d_valueType == Parameters::e_OFFSET) { + // Add OffsetDecorator if 'valueLt' is given and value type is + // `e_OFFSET`. searchResult.reset( new (*alloc) SearchResultOffsetDecorator(searchResult, - params->d_valueLt, - alloc), + params->d_valueLt, + alloc), alloc); } } - // Add SequenceNumberDecorator if 'seqNumLt' is given value type is `e_SEQUENCE_NUM`. - if (params->d_valueType == Parameters::e_SEQUENCE_NUM && !params->d_seqNumLt.isUnset()) { - searchResult.reset( - new (*alloc) SearchResultSequenceNumberDecorator(searchResult, - params->d_seqNumLt, - alloc), - alloc); + // Add SequenceNumberDecorator if 'seqNumLt' is given value type is + // `e_SEQUENCE_NUM`. + if (params->d_valueType == Parameters::e_SEQUENCE_NUM && + !params->d_seqNumLt.isUnset()) { + searchResult.reset(new (*alloc) SearchResultSequenceNumberDecorator( + searchResult, + params->d_seqNumLt, + alloc), + alloc); } BSLS_ASSERT(searchResult); From 9898b5d976db2846beeef6987577966d945734c7 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Mon, 11 Nov 2024 16:29:41 +0200 Subject: [PATCH 08/21] Fix code style Signed-off-by: Aleksandr Ivanov --- .../m_bmqstoragetool_compositesequencenumber.h | 4 ++-- .../m_bmqstoragetool_journalfileprocessor.t.cpp | 12 ++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index 24a03e90e..049d0d5fe 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -17,14 +17,14 @@ #define INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER //@PURPOSE: Provide value-semantic type to represent composite sequence number, -//which is used for message filtering. +// which is used for message filtering. // //@CLASSES: // m_bmqstoragetool::CompositeSequenceNumber: Value-semantic type to represent // composite sequence number. // //@DESCRIPTION: 'CompositeSequenceNumber' provides value-semantic type to -//represent sequence number. +// represent sequence number. // There could be sequence numbers collision inside journal file for different // lease Ids, so need to handle composite sequence number taking into account // Primary Lease Id too. diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index ef3977d69..2031dbfbc 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -1304,20 +1304,16 @@ static void test16_sequenceNumberLowerBoundTest() unsigned int d_leaseIdGt; bsls::Types::Uint64 d_seqNumberGt; } k_DATA[] = { - {L_, 32, 4, 3, 2}, {L_, 300, 10, 3, 2}, {L_, 300, 11, 3, 2}, + {L_, 32, 4, 3, 2}, + {L_, 3, 2, 1, 2}, + {L_, 300, 10, 3, 2}, + {L_, 300, 11, 3, 2}, {L_, 300, 11, 3, 1}, // edge case (first seqNum inside leaseId) {L_, 300, 11, 3, 11}, // edge case (last seqNum inside leaseId) {L_, 300, 11, 1, 1}, // edge case (left seqNum edge inside first // leaseId) {L_, 330, 11, 30, 10}, // edge case (prev before last seqNum inside // last leaseId) - {L_, 3, 2, 1, 2}, {L_, 30, 29, 1, 29}, {L_, 30, 29, 1, 28}, - {L_, 300, 9, 1, 9}, {L_, 300, 9, 1, 8}, {L_, 300, 9, 1, 7}, - {L_, 300, 9, 1, 6}, {L_, 300, 9, 1, 5}, {L_, 300, 9, 1, 4}, - {L_, 300, 9, 1, 3}, {L_, 300, 9, 1, 2}, {L_, 300, 9, 1, 1}, - {L_, 300, 9, 2, 9}, {L_, 300, 9, 2, 8}, {L_, 300, 9, 2, 7}, - {L_, 300, 9, 2, 6}, {L_, 300, 9, 2, 5}, {L_, 300, 9, 2, 4}, - {L_, 300, 9, 2, 3}, {L_, 300, 9, 2, 2}, {L_, 300, 9, 2, 1}, }; const size_t k_NUM_DATA = sizeof(k_DATA) / sizeof(*k_DATA); From d00d17c8dbc6c7bebda85b8dab61c335d8e9f5b0 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 12 Nov 2024 14:55:18 +0200 Subject: [PATCH 09/21] Add search for specific sequence numbers and offsets Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/README.md | 46 ++++++ .../bmqstoragetool/bmqstoragetool.m.cpp | 16 ++- ...m_bmqstoragetool_compositesequencenumber.h | 16 +++ .../m_bmqstoragetool_parameters.cpp | 39 +++-- .../m_bmqstoragetool_parameters.h | 6 +- .../m_bmqstoragetool_searchresult.cpp | 133 ++++++++++++++++++ .../m_bmqstoragetool_searchresult.h | 98 ++++++++++++- .../m_bmqstoragetool_searchresultfactory.cpp | 21 ++- 8 files changed, 355 insertions(+), 20 deletions(-) diff --git a/src/applications/bmqstoragetool/README.md b/src/applications/bmqstoragetool/README.md index 6c7a6b5b6..3dec59e48 100644 --- a/src/applications/bmqstoragetool/README.md +++ b/src/applications/bmqstoragetool/README.md @@ -22,6 +22,10 @@ Usage: bmqstoragetool [--journal-path ] [--queue-key ]* [--timestamp-gt ] [--timestamp-lt ] + [--seqnum-gt ] + [--seqnum-lt ] + [--offset-gt ] + [--offset-lt ] [--outstanding] [--confirmed] [--partially-confirmed] @@ -50,6 +54,14 @@ Where: lower timestamp bound --timestamp-lt higher timestamp bound + --seqnum-gt + lower composit sequence number bound, defined in form , e.g. 123-456 + --seqnum-lt + higher composit sequence number bound, defined in form , e.g. 123-456 + --offset-gt + lower offset bound + --offset-lt + higher offset bound --outstanding show only outstanding (not deleted) messages --confirmed @@ -122,6 +134,22 @@ bmqstoragetool --journal-file= --guid= --guid= ``` NOTE: no other filters are allowed with this one +Filter messages with corresponding composite sequence numbers (defined in form ) +--------------------------------------------------------------------------------------------------------------- +Example: +```bash +bmqstoragetool --journal-file= --seqnum= --seqnum= +``` +NOTE: no other filters are allowed with this one + +Filter messages with corresponding record offsets +---------------------------------------- +Example: +```bash +bmqstoragetool --journal-file= --offset= --offset= +``` +NOTE: no other filters are allowed with this one + Filter messages within time range --------------------------------- Example: @@ -131,6 +159,24 @@ bmqstoragetool --journal-file= --timestamp-gt= bmqstoragetool --journal-file= --timestamp-lt= --timestamp-gt= ``` +Filter messages within composite sequence numbers (primaryLeaseId, sequenceNumber) range +---------------------------------------------------------------------------------------- +Example: +```bash +bmqstoragetool --journal-file= --seqnum-lt= +bmqstoragetool --journal-file= --seqnum-gt= +bmqstoragetool --journal-file= --seqnum-lt= --seqnum-gt= +``` + +Filter messages within record offsets range +------------------------------------------- +Example: +```bash +bmqstoragetool --journal-file= --offset-lt= +bmqstoragetool --journal-file= --offset-gt= +bmqstoragetool --journal-file= --offset-lt= --offset-gt= +``` + Filter messages by queue key ---------------------------- Example: diff --git a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp index cf36cb0f9..169e6d5e1 100644 --- a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp +++ b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp @@ -64,6 +64,16 @@ static bool parseArgs(CommandLineArguments& arguments, "message guid", balcl::TypeInfo(&arguments.d_guid), balcl::OccurrenceInfo::e_OPTIONAL}, + {"seqnum", + "seqnum", + "message composite sequence number", + balcl::TypeInfo(&arguments.d_seqNum), + balcl::OccurrenceInfo::e_OPTIONAL}, + {"offset", + "offset", + "message offset", + balcl::TypeInfo(&arguments.d_offset), + balcl::OccurrenceInfo::e_OPTIONAL}, {"queue-name", "queue name", "message queue name", @@ -86,12 +96,14 @@ static bool parseArgs(CommandLineArguments& arguments, balcl::OccurrenceInfo::e_OPTIONAL}, {"seqnum-gt", "record composite sequence number greater than", - "lower record sequence number bound", + "lower record sequence number bound, defined in form " + "", balcl::TypeInfo(&arguments.d_seqNumGt), balcl::OccurrenceInfo::e_OPTIONAL}, {"seqnum-lt", "record composite sequence number less than", - "higher sequence number bound", + "higher sequence number bound, defined in form " + "", balcl::TypeInfo(&arguments.d_seqNumLt), balcl::OccurrenceInfo::e_OPTIONAL}, {"offset-gt", diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index 049d0d5fe..6f48fdd9e 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -122,6 +122,11 @@ bool operator<(const CompositeSequenceNumber& lhs, bool operator<=(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); +/// Return true if the specified `lhs` instance is equal to the +/// specified `rhs` instance, false otherwise. +bool operator==(const CompositeSequenceNumber& lhs, + const CompositeSequenceNumber& rhs); + // ============================================================================ // INLINE DEFINITIONS // ============================================================================ @@ -200,6 +205,17 @@ inline bool m_bmqstoragetool::operator<=( return lhs < rhs; } +inline bool m_bmqstoragetool::operator==( + const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) +{ + // PRECONDITIONS + BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + + return (lhs.leaseId() == rhs.leaseId() && + lhs.sequenceNumber() == rhs.sequenceNumber()); +} + } // close enterprise namespace #endif diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 3f6ce4ff0..c84b1d5c6 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -218,23 +218,28 @@ bool CommandLineArguments::validate(bsl::string* error, if (!d_guid.empty() && (!d_queueKey.empty() || !d_queueName.empty() || !d_seqNum.empty() || - d_outstanding || d_confirmed || d_partiallyConfirmed || - rangesCnt > 0 || d_summary)) { + !d_offset.empty() || d_outstanding || d_confirmed || + d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { ss << "Giud filter can't be combined with any other filters, as it is " "specific enough to find a particular message\n"; } - if (!d_seqNum.empty() && (!d_queueKey.empty() || !d_queueName.empty() || !d_guid.empty() || - d_outstanding || d_confirmed || d_partiallyConfirmed || - rangesCnt > 0 || d_summary)) { - ss << "secnum filter can't be combined with any other filters, as it " + !d_offset.empty() || d_outstanding || d_confirmed || + d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { + ss << "Secnum filter can't be combined with any other filters, as it " + "is " + "specific enough to find a particular message\n"; + } + if (!d_offset.empty() && + (!d_queueKey.empty() || !d_queueName.empty() || !d_guid.empty() || + !d_seqNum.empty() || d_outstanding || d_confirmed || + d_partiallyConfirmed || rangesCnt > 0 || d_summary)) { + ss << "Offset filter can't be combined with any other filters, as it " "is " "specific enough to find a particular message\n"; } if (!d_seqNum.empty()) { - // TODO: move to method - CompositeSequenceNumber seqNum; bmqu::MemOutStream errorDescr(allocator); for (bsl::vector::const_iterator cit = d_seqNum.begin(); @@ -247,7 +252,16 @@ bool CommandLineArguments::validate(bsl::string* error, } } - // TODO: offset check too + if (!d_offset.empty()) { + for (bsl::vector::const_iterator cit = + d_offset.begin(); + cit != d_offset.end(); + ++cit) { + if (*cit < 0) { + ss << "--offset: " << *cit << " cannot be negative\n"; + } + } + } if (d_summary && (d_outstanding || d_confirmed || d_partiallyConfirmed || d_details)) { @@ -290,6 +304,8 @@ Parameters::Parameters(bslma::Allocator* allocator) , d_valueGt(0) , d_valueLt(0) , d_guid(allocator) +, d_seqNum(allocator) +, d_offset(allocator) , d_queueKey(allocator) , d_queueName(allocator) , d_dumpLimit(0) @@ -311,6 +327,7 @@ Parameters::Parameters(const CommandLineArguments& arguments, , d_valueLt(0) , d_guid(arguments.d_guid, allocator) , d_seqNum(allocator) +, d_offset(arguments.d_offset, allocator) , d_queueKey(arguments.d_queueKey, allocator) , d_queueName(arguments.d_queueName, allocator) , d_dumpLimit(arguments.d_dumpLimit) @@ -328,7 +345,6 @@ Parameters::Parameters(const CommandLineArguments& arguments, d_valueGt = static_cast(arguments.d_timestampGt); } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { - bsl::cout << "INSIDE!!!!" << arguments.d_seqNumGt << "\n"; d_valueType = e_SEQUENCE_NUM; CompositeSequenceNumber seqNum; bmqu::MemOutStream errorDescr(allocator); @@ -337,10 +353,9 @@ Parameters::Parameters(const CommandLineArguments& arguments, } if (!arguments.d_seqNumGt.empty()) { d_seqNumGt.fromString(errorDescr, arguments.d_seqNumGt); - // bsl::cout << "INSIDE _1 !!!!" << arguments.d_seqNumGt << "\n"; } } - else { + else if (arguments.d_offsetLt || arguments.d_offsetGt) { d_valueType = e_OFFSET; d_valueLt = static_cast(arguments.d_offsetLt); d_valueGt = static_cast(arguments.d_offsetGt); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h index 721c5ca9c..e3c0be350 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h @@ -77,7 +77,9 @@ struct CommandLineArguments { bsl::vector d_guid; // Filter messages by message guids bsl::vector d_seqNum; - // Filter messages by message composite sequence numbers + // Filter messages by record composite sequence numbers + bsl::vector d_offset; + // Filter messages by record offsets bsl::vector d_queueKey; // Filter messages by queue keys bsl::vector d_queueName; @@ -131,6 +133,8 @@ struct Parameters { // Filter messages by message guids bsl::vector d_seqNum; // Filter messages by message sequence number + bsl::vector d_offset; + // Filter messages by message offsets bsl::vector d_queueKey; // Filter messages by queue keys bsl::vector d_queueName; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp index 9100c262d..0e24f517f 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp @@ -14,6 +14,7 @@ // limitations under the License. // bmqstoragetool +#include "m_bmqstoragetool_compositesequencenumber.h" #include // MQB @@ -895,6 +896,138 @@ void SearchGuidDecorator::outputResult() } } +// =========================== +// class SearchOffsetDecorator +// =========================== +SearchOffsetDecorator::SearchOffsetDecorator( + const bsl::shared_ptr& component, + const bsl::vector& offsets, + bsl::ostream& ostream, + bool withDetails, + bslma::Allocator* allocator) +: SearchResultDecorator(component, allocator) +, d_offsets(offsets, allocator) +, d_ostream(ostream) +, d_withDetails(withDetails) +{ + // NOTHING +} + +bool SearchOffsetDecorator::processMessageRecord( + const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + bsl::vector::const_iterator it = + bsl::find(d_offsets.cbegin(), d_offsets.cend(), recordOffset); + if (it != d_offsets.cend()) { + SearchResultDecorator::processMessageRecord(record, + recordIndex, + recordOffset); + // Remove processed offset. + d_offsets.erase(it); + } + + // return true (stop search) if no detail is needed and d_offsets is empty. + return (!d_withDetails && d_offsets.empty()); +} + +bool SearchOffsetDecorator::processDeletionRecord( + const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + SearchResultDecorator::processDeletionRecord(record, + recordIndex, + recordOffset); + // return true (stop search) when details needed and search is done + // (d_offsets is empty). + return (d_withDetails && d_offsets.empty()); +} + +void SearchOffsetDecorator::outputResult() +{ + SearchResultDecorator::outputResult(); + // Print non found offsets + if (!d_offsets.empty()) { + d_ostream << '\n' + << "The following " << d_offsets.size() + << " offset(s) not found:" << '\n'; + bsl::vector::const_iterator it = + d_offsets.cbegin(); + for (; it != d_offsets.cend(); ++it) { + d_ostream << *it << '\n'; + } + } +} + +// =================================== +// class SearchSequenceNumberDecorator +// =================================== +SearchSequenceNumberDecorator::SearchSequenceNumberDecorator( + const bsl::shared_ptr& component, + const bsl::vector& seqNums, + bsl::ostream& ostream, + bool withDetails, + bslma::Allocator* allocator) +: SearchResultDecorator(component, allocator) +, d_seqNums(seqNums, allocator) +, d_ostream(ostream) +, d_withDetails(withDetails) +{ + // NOTHING +} + +bool SearchSequenceNumberDecorator::processMessageRecord( + const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + CompositeSequenceNumber seqNum(record.header().primaryLeaseId(), + record.header().sequenceNumber()); + bsl::vector::const_iterator it = + bsl::find(d_seqNums.cbegin(), d_seqNums.cend(), seqNum); + if (it != d_seqNums.cend()) { + SearchResultDecorator::processMessageRecord(record, + recordIndex, + recordOffset); + // Remove processed offset. + d_seqNums.erase(it); + } + + // return true (stop search) if no detail is needed and d_offsets is empty. + return (!d_withDetails && d_seqNums.empty()); +} + +bool SearchSequenceNumberDecorator::processDeletionRecord( + const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) +{ + SearchResultDecorator::processDeletionRecord(record, + recordIndex, + recordOffset); + // return true (stop search) when details needed and search is done + // (d_offsets is empty). + return (d_withDetails && d_seqNums.empty()); +} + +void SearchSequenceNumberDecorator::outputResult() +{ + SearchResultDecorator::outputResult(); + // Print non found offsets + if (!d_seqNums.empty()) { + d_ostream << '\n' + << "The following " << d_seqNums.size() + << " sequence number(s) not found:" << '\n'; + bsl::vector::const_iterator it = + d_seqNums.cbegin(); + for (; it != d_seqNums.cend(); ++it) { + d_ostream << *it << '\n'; + } + } +} + // ====================== // class SummaryProcessor // ====================== diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 03cf1b3fe..edca44887 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -106,10 +106,10 @@ class SearchResult { /// Output result of a search filtered by the specified GUIDs filter. virtual void outputResult(const GuidsList& guidFilter) = 0; - virtual bool hasCache() const { return false; } /// Return `false` if all required data is processed, e.g. all given GUIDs /// are output and search could be stopped. Return `true` to indicate that /// there is incomplete data. + virtual bool hasCache() const { return false; } }; // ======================= @@ -357,10 +357,10 @@ class SearchResultDecorator : public SearchResult { // ACCESSORS + /// Return 'false' if all required data is processed, e.g. all given GUIDs + /// are output and search could be stopped. Return 'true' to indicate that + /// there is incomplete data. bool hasCache() const BSLS_KEYWORD_OVERRIDE; - // Return 'false' if all required data is processed, e.g. all given GUIDs - // are output and search could be stopped. Return 'true' to indicate that - // there is incomplete data. }; // ==================================== @@ -678,6 +678,96 @@ class SearchGuidDecorator : public SearchResultDecorator { void outputResult() BSLS_KEYWORD_OVERRIDE; }; +// =========================== +// class SearchOffsetDecorator +// =========================== + +/// This class provides decorator to handle search of given offsets. +class SearchOffsetDecorator : public SearchResultDecorator { + private: + // PRIVATE DATA + bsl::vector d_offsets; + // List of offsets to search for. + bsl::ostream& d_ostream; + // Reference to output stream. + bool d_withDetails; + // If 'true', output detailed result, output short one otherwise. + + public: + // CREATORS + + /// Constructor using the specified `component`, `guids`, `ostream`, + /// `withDetails` and `allocator`. + SearchOffsetDecorator(const bsl::shared_ptr& component, + const bsl::vector& offsets, + bsl::ostream& ostream, + bool withDetails, + bslma::Allocator* allocator); + + // MANIPULATORS + + /// Process `message` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processMessageRecord(const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `deletion` record with the specified `record`, `recordIndex` + /// and `recordOffset`. + bool processDeletionRecord(const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Output result of a search. + void outputResult() BSLS_KEYWORD_OVERRIDE; +}; + +// =================================== +// class SearchSequenceNumberDecorator +// =================================== + +/// This class provides decorator to handle search of given composite sequence +/// numbers. +class SearchSequenceNumberDecorator : public SearchResultDecorator { + private: + // PRIVATE DATA + bsl::vector d_seqNums; + // List of composite sequence numbers to search for. + bsl::ostream& d_ostream; + // Reference to output stream. + bool d_withDetails; + // If 'true', output detailed result, output short one otherwise. + + public: + // CREATORS + + /// Constructor using the specified `component`, `seqNums`, `ostream`, + /// `withDetails` and `allocator`. + SearchSequenceNumberDecorator( + const bsl::shared_ptr& component, + const bsl::vector& seqNums, + bsl::ostream& ostream, + bool withDetails, + bslma::Allocator* allocator); + + // MANIPULATORS + + /// Process `message` record with the specified `record`, `recordIndex` and + /// `recordOffset`. + bool processMessageRecord(const mqbs::MessageRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Process `deletion` record with the specified `record`, `recordIndex` + /// and `recordOffset`. + bool processDeletionRecord(const mqbs::DeletionRecord& record, + bsls::Types::Uint64 recordIndex, + bsls::Types::Uint64 recordOffset) + BSLS_KEYWORD_OVERRIDE; + /// Output result of a search. + void outputResult() BSLS_KEYWORD_OVERRIDE; +}; + // ====================== // class SummaryProcessor // ====================== diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp index e9665479c..10f7cff77 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp @@ -92,6 +92,25 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( alloc), alloc); } + else if (!params->d_seqNum.empty()) { + // Search offsets + searchResult.reset(new (*alloc) + SearchSequenceNumberDecorator(searchResult, + params->d_seqNum, + ostream, + details, + alloc), + alloc); + } + else if (!params->d_offset.empty()) { + // Search composite sequence numbers + searchResult.reset(new (*alloc) SearchOffsetDecorator(searchResult, + params->d_offset, + ostream, + details, + alloc), + alloc); + } else if (params->d_summary) { // Summary searchResult.reset( @@ -144,7 +163,7 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( } } - // Add SequenceNumberDecorator if 'seqNumLt' is given value type is + // Add SequenceNumberDecorator if 'seqNumLt' is given and value type is // `e_SEQUENCE_NUM`. if (params->d_valueType == Parameters::e_SEQUENCE_NUM && !params->d_seqNumLt.isUnset()) { From 1435ed4f970e5c02215a9b010625e268d3fd1e59 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 12 Nov 2024 16:59:18 +0200 Subject: [PATCH 10/21] Cleanup Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/README.md | 2 +- .../bmqstoragetool/bmqstoragetool.m.cpp | 8 +- ...bmqstoragetool_compositesequencenumber.cpp | 9 +-- ...m_bmqstoragetool_compositesequencenumber.h | 53 ++++++------ ...qstoragetool_compositesequencenumber.t.cpp | 81 ++++++------------- .../m_bmqstoragetool_journalfile.cpp | 30 +------ .../m_bmqstoragetool_journalfile.h | 11 +-- .../m_bmqstoragetool_journalfileprocessor.cpp | 2 - ..._bmqstoragetool_journalfileprocessor.t.cpp | 15 ++-- .../m_bmqstoragetool_parameters.cpp | 12 ++- .../m_bmqstoragetool_searchresult.cpp | 6 +- .../m_bmqstoragetool_searchresult.h | 4 +- 12 files changed, 89 insertions(+), 144 deletions(-) diff --git a/src/applications/bmqstoragetool/README.md b/src/applications/bmqstoragetool/README.md index 3dec59e48..19dd3ff68 100644 --- a/src/applications/bmqstoragetool/README.md +++ b/src/applications/bmqstoragetool/README.md @@ -143,7 +143,7 @@ bmqstoragetool --journal-file= --seqnum= --seqnu NOTE: no other filters are allowed with this one Filter messages with corresponding record offsets ----------------------------------------- +------------------------------------------------- Example: ```bash bmqstoragetool --journal-file= --offset= --offset= diff --git a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp index 169e6d5e1..6b816cd6c 100644 --- a/src/applications/bmqstoragetool/bmqstoragetool.m.cpp +++ b/src/applications/bmqstoragetool/bmqstoragetool.m.cpp @@ -95,24 +95,24 @@ static bool parseArgs(CommandLineArguments& arguments, balcl::TypeInfo(&arguments.d_timestampLt), balcl::OccurrenceInfo::e_OPTIONAL}, {"seqnum-gt", - "record composite sequence number greater than", + "message composite sequence number greater than", "lower record sequence number bound, defined in form " "", balcl::TypeInfo(&arguments.d_seqNumGt), balcl::OccurrenceInfo::e_OPTIONAL}, {"seqnum-lt", - "record composite sequence number less than", + "message composite sequence number less than", "higher sequence number bound, defined in form " "", balcl::TypeInfo(&arguments.d_seqNumLt), balcl::OccurrenceInfo::e_OPTIONAL}, {"offset-gt", - "record offset greater than", + "message offset greater than", "lower record offset bound", balcl::TypeInfo(&arguments.d_offsetGt), balcl::OccurrenceInfo::e_OPTIONAL}, {"offset-lt", - "record offset less than", + "message offset less than", "higher record offset bound", balcl::TypeInfo(&arguments.d_offsetLt), balcl::OccurrenceInfo::e_OPTIONAL}, diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index b64cfd5d8..985c3b4af 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -64,9 +64,8 @@ CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, } // Extract parts - // TODO: use allocator! - bsl::string firstPart = seqNumString.substr(0, separatorPos); - bsl::string secondPart = seqNumString.substr(separatorPos + 1); + const bsl::string firstPart = seqNumString.substr(0, separatorPos); + const bsl::string secondPart = seqNumString.substr(separatorPos + 1); // Convert parts to numbers try { @@ -76,12 +75,12 @@ CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, d_seqNumber = bsl::stoul(secondPart, &posSecond); if (posFirst != firstPart.size() || posSecond != secondPart.size()) { - throw bsl::invalid_argument(""); + throw bsl::invalid_argument(""); // THROW } d_leaseId = static_cast(uLong); if (uLong != d_leaseId) { - throw bsl::out_of_range(""); + throw bsl::out_of_range(""); // THROW } if (d_leaseId == 0 || d_seqNumber == 0) { diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index 6f48fdd9e..21984b45b 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -16,7 +16,8 @@ #ifndef INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER #define INCLUDED_M_BMQSTORAGETOOL_COMPOSITESEQUENCENUMBER -//@PURPOSE: Provide value-semantic type to represent composite sequence number, +//@PURPOSE: Provide value-semantic type to represent composite sequence number +//(consists of primary lease Id and sequence number), // which is used for message filtering. // //@CLASSES: @@ -24,10 +25,10 @@ // composite sequence number. // //@DESCRIPTION: 'CompositeSequenceNumber' provides value-semantic type to -// represent sequence number. +// represent composite sequence number. // There could be sequence numbers collision inside journal file for different // lease Ids, so need to handle composite sequence number taking into account -// Primary Lease Id too. +// primary lease Id too. // BDE #include @@ -49,6 +50,7 @@ class CompositeSequenceNumber { bsls::Types::Uint64 d_seqNumber; // Sequence Number bool d_isUnset; + // Set to `true` if the value of this object is not set public: // CREATORS @@ -101,9 +103,9 @@ class CompositeSequenceNumber { // FREE OPERATORS -// ----------------- -// class MessageGUID -// ----------------- +// ----------------------------- +// class CompositeSequenceNumber +// ----------------------------- /// Write the value of the specified `rhs` object to the specified output /// `stream` in a human-readable format, and return a reference to `stream`. @@ -112,6 +114,11 @@ class CompositeSequenceNumber { bsl::ostream& operator<<(bsl::ostream& stream, const CompositeSequenceNumber& rhs); +/// Return true if the specified `lhs` instance is equal to the +/// specified `rhs` instance, false otherwise. +bool operator==(const CompositeSequenceNumber& lhs, + const CompositeSequenceNumber& rhs); + /// Return true if the specified `lhs` instance is less than the /// specified `rhs` instance, false otherwise. bool operator<(const CompositeSequenceNumber& lhs, @@ -122,11 +129,6 @@ bool operator<(const CompositeSequenceNumber& lhs, bool operator<=(const CompositeSequenceNumber& lhs, const CompositeSequenceNumber& rhs); -/// Return true if the specified `lhs` instance is equal to the -/// specified `rhs` instance, false otherwise. -bool operator==(const CompositeSequenceNumber& lhs, - const CompositeSequenceNumber& rhs); - // ============================================================================ // INLINE DEFINITIONS // ============================================================================ @@ -170,6 +172,17 @@ inline bsl::ostream& m_bmqstoragetool::operator<<( return rhs.print(stream, 0, -1); } +inline bool m_bmqstoragetool::operator==( + const m_bmqstoragetool::CompositeSequenceNumber& lhs, + const m_bmqstoragetool::CompositeSequenceNumber& rhs) +{ + // PRECONDITIONS + BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + + return (lhs.leaseId() == rhs.leaseId() && + lhs.sequenceNumber() == rhs.sequenceNumber()); +} + inline bool m_bmqstoragetool::operator<( const m_bmqstoragetool::CompositeSequenceNumber& lhs, const m_bmqstoragetool::CompositeSequenceNumber& rhs) @@ -197,23 +210,7 @@ inline bool m_bmqstoragetool::operator<=( // PRECONDITIONS BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); - if (lhs.leaseId() == rhs.leaseId() && - lhs.sequenceNumber() == rhs.sequenceNumber()) { - return true; - } - - return lhs < rhs; -} - -inline bool m_bmqstoragetool::operator==( - const m_bmqstoragetool::CompositeSequenceNumber& lhs, - const m_bmqstoragetool::CompositeSequenceNumber& rhs) -{ - // PRECONDITIONS - BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); - - return (lhs.leaseId() == rhs.leaseId() && - lhs.sequenceNumber() == rhs.sequenceNumber()); + return (lhs < rhs || lhs == rhs); } } // close enterprise namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index c8d81320b..a9f8e8696 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -36,10 +36,10 @@ static void test1_breathingTest() // BREATHING TEST // // Concerns: -// Exercise the basic functionality of the component. +// Exercise the component initialization. // // Testing: -// Basic functionality +// Component initialization // ------------------------------------------------------------------------ { bmqtst::TestHelper::printTestName("BREATHING TEST"); @@ -78,7 +78,6 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; bsl::string inputString("123-456", s_allocator_p); - errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), false); @@ -92,7 +91,6 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; bsl::string inputString("00123-000456", s_allocator_p); - errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), false); @@ -106,7 +104,6 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; bsl::string inputString("", s_allocator_p); - errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isUnset(), true); @@ -237,94 +234,64 @@ static void test3_comparisonTest() // Exercise the functionality to compare objects. // // Testing: -// operator<() and operator<=() methods +// operator<()==, operator<() and operator<=() methods // ------------------------------------------------------------------------ { bmqtst::TestHelper::printTestName("COMPARISON TEST"); - bmqu::MemOutStream errorDescription(s_allocator_p); - // leaseId is less, seqNumber is greater { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("2-1", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(1, 2); + CompositeSequenceNumber rhs(2, 1); ASSERT(lhs < rhs); } // leaseId is less, seqNumber is less { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("2-2", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(1, 1); + CompositeSequenceNumber rhs(2, 2); ASSERT(lhs < rhs); } // leaseId is greater, seqNumber is greater { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("3-2", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("2-1", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(3, 2); + CompositeSequenceNumber rhs(2, 1); ASSERT_EQ((lhs < rhs), false); } // leaseId is greater, seqNumber is less { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("3-1", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("2-2", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(3, 1); + CompositeSequenceNumber rhs(2, 2); ASSERT_EQ((lhs < rhs), false); } // leaseId is equal, seqNumber is less { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(1, 1); + CompositeSequenceNumber rhs(1, 2); ASSERT(lhs < rhs); } // leaseId is equal, seqNumber is greater { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("1-1", s_allocator_p)); - - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + CompositeSequenceNumber lhs(1, 2); + CompositeSequenceNumber rhs(1, 1); ASSERT_EQ((lhs < rhs), false); } - // Compare for equality using '<=': leaseId is equal, seqNumber is equal + // Compare for equality: leaseId is equal, seqNumber is equal { - CompositeSequenceNumber lhs; - lhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); - - CompositeSequenceNumber rhs; - rhs.fromString(errorDescription, bsl::string("1-2", s_allocator_p)); + CompositeSequenceNumber lhs(1, 2); + CompositeSequenceNumber rhs(1, 2); + ASSERT_EQ((lhs == rhs), true); + } - ASSERT(!lhs.isUnset() && !rhs.isUnset()); + // Compare for equality using '<=': leaseId is equal, seqNumber is equal + { + CompositeSequenceNumber lhs(1, 2); + CompositeSequenceNumber rhs(1, 2); ASSERT_EQ((lhs <= rhs), true); } } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp index d820a9efb..a420382f2 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.cpp @@ -602,9 +602,9 @@ void JournalFile::addJournalRecordsWithConfirmedMessagesWithDifferentOrder( } } -void JournalFile::addAllTypesRecordsWithMultipleLeaseId( +void JournalFile::addMultipleTypesRecordsWithMultipleLeaseId( RecordsListType* records, - size_t leaseCount) + size_t numRecordsWithSameLeaseId) { // PRECONDITIONS BSLS_ASSERT(records); @@ -614,7 +614,7 @@ void JournalFile::addAllTypesRecordsWithMultipleLeaseId( for (unsigned int i = 1; i <= d_numRecords; ++i) { unsigned int remainder = i % 4; - if (i % leaseCount == 1) { + if (i % numRecordsWithSameLeaseId == 1) { leaseId++; seqNumber = 1; } @@ -696,7 +696,7 @@ void JournalFile::addAllTypesRecordsWithMultipleLeaseId( FileStoreProtocol::k_JOURNAL_RECORD_SIZE); records->push_back(bsl::make_pair(RecordType::e_DELETION, buf)); } - else if (3 == remainder) { + else { // QueueOpRec OffsetPtr rec(d_block, d_currPos); new (rec.get()) QueueOpRecord(); @@ -720,28 +720,6 @@ void JournalFile::addAllTypesRecordsWithMultipleLeaseId( FileStoreProtocol::k_JOURNAL_RECORD_SIZE); records->push_back(bsl::make_pair(RecordType::e_QUEUE_OP, buf)); } - // else { - // OffsetPtr rec(d_block, d_currPos); - // new (rec.get()) JournalOpRecord(JournalOpType::e_SYNCPOINT, - // SyncPointType::e_REGULAR, - // 1234567, // seqNum - // 25, // leaderTerm - // 121, // leaderNodeId - // 8800, // dataFilePosition - // 100, // qlistFilePosition - // RecordHeader::k_MAGIC); - - // rec->header() - // .setPrimaryLeaseId(100) - // .setSequenceNumber(i) - // .setTimestamp(i * d_timestampIncrement); - // RecordBufferType buf; - // bsl::memcpy(buf.buffer(), - // rec.get(), - // FileStoreProtocol::k_JOURNAL_RECORD_SIZE); - // records->push_back(bsl::make_pair(RecordType::e_JOURNAL_OP, - // buf)); - // } d_currPos += FileStoreProtocol::k_JOURNAL_RECORD_SIZE; } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h index c34840738..080cb9406 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfile.h @@ -158,11 +158,12 @@ class JournalFile { size_t numMessages, bsl::vector& messageOffsets); - /// Generate sequence of all types of records. Increase Primary Lease Id - /// after the specified `leaseCount` records. Store list of created records - /// in the specified `records`. - void addAllTypesRecordsWithMultipleLeaseId(RecordsListType* records, - size_t leaseCount); + /// Generate sequence of multiple types of records. Increase Primary Lease + /// Id after the specified `numRecordsWithSameLeaseId` records. Store list + /// of created records in the specified `records`. + void addMultipleTypesRecordsWithMultipleLeaseId( + RecordsListType* records, + size_t numRecordsWithSameLeaseId); }; // ============================================================================ diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index e27a3bdee..6ad42616b 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -222,7 +222,6 @@ void JournalFileProcessor::process() // ConfirmRecord else if (iter->recordType() == mqbs::RecordType::e_CONFIRM) { const mqbs::ConfirmRecord& record = iter->asConfirmRecord(); - stopSearch = d_searchResult_p->processConfirmRecord( record, iter->recordIndex(), @@ -231,7 +230,6 @@ void JournalFileProcessor::process() // DeletionRecord else if (iter->recordType() == mqbs::RecordType::e_DELETION) { const mqbs::DeletionRecord& record = iter->asDeletionRecord(); - stopSearch = d_searchResult_p->processDeletionRecord( record, iter->recordIndex(), diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index 2031dbfbc..aabd8efb1 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -1324,7 +1324,7 @@ static void test16_sequenceNumberLowerBoundTest() // Simulate journal file JournalFile::RecordsListType records(s_allocator_p); JournalFile journalFile(test.d_numRecords, s_allocator_p); - journalFile.addAllTypesRecordsWithMultipleLeaseId( + journalFile.addMultipleTypesRecordsWithMultipleLeaseId( &records, test.d_numRecordsWithSameLeaseId); @@ -1361,11 +1361,11 @@ static void test16_sequenceNumberLowerBoundTest() // Edge case: not in the range (greater then the last record) { - const size_t k_NUM_RECORDS = 300; + const size_t k_NUM_RECORDS = 30; JournalFile::RecordsListType records(s_allocator_p); JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); - journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, - k_NUM_RECORDS); + journalFile.addMultipleTypesRecordsWithMultipleLeaseId(&records, + k_NUM_RECORDS); mqbs::JournalFileIterator journalFileIt( &journalFile.mappedFileDescriptor(), @@ -1391,7 +1391,8 @@ static void test17_searchMessagesBySequenceNumbersRange() // SEARCH MESSAGES BY SEQUENCE NUMBERS RANGE TEST // // Concerns: -// Search messages by sequence number in journal file and output GUIDs. +// Search messages by sequence numbers range in journal file and output +// GUIDs. // // Testing: // JournalFileProcessor::process() @@ -1404,7 +1405,7 @@ static void test17_searchMessagesBySequenceNumbersRange() const size_t k_NUM_RECORDS = 100; JournalFile::RecordsListType records(s_allocator_p); JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); - journalFile.addAllTypesRecordsWithMultipleLeaseId(&records, 10); + journalFile.addMultipleTypesRecordsWithMultipleLeaseId(&records, 10); const CompositeSequenceNumber seqNumGt(3, 3); const CompositeSequenceNumber seqNumLt(4, 6); @@ -1418,7 +1419,7 @@ static void test17_searchMessagesBySequenceNumbersRange() new (*s_allocator_p) FileManagerMock(journalFile), s_allocator_p); - // Get GUIDs of messages inside sequence nums range and prepare expected + // Get GUIDs of messages inside sequence numbers range and prepare expected // output bmqu::MemOutStream expectedStream(s_allocator_p); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index c84b1d5c6..bff89b9b7 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -87,6 +87,7 @@ CommandLineArguments::CommandLineArguments(bslma::Allocator* allocator) , d_cslFile(allocator) , d_guid(allocator) , d_seqNum(allocator) +, d_offset(allocator) , d_queueKey(allocator) , d_queueName(allocator) , d_dumpLimit(0) @@ -200,7 +201,7 @@ bool CommandLineArguments::validate(bsl::string* error, (d_offsetLt > 0 && d_offsetGt >= d_offsetLt)) { ss << "Invalid offset range specified\n"; } - // Check that only one range type can be selected + // Check that only one range type is selected bsl::size_t rangesCnt = 0; if (d_timestampLt || d_timestampGt) { rangesCnt++; @@ -251,7 +252,6 @@ bool CommandLineArguments::validate(bsl::string* error, } } } - if (!d_offset.empty()) { for (bsl::vector::const_iterator cit = d_offset.begin(); @@ -303,6 +303,8 @@ Parameters::Parameters(bslma::Allocator* allocator) , d_valueType(e_NONE) , d_valueGt(0) , d_valueLt(0) +, d_seqNumGt() +, d_seqNumLt() , d_guid(allocator) , d_seqNum(allocator) , d_offset(allocator) @@ -325,6 +327,8 @@ Parameters::Parameters(const CommandLineArguments& arguments, , d_valueType(e_NONE) , d_valueGt(0) , d_valueLt(0) +, d_seqNumGt() +, d_seqNumLt() , d_guid(arguments.d_guid, allocator) , d_seqNum(allocator) , d_offset(arguments.d_offset, allocator) @@ -346,8 +350,7 @@ Parameters::Parameters(const CommandLineArguments& arguments, } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { d_valueType = e_SEQUENCE_NUM; - CompositeSequenceNumber seqNum; - bmqu::MemOutStream errorDescr(allocator); + bmqu::MemOutStream errorDescr(allocator); if (!arguments.d_seqNumLt.empty()) { d_seqNumLt.fromString(errorDescr, arguments.d_seqNumLt); } @@ -361,6 +364,7 @@ Parameters::Parameters(const CommandLineArguments& arguments, d_valueGt = static_cast(arguments.d_offsetGt); } + // Set specific sequence numbers if present if (!arguments.d_seqNum.empty()) { CompositeSequenceNumber seqNum; bmqu::MemOutStream errorDescr(allocator); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp index 0e24f517f..ceec1dd7e 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.cpp @@ -991,11 +991,11 @@ bool SearchSequenceNumberDecorator::processMessageRecord( SearchResultDecorator::processMessageRecord(record, recordIndex, recordOffset); - // Remove processed offset. + // Remove processed sequence number. d_seqNums.erase(it); } - // return true (stop search) if no detail is needed and d_offsets is empty. + // return true (stop search) if no detail is needed and d_seqNums is empty. return (!d_withDetails && d_seqNums.empty()); } @@ -1008,7 +1008,7 @@ bool SearchSequenceNumberDecorator::processDeletionRecord( recordIndex, recordOffset); // return true (stop search) when details needed and search is done - // (d_offsets is empty). + // (d_seqNums is empty). return (d_withDetails && d_seqNums.empty()); } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index edca44887..6a3f658e3 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -477,7 +477,7 @@ class SearchResultSequenceNumberDecorator : public SearchResultDecorator { public: // CREATORS - /// Constructor using the specified `component`, `offsetLt` and + /// Constructor using the specified `component`, `seqNumberLt` and /// `allocator`. SearchResultSequenceNumberDecorator( const bsl::shared_ptr& component, @@ -696,7 +696,7 @@ class SearchOffsetDecorator : public SearchResultDecorator { public: // CREATORS - /// Constructor using the specified `component`, `guids`, `ostream`, + /// Constructor using the specified `component`, `offsets`, `ostream`, /// `withDetails` and `allocator`. SearchOffsetDecorator(const bsl::shared_ptr& component, const bsl::vector& offsets, From f1d28fa654ee52fc50b8b46dc6d0e571491b3226 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Wed, 13 Nov 2024 17:26:30 +0200 Subject: [PATCH 11/21] Fix README.md Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/applications/bmqstoragetool/README.md b/src/applications/bmqstoragetool/README.md index 19dd3ff68..11a51196c 100644 --- a/src/applications/bmqstoragetool/README.md +++ b/src/applications/bmqstoragetool/README.md @@ -18,6 +18,8 @@ Usage: bmqstoragetool [--journal-path ] [--data-file ] [--csl-file ] [--guid ]* + [--seqnum ]* + [--offset ]* [--queue-name ]* [--queue-key ]* [--timestamp-gt ] @@ -46,6 +48,10 @@ Where: path to a .bmq_csl file --guid message guid + --seqnum + message composite sequence number + --offset + message offset --queue-name message queue name --queue-key From f69ee413aee4e046cc74c07f60f70bc4ac20d2ed Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Wed, 13 Nov 2024 17:27:39 +0200 Subject: [PATCH 12/21] Fix typo in README.md Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/bmqstoragetool/README.md b/src/applications/bmqstoragetool/README.md index 11a51196c..683b3c9eb 100644 --- a/src/applications/bmqstoragetool/README.md +++ b/src/applications/bmqstoragetool/README.md @@ -18,7 +18,7 @@ Usage: bmqstoragetool [--journal-path ] [--data-file ] [--csl-file ] [--guid ]* - [--seqnum ]* + [--seqnum ]* [--offset ]* [--queue-name ]* [--queue-key ]* From 6897db65c7b5619d256f7d560cfa7c490ff28a1a Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Thu, 14 Nov 2024 16:34:49 +0200 Subject: [PATCH 13/21] Update header caption Signed-off-by: Aleksandr Ivanov --- .../bmqstoragetool/m_bmqstoragetool_searchresult.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 6a3f658e3..77ae0de1c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -28,6 +28,10 @@ // search processor. // m_bmqstoragetool::SearchResultTimestampDecorator: // provides decorator to handle timestamps. +// m_bmqstoragetool::SearchResultOffsetDecorator: +// provides decorator to handle offsets. +// m_bmqstoragetool::SearchResultSequenceNumberDecorator: +// provides decorator to handle composite sequence numbers. // m_bmqstoragetool::SearchAllDecorator: provides decorator to handle all // messages. // m_bmqstoragetool::SearchOutstandingDecorator: provides decorator @@ -36,6 +40,10 @@ // handle partially confirmed messages. // m_bmqstoragetool::SearchGuidDecorator: // provides decorator to handle search of given GUIDs. +// m_bmqstoragetool::SearchOffsetDecorator: +// provides decorator to handle search of given offsets. +// m_bmqstoragetool::SearchSequenceNumberDecorator: +// provides decorator to handle search of given composite sequence numbers. // m_bmqstoragetool::SummaryProcessor: provides logic to collect summary of // journal file. // @@ -462,7 +470,7 @@ class SearchResultOffsetDecorator : public SearchResultDecorator { // class SearchResultSequenceNumberDecorator // ========================================= -/// This class provides decorator to handle offsets. +/// This class provides decorator to handle composite sequence numbers. class SearchResultSequenceNumberDecorator : public SearchResultDecorator { private: const CompositeSequenceNumber sequenceNumberLt; From 08e4983be7427816f9d46660a09c7e60c3f0804c Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 19 Nov 2024 11:23:53 +0200 Subject: [PATCH 14/21] Fix review comments Signed-off-by: Aleksandr Ivanov --- ...bmqstoragetool_compositesequencenumber.cpp | 16 +-- ...m_bmqstoragetool_compositesequencenumber.h | 24 ++-- ...qstoragetool_compositesequencenumber.t.cpp | 26 ++-- .../m_bmqstoragetool_filters.cpp | 51 ++++---- .../bmqstoragetool/m_bmqstoragetool_filters.h | 20 +-- .../m_bmqstoragetool_journalfileprocessor.cpp | 114 ++++++++--------- .../m_bmqstoragetool_journalfileprocessor.h | 28 ++++- ..._bmqstoragetool_journalfileprocessor.t.cpp | 116 ++++++++++-------- .../m_bmqstoragetool_parameters.cpp | 58 +++++---- .../m_bmqstoragetool_parameters.h | 46 ++++--- .../m_bmqstoragetool_searchresultfactory.cpp | 49 ++++---- 11 files changed, 296 insertions(+), 252 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index 985c3b4af..261fe8fb5 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -30,7 +30,7 @@ namespace m_bmqstoragetool { CompositeSequenceNumber::CompositeSequenceNumber() : d_leaseId(0) , d_seqNumber(0) -, d_isUnset(true) +, d_isSet(false) { // NOTHING } @@ -42,14 +42,14 @@ CompositeSequenceNumber::CompositeSequenceNumber( , d_seqNumber(sequenceNumber) { BSLS_ASSERT(d_leaseId > 0 && d_seqNumber > 0); - d_isUnset = !(d_leaseId > 0 && d_seqNumber > 0); + d_isSet = d_leaseId > 0 && d_seqNumber > 0; } CompositeSequenceNumber& CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString) { - d_isUnset = true; + d_isSet = false; if (seqNumString.empty()) { errorDescription << "Invalid input: empty string."; @@ -88,7 +88,7 @@ CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, return *this; // RETURN } - d_isUnset = false; + d_isSet = true; } catch (const bsl::invalid_argument& e) { errorDescription << "Invalid input: non-numeric values encountered."; @@ -110,13 +110,13 @@ bsl::ostream& CompositeSequenceNumber::print(bsl::ostream& stream, bdlb::Print::indent(stream, level, spacesPerLevel); - if (isUnset()) { - stream << "** UNSET **"; - } - else { + if (isSet()) { stream << "leaseId: " << leaseId() << ", sequenceNumber: " << sequenceNumber(); } + else { + stream << "** UNSET **"; + } if (spacesPerLevel >= 0) { stream << '\n'; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index 21984b45b..a8c5da817 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -49,14 +49,14 @@ class CompositeSequenceNumber { // Primary Lease Id bsls::Types::Uint64 d_seqNumber; // Sequence Number - bool d_isUnset; - // Set to `true` if the value of this object is not set + bool d_isSet; + // Set to `true` if the value of this object is set public: // CREATORS /// Create an un-initialized CompositeSequenceNumber. Note that - /// `isUnset()` would return true. + /// `isSet()` would return false. CompositeSequenceNumber(); /// Create CompositeSequenceNumber from the specified `leaseId` and @@ -69,8 +69,8 @@ class CompositeSequenceNumber { /// Initialize this CompositeSequenceNumber from the specified /// `seqNumString` representation in format `-`. /// Return a reference offering modifiable access to this object. If - /// convertion is successfull, `isUnset()` would return `true`. Otherwise, - /// `isUnset()` would return `false` and specified `errorDescription` is + /// convertion is successfull, `isSet()` would return `true`. Otherwise, + /// `isSet()` would return `false` and specified `errorDescription` is /// filled with error description. CompositeSequenceNumber& fromString(bsl::ostream& errorDescription, const bsl::string& seqNumString); @@ -78,7 +78,7 @@ class CompositeSequenceNumber { // ACCESSORS /// Return `true` if the value of this object is not set. - bool isUnset() const; + bool isSet() const; /// Return Primary Lease Id value. unsigned int leaseId() const; @@ -139,9 +139,9 @@ bool operator<=(const CompositeSequenceNumber& lhs, // ACCESSORS -inline bool CompositeSequenceNumber::isUnset() const +inline bool CompositeSequenceNumber::isSet() const { - return d_isUnset; + return d_isSet; } inline unsigned int CompositeSequenceNumber::leaseId() const @@ -167,7 +167,7 @@ inline bsl::ostream& m_bmqstoragetool::operator<<( const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS - BSLS_ASSERT(!rhs.isUnset()); + BSLS_ASSERT(rhs.isSet()); return rhs.print(stream, 0, -1); } @@ -177,7 +177,7 @@ inline bool m_bmqstoragetool::operator==( const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS - BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + BSLS_ASSERT(lhs.isSet() && rhs.isSet()); return (lhs.leaseId() == rhs.leaseId() && lhs.sequenceNumber() == rhs.sequenceNumber()); @@ -188,7 +188,7 @@ inline bool m_bmqstoragetool::operator<( const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS - BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + BSLS_ASSERT(lhs.isSet() && rhs.isSet()); // Check leaseId first if (lhs.leaseId() < rhs.leaseId()) { @@ -208,7 +208,7 @@ inline bool m_bmqstoragetool::operator<=( const m_bmqstoragetool::CompositeSequenceNumber& rhs) { // PRECONDITIONS - BSLS_ASSERT(!lhs.isUnset() && !rhs.isUnset()); + BSLS_ASSERT(lhs.isSet() && rhs.isSet()); return (lhs < rhs || lhs == rhs); } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index a9f8e8696..346b25c90 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -46,12 +46,12 @@ static void test1_breathingTest() { CompositeSequenceNumber compositeSeqNum; - ASSERT(compositeSeqNum.isUnset()); + ASSERT(!compositeSeqNum.isSet()); } { CompositeSequenceNumber compositeSeqNum(1, 2); - ASSERT(!compositeSeqNum.isUnset()); + ASSERT(compositeSeqNum.isSet()); ASSERT_EQ(compositeSeqNum.leaseId(), 1ul); ASSERT_EQ(compositeSeqNum.sequenceNumber(), 2ul); } @@ -80,7 +80,7 @@ static void test2_fromStringTest() bsl::string inputString("123-456", s_allocator_p); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), false); + ASSERT(compositeSeqNum.isSet()); ASSERT_EQ(compositeSeqNum.leaseId(), 123u); ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); ASSERT(errorDescription.str().empty()); @@ -93,7 +93,7 @@ static void test2_fromStringTest() bsl::string inputString("00123-000456", s_allocator_p); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), false); + ASSERT(compositeSeqNum.isSet()); ASSERT_EQ(compositeSeqNum.leaseId(), 123u); ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); ASSERT(errorDescription.str().empty()); @@ -106,7 +106,7 @@ static void test2_fromStringTest() bsl::string inputString("", s_allocator_p); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: empty string."); } @@ -119,7 +119,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); @@ -133,7 +133,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); @@ -147,7 +147,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); @@ -161,7 +161,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); @@ -175,7 +175,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); @@ -189,7 +189,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); @@ -204,7 +204,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); @@ -219,7 +219,7 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isUnset(), true); + ASSERT_EQ(compositeSeqNum.isSet(), false); ASSERT(!errorDescription.str().empty()); ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp index 3e3a64f22..925541948 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.cpp @@ -23,21 +23,13 @@ namespace m_bmqstoragetool { // class Filters // ============= -Filters::Filters(const bsl::vector& queueKeys, - const bsl::vector& queueUris, - const QueueMap& queueMap, - const Parameters::SearchValueType valueType, - const bsls::Types::Uint64 valueGt, - const bsls::Types::Uint64 valueLt, - const CompositeSequenceNumber seqNumGt, - const CompositeSequenceNumber seqNumLt, - bslma::Allocator* allocator) +Filters::Filters(const bsl::vector& queueKeys, + const bsl::vector& queueUris, + const QueueMap& queueMap, + const Parameters::Range& range, + bslma::Allocator* allocator) : d_queueKeys(allocator) -, d_valueType(valueType) -, d_valueGt(valueGt) -, d_valueLt(valueLt) -, d_seqNumGt(seqNumGt) -, d_seqNumLt(seqNumLt) +, d_range(range) { // Fill internal structures if (!queueKeys.empty()) { @@ -76,25 +68,32 @@ bool Filters::apply(const mqbs::MessageRecord& record, } // Apply `range` filter - bsls::Types::Uint64 value; - switch (d_valueType) { - case Parameters::e_TIMESTAMP: value = record.header().timestamp(); break; - case Parameters::e_SEQUENCE_NUM: { + bsls::Types::Uint64 value, valueGt, valueLt; + switch (d_range.d_type) { + case Parameters::Range::e_TIMESTAMP: + value = record.header().timestamp(); + valueGt = d_range.d_timestampGt; + valueLt = d_range.d_timestampLt; + break; + case Parameters::Range::e_OFFSET: + value = offset; + valueGt = d_range.d_offsetGt; + valueLt = d_range.d_offsetLt; + break; + case Parameters::Range::e_SEQUENCE_NUM: { CompositeSequenceNumber seqNum(record.header().primaryLeaseId(), record.header().sequenceNumber()); - if ((!d_seqNumGt.isUnset() && seqNum <= d_seqNumGt) || - (!d_seqNumLt.isUnset() && d_seqNumLt <= seqNum)) { - // Not inside range - return false; // RETURN - } + return !( + (d_range.d_seqNumGt.isSet() && seqNum <= d_range.d_seqNumGt) || + (d_range.d_seqNumLt.isSet() && + d_range.d_seqNumLt <= seqNum)); // RETURN } break; - case Parameters::e_OFFSET: value = offset; break; default: // No range filter defined return true; // RETURN } - if ((d_valueGt > 0 && value <= d_valueGt) || - (d_valueLt > 0 && value >= d_valueLt)) { + if ((valueGt > 0 && value <= valueGt) || + (valueLt > 0 && value >= valueLt)) { // Not inside range return false; // RETURN } diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h index b74c7b571..608f3fbd1 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_filters.h @@ -43,25 +43,17 @@ class Filters { private: // DATA bsl::unordered_set d_queueKeys; - const Parameters::SearchValueType d_valueType; - const bsls::Types::Uint64 d_valueGt; - const bsls::Types::Uint64 d_valueLt; - const CompositeSequenceNumber d_seqNumGt; - const CompositeSequenceNumber d_seqNumLt; + const Parameters::Range d_range; public: // CREATORS /// Constructor using the specified arguments. - explicit Filters(const bsl::vector& queueKeys, - const bsl::vector& queueUris, - const QueueMap& queueMap, - const Parameters::SearchValueType valueType, - const bsls::Types::Uint64 valueGt, - const bsls::Types::Uint64 valueLt, - const CompositeSequenceNumber seqNumGt, - const CompositeSequenceNumber seqNumLt, - bslma::Allocator* allocator); + explicit Filters(const bsl::vector& queueKeys, + const bsl::vector& queueUris, + const QueueMap& queueMap, + const Parameters::Range& range, + bslma::Allocator* allocator); // ACCESSORS diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index 6ad42616b..823284d59 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -38,49 +38,15 @@ namespace BloombergLP { namespace m_bmqstoragetool { -namespace { -template -T getValue(const mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType); - -template <> -bsls::Types::Uint64 getValue(const mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - BSLS_ASSERT(valueType == Parameters::e_TIMESTAMP || - valueType == Parameters::e_OFFSET); - - return (valueType == Parameters::e_TIMESTAMP) - ? jit->recordHeader().timestamp() - : jit->recordOffset(); -} - -template <> -CompositeSequenceNumber getValue(const mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType) -{ - // PRECONDITIONS - BSLS_ASSERT(jit); - BSLS_ASSERT(valueType == Parameters::e_SEQUENCE_NUM); - - return CompositeSequenceNumber(jit->recordHeader().primaryLeaseId(), - jit->recordHeader().sequenceNumber()); -} - -} // close unnamed namespace - /// Move the journal iterator pointed by the specified 'jit' to the first -/// record whose value `T` is more then the specified 'valueGt'. Return '1' -/// on success, '0' if there are no such records or negative value if an error -/// was encountered. Note that if this method returns < 0, the specified 'jit' -/// is invalidated. Behavior is undefined unless last call to `nextRecord` or +/// record whose value is more then the range lower bound. The specified +/// `lessThanLowerBoundFn` functor is used for comparison. Return '1' on +/// success, '0' if there are no such records or negative value if an error was +/// encountered. Note that if this method returns < 0, the specified 'jit' is +/// invalidated. Behavior is undefined unless last call to `nextRecord` or /// 'advance' returned '1' and the iterator points to a valid record. -template -int moveToLowerBound(mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType, - const T& valueGt) +int moveToLowerBound(mqbs::JournalFileIterator* jit, + LessThanLowerBoundFn& lessThanLowerBoundFn) { // PRECONDITIONS BSLS_ASSERT(jit); @@ -94,7 +60,7 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, bsls::Types::Uint64 left = 0; bsls::Types::Uint64 right = recordsNumber; while (right > left + 1) { - const bool goBackwards = valueGt < getValue(jit, valueType); + const bool goBackwards = lessThanLowerBoundFn(jit, true); if (goBackwards != jit->isReverseMode()) { jit->flipDirection(); } @@ -118,7 +84,8 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, if (jit->isReverseMode()) { jit->flipDirection(); } - if (getValue(jit, valueType) <= valueGt) { + // Move to next record if value <= lower bound) { + if (lessThanLowerBoundFn(jit) || !lessThanLowerBoundFn(jit, true)) { if (jit->recordIndex() < recordsNumber) { rc = jit->nextRecord(); } @@ -132,6 +99,42 @@ int moveToLowerBound(mqbs::JournalFileIterator* jit, return rc; // RETURN } +// ========================== +// class LessThanLowerBoundFn +// ========================== + +LessThanLowerBoundFn::LessThanLowerBoundFn(const Parameters::Range& range) +: d_range(range) +{ + BSLS_ASSERT(d_range.d_type != Parameters::Range::e_NONE); +} + +bool LessThanLowerBoundFn::operator()(const mqbs::JournalFileIterator* jit, + bool inverseOrder) +{ + // PRECONDITIONS + BSLS_ASSERT(jit); + + bool res; + if (d_range.d_type == Parameters::Range::e_TIMESTAMP) { + res = inverseOrder + ? d_range.d_timestampGt < jit->recordHeader().timestamp() + : jit->recordHeader().timestamp() < d_range.d_timestampGt; + } + else if (d_range.d_type == Parameters::Range::e_OFFSET) { + res = inverseOrder ? d_range.d_offsetGt < jit->recordOffset() + : jit->recordOffset() < d_range.d_offsetGt; + } + else { + CompositeSequenceNumber seqNum(jit->recordHeader().primaryLeaseId(), + jit->recordHeader().sequenceNumber()); + res = inverseOrder ? d_range.d_seqNumGt < seqNum + : seqNum < d_range.d_seqNumGt; + } + + return res; +} + // ========================== // class JournalFileProcessor // ========================== @@ -158,16 +161,13 @@ void JournalFileProcessor::process() Filters filters(d_parameters->d_queueKey, d_parameters->d_queueName, d_parameters->d_queueMap, - d_parameters->d_valueType, - d_parameters->d_valueGt, - d_parameters->d_valueLt, - d_parameters->d_seqNumGt, - d_parameters->d_seqNumLt, + d_parameters->d_range, d_allocator_p); bool stopSearch = false; - bool needMoveToLowerBound = d_parameters->d_valueGt > 0 || - !d_parameters->d_seqNumGt.isUnset(); + bool needMoveToLowerBound = d_parameters->d_range.d_timestampGt > 0 || + d_parameters->d_range.d_offsetGt > 0 || + d_parameters->d_range.d_seqNumGt.isSet(); // Iterate through all Journal file records mqbs::JournalFileIterator* iter = d_fileManager->journalFileIterator(); @@ -183,18 +183,8 @@ void JournalFileProcessor::process() } if (needMoveToLowerBound) { - if (d_parameters->d_valueGt > 0) { - rc = moveToLowerBound( - iter, - d_parameters->d_valueType, - d_parameters->d_valueGt); - } - else { - rc = moveToLowerBound( - iter, - d_parameters->d_valueType, - d_parameters->d_seqNumGt); - } + LessThanLowerBoundFn lessThanLowerBoundFn(d_parameters->d_range); + rc = moveToLowerBound(iter, lessThanLowerBoundFn); if (rc == 0) { stopSearch = true; continue; // CONTINUE diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h index 1b7c81751..afd4bea0b 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h @@ -40,10 +40,30 @@ namespace BloombergLP { namespace m_bmqstoragetool { -template -int moveToLowerBound(mqbs::JournalFileIterator* jit, - const Parameters::SearchValueType valueType, - const T& value); +// ========================== +// class LessThanLowerBoundFn +// ========================== + +// Functor to perform comparison with range lower bound. +class LessThanLowerBoundFn { + private: + // PRIVATE DATA + const Parameters::Range d_range; + + public: + // CREATORS + explicit LessThanLowerBoundFn(const Parameters::Range& range); + + bool operator()(const mqbs::JournalFileIterator* jit, + bool inverseOrder = false); + // Return true if value specified by `jit` is less than range lower bound + // when the specified `inverseOrder` is false, false otherwise. + // Return true if range lower bound is less than value specified by `jit` + // when the specified `inverseOrder` is true, false otherwise. +}; + +int moveToLowerBound(mqbs::JournalFileIterator* jit, + LessThanLowerBoundFn& lessThanLowerBoundFn); // ========================== // class JournalFileProcessor diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index aabd8efb1..b533e24d1 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -824,9 +824,9 @@ static void test11_searchMessagesByTimestamp() // Configure parameters to search messages by timestamps Parameters params(s_allocator_p); - params.d_valueGt = ts1; - params.d_valueLt = ts2; - params.d_valueType = Parameters::e_TIMESTAMP; + params.d_range.d_timestampGt = ts1; + params.d_range.d_timestampLt = ts2; + params.d_range.d_type = Parameters::Range::e_TIMESTAMP; // Prepare file manager bslma::ManagedPtr fileManager( new (*s_allocator_p) FileManagerMock(journalFile), @@ -1176,10 +1176,14 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts), + + Parameters::Range range; + range.d_type = Parameters::Range::e_TIMESTAMP; + range.d_timestampGt = ts; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 1); ResultChecker::check(journalFileIt, ts); } @@ -1200,20 +1204,25 @@ static void test15_timestampSearchTest() // Find record with lower timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts1), + + Parameters::Range range; + range.d_type = Parameters::Range::e_TIMESTAMP; + range.d_timestampGt = ts1; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 1); ResultChecker::check(journalFileIt, ts1); // Find record with higher timestamp than the record pointed by the // specified iterator, which is initially forward ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts2), + range.d_timestampGt = ts2; + + LessThanLowerBoundFn lessThanLowerBoundFn2(range); + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn2), 1); ResultChecker::check(journalFileIt, ts2); @@ -1222,10 +1231,8 @@ static void test15_timestampSearchTest() ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts1); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts1), + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 1); ResultChecker::check(journalFileIt, ts1); @@ -1234,10 +1241,8 @@ static void test15_timestampSearchTest() ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts2); journalFileIt.flipDirection(); ASSERT(journalFileIt.isReverseMode()); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts2), + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn2), 1); ResultChecker::check(journalFileIt, ts2); } @@ -1252,10 +1257,14 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts), + + Parameters::Range range; + range.d_type = Parameters::Range::e_TIMESTAMP; + range.d_timestampGt = ts; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 0); ASSERT_EQ(journalFileIt.recordIndex(), k_NUM_RECORDS - 1); ASSERT_LT(journalFileIt.recordHeader().timestamp(), ts); @@ -1271,10 +1280,14 @@ static void test15_timestampSearchTest() false); // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_TIMESTAMP, - ts), + + Parameters::Range range; + range.d_type = Parameters::Range::e_TIMESTAMP; + range.d_timestampGt = ts; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 1); ASSERT_EQ(journalFileIt.recordIndex(), 0U); ASSERT_GT(journalFileIt.recordHeader().timestamp(), ts); @@ -1344,13 +1357,16 @@ static void test16_sequenceNumberLowerBoundTest() // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); - ASSERT_EQ_D( - test.d_line, - m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_SEQUENCE_NUM, - seqNumGt), - 1); + + Parameters::Range range; + range.d_type = Parameters::Range::e_SEQUENCE_NUM; + range.d_seqNumGt = seqNumGt; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ_D(test.d_line, + m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), + 1); ASSERT_EQ_D(test.d_line, journalFileIt.recordHeader().primaryLeaseId(), expectedLeaseId); @@ -1374,11 +1390,15 @@ static void test16_sequenceNumberLowerBoundTest() // Move the iterator to the beginning of the file ASSERT_EQ(journalFileIt.nextRecord(), 1); + CompositeSequenceNumber seqNumGt(1, k_NUM_RECORDS); - ASSERT_EQ(m_bmqstoragetool::moveToLowerBound( - &journalFileIt, - Parameters::e_SEQUENCE_NUM, - seqNumGt), + Parameters::Range range; + range.d_type = Parameters::Range::e_SEQUENCE_NUM; + range.d_seqNumGt = seqNumGt; + LessThanLowerBoundFn lessThanLowerBoundFn(range); + + ASSERT_EQ(m_bmqstoragetool::moveToLowerBound(&journalFileIt, + lessThanLowerBoundFn), 0); ASSERT_EQ(journalFileIt.recordHeader().primaryLeaseId(), 1u); ASSERT_EQ(journalFileIt.recordHeader().sequenceNumber(), @@ -1411,9 +1431,9 @@ static void test17_searchMessagesBySequenceNumbersRange() // Configure parameters to search messages by sequence number range Parameters params(s_allocator_p); - params.d_seqNumGt = seqNumGt; - params.d_seqNumLt = seqNumLt; - params.d_valueType = Parameters::e_SEQUENCE_NUM; + params.d_range.d_seqNumGt = seqNumGt; + params.d_range.d_seqNumLt = seqNumLt; + params.d_range.d_type = Parameters::Range::e_SEQUENCE_NUM; // Prepare file manager bslma::ManagedPtr fileManager( new (*s_allocator_p) FileManagerMock(journalFile), @@ -1481,9 +1501,9 @@ static void test18_searchMessagesByOffsetsRange() // Configure parameters to search messages by timestamps Parameters params(s_allocator_p); - params.d_valueGt = offsetGt; - params.d_valueLt = offsetLt; - params.d_valueType = Parameters::e_OFFSET; + params.d_range.d_offsetGt = offsetGt; + params.d_range.d_offsetLt = offsetLt; + params.d_range.d_type = Parameters::Range::e_OFFSET; // Prepare file manager bslma::ManagedPtr fileManager( new (*s_allocator_p) FileManagerMock(journalFile), diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index bff89b9b7..2febd2dc6 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -179,19 +179,19 @@ bool CommandLineArguments::validate(bsl::string* error, CompositeSequenceNumber seqNumLt, seqNumGt; if (!d_seqNumLt.empty()) { seqNumLt.fromString(errorDescr, d_seqNumLt); - if (seqNumLt.isUnset()) { + if (!seqNumLt.isSet()) { ss << "--seqnum-lt: " << errorDescr.str() << "\n"; errorDescr.reset(); } } if (!d_seqNumGt.empty()) { seqNumGt.fromString(errorDescr, d_seqNumGt); - if (seqNumGt.isUnset()) { + if (!seqNumGt.isSet()) { ss << "--seqnum-gt: " << errorDescr.str() << "\n"; } } - if (!seqNumLt.isUnset() && !seqNumGt.isUnset()) { + if (seqNumLt.isSet() && seqNumGt.isSet()) { if (seqNumLt <= seqNumGt) { ss << "Invalid sequence number range specified\n"; } @@ -247,7 +247,7 @@ bool CommandLineArguments::validate(bsl::string* error, cit != d_seqNum.end(); ++cit) { seqNum.fromString(errorDescr, *cit); - if (seqNum.isUnset()) { + if (!seqNum.isSet()) { ss << "--seqnum: " << errorDescr.str() << "\n"; } } @@ -298,13 +298,21 @@ bool CommandLineArguments::validate(bsl::string* error, return error->empty(); } -Parameters::Parameters(bslma::Allocator* allocator) -: d_queueMap(allocator) -, d_valueType(e_NONE) -, d_valueGt(0) -, d_valueLt(0) +Parameters::Range::Range() +: d_type(Range::e_NONE) +, d_timestampGt(0) +, d_timestampLt(0) +, d_offsetGt(0) +, d_offsetLt(0) , d_seqNumGt() , d_seqNumLt() +{ + // NOTHING +} + +Parameters::Parameters(bslma::Allocator* allocator) +: d_queueMap(allocator) +, d_range() , d_guid(allocator) , d_seqNum(allocator) , d_offset(allocator) @@ -324,11 +332,7 @@ Parameters::Parameters(bslma::Allocator* allocator) Parameters::Parameters(const CommandLineArguments& arguments, bslma::Allocator* allocator) : d_queueMap(allocator) -, d_valueType(e_NONE) -, d_valueGt(0) -, d_valueLt(0) -, d_seqNumGt() -, d_seqNumLt() +, d_range() , d_guid(arguments.d_guid, allocator) , d_seqNum(allocator) , d_offset(arguments.d_offset, allocator) @@ -344,25 +348,29 @@ Parameters::Parameters(const CommandLineArguments& arguments, { // Set search range type and values if present if (arguments.d_timestampLt || arguments.d_timestampGt) { - d_valueType = e_TIMESTAMP; - d_valueLt = static_cast(arguments.d_timestampLt); - d_valueGt = static_cast(arguments.d_timestampGt); + d_range.d_type = Range::e_TIMESTAMP; + d_range.d_timestampLt = static_cast( + arguments.d_timestampLt); + d_range.d_timestampGt = static_cast( + arguments.d_timestampGt); + } + else if (arguments.d_offsetLt || arguments.d_offsetGt) { + d_range.d_type = Range::e_OFFSET; + d_range.d_offsetLt = static_cast( + arguments.d_offsetLt); + d_range.d_offsetGt = static_cast( + arguments.d_offsetGt); } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { - d_valueType = e_SEQUENCE_NUM; + d_range.d_type = Range::e_SEQUENCE_NUM; bmqu::MemOutStream errorDescr(allocator); if (!arguments.d_seqNumLt.empty()) { - d_seqNumLt.fromString(errorDescr, arguments.d_seqNumLt); + d_range.d_seqNumLt.fromString(errorDescr, arguments.d_seqNumLt); } if (!arguments.d_seqNumGt.empty()) { - d_seqNumGt.fromString(errorDescr, arguments.d_seqNumGt); + d_range.d_seqNumGt.fromString(errorDescr, arguments.d_seqNumGt); } } - else if (arguments.d_offsetLt || arguments.d_offsetGt) { - d_valueType = e_OFFSET; - d_valueLt = static_cast(arguments.d_offsetLt); - d_valueGt = static_cast(arguments.d_offsetGt); - } // Set specific sequence numbers if present if (!arguments.d_seqNum.empty()) { diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h index e3c0be350..7d2cf71fc 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h @@ -109,26 +109,42 @@ struct CommandLineArguments { struct Parameters { // PUBLIC TYPES - enum SearchValueType { - e_NONE = 0, - e_TIMESTAMP = 1, - e_SEQUENCE_NUM = 2, - e_OFFSET = 3 + + // VST representing search range parameters + struct Range { + // PUBLIC TYPES + enum Type { + e_NONE = 0, + e_TIMESTAMP = 1, + e_SEQUENCE_NUM = 2, + e_OFFSET = 3 + }; + + // PUBLIC DATA + Type d_type; + /// Range type + bsls::Types::Uint64 d_timestampGt; + // Filter messages greater than timestamp value + bsls::Types::Uint64 d_timestampLt; + // Filter messages less than timestamp value + bsls::Types::Uint64 d_offsetGt; + // Filter messages greater than offset value + bsls::Types::Uint64 d_offsetLt; + // Filter messages less than offset value + CompositeSequenceNumber d_seqNumGt; + // Filter messages greater than sequence number + CompositeSequenceNumber d_seqNumLt; + // Filter messages less than sequence number + + // CREATORS + explicit Range(); }; // PUBLIC DATA QueueMap d_queueMap; // Queue map containing uri to key and key to info mappings - SearchValueType d_valueType; - // Search value type for message filtering - bsls::Types::Uint64 d_valueGt; - // Filter messages greater than value - bsls::Types::Uint64 d_valueLt; - // Filter messages less than value - CompositeSequenceNumber d_seqNumGt; - // Filter messages greater than sequence number - CompositeSequenceNumber d_seqNumLt; - // Filter messages less than sequence number + Range d_range; + // Range parameters for filtering bsl::vector d_guid; // Filter messages by message guids bsl::vector d_seqNum; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp index 10f7cff77..3caec9eb1 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresultfactory.cpp @@ -142,34 +142,33 @@ bsl::shared_ptr SearchResultFactory::createSearchResult( alloc); } - if (params->d_valueLt > 0) { - // Add TimestampDecorator if 'valueLt' is given and value type is - // `e_TIMESTAMP`. - if (params->d_valueType == Parameters::e_TIMESTAMP) { - searchResult.reset( - new (*alloc) SearchResultTimestampDecorator(searchResult, - params->d_valueLt, - alloc), - alloc); - } - else if (params->d_valueType == Parameters::e_OFFSET) { - // Add OffsetDecorator if 'valueLt' is given and value type is - // `e_OFFSET`. - searchResult.reset( - new (*alloc) SearchResultOffsetDecorator(searchResult, - params->d_valueLt, - alloc), - alloc); - } + // Add TimestampDecorator if 'timestampLt' is given and value type is + // `e_TIMESTAMP`. + if (params->d_range.d_type == Parameters::Range::e_TIMESTAMP && + params->d_range.d_timestampLt > 0) { + searchResult.reset(new (*alloc) SearchResultTimestampDecorator( + searchResult, + params->d_range.d_timestampLt, + alloc), + alloc); } - - // Add SequenceNumberDecorator if 'seqNumLt' is given and value type is - // `e_SEQUENCE_NUM`. - if (params->d_valueType == Parameters::e_SEQUENCE_NUM && - !params->d_seqNumLt.isUnset()) { + else if (params->d_range.d_type == Parameters::Range::e_OFFSET && + params->d_range.d_offsetLt > 0) { + // Add OffsetDecorator if 'offsetLt' is given and value type is + // `e_OFFSET`. + searchResult.reset(new (*alloc) SearchResultOffsetDecorator( + searchResult, + params->d_range.d_offsetLt, + alloc), + alloc); + } + else if (params->d_range.d_type == Parameters::Range::e_SEQUENCE_NUM && + params->d_range.d_seqNumLt.isSet()) { + // Add SequenceNumberDecorator if 'seqNumLt' is given and value type is + // `e_SEQUENCE_NUM`. searchResult.reset(new (*alloc) SearchResultSequenceNumberDecorator( searchResult, - params->d_seqNumLt, + params->d_range.d_seqNumLt, alloc), alloc); } From 27194b862adbf0d93f7ff6e1120ac6e107316295 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 19 Nov 2024 11:36:28 +0200 Subject: [PATCH 15/21] Fix code style Signed-off-by: Aleksandr Ivanov --- .../bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp | 2 +- .../bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp index 823284d59..edd55f390 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.cpp @@ -110,7 +110,7 @@ LessThanLowerBoundFn::LessThanLowerBoundFn(const Parameters::Range& range) } bool LessThanLowerBoundFn::operator()(const mqbs::JournalFileIterator* jit, - bool inverseOrder) + bool inverseOrder) const { // PRECONDITIONS BSLS_ASSERT(jit); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h index afd4bea0b..1abfc2d92 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.h @@ -52,10 +52,13 @@ class LessThanLowerBoundFn { public: // CREATORS + explicit LessThanLowerBoundFn(const Parameters::Range& range); + // ACCESSORS + bool operator()(const mqbs::JournalFileIterator* jit, - bool inverseOrder = false); + bool inverseOrder = false) const; // Return true if value specified by `jit` is less than range lower bound // when the specified `inverseOrder` is false, false otherwise. // Return true if range lower bound is less than value specified by `jit` From c8758adf12e0c51a6225900185d7a37b2212e55d Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Fri, 29 Nov 2024 16:26:22 +0200 Subject: [PATCH 16/21] Reset errorDescr Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 2febd2dc6..7d0f950c4 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -249,6 +249,7 @@ bool CommandLineArguments::validate(bsl::string* error, seqNum.fromString(errorDescr, *cit); if (!seqNum.isSet()) { ss << "--seqnum: " << errorDescr.str() << "\n"; + errorDescr.reset(); } } } From 768b164fdfb78af0862849ae2f1922645d0c1ffa Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 3 Dec 2024 11:09:49 +0200 Subject: [PATCH 17/21] Fix merge conflicts Signed-off-by: Aleksandr Ivanov --- ..._bmqstoragetool_journalfileprocessor.t.cpp | 62 +++++++++++-------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp index 521fcff2e..8d57df8b1 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_journalfileprocessor.t.cpp @@ -1396,8 +1396,10 @@ static void test16_sequenceNumberLowerBoundTest() const Test& test = k_DATA[idx]; // Simulate journal file - JournalFile::RecordsListType records(s_allocator_p); - JournalFile journalFile(test.d_numRecords, s_allocator_p); + JournalFile::RecordsListType records( + bmqtst::TestHelperUtil::allocator()); + JournalFile journalFile(test.d_numRecords, + bmqtst::TestHelperUtil::allocator()); journalFile.addMultipleTypesRecordsWithMultipleLeaseId( &records, test.d_numRecordsWithSameLeaseId); @@ -1439,8 +1441,10 @@ static void test16_sequenceNumberLowerBoundTest() // Edge case: not in the range (greater then the last record) { const size_t k_NUM_RECORDS = 30; - JournalFile::RecordsListType records(s_allocator_p); - JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + JournalFile::RecordsListType records( + bmqtst::TestHelperUtil::allocator()); + JournalFile journalFile(k_NUM_RECORDS, + bmqtst::TestHelperUtil::allocator()); journalFile.addMultipleTypesRecordsWithMultipleLeaseId(&records, k_NUM_RECORDS); @@ -1484,25 +1488,27 @@ static void test17_searchMessagesBySequenceNumbersRange() // Simulate journal file const size_t k_NUM_RECORDS = 100; - JournalFile::RecordsListType records(s_allocator_p); - JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + JournalFile::RecordsListType records(bmqtst::TestHelperUtil::allocator()); + JournalFile journalFile(k_NUM_RECORDS, + bmqtst::TestHelperUtil::allocator()); journalFile.addMultipleTypesRecordsWithMultipleLeaseId(&records, 10); const CompositeSequenceNumber seqNumGt(3, 3); const CompositeSequenceNumber seqNumLt(4, 6); // Configure parameters to search messages by sequence number range - Parameters params(s_allocator_p); + Parameters params(bmqtst::TestHelperUtil::allocator()); params.d_range.d_seqNumGt = seqNumGt; params.d_range.d_seqNumLt = seqNumLt; params.d_range.d_type = Parameters::Range::e_SEQUENCE_NUM; // Prepare file manager bslma::ManagedPtr fileManager( - new (*s_allocator_p) FileManagerMock(journalFile), - s_allocator_p); + new (*bmqtst::TestHelperUtil::allocator()) + FileManagerMock(journalFile), + bmqtst::TestHelperUtil::allocator()); // Get GUIDs of messages inside sequence numbers range and prepare expected // output - bmqu::MemOutStream expectedStream(s_allocator_p); + bmqu::MemOutStream expectedStream(bmqtst::TestHelperUtil::allocator()); bsl::list::const_iterator recordIter = records.begin(); @@ -1524,12 +1530,13 @@ static void test17_searchMessagesBySequenceNumbersRange() expectedStream << msgCnt << " message GUID(s) found." << bsl::endl; // Run search - bmqu::MemOutStream resultStream(s_allocator_p); + bmqu::MemOutStream resultStream(bmqtst::TestHelperUtil::allocator()); bslma::ManagedPtr searchProcessor = - CommandProcessorFactory::createCommandProcessor(¶ms, - fileManager, - resultStream, - s_allocator_p); + CommandProcessorFactory::createCommandProcessor( + ¶ms, + fileManager, + resultStream, + bmqtst::TestHelperUtil::allocator()); searchProcessor->process(); ASSERT_EQ(resultStream.str(), expectedStream.str()); @@ -1550,8 +1557,9 @@ static void test18_searchMessagesByOffsetsRange() // Simulate journal file const size_t k_NUM_RECORDS = 50; - JournalFile::RecordsListType records(s_allocator_p); - JournalFile journalFile(k_NUM_RECORDS, s_allocator_p); + JournalFile::RecordsListType records(bmqtst::TestHelperUtil::allocator()); + JournalFile journalFile(k_NUM_RECORDS, + bmqtst::TestHelperUtil::allocator()); journalFile.addAllTypesRecords(&records); const size_t k_HEADER_SIZE = sizeof(mqbs::FileHeader) + sizeof(mqbs::JournalFileHeader); @@ -1561,18 +1569,19 @@ static void test18_searchMessagesByOffsetsRange() mqbs::FileStoreProtocol::k_JOURNAL_RECORD_SIZE * 35 + k_HEADER_SIZE; // Configure parameters to search messages by timestamps - Parameters params(s_allocator_p); + Parameters params(bmqtst::TestHelperUtil::allocator()); params.d_range.d_offsetGt = offsetGt; params.d_range.d_offsetLt = offsetLt; params.d_range.d_type = Parameters::Range::e_OFFSET; // Prepare file manager bslma::ManagedPtr fileManager( - new (*s_allocator_p) FileManagerMock(journalFile), - s_allocator_p); + new (*bmqtst::TestHelperUtil::allocator()) + FileManagerMock(journalFile), + bmqtst::TestHelperUtil::allocator()); // Get GUIDs of messages within offsets range and prepare expected // output - bmqu::MemOutStream expectedStream(s_allocator_p); + bmqu::MemOutStream expectedStream(bmqtst::TestHelperUtil::allocator()); bsl::list::const_iterator recordIter = records.begin(); @@ -1594,12 +1603,13 @@ static void test18_searchMessagesByOffsetsRange() expectedStream << msgCnt << " message GUID(s) found." << bsl::endl; // Run search - bmqu::MemOutStream resultStream(s_allocator_p); + bmqu::MemOutStream resultStream(bmqtst::TestHelperUtil::allocator()); bslma::ManagedPtr searchProcessor = - CommandProcessorFactory::createCommandProcessor(¶ms, - fileManager, - resultStream, - s_allocator_p); + CommandProcessorFactory::createCommandProcessor( + ¶ms, + fileManager, + resultStream, + bmqtst::TestHelperUtil::allocator()); searchProcessor->process(); ASSERT_EQ(resultStream.str(), expectedStream.str()); From 6ecd16777f90ac4489ba5a0a6766a10257948507 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 3 Dec 2024 11:32:03 +0200 Subject: [PATCH 18/21] Fix merge conflicts Signed-off-by: Aleksandr Ivanov --- ...qstoragetool_compositesequencenumber.t.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index 346b25c90..4a2a5f062 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -71,13 +71,13 @@ static void test2_fromStringTest() { bmqtst::TestHelper::printTestName("FROM STRING TEST"); - bmqu::MemOutStream errorDescription(s_allocator_p); + bmqu::MemOutStream errorDescription(bmqtst::TestHelperUtil::allocator()); // Valid string { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123-456", s_allocator_p); + bsl::string inputString("123-456", bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); ASSERT(compositeSeqNum.isSet()); @@ -90,7 +90,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("00123-000456", s_allocator_p); + bsl::string inputString("00123-000456", bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); ASSERT(compositeSeqNum.isSet()); @@ -103,7 +103,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("", s_allocator_p); + bsl::string inputString("", bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); ASSERT_EQ(compositeSeqNum.isSet(), false); @@ -115,7 +115,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123456", s_allocator_p); + bsl::string inputString("123456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -129,7 +129,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123_456", s_allocator_p); + bsl::string inputString("123_456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -143,7 +143,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("1a23-456", s_allocator_p); + bsl::string inputString("1a23-456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -157,7 +157,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123-45a6", s_allocator_p); + bsl::string inputString("123-45a6", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -171,7 +171,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("0-456", s_allocator_p); + bsl::string inputString("0-456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -185,7 +185,7 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123-0", s_allocator_p); + bsl::string inputString("123-0", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -200,7 +200,7 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; // Simulate unsigned int overflow - bsl::string inputString("11111111111-123", s_allocator_p); + bsl::string inputString("11111111111-123", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -215,7 +215,7 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; // Simulate bsls::Types::Uint64 overflow - bsl::string inputString("123-111111111111111111111", s_allocator_p); + bsl::string inputString("123-111111111111111111111", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -311,7 +311,7 @@ int main(int argc, char* argv[]) case 3: test3_comparisonTest(); break; default: { cerr << "WARNING: CASE '" << _testCase << "' NOT FOUND." << endl; - s_testStatus = -1; + bmqtst::TestHelperUtil::testStatus() = -1; } break; } From 10b24b5fd04c63defc20a2c1c9896a8a06068489 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Tue, 3 Dec 2024 12:03:07 +0200 Subject: [PATCH 19/21] Fix formatting Signed-off-by: Aleksandr Ivanov --- ...qstoragetool_compositesequencenumber.t.cpp | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index 4a2a5f062..4cb74d80c 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -77,7 +77,8 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123-456", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("123-456", + bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); ASSERT(compositeSeqNum.isSet()); @@ -90,7 +91,8 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("00123-000456", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("00123-000456", + bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); ASSERT(compositeSeqNum.isSet()); @@ -129,7 +131,8 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123_456", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("123_456", + bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -143,7 +146,8 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("1a23-456", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("1a23-456", + bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -157,7 +161,8 @@ static void test2_fromStringTest() { CompositeSequenceNumber compositeSeqNum; - bsl::string inputString("123-45a6", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("123-45a6", + bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -200,7 +205,8 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; // Simulate unsigned int overflow - bsl::string inputString("11111111111-123", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("11111111111-123", + bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); @@ -215,7 +221,8 @@ static void test2_fromStringTest() CompositeSequenceNumber compositeSeqNum; // Simulate bsls::Types::Uint64 overflow - bsl::string inputString("123-111111111111111111111", bmqtst::TestHelperUtil::allocator()); + bsl::string inputString("123-111111111111111111111", + bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); From e9cf8dd2f6970229c641287ba74d3f2d6323c82f Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Mon, 16 Dec 2024 13:06:06 +0200 Subject: [PATCH 20/21] Fix assert macro names in compositesequencenumber.t Signed-off-by: Aleksandr Ivanov --- ...qstoragetool_compositesequencenumber.t.cpp | 111 +++++++++--------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index 4cb74d80c..779386935 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -46,14 +46,14 @@ static void test1_breathingTest() { CompositeSequenceNumber compositeSeqNum; - ASSERT(!compositeSeqNum.isSet()); + BMQTST_ASSERT(!compositeSeqNum.isSet()); } { CompositeSequenceNumber compositeSeqNum(1, 2); - ASSERT(compositeSeqNum.isSet()); - ASSERT_EQ(compositeSeqNum.leaseId(), 1ul); - ASSERT_EQ(compositeSeqNum.sequenceNumber(), 2ul); + BMQTST_ASSERT(compositeSeqNum.isSet()); + BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 1ul); + BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 2ul); } } @@ -81,10 +81,10 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT(compositeSeqNum.isSet()); - ASSERT_EQ(compositeSeqNum.leaseId(), 123u); - ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); - ASSERT(errorDescription.str().empty()); + BMQTST_ASSERT(compositeSeqNum.isSet()); + BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 123u); + BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); + BMQTST_ASSERT(errorDescription.str().empty()); } // Valid string with leading zeros @@ -95,10 +95,10 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT(compositeSeqNum.isSet()); - ASSERT_EQ(compositeSeqNum.leaseId(), 123u); - ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); - ASSERT(errorDescription.str().empty()); + BMQTST_ASSERT(compositeSeqNum.isSet()); + BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 123u); + BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); + BMQTST_ASSERT(errorDescription.str().empty()); } // Empty string @@ -108,9 +108,10 @@ static void test2_fromStringTest() bsl::string inputString("", bmqtst::TestHelperUtil::allocator()); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), "Invalid input: empty string."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: empty string."); } // Invalid string with missed separator @@ -121,10 +122,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid format: no '-' separator found."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid format: no '-' separator found."); } // Invalid string with wrong separator @@ -136,10 +137,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid format: no '-' separator found."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid format: no '-' separator found."); } // Invalid string with non-numeric value in first part @@ -151,10 +152,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: non-numeric values encountered."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: non-numeric values encountered."); } // Invalid string with non-numeric value in second part @@ -166,10 +167,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: non-numeric values encountered."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: non-numeric values encountered."); } // Invalid string with zero value in first part @@ -180,10 +181,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: zero values encountered."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: zero values encountered."); } // Invalid string with zero value in second part @@ -194,10 +195,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: zero values encountered."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: zero values encountered."); } // Invalid string with out of range value in first part @@ -210,10 +211,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: number out of range."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: number out of range."); } // Invalid string with out of range value in second part @@ -226,10 +227,10 @@ static void test2_fromStringTest() errorDescription.reset(); compositeSeqNum.fromString(errorDescription, inputString); - ASSERT_EQ(compositeSeqNum.isSet(), false); - ASSERT(!errorDescription.str().empty()); - ASSERT_EQ(errorDescription.str(), - "Invalid input: number out of range."); + BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + BMQTST_ASSERT(!errorDescription.str().empty()); + BMQTST_ASSERT_EQ(errorDescription.str(), + "Invalid input: number out of range."); } } @@ -250,56 +251,56 @@ static void test3_comparisonTest() { CompositeSequenceNumber lhs(1, 2); CompositeSequenceNumber rhs(2, 1); - ASSERT(lhs < rhs); + BMQTST_ASSERT(lhs < rhs); } // leaseId is less, seqNumber is less { CompositeSequenceNumber lhs(1, 1); CompositeSequenceNumber rhs(2, 2); - ASSERT(lhs < rhs); + BMQTST_ASSERT(lhs < rhs); } // leaseId is greater, seqNumber is greater { CompositeSequenceNumber lhs(3, 2); CompositeSequenceNumber rhs(2, 1); - ASSERT_EQ((lhs < rhs), false); + BMQTST_ASSERT_EQ((lhs < rhs), false); } // leaseId is greater, seqNumber is less { CompositeSequenceNumber lhs(3, 1); CompositeSequenceNumber rhs(2, 2); - ASSERT_EQ((lhs < rhs), false); + BMQTST_ASSERT_EQ((lhs < rhs), false); } // leaseId is equal, seqNumber is less { CompositeSequenceNumber lhs(1, 1); CompositeSequenceNumber rhs(1, 2); - ASSERT(lhs < rhs); + BMQTST_ASSERT(lhs < rhs); } // leaseId is equal, seqNumber is greater { CompositeSequenceNumber lhs(1, 2); CompositeSequenceNumber rhs(1, 1); - ASSERT_EQ((lhs < rhs), false); + BMQTST_ASSERT_EQ((lhs < rhs), false); } // Compare for equality: leaseId is equal, seqNumber is equal { CompositeSequenceNumber lhs(1, 2); CompositeSequenceNumber rhs(1, 2); - ASSERT_EQ((lhs == rhs), true); + BMQTST_ASSERT_EQ((lhs == rhs), true); } // Compare for equality using '<=': leaseId is equal, seqNumber is equal { CompositeSequenceNumber lhs(1, 2); CompositeSequenceNumber rhs(1, 2); - ASSERT_EQ((lhs <= rhs), true); + BMQTST_ASSERT_EQ((lhs <= rhs), true); } } From 73cb8d0fc79747edd3accd36affd7a3760e59e20 Mon Sep 17 00:00:00 2001 From: Aleksandr Ivanov Date: Thu, 19 Dec 2024 12:33:51 +0200 Subject: [PATCH 21/21] Fix review comments: typos, doxygen comments Signed-off-by: Aleksandr Ivanov --- src/applications/bmqstoragetool/README.md | 12 +-- .../m_bmqstoragetool_parameters.h | 89 ++++++++++--------- .../m_bmqstoragetool_searchresult.h | 22 ++--- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/applications/bmqstoragetool/README.md b/src/applications/bmqstoragetool/README.md index 683b3c9eb..6be2f8747 100644 --- a/src/applications/bmqstoragetool/README.md +++ b/src/applications/bmqstoragetool/README.md @@ -24,8 +24,8 @@ Usage: bmqstoragetool [--journal-path ] [--queue-key ]* [--timestamp-gt ] [--timestamp-lt ] - [--seqnum-gt ] - [--seqnum-lt ] + [--seqnum-gt ] + [--seqnum-lt ] [--offset-gt ] [--offset-lt ] [--outstanding] @@ -60,10 +60,10 @@ Where: lower timestamp bound --timestamp-lt higher timestamp bound - --seqnum-gt - lower composit sequence number bound, defined in form , e.g. 123-456 - --seqnum-lt - higher composit sequence number bound, defined in form , e.g. 123-456 + --seqnum-gt + lower composite sequence number bound, defined in form , e.g. 123-456 + --seqnum-lt + higher composite sequence number bound, defined in form , e.g. 123-456 --offset-gt lower offset bound --offset-lt diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h index 7d2cf71fc..d9a465413 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.h @@ -54,50 +54,50 @@ namespace m_bmqstoragetool { struct CommandLineArguments { // PUBLIC DATA + /// Filter messages by minimum timestamp bsls::Types::Int64 d_timestampGt; - // Filter messages by minimum timestamp + /// Filter messages by maximum timestamp bsls::Types::Int64 d_timestampLt; - // Filter messages by maximum timestamp + /// Filter messages by minimum record composite sequence number bsl::string d_seqNumGt; - // Filter messages by minimum record composite sequence number + /// Filter messages by maximum record composite sequence number bsl::string d_seqNumLt; - // Filter messages by maximum record composite sequence number + /// Filter messages by minimum record offset bsls::Types::Int64 d_offsetGt; - // Filter messages by minimum record offset + /// Filter messages by maximum record offset bsls::Types::Int64 d_offsetLt; - // Filter messages by maximum record offset + /// Path to find all files from bsl::string d_journalPath; - // Path to find all files from + /// Path to read journal files from bsl::string d_journalFile; - // Path to read journal files from + /// Path to read data files from bsl::string d_dataFile; - // Path to read data files from + /// Path to read CSL files from bsl::string d_cslFile; - // Path to read CSL files from + /// Filter messages by message guids bsl::vector d_guid; - // Filter messages by message guids + /// Filter messages by record composite sequence numbers bsl::vector d_seqNum; - // Filter messages by record composite sequence numbers + /// Filter messages by record offsets bsl::vector d_offset; - // Filter messages by record offsets + /// Filter messages by queue keys bsl::vector d_queueKey; - // Filter messages by queue keys + /// Filter messages by queue names bsl::vector d_queueName; - // Filter messages by queue names + /// Limit number of bytes to int d_dumpLimit; - // Limit number of bytes to + /// Print message details bool d_details; - // Print message details + /// Print message payload bool d_dumpPayload; - // Print message payload + /// Print summary of messages bool d_summary; - // Print summary of messages + /// Show only outstanding messages (not deleted) bool d_outstanding; - // Show only outstanding messages (not deleted) + /// Show only messages, confirmed by all the appId's bool d_confirmed; - // Show only messages, confirmed by all the appId's + /// Show only messages, confirmed by some of the appId's bool d_partiallyConfirmed; - // Show only messages, confirmed by some of the appId's // CREATORS explicit CommandLineArguments(bslma::Allocator* allocator = 0); @@ -110,7 +110,7 @@ struct CommandLineArguments { struct Parameters { // PUBLIC TYPES - // VST representing search range parameters + /// VST representing search range parameters struct Range { // PUBLIC TYPES enum Type { @@ -121,54 +121,55 @@ struct Parameters { }; // PUBLIC DATA - Type d_type; /// Range type + Type d_type; + /// Filter messages greater than timestamp value bsls::Types::Uint64 d_timestampGt; - // Filter messages greater than timestamp value + /// Filter messages less than timestamp value bsls::Types::Uint64 d_timestampLt; - // Filter messages less than timestamp value + /// Filter messages greater than offset value bsls::Types::Uint64 d_offsetGt; - // Filter messages greater than offset value + /// Filter messages less than offset value bsls::Types::Uint64 d_offsetLt; - // Filter messages less than offset value + /// Filter messages greater than sequence number CompositeSequenceNumber d_seqNumGt; - // Filter messages greater than sequence number + /// Filter messages less than sequence number CompositeSequenceNumber d_seqNumLt; - // Filter messages less than sequence number // CREATORS + /// Default constructor explicit Range(); }; // PUBLIC DATA + /// Queue map containing uri to key and key to info mappings QueueMap d_queueMap; - // Queue map containing uri to key and key to info mappings + /// Range parameters for filtering Range d_range; - // Range parameters for filtering + /// Filter messages by message guids bsl::vector d_guid; - // Filter messages by message guids + /// Filter messages by message sequence number bsl::vector d_seqNum; - // Filter messages by message sequence number + /// Filter messages by message offsets bsl::vector d_offset; - // Filter messages by message offsets + /// Filter messages by queue keys bsl::vector d_queueKey; - // Filter messages by queue keys + /// Filter messages by queue names bsl::vector d_queueName; - // Filter messages by queue names + /// Limit number of bytes to dump unsigned int d_dumpLimit; - // Limit number of bytes to dump + /// Print message details bool d_details; - // Print message details + /// Print message payload bool d_dumpPayload; - // Print message payload + /// Print summary of messages bool d_summary; - // Print summary of messages + /// Show only outstanding messages (not deleted) bool d_outstanding; - // Show only outstanding messages (not deleted) + /// Show only messages, confirmed by all the appId's bool d_confirmed; - // Show only messages, confirmed by all the appId's + /// Show only messages, confirmed by some of the appId's bool d_partiallyConfirmed; - // Show only messages, confirmed by some of the appId's // CREATORS /// Default constructor diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h index 62d5f364f..eaf111474 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_searchresult.h @@ -385,9 +385,9 @@ class SearchResultTimestampDecorator : public SearchResultDecorator { // ACCESSORS + /// Return 'true' if the specified 'timestamp' is greater than + /// 'd_timestampLt' and internal cache is empty. bool stop(const bsls::Types::Uint64 timestamp) const; - // Return 'true' if the specified 'timestamp' is greater than - // 'd_timestampLt' and internal cache is empty. public: // CREATORS @@ -428,14 +428,14 @@ class SearchResultTimestampDecorator : public SearchResultDecorator { /// This class provides decorator to handle offsets. class SearchResultOffsetDecorator : public SearchResultDecorator { private: + /// Higher bound offset. const bsls::Types::Uint64 d_offsetLt; - // Higher bound offset. // ACCESSORS + /// Return 'true' if the specified 'offset' is greater than + /// 'd_offsetLt' and internal cache is empty. bool stop(const bsls::Types::Uint64 offset) const; - // Return 'true' if the specified 'offset' is greater than - // 'd_offsetLt' and internal cache is empty. public: // CREATORS @@ -475,14 +475,14 @@ class SearchResultOffsetDecorator : public SearchResultDecorator { /// This class provides decorator to handle composite sequence numbers. class SearchResultSequenceNumberDecorator : public SearchResultDecorator { private: + /// Higher bound sequence number. const CompositeSequenceNumber sequenceNumberLt; - // Higher bound sequence number. // ACCESSORS + /// Return 'true' if the specified 'sequenceNumber' is greater than + /// 'sequenceNumberLt' and internal cache is empty. bool stop(const CompositeSequenceNumber& sequenceNumber) const; - // Return 'true' if the specified 'sequenceNumber' is greater than - // 'sequenceNumberLt' and internal cache is empty. public: // CREATORS @@ -696,12 +696,12 @@ class SearchGuidDecorator : public SearchResultDecorator { class SearchOffsetDecorator : public SearchResultDecorator { private: // PRIVATE DATA + /// List of offsets to search for. bsl::vector d_offsets; - // List of offsets to search for. + /// Reference to output stream. bsl::ostream& d_ostream; - // Reference to output stream. - bool d_withDetails; // If 'true', output detailed result, output short one otherwise. + bool d_withDetails; public: // CREATORS