Skip to content

Commit

Permalink
Merge #13686: ZMQ: Small cleanups in the ZMQ code
Browse files Browse the repository at this point in the history
6fe2ef2 scripted-diff: Rename SendMessage to SendZmqMessage. (Daniel Kraft)
a3ffb6e Replace zmqconfig.h by a simple zmqutil. (Daniel Kraft)
7f2ad1b Use std::unique_ptr for CZMQNotifierFactory. (Daniel Kraft)
b93b9d5 Simplify and fix notifier removal on error. (Daniel Kraft)
e15b1cf Various cleanups in zmqnotificationinterface. (Daniel Kraft)

Pull request description:

  This contains various small code cleanups that make the ZMQ code easier to read and maintain (at least in my opinion).  The only functional change is that a potential memory leak is fixed that would have occured when a notifier is removed from the `notifiers` list after its callback function returned `false` (which is likely not relevant in practice but still a bug).

ACKs for top commit:
  instagibbs:
    utACK 6fe2ef2
  hebasto:
    re-ACK 6fe2ef2, only the latest commit got a scripted-diff since my [previous](bitcoin/bitcoin#13686 (review)) review.

Tree-SHA512: 8206f8713bf3698d7cd4cb235f6657dc1c4dd920f50a8c5f371a559dd17ce5ab6d94d6281165eef860a22fc844a6bb25489ada12c83ebc780efd7ccdc0860f70
  • Loading branch information
fanquake committed Sep 19, 2020
2 parents 83b2384 + 6fe2ef2 commit 831b0ec
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 109 deletions.
7 changes: 4 additions & 3 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,10 @@ BITCOIN_CORE_H = \
walletinitinterface.h \
warnings.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
zmq/zmqpublishnotifier.h \
zmq/zmqrpc.h
zmq/zmqrpc.h \
zmq/zmqutil.h


obj/build.h: FORCE
Expand Down Expand Up @@ -345,7 +345,8 @@ libbitcoin_zmq_a_SOURCES = \
zmq/zmqabstractnotifier.cpp \
zmq/zmqnotificationinterface.cpp \
zmq/zmqpublishnotifier.cpp \
zmq/zmqrpc.cpp
zmq/zmqrpc.cpp \
zmq/zmqutil.cpp
endif


Expand Down
2 changes: 2 additions & 0 deletions src/zmq/zmqabstractnotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <zmq/zmqabstractnotifier.h>

#include <cassert>

const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM;

CZMQAbstractNotifier::~CZMQAbstractNotifier()
Expand Down
12 changes: 8 additions & 4 deletions src/zmq/zmqabstractnotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
#ifndef BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
#define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H

#include <zmq/zmqconfig.h>
#include <util/memory.h>

#include <memory>
#include <string>

class CBlockIndex;
class CTransaction;
class CZMQAbstractNotifier;

typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)();
using CZMQNotifierFactory = std::unique_ptr<CZMQAbstractNotifier> (*)();

class CZMQAbstractNotifier
{
Expand All @@ -21,9 +25,9 @@ class CZMQAbstractNotifier
virtual ~CZMQAbstractNotifier();

template <typename T>
static CZMQAbstractNotifier* Create()
static std::unique_ptr<CZMQAbstractNotifier> Create()
{
return new T();
return MakeUnique<T>();
}

std::string GetType() const { return type; }
Expand Down
22 changes: 0 additions & 22 deletions src/zmq/zmqconfig.h

This file was deleted.

114 changes: 44 additions & 70 deletions src/zmq/zmqnotificationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,77 +4,66 @@

#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqpublishnotifier.h>
#include <zmq/zmqutil.h>

#include <zmq.h>

#include <validation.h>
#include <util/system.h>

void zmqError(const char *str)
{
LogPrint(BCLog::ZMQ, "zmq: Error: %s, errno=%s\n", str, zmq_strerror(errno));
}

CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(nullptr)
{
}

CZMQNotificationInterface::~CZMQNotificationInterface()
{
Shutdown();

for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
{
delete *i;
}
}

std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
{
std::list<const CZMQAbstractNotifier*> result;
for (const auto* n : notifiers) {
result.push_back(n);
for (const auto& n : notifiers) {
result.push_back(n.get());
}
return result;
}

CZMQNotificationInterface* CZMQNotificationInterface::Create()
{
CZMQNotificationInterface* notificationInterface = nullptr;
std::map<std::string, CZMQNotifierFactory> factories;
std::list<CZMQAbstractNotifier*> notifiers;

factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;

std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
for (const auto& entry : factories)
{
std::string arg("-zmq" + entry.first);
if (gArgs.IsArgSet(arg))
{
CZMQNotifierFactory factory = entry.second;
std::string address = gArgs.GetArg(arg, "");
CZMQAbstractNotifier *notifier = factory();
const auto& factory = entry.second;
const std::string address = gArgs.GetArg(arg, "");
std::unique_ptr<CZMQAbstractNotifier> notifier = factory();
notifier->SetType(entry.first);
notifier->SetAddress(address);
notifier->SetOutboundMessageHighWaterMark(static_cast<int>(gArgs.GetArg(arg + "hwm", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM)));
notifiers.push_back(notifier);
notifiers.push_back(std::move(notifier));
}
}

if (!notifiers.empty())
{
notificationInterface = new CZMQNotificationInterface();
notificationInterface->notifiers = notifiers;
std::unique_ptr<CZMQNotificationInterface> notificationInterface(new CZMQNotificationInterface());
notificationInterface->notifiers = std::move(notifiers);

if (!notificationInterface->Initialize())
{
delete notificationInterface;
notificationInterface = nullptr;
if (notificationInterface->Initialize()) {
return notificationInterface.release();
}
}

return notificationInterface;
return nullptr;
}

// Called at startup to conditionally set up ZMQ socket(s)
Expand All @@ -95,26 +84,15 @@ bool CZMQNotificationInterface::Initialize()
return false;
}

std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin();
for (; i!=notifiers.end(); ++i)
{
CZMQAbstractNotifier *notifier = *i;
if (notifier->Initialize(pcontext))
{
for (auto& notifier : notifiers) {
if (notifier->Initialize(pcontext)) {
LogPrint(BCLog::ZMQ, "zmq: Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
}
else
{
} else {
LogPrint(BCLog::ZMQ, "zmq: Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
break;
return false;
}
}

if (i!=notifiers.end())
{
return false;
}

return true;
}

Expand All @@ -124,9 +102,7 @@ void CZMQNotificationInterface::Shutdown()
LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n");
if (pcontext)
{
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
{
CZMQAbstractNotifier *notifier = *i;
for (auto& notifier : notifiers) {
LogPrint(BCLog::ZMQ, "zmq: Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
notifier->Shutdown();
}
Expand All @@ -136,45 +112,43 @@ void CZMQNotificationInterface::Shutdown()
}
}

void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
return;
namespace {

for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
{
CZMQAbstractNotifier *notifier = *i;
if (notifier->NotifyBlock(pindexNew))
{
i++;
}
else
{
template <typename Function>
void TryForEachAndRemoveFailed(std::list<std::unique_ptr<CZMQAbstractNotifier>>& notifiers, const Function& func)
{
for (auto i = notifiers.begin(); i != notifiers.end(); ) {
CZMQAbstractNotifier* notifier = i->get();
if (func(notifier)) {
++i;
} else {
notifier->Shutdown();
i = notifiers.erase(i);
}
}
}

} // anonymous namespace

void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
return;

TryForEachAndRemoveFailed(notifiers, [pindexNew](CZMQAbstractNotifier* notifier) {
return notifier->NotifyBlock(pindexNew);
});
}

void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx)
{
// Used by BlockConnected and BlockDisconnected as well, because they're
// all the same external callback.
const CTransaction& tx = *ptx;

for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
{
CZMQAbstractNotifier *notifier = *i;
if (notifier->NotifyTransaction(tx))
{
i++;
}
else
{
notifier->Shutdown();
i = notifiers.erase(i);
}
}
TryForEachAndRemoveFailed(notifiers, [&tx](CZMQAbstractNotifier* notifier) {
return notifier->NotifyTransaction(tx);
});
}

void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected)
Expand Down
3 changes: 2 additions & 1 deletion src/zmq/zmqnotificationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <validationinterface.h>
#include <list>
#include <memory>

class CBlockIndex;
class CZMQAbstractNotifier;
Expand Down Expand Up @@ -34,7 +35,7 @@ class CZMQNotificationInterface final : public CValidationInterface
CZMQNotificationInterface();

void *pcontext;
std::list<CZMQAbstractNotifier*> notifiers;
std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
};

extern CZMQNotificationInterface* g_zmq_notification_interface;
Expand Down
26 changes: 18 additions & 8 deletions src/zmq/zmqpublishnotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <zmq/zmqpublishnotifier.h>

#include <chain.h>
#include <chainparams.h>
#include <rpc/server.h>
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
#include <util/system.h>
#include <rpc/server.h>
#include <validation.h>
#include <zmq/zmqutil.h>

#include <zmq.h>

#include <cstdarg>
#include <cstddef>
#include <map>
#include <string>
#include <utility>

static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;

Expand Down Expand Up @@ -149,7 +159,7 @@ void CZMQAbstractPublishNotifier::Shutdown()
psocket = nullptr;
}

bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
bool CZMQAbstractPublishNotifier::SendZmqMessage(const char *command, const void* data, size_t size)
{
assert(psocket);

Expand All @@ -173,7 +183,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
char data[32];
for (unsigned int i = 0; i < 32; i++)
data[31 - i] = hash.begin()[i];
return SendMessage(MSG_HASHBLOCK, data, 32);
return SendZmqMessage(MSG_HASHBLOCK, data, 32);
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
Expand All @@ -183,7 +193,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
char data[32];
for (unsigned int i = 0; i < 32; i++)
data[31 - i] = hash.begin()[i];
return SendMessage(MSG_HASHTX, data, 32);
return SendZmqMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
Expand All @@ -204,7 +214,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
ss << block;
}

return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
return SendZmqMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
Expand All @@ -213,5 +223,5 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ss << transaction;
return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
return SendZmqMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}
2 changes: 1 addition & 1 deletion src/zmq/zmqpublishnotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
* data
* message sequence number
*/
bool SendMessage(const char *command, const void* data, size_t size);
bool SendZmqMessage(const char *command, const void* data, size_t size);

bool Initialize(void *pcontext) override;
void Shutdown() override;
Expand Down
Loading

0 comments on commit 831b0ec

Please sign in to comment.