-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhance bmqtool to handle poison pill message dumps #288
Conversation
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
…nto poisonpill
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
@@ -474,11 +578,8 @@ void Interactive::processCommand(const PostCommand& command, bool hasMPs) | |||
|
|||
if (hasMPs) { | |||
d_session_p->loadMessageProperties(&properties); | |||
|
|||
for (size_t j = 0; j < command.messageProperties().size(); ++j) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand what is the purpose of this for
cycle. Inside InputUtil::populateProperties() there is also for
cycle which is used to process properties. Removed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments
@@ -149,11 +150,55 @@ void InputUtil::populateProperties( | |||
BSLS_ASSERT_SAFE(0 == result); | |||
} break; // BREAK | |||
|
|||
case MessagePropertyType::E_INT: { | |||
case MessagePropertyType::E_INT32: { | |||
BSLA_MAYBE_UNUSED int result = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, and in other places:
BSLA_MAYBE_UNUSED int result = | |
BSLA_MAYBE_UNUSED const int result = |
@@ -149,11 +150,55 @@ void InputUtil::populateProperties( | |||
BSLS_ASSERT_SAFE(0 == result); | |||
} break; // BREAK | |||
|
|||
case MessagePropertyType::E_INT: { | |||
case MessagePropertyType::E_INT32: { | |||
BSLA_MAYBE_UNUSED int result = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be also good to replace result
-> rc
to make it shorter and easier everywhere
|
||
case MessagePropertyType::E_BOOL: { | ||
bool boolValue; | ||
bsl::istringstream(value) >> bsl::boolalpha >> boolValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 166: uninitialized bool
Line 167: try to read bool value without check that the read reads something
Line 168: setting possibly random value of this bool as property
Maybe something like this will work:
bsl::stringstream iss(value);
BSLA_MAYBE_UNUSED const bool readSuccess = (iss >> bsl::boolalpha >> boolValue);
BSLS_ASSERT(readSuccess);
...
@@ -149,11 +150,55 @@ void InputUtil::populateProperties( | |||
BSLS_ASSERT_SAFE(0 == result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think BSLS_ASSERT_SAFE
is not enough here, since we deal with user provided data here. When compiled as Release, we still want to have these values checks.
Consider using BSLS_ASSERT
instead
@@ -80,6 +88,13 @@ struct InputUtil { | |||
bsl::string* error, | |||
const bsl::string& jsonInput); | |||
|
|||
/// Decode hexdump produced by bdlb::Print::hexDump() into binary format. | |||
/// Read hexdump from the specified `in` and write binary into th specified |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Read hexdump from the specified `in` and write binary into th specified | |
/// Read hexdump from the specified `in` and write binary into the specified |
bool loadMessageContentFromFile( | ||
bsl::vector<bsl::string>* payload, | ||
bsl::vector<MessageProperty>* messageProperties, | ||
bsl::ostream& errorDescription, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In some places, bsl::string *
is passed to return error messages, here bsl::ostream
.
Might be good to unify it. I believe passing bsl::ostream
might be better, since it will be easier to output variable parameters like tokens, strings etc without intermediate mwcu::MemOutStream
. What do you think?
&parseError)) { | ||
errorDescription << "Message properties parse error: " | ||
<< parseError; | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, and in other places below
return false; | |
return false; // RETURN |
@@ -900,7 +1027,15 @@ int Interactive::mainLoop() | |||
if (mps) { | |||
hasMPs = keys.find(mps->name()) != keys.cend(); | |||
} | |||
processCommand(command, hasMPs); | |||
|
|||
bool commandValid = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool commandValid = true; | |
bool commandIsValid = true; |
} | ||
if (commandValid) { | ||
processCommand(command, hasMPs); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we log something if the command is not valid?
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
@678098 What do you think about the following idea. To avoid reinventing the wheel during dump/parse message properties and keep existing functionality (human readable text) we can add properties hexdump using existing functionality:
In this case we keep dump file human readable (just one more hexdump will be added) and no need to create new format of properties dump. Below is simplified prototype // During message dump add properties hexdump
bdlbb::PooledBlobBufferFactory bufferFactory(1024);
const bdlbb::Blob& blob = properties.streamOut(&bufferFactory);
dumpFileStream << bdlbb::BlobUtilHexDumper(&blob);
// When reading dump from the file
mwcu::MemOutStream binaryStream;
bsl::istringstream inpStream(hexdumpStream.str());
InputUtil::decodeHexDump(&binaryStream, inpStream)
bdlbb::Blob resultBlob(&bufferFactory);
bdlbb::BlobUtil::append(&resultBlob, binaryStream.str().data(), binaryStream.str().length());
bmqa::MessageProperties properties;
properties.streamIn(resultBlob); |
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
@678098 Would you please look again, I've rolled back previous solution and implemented new one, also added unit tests. Thank you. |
Hi @alexander-e1off, thanks for the changes! Will look soon |
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, a few smaller suggestions
<element name='uri' type='string'/> | ||
<element name='file' type='string'/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<element name='uri' type='string'/> | |
<element name='file' type='string'/> | |
<element name='uri' type='string'/> | |
<element name='file' type='string'/> |
|
||
while (bsl::getline(in, line)) { | ||
if (line.empty()) { | ||
break; // stop at the end of hexdump (empty line) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
break; // stop at the end of hexdump (empty line) | |
// stop at the end of hexdump (empty line) | |
break; // BREAK |
bsl::istream& in, | ||
bslma::Allocator* allocator); | ||
|
||
/// Load message content from the specified `file` (created by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Load message content from the specified `file` (created by | |
/// Load message content from the specified `filePath` (created by |
// BMQ | ||
#include <bdlbb_pooledblobbufferfactory.h> | ||
#include <bmqa_messageproperties.h> | ||
#include <mwcu_memoutstream.h> | ||
#include <mwcu_tempfile.h> | ||
|
||
// BDE | ||
#include <bdlbb_blob.h> | ||
#include <bdlbb_blobutil.h> | ||
|
||
// TEST DRIVER | ||
#include <mwctst_testhelper.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// BMQ | |
#include <bdlbb_pooledblobbufferfactory.h> | |
#include <bmqa_messageproperties.h> | |
#include <mwcu_memoutstream.h> | |
#include <mwcu_tempfile.h> | |
// BDE | |
#include <bdlbb_blob.h> | |
#include <bdlbb_blobutil.h> | |
// TEST DRIVER | |
#include <mwctst_testhelper.h> | |
// BMQ | |
#include <bmqa_messageproperties.h> | |
// MWC | |
#include <mwcu_memoutstream.h> | |
#include <mwcu_tempfile.h> | |
// BDE | |
#include <bdlbb_blob.h> | |
#include <bdlbb_blobutil.h> | |
#include <bdlbb_pooledblobbufferfactory.h> | |
// TEST DRIVER | |
#include <mwctst_testhelper.h> |
@@ -159,6 +159,12 @@ void Interactive::printHelp() | |||
<< " - 'batch-post' command requires 'uri' argument, " | |||
"all the rest are optional" | |||
<< bsl::endl | |||
<< bsl::endl | |||
<< " load-post uri=\"bmq://bmq.test.persistent.priority/qqq\" " | |||
"file=[\"message.dump\"]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to specify file path in []
brackets? It is the same string type as uri, right?
|
||
BALL_LOG_INFO << "--> Loading and posting message: " << command; | ||
|
||
int rc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be moved and const initialized in place below
int rc; |
} | ||
|
||
// Post | ||
rc = d_session_p->post(eventBuilder.messageEvent()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rc = d_session_p->post(eventBuilder.messageEvent()); | |
const int rc = d_session_p->post(eventBuilder.messageEvent()); |
Signed-off-by: Aleksandr Ivanov <aivanov71@bloomberg.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Enhance
bmqtool
to add ability to read and replay thepoison pill
message dumped in the file by the broker, so that consumers can debug their applications.Proposed changes
Format of the dump file is defined in QueueEngineUtil::dumpMessageInTempfile() method. Since message properties are dumped as a string, it is impossible to parse them properly. Thus, it is proposed to enhance dump, and add properties hexdump (similar way as payload).
Add new command to
bmqtool
:load-post uri=<uri> file=<path-to-dump-file>
Message content is loaded from dump file and posted to the specified uri.
Testing performed
Unit tests for parsing of dump file are added.
Manually with bmqtool simulated poison pill conditions and created dumps with and w/o message properties. Then tested these dumps with
load-post
commands.