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"))
setDebugJournalSink (logs->get("Debug"));
{
setDebugLogSink (logs->makeSink (
"Debug", beast::severities::kTrace));
}
auto timeKeeper = make_TimeKeeper(
logs->journal("TimeKeeper"));

View File

@@ -249,18 +249,18 @@ private:
//------------------------------------------------------------------------------
// Debug logging:
/** Returns the debug journal. The journal may drain to a null sink. */
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.
*/
/** Set the sink for the debug journal. */
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

View File

@@ -20,10 +20,14 @@
#include <BeastConfig.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/contract.h>
#include <boost/algorithm/string.hpp>
#include <cassert>
#include <iostream>
#include <fstream>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
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&
debugJournal()
class DebugSink
{
if (!debugJournal_)
debugJournal_ = std::make_unique<beast::Journal>();
private:
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
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

View File

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

View File

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

View File

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

View File

@@ -76,7 +76,7 @@ STArray::STArray (SerialIter& sit, SField const& f)
if ((type == STI_OBJECT) && (field == 1))
{
JLOG (debugJournal().warn()) <<
JLOG (debugLog()) <<
"Encountered array with end of object marker";
Throw<std::runtime_error> ("Illegal terminator in array");
}
@@ -85,14 +85,14 @@ STArray::STArray (SerialIter& sit, SField const& f)
if (fn.isInvalid ())
{
JLOG (debugJournal().trace()) <<
JLOG (debugLog()) <<
"Unknown field: " << type << "/" << field;
Throw<std::runtime_error> ("Unknown field");
}
if (fn.fieldType != STI_OBJECT)
{
JLOG (debugJournal().trace()) <<
JLOG (debugLog()) <<
"Array contains non-object";
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))
return human;
JLOG (debugJournal().warn())
JLOG (debugLog())
<< "Unknown result code in metadata: " << value_;
}
@@ -70,7 +70,7 @@ STUInt8::getJson (int) const
if (transResultInfo (static_cast<TER> (value_), token, human))
return token;
JLOG (debugJournal().warn())
JLOG (debugLog())
<< "Unknown result code in metadata: " << value_;
}

View File

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

View File

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

View File

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

View File

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

View File

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