Skip to content

Commit

Permalink
Feat[Storagetool]: Add searching by record sequence numbers and offse…
Browse files Browse the repository at this point in the history
…ts (#508)

Signed-off-by: Alexander Ivanov <[email protected]>
  • Loading branch information
alexander-e1off authored Dec 20, 2024
1 parent 5a6670d commit 6b34d52
Show file tree
Hide file tree
Showing 18 changed files with 2,107 additions and 132 deletions.
52 changes: 52 additions & 0 deletions src/applications/bmqstoragetool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ Usage: bmqstoragetool [--journal-path <journal path>]
[--data-file <data file>]
[--csl-file <csl file>]
[--guid <guid>]*
[--seqnum <seqnum>]*
[--offset <offset>]*
[--queue-name <queue name>]*
[--queue-key <queue key>]*
[--timestamp-gt <timestamp greater than>]
[--timestamp-lt <timestamp less than>]
[--seqnum-gt <composite sequence number greater than>]
[--seqnum-lt <composite sequence number less than>]
[--offset-gt <offset greater than>]
[--offset-lt <offset less than>]
[--outstanding]
[--confirmed]
[--partially-confirmed]
Expand All @@ -42,6 +48,10 @@ Where:
path to a .bmq_csl file
--guid <guid>
message guid
--seqnum <seqnum>
message composite sequence number
--offset <offset>
message offset
--queue-name <queue name>
message queue name
--queue-key <queue key>
Expand All @@ -50,6 +60,14 @@ Where:
lower timestamp bound
--timestamp-lt <timestamp less than>
higher timestamp bound
--seqnum-gt <composite sequence number greater than>
lower composite sequence number bound, defined in form <leaseId-sequenceNumber>, e.g. 123-456
--seqnum-lt <composite sequence number less than>
higher composite sequence number bound, defined in form <leaseId-sequenceNumber>, e.g. 123-456
--offset-gt <offset greater than>
lower offset bound
--offset-lt <offset less than>
higher offset bound
--outstanding
show only outstanding (not deleted) messages
--confirmed
Expand Down Expand Up @@ -122,6 +140,22 @@ bmqstoragetool --journal-file=<path> --guid=<guid_1> --guid=<guid_N>
```
NOTE: no other filters are allowed with this one
Filter messages with corresponding composite sequence numbers (defined in form <primaryLeaseId-sequenceNumber>)
---------------------------------------------------------------------------------------------------------------
Example:
```bash
bmqstoragetool --journal-file=<path> --seqnum=<leaseId-sequenceNumber_1> --seqnum=<leaseId-sequenceNumber_N>
```
NOTE: no other filters are allowed with this one
Filter messages with corresponding record offsets
-------------------------------------------------
Example:
```bash
bmqstoragetool --journal-file=<path> --offset=<offset_1> --offset=<offset_N>
```
NOTE: no other filters are allowed with this one
Filter messages within time range
---------------------------------
Example:
Expand All @@ -131,6 +165,24 @@ bmqstoragetool --journal-file=<path> --timestamp-gt=<stamp>
bmqstoragetool --journal-file=<path> --timestamp-lt=<stamp1> --timestamp-gt=<stamp2>
```
Filter messages within composite sequence numbers (primaryLeaseId, sequenceNumber) range
----------------------------------------------------------------------------------------
Example:
```bash
bmqstoragetool --journal-file=<path> --seqnum-lt=<leaseId-sequenceNumber>
bmqstoragetool --journal-file=<path> --seqnum-gt=<leaseId-sequenceNumber>
bmqstoragetool --journal-file=<path> --seqnum-lt=<leaseId1-sequenceNumber1> --seqnum-gt=<leaseId2-sequenceNumber2>
```
Filter messages within record offsets range
-------------------------------------------
Example:
```bash
bmqstoragetool --journal-file=<path> --offset-lt=<offset>
bmqstoragetool --journal-file=<path> --offset-gt=<offset>
bmqstoragetool --journal-file=<path> --offset-lt=<offset1> --offset-gt=<offset2>
```
Filter messages by queue key
----------------------------
Example:
Expand Down
42 changes: 38 additions & 4 deletions src/applications/bmqstoragetool/bmqstoragetool.m.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
using namespace BloombergLP;
using namespace m_bmqstoragetool;

static bool
parseArgs(CommandLineArguments& arguments, int argc, const char* argv[])
static bool parseArgs(CommandLineArguments& arguments,
int argc,
const char* argv[],
bslma::Allocator* allocator)
{
bool showHelp = false;

Expand Down Expand Up @@ -62,6 +64,16 @@ parseArgs(CommandLineArguments& arguments, int argc, const char* argv[])
"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",
Expand All @@ -82,6 +94,28 @@ parseArgs(CommandLineArguments& arguments, int argc, const char* argv[])
"higher timestamp bound",
balcl::TypeInfo(&arguments.d_timestampLt),
balcl::OccurrenceInfo::e_OPTIONAL},
{"seqnum-gt",
"message composite sequence number greater than",
"lower record sequence number bound, defined in form "
"<leaseId-sequenceNumber>",
balcl::TypeInfo(&arguments.d_seqNumGt),
balcl::OccurrenceInfo::e_OPTIONAL},
{"seqnum-lt",
"message composite sequence number less than",
"higher sequence number bound, defined in form "
"<leaseId-sequenceNumber>",
balcl::TypeInfo(&arguments.d_seqNumLt),
balcl::OccurrenceInfo::e_OPTIONAL},
{"offset-gt",
"message offset greater than",
"lower record offset bound",
balcl::TypeInfo(&arguments.d_offsetGt),
balcl::OccurrenceInfo::e_OPTIONAL},
{"offset-lt",
"message 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",
Expand Down Expand Up @@ -130,7 +164,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
}
Expand All @@ -157,7 +191,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
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// 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 <m_bmqstoragetool_compositesequencenumber.h>

// BDE
#include <bdlb_print.h>
#include <bsl_stdexcept.h>

namespace BloombergLP {
namespace m_bmqstoragetool {

// =============================
// class CompositeSequenceNumber
// =============================

CompositeSequenceNumber::CompositeSequenceNumber()
: d_leaseId(0)
, d_seqNumber(0)
, d_isSet(false)
{
// 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_isSet = d_leaseId > 0 && d_seqNumber > 0;
}

CompositeSequenceNumber&
CompositeSequenceNumber::fromString(bsl::ostream& errorDescription,
const bsl::string& seqNumString)
{
d_isSet = false;

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
const bsl::string firstPart = seqNumString.substr(0, separatorPos);
const 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(""); // THROW
}

d_leaseId = static_cast<unsigned int>(uLong);
if (uLong != d_leaseId) {
throw bsl::out_of_range(""); // THROW
}

if (d_leaseId == 0 || d_seqNumber == 0) {
errorDescription << "Invalid input: zero values encountered.";
return *this; // RETURN
}

d_isSet = true;
}
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 (isSet()) {
stream << "leaseId: " << leaseId()
<< ", sequenceNumber: " << sequenceNumber();
}
else {
stream << "** UNSET **";
}

if (spacesPerLevel >= 0) {
stream << '\n';
}

return stream;
}

} // close package namespace
} // close enterprise namespace
Loading

0 comments on commit 6b34d52

Please sign in to comment.