diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index 985c3b4aff..261fe8fb51 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 21984b45b1..a8c5da8170 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 a9f8e86963..346b25c900 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 3e3a64f220..9255419481 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 b74c7b5712..608f3fbd13 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 6ad42616bf..823284d590 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 1b7c817517..afd4bea0b6 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 aabd8efb13..b533e24d12 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 bff89b9b77..2febd2dc68 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 e3c0be350b..7d2cf71fc0 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 10f7cff772..3caec9eb14 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); }