Serialize access to the debug journal

This commit is contained in:
Nik Bougalis
2016-05-19 00:39:19 -07:00
parent acebbf58eb
commit a039e7593a
13 changed files with 99 additions and 43 deletions

View File

@@ -465,7 +465,10 @@ int run (int argc, char** argv)
} }
if (vm.count ("debug")) if (vm.count ("debug"))
setDebugJournalSink (logs->get("Debug")); {
setDebugLogSink (logs->makeSink (
"Debug", beast::severities::kTrace));
}
auto timeKeeper = make_TimeKeeper( auto timeKeeper = make_TimeKeeper(
logs->journal("TimeKeeper")); logs->journal("TimeKeeper"));

View File

@@ -249,18 +249,18 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Debug logging: // Debug logging:
/** Returns the debug journal. The journal may drain to a null sink. */ /** Set the sink for the debug journal. */
beast::Journal const&
debugJournal();
/** Set the sink for the debug journal
This operation is not thread safe and should only be called
from a controlled context, when no other threads are in a
call to debugJournal.
*/
void void
setDebugJournalSink(beast::Journal::Sink& sink); setDebugLogSink(
std::unique_ptr<beast::Journal::Sink> sink);
/** Returns a debug journal.
The journal may drain to a null sink, so its output
may never be seen. Never use it for critical
information.
*/
beast::Journal::Stream
debugLog();
} // ripple } // ripple

View File

@@ -20,10 +20,14 @@
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/basics/chrono.h> #include <ripple/basics/chrono.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/basics/contract.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <cassert> #include <cassert>
#include <iostream>
#include <fstream> #include <fstream>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
namespace ripple { namespace ripple {
@@ -340,21 +344,66 @@ Logs::format (std::string& output, std::string const& message,
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static std::unique_ptr<beast::Journal> debugJournal_;
beast::Journal const& class DebugSink
debugJournal()
{ {
if (!debugJournal_) private:
debugJournal_ = std::make_unique<beast::Journal>(); std::reference_wrapper<beast::Journal::Sink> sink_;
std::unique_ptr<beast::Journal::Sink> holder_;
std::mutex m_;
return *debugJournal_; public:
DebugSink ()
: sink_ (beast::Journal::getNullSink())
{
}
DebugSink (DebugSink const&) = delete;
DebugSink& operator=(DebugSink const&) = delete;
DebugSink(DebugSink&&) = delete;
DebugSink& operator=(DebugSink&&) = delete;
void
set(std::unique_ptr<beast::Journal::Sink> sink)
{
std::lock_guard<std::mutex> _(m_);
holder_ = std::move(sink);
if (holder_)
sink_ = *holder_;
else
sink_ = beast::Journal::getNullSink();
}
beast::Journal::Sink&
get()
{
std::lock_guard<std::mutex> _(m_);
return sink_.get();
}
};
static
DebugSink&
debugSink()
{
static DebugSink _;
return _;
} }
void void
setDebugJournalSink(beast::Journal::Sink& sink) setDebugLogSink(
std::unique_ptr<beast::Journal::Sink> sink)
{ {
debugJournal_ = std::make_unique<beast::Journal>(sink); debugSink().set(std::move(sink));
}
beast::Journal::Stream
debugLog()
{
return { debugSink().get() };
} }
} // ripple } // ripple

View File

@@ -176,8 +176,13 @@ public:
public: public:
/** Create a stream which produces no output. */ /** Create a stream which produces no output. */
Stream () Stream ()
: m_sink (getNullSink()) : m_sink (getNullSink())
, m_level (severities::kDisabled) , m_level (severities::kDisabled)
{ }
Stream (Sink& sink)
: m_sink (sink)
, m_level (sink.threshold())
{ } { }
/** Create stream that writes at the given level. /** Create stream that writes at the given level.
@@ -194,7 +199,7 @@ public:
/** Construct or copy another Stream. */ /** Construct or copy another Stream. */
Stream (Stream const& other) Stream (Stream const& other)
: Stream (other.m_sink, other.m_level) : Stream (other.m_sink, other.m_level)
{ } { }
Stream& operator= (Stream const& other) = delete; Stream& operator= (Stream const& other) = delete;

View File

@@ -52,7 +52,7 @@ T rangeCheckedCast (C c)
std::numeric_limits<C>::is_signed && std::numeric_limits<C>::is_signed &&
c < std::numeric_limits<T>::lowest ())) c < std::numeric_limits<T>::lowest ()))
{ {
JLOG (debugJournal().error()) << "rangeCheckedCast domain error:" JLOG (debugLog()) << "rangeCheckedCast domain error:"
<< " value = " << c << " value = " << c
<< " min = " << std::numeric_limits<T>::lowest () << " min = " << std::numeric_limits<T>::lowest ()
<< " max: " << std::numeric_limits<T>::max (); << " max: " << std::numeric_limits<T>::max ();

View File

@@ -915,7 +915,7 @@ amountFromJsonNoThrow (STAmount& result, Json::Value const& jvSource)
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
JLOG (debugJournal().debug()) << JLOG (debugLog()) <<
"amountFromJsonNoThrow: caught: " << e.what (); "amountFromJsonNoThrow: caught: " << e.what ();
} }
return false; return false;

View File

@@ -76,7 +76,7 @@ STArray::STArray (SerialIter& sit, SField const& f)
if ((type == STI_OBJECT) && (field == 1)) if ((type == STI_OBJECT) && (field == 1))
{ {
JLOG (debugJournal().warn()) << JLOG (debugLog()) <<
"Encountered array with end of object marker"; "Encountered array with end of object marker";
Throw<std::runtime_error> ("Illegal terminator in array"); Throw<std::runtime_error> ("Illegal terminator in array");
} }
@@ -85,14 +85,14 @@ STArray::STArray (SerialIter& sit, SField const& f)
if (fn.isInvalid ()) if (fn.isInvalid ())
{ {
JLOG (debugJournal().trace()) << JLOG (debugLog()) <<
"Unknown field: " << type << "/" << field; "Unknown field: " << type << "/" << field;
Throw<std::runtime_error> ("Unknown field"); Throw<std::runtime_error> ("Unknown field");
} }
if (fn.fieldType != STI_OBJECT) if (fn.fieldType != STI_OBJECT)
{ {
JLOG (debugJournal().trace()) << JLOG (debugLog()) <<
"Array contains non-object"; "Array contains non-object";
Throw<std::runtime_error> ("Non-object in array"); Throw<std::runtime_error> ("Non-object in array");
} }

View File

@@ -52,7 +52,7 @@ STUInt8::getText () const
if (transResultInfo (static_cast<TER> (value_), token, human)) if (transResultInfo (static_cast<TER> (value_), token, human))
return human; return human;
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "Unknown result code in metadata: " << value_; << "Unknown result code in metadata: " << value_;
} }
@@ -70,7 +70,7 @@ STUInt8::getJson (int) const
if (transResultInfo (static_cast<TER> (value_), token, human)) if (transResultInfo (static_cast<TER> (value_), token, human))
return token; return token;
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "Unknown result code in metadata: " << value_; << "Unknown result code in metadata: " << value_;
} }

View File

@@ -78,7 +78,7 @@ void STLedgerEntry::setSLEType ()
type_ = mFormat->getType (); type_ = mFormat->getType ();
if (!setType (mFormat->elements)) if (!setType (mFormat->elements))
{ {
if (auto j = debugJournal().warn()) if (auto j = debugLog())
{ {
j << "Ledger entry not valid for type " << mFormat->getName (); j << "Ledger entry not valid for type " << mFormat->getName ();
j << "Object: " << getJson (0); j << "Object: " << getJson (0);
@@ -141,7 +141,7 @@ bool STLedgerEntry::thread (uint256 const& txID, std::uint32_t ledgerSeq,
{ {
uint256 oldPrevTxID = getFieldH256 (sfPreviousTxnID); uint256 oldPrevTxID = getFieldH256 (sfPreviousTxnID);
JLOG (debugJournal().trace()) JLOG (debugLog())
<< "Thread Tx:" << txID << " prev:" << oldPrevTxID; << "Thread Tx:" << txID << " prev:" << oldPrevTxID;
if (oldPrevTxID == txID) if (oldPrevTxID == txID)

View File

@@ -113,7 +113,7 @@ bool STObject::setType (const SOTemplate& type)
{ {
if ((e->flags == SOE_DEFAULT) && iter->get().isDefault()) if ((e->flags == SOE_DEFAULT) && iter->get().isDefault())
{ {
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "setType(" << getFName().getName() << "setType(" << getFName().getName()
<< "): explicit default " << e->e_field.fieldName; << "): explicit default " << e->e_field.fieldName;
valid = false; valid = false;
@@ -125,7 +125,7 @@ bool STObject::setType (const SOTemplate& type)
{ {
if (e->flags == SOE_REQUIRED) if (e->flags == SOE_REQUIRED)
{ {
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "setType(" << getFName().getName() << "setType(" << getFName().getName()
<< "): missing " << e->e_field.fieldName; << "): missing " << e->e_field.fieldName;
valid = false; valid = false;
@@ -138,7 +138,7 @@ bool STObject::setType (const SOTemplate& type)
// Anything left over in the object must be discardable // Anything left over in the object must be discardable
if (! e->getFName().isDiscardable()) if (! e->getFName().isDiscardable())
{ {
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "setType(" << getFName().getName() << "setType(" << getFName().getName()
<< "): non-discardable leftover " << e->getFName().getName (); << "): non-discardable leftover " << e->getFName().getName ();
valid = false; valid = false;
@@ -208,7 +208,7 @@ bool STObject::set (SerialIter& sit, int depth)
if ((type == STI_ARRAY) && (field == 1)) if ((type == STI_ARRAY) && (field == 1))
{ {
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "Encountered object with end of array marker"; << "Encountered object with end of array marker";
Throw<std::runtime_error> ("Illegal terminator in object"); Throw<std::runtime_error> ("Illegal terminator in object");
} }
@@ -221,7 +221,7 @@ bool STObject::set (SerialIter& sit, int depth)
if (fn.isInvalid ()) if (fn.isInvalid ())
{ {
JLOG (debugJournal().warn()) JLOG (debugLog())
<< "Unknown field: field_type=" << type << "Unknown field: field_type=" << type
<< ", field_name=" << field; << ", field_name=" << field;
Throw<std::runtime_error> ("Unknown field"); Throw<std::runtime_error> ("Unknown field");

View File

@@ -64,7 +64,7 @@ STPathSet::STPathSet (SerialIter& sit, SField const& name)
{ {
if (path.empty ()) if (path.empty ())
{ {
JLOG (debugJournal().info()) JLOG (debugLog())
<< "Empty path in pathset"; << "Empty path in pathset";
Throw<std::runtime_error> ("empty path"); Throw<std::runtime_error> ("empty path");
} }
@@ -77,7 +77,7 @@ STPathSet::STPathSet (SerialIter& sit, SField const& name)
} }
else if (iType & ~STPathElement::typeAll) else if (iType & ~STPathElement::typeAll)
{ {
JLOG (debugJournal().info()) JLOG (debugLog())
<< "Bad path element " << iType << " in pathset"; << "Bad path element " << iType << " in pathset";
Throw<std::runtime_error> ("bad path element"); Throw<std::runtime_error> ("bad path element");
} }

View File

@@ -35,7 +35,7 @@ STValidation::STValidation (SerialIter& sit, bool checkSignature)
if (checkSignature && !isValid ()) if (checkSignature && !isValid ())
{ {
JLOG (debugJournal().trace()) JLOG (debugLog())
<< "Invalid validation" << getJson (0); << "Invalid validation" << getJson (0);
Throw<std::runtime_error> ("Invalid validation"); Throw<std::runtime_error> ("Invalid validation");
} }
@@ -113,7 +113,7 @@ bool STValidation::isValid (uint256 const& signingHash) const
} }
catch (std::exception const&) catch (std::exception const&)
{ {
JLOG (debugJournal().info()) JLOG (debugLog())
<< "Exception validating validation"; << "Exception validating validation";
return false; return false;
} }

View File

@@ -53,7 +53,6 @@ public:
bool plainOnly) bool plainOnly)
: mSecure (secureOnly) : mSecure (secureOnly)
, mBuffer ((plainOnly || secureOnly) ? 0 : 4) , mBuffer ((plainOnly || secureOnly) ? 0 : 4)
, j_ (ripple::debugJournal())
{ {
mSocket = std::make_unique<ssl_socket> (s, c); mSocket = std::make_unique<ssl_socket> (s, c);
} }