From 2c02580c379afa52302a1c3e6c36dfc60de3b83d Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 7 Oct 2013 13:26:56 -0700 Subject: [PATCH] Add PropertyStream for server state introspection --- beast/utility/PropertyStream.h | 309 ++++++++++-------- beast/utility/impl/PropertyStream.cpp | 440 +++++++++++++++----------- 2 files changed, 420 insertions(+), 329 deletions(-) diff --git a/beast/utility/PropertyStream.h b/beast/utility/PropertyStream.h index d5181ff2ba..6e46198917 100644 --- a/beast/utility/PropertyStream.h +++ b/beast/utility/PropertyStream.h @@ -26,182 +26,184 @@ #include "../threads/SharedData.h" #include +#include namespace beast { -/** An output stream to procedurally generate an abstract property tree. */ +//------------------------------------------------------------------------------ + +/** Abstract stream with RAII containers that produce a property tree. */ class PropertyStream { -private: - class Proxy; - public: - class ScopedArray; - class ScopedObject; + class Map; + class Set; class Source; -private: - class Item : public List ::Node - { - public: - explicit Item (Source* source); - Source& source() const; - Source* operator-> () const; - Source& operator* () const; - private: - Source* m_source; - }; - -public: - //-------------------------------------------------------------------------- - - class Sink : Uncopyable - { - public: - // Object output - // - // Default implementations convert to string - // Json doesn't support 64 bit so we convert these to string - // if they are outside the range of the corresponding 32 bit int - virtual void begin_object (std::string const& key) = 0; - virtual void end_object () = 0; - template - void lexical_write (std::string const &key, Value value) - { - std::stringstream ss; - ss << value; - write (key, ss.str()); - } - virtual void write (std::string const& key, int32 value); - virtual void write (std::string const& key, uint32 value); - virtual void write (std::string const& key, int64 value); - virtual void write (std::string const& key, uint64 value); - virtual void write (std::string const& key, std::string const& value) = 0; - - // Array output - // - virtual void begin_array (std::string const& key) = 0; - virtual void end_array () = 0; - template - void lexical_write (Value value) - { - std::stringstream ss; - ss << value; - write (ss.str()); - } - virtual void write ( int32 value); - virtual void write (uint32 value); - virtual void write ( int64 value); - virtual void write (uint64 value); - virtual void write (std::string const& value) = 0; - }; - - //-------------------------------------------------------------------------- - PropertyStream (); - PropertyStream (Sink& sink); - PropertyStream (PropertyStream const& other); - PropertyStream& operator= (PropertyStream const& other); + virtual ~PropertyStream (); - /** Object output. - */ - /** @{ */ - void begin_object (std::string const& key) const; - void end_object () const; +protected: + virtual void map_begin () = 0; + virtual void map_begin (std::string const& key) = 0; + virtual void map_end () = 0; + + virtual void add (std::string const& key, std::string const& value) = 0; template - void write (std::string const& key, Value value) const - { - m_sink->write (key, value); - } - - template - void write (Key key, Value value) const + void lexical_add (std::string const &key, Value value) { std::stringstream ss; - ss << key; - write (ss.str(), value); + ss << value; + add (key, ss.str()); } + virtual void add (std::string const& key, int32 value); + virtual void add (std::string const& key, uint32 value); + virtual void add (std::string const& key, int64 value); + virtual void add (std::string const& key, uint64 value); - Proxy operator[] (std::string const& key) const; + virtual void array_begin () = 0; + virtual void array_begin (std::string const& key) = 0; + virtual void array_end () = 0; - template - Proxy operator[] (Key key) const; - - /** @} */ - - /** Array output. - */ - /** @{ */ - void begin_array (std::string const& key) const; - void end_array () const; + virtual void add (std::string const& value) = 0; template - void append (Value value) const - { m_sink->write (value); } - - template - PropertyStream const& operator<< (Value value) const - { append (value); return *this; } - /** @} */ + void lexical_add (Value value) + { + std::stringstream ss; + ss << value; + add (ss.str()); + } + virtual void add ( int32 value); + virtual void add (uint32 value); + virtual void add ( int64 value); + virtual void add (uint64 value); private: - static Sink& nullSink(); - - Sink* m_sink; + class Item; + class Proxy; }; //------------------------------------------------------------------------------ +// +// Item +// + +class PropertyStream::Item : public List ::Node +{ +public: + explicit Item (Source* source); + Source& source() const; + Source* operator-> () const; + Source& operator* () const; +private: + Source* m_source; +}; + +//------------------------------------------------------------------------------ +// +// Proxy +// class PropertyStream::Proxy { private: - PropertyStream m_stream; + Map* m_map; std::string m_key; public: - Proxy (PropertyStream stream, std::string const& key); + Proxy (Map& map, std::string const& key); template - Proxy& operator= (Value value) - { m_stream.write (m_key, value); return *this; } + Proxy& operator= (Value value); }; //------------------------------------------------------------------------------ +// +// Map +// -template -PropertyStream::Proxy PropertyStream::operator[] (Key key) const +class PropertyStream::Map : public Uncopyable { - std::stringstream ss; - ss << key; - return operator[] (ss.str()); +private: + PropertyStream& m_stream; + +public: + explicit Map (PropertyStream& stream); + explicit Map (Set& parent); + Map (std::string const& key, Map& parent); + Map (std::string const& key, PropertyStream& stream); + ~Map (); + + PropertyStream& stream(); + PropertyStream const& stream() const; + + template + void add (std::string const& key, Value value) const + { + m_stream.add (key, value); + } + + template + void add (Key key, Value value) const + { + std::stringstream ss; + ss << key; + add (ss.str(), value); + } + + Proxy operator[] (std::string const& key); + + Proxy operator[] (char const* key) + { return Proxy (*this, key); } + + template + Proxy operator[] (Key key) const + { + std::stringstream ss; + ss << key; + return Proxy (*this, ss.str()); + } +}; + +//-------------------------------------------------------------------------- + +template +PropertyStream::Proxy& PropertyStream::Proxy::operator= (Value value) +{ + m_map->add (m_key, value); + return *this; } -//------------------------------------------------------------------------------ +//-------------------------------------------------------------------------- +// +// Set +// -class PropertyStream::ScopedObject +class PropertyStream::Set : public Uncopyable { private: - PropertyStream m_stream; + PropertyStream& m_stream; public: - ScopedObject (std::string const& key, PropertyStream stream); - ~ScopedObject (); -}; - -//------------------------------------------------------------------------------ - -class PropertyStream::ScopedArray -{ -private: - PropertyStream m_stream; - -public: - ScopedArray (std::string const& key, PropertyStream stream); - ~ScopedArray (); + explicit Set (Set& set); + Set (std::string const& key, Map& map); + Set (std::string const& key, PropertyStream& stream); + ~Set (); + + PropertyStream& stream(); + PropertyStream const& stream() const; + + template + void add (Value value) const + { m_stream.add (value); } }; //------------------------------------------------------------------------------ +// +// Source +// /** Subclasses can be called to write to a stream and have children. */ class PropertyStream::Source : public Uncopyable @@ -213,6 +215,7 @@ private: : item (source) , parent (nullptr) { } + Item item; Source* parent; List children; @@ -223,19 +226,27 @@ private: std::string const m_name; SharedState m_state; - void remove (SharedState::Access& state, SharedState::Access& childState); + //-------------------------------------------------------------------------- + + void remove (SharedState::Access& state, + SharedState::Access& childState); + void removeAll (SharedState::Access& state); + void write (SharedState::Access& state, PropertyStream& stream); + public: explicit Source (std::string const& name); ~Source (); + /** Returns the name of this source. */ + std::string const& name() const; + /** Add a child source. */ void add (Source& source); /** Add a child source by pointer. - This returns the passed source so it can be conveniently chained - in ctor-initializer lists. + The source pointer is returned so it can be used in ctor-initializers. */ template Derived* add (Derived* child) @@ -244,20 +255,42 @@ public: return child; } - /** Remove a child source. */ + /** Remove a child source from this Source. */ void remove (Source& child); - /** Remove all child sources. */ + /** Remove all child sources of this Source. */ void removeAll (); - void write (PropertyStream stream, bool includeChildren); - void write (std::string const& path, PropertyStream stream); + /** Write only this Source to the stream. */ + void write_one (PropertyStream& stream); - virtual void onWrite (PropertyStream) { } + /** write this source and all its children recursively to the stream. */ + void write (PropertyStream& stream); + + /** Parse the path and write the corresponding Source and optional children. + If the source is found, it is written. If the wildcard character '*' + exists as the last character in the path, then all the children are + written recursively. + */ + void write (PropertyStream& stream, std::string const& path); + + /** Parse the dot-delimited Source path and return the result. + The first value will be a pointer to the Source object corresponding + to the given path. If no Source object exists, then the first value + will be nullptr and the second value will be undefined. + The second value is a boolean indicating whether or not the path string + specifies the wildcard character '*' as the last character. + */ + std::pair find (std::string const& path); + + //-------------------------------------------------------------------------- + + /** Subclass override. + The default version does nothing. + */ + virtual void onWrite (Map&); }; -//------------------------------------------------------------------------------ - } #endif diff --git a/beast/utility/impl/PropertyStream.cpp b/beast/utility/impl/PropertyStream.cpp index b1f5b5863a..239ba4f67f 100644 --- a/beast/utility/impl/PropertyStream.cpp +++ b/beast/utility/impl/PropertyStream.cpp @@ -23,6 +23,12 @@ namespace beast { +//------------------------------------------------------------------------------ +// +// Item +// +//------------------------------------------------------------------------------ + PropertyStream::Item::Item (Source* source) : m_source (source) { @@ -44,113 +50,110 @@ PropertyStream::Source& PropertyStream::Item::operator* () const } //------------------------------------------------------------------------------ - -void PropertyStream::Sink::write (std::string const& key, int32 value) -{ - lexical_write (key, value); -} - -void PropertyStream::Sink::write (std::string const& key, uint32 value) -{ - lexical_write (key, value); -} - -void PropertyStream::Sink::write (std::string const& key, int64 value) -{ - if (value <= std::numeric_limits ::max() && - value >= std::numeric_limits ::min()) - { - write (key, int32(value)); - } - else - { - lexical_write (key, value); - } -} - -void PropertyStream::Sink::write (std::string const& key, uint64 value) -{ - if (value <= std::numeric_limits ::max() && - value >= std::numeric_limits ::min()) - { - write (key, uint32(value)); - } - else - { - lexical_write (key, value); - } -} - -void PropertyStream::Sink::write (int32 value) -{ - lexical_write (value); -} - -void PropertyStream::Sink::write (uint32 value) -{ - lexical_write (value); -} - -void PropertyStream::Sink::write (int64 value) -{ - if (value <= std::numeric_limits ::max() && - value >= std::numeric_limits ::min()) - { - write (int32(value)); - } - else - { - lexical_write (value); - } -} - -void PropertyStream::Sink::write (uint64 value) -{ - if (value <= std::numeric_limits ::max() && - value >= std::numeric_limits ::min()) - { - write (uint32(value)); - } - else - { - lexical_write (value); - } -} - +// +// Proxy +// //------------------------------------------------------------------------------ -PropertyStream::Proxy::Proxy (PropertyStream stream, std::string const& key) - : m_stream (stream) +PropertyStream::Proxy::Proxy ( + Map& map, std::string const& key) + : m_map (&map) , m_key (key) { } +//------------------------------------------------------------------------------ +// +// Map +// //------------------------------------------------------------------------------ -PropertyStream::ScopedObject::ScopedObject (std::string const& key, PropertyStream stream) +PropertyStream::Map::Map (PropertyStream& stream) : m_stream (stream) { - m_stream.begin_object (key); } - -PropertyStream::ScopedObject::~ScopedObject () + +PropertyStream::Map::Map (Set& parent) + : m_stream (parent.stream()) { - m_stream.end_object (); + m_stream.map_begin (); +} + +PropertyStream::Map::Map (std::string const& key, Map& map) + : m_stream (map.stream()) +{ + m_stream.map_begin (key); +} + +PropertyStream::Map::Map (std::string const& key, PropertyStream& stream) + : m_stream (stream) +{ + m_stream.map_begin (key); +} + +PropertyStream::Map::~Map () +{ + m_stream.map_end (); +} + +PropertyStream& PropertyStream::Map::stream() +{ + return m_stream; +} + +PropertyStream const& PropertyStream::Map::stream() const +{ + return m_stream; +} + +PropertyStream::Proxy PropertyStream::Map::operator[] (std::string const& key) +{ + return Proxy (*this, key); } +//------------------------------------------------------------------------------ +// +// Set +// //------------------------------------------------------------------------------ -PropertyStream::ScopedArray::ScopedArray (std::string const& key, PropertyStream stream) +PropertyStream::Set::Set (Set& set) + : m_stream (set.m_stream) +{ + m_stream.array_begin (); +} + +PropertyStream::Set::Set (std::string const& key, Map& map) + : m_stream (map.stream()) +{ + m_stream.array_begin (key); +} + +PropertyStream::Set::Set (std::string const& key, PropertyStream& stream) : m_stream (stream) { - m_stream.begin_array (key); -} - -PropertyStream::ScopedArray::~ScopedArray () -{ - m_stream.end_array (); + m_stream.array_begin (key); } +PropertyStream::Set::~Set () +{ + m_stream.array_end (); +} + +PropertyStream& PropertyStream::Set::stream() +{ + return m_stream; +} + +PropertyStream const& PropertyStream::Set::stream() const +{ + return m_stream; +} + +//------------------------------------------------------------------------------ +// +// Source +// //------------------------------------------------------------------------------ PropertyStream::Source::Source (std::string const& name) @@ -167,24 +170,9 @@ PropertyStream::Source::~Source () removeAll (state); } -void PropertyStream::Source::remove ( - SharedState::Access& state, SharedState::Access& childState) +std::string const& PropertyStream::Source::name () const { - bassert (childState->parent == this); - state->children.erase ( - state->children.iterator_to ( - childState->item)); - childState->parent = nullptr; -} - -void PropertyStream::Source::removeAll (SharedState::Access& state) -{ - for (List ::iterator iter (state->children.begin()); - iter != state->children.end();) - { - SharedState::Access childState ((*iter)->m_state); - remove (state, childState); - } + return m_name; } void PropertyStream::Source::add (Source& source) @@ -209,23 +197,57 @@ void PropertyStream::Source::removeAll () removeAll (state); } -void PropertyStream::Source::write (PropertyStream stream, bool includeChildren) -{ - ScopedObject child (m_name, stream); - onWrite (stream); +//------------------------------------------------------------------------------ - if (includeChildren) +void PropertyStream::Source::write ( + SharedState::Access& state, PropertyStream &stream) +{ + for (List ::iterator iter (state->children.begin()); + iter != state->children.end(); ++iter) { - SharedState::Access state (m_state); - for (List ::iterator iter (state->children.begin()); - iter != state->children.end(); ++iter) - { - (*iter)->write (stream, true); - } + Source& source (iter->source()); + Map map (source.name(), stream); + source.write (stream); } } -void PropertyStream::Source::write (std::string const& path, PropertyStream stream) +//------------------------------------------------------------------------------ + +void PropertyStream::Source::write_one (PropertyStream& stream) +{ + Map map (m_name, stream); + //onWrite (map); +} + +void PropertyStream::Source::write (PropertyStream& stream) +{ + Map map (m_name, stream); + onWrite (map); + + SharedState::Access state (m_state); + + for (List ::iterator iter (state->children.begin()); + iter != state->children.end(); ++iter) + { + Source& source (iter->source()); + source.write (stream); + } +} + +void PropertyStream::Source::write (PropertyStream& stream, std::string const& path) +{ + std::pair result (find (path)); + + if (result.first == nullptr) + return; + + if (result.second) + result.first->write (stream); + else + result.first->write_one (stream); +} + +std::pair PropertyStream::Source::find (std::string const& path) { struct Parser { @@ -251,114 +273,150 @@ void PropertyStream::Source::write (std::string const& path, PropertyStream stre std::string::const_iterator m_last; }; - //----------------------------------------- - if (path.empty ()) - { - write (stream, true); - return; - } + return std::make_pair (this, false); Parser p (path); Source* source (this); - if (p.next() != source->m_name) - return; + if (p.next() != this->m_name) + return std::make_pair (nullptr, false); for (;;) { std::string const s (p.next()); if (s.empty()) - { - source->write (stream, false); - break; - } - else if (s == "*") - { - source->write (stream, true); - break; - } - else - { - SharedState::Access state (source->m_state); - for (List ::iterator iter (state->children.begin());;) - { - if (iter->source().m_name == s) - { - source = &iter->source(); - break; - } + return std::make_pair (source, false); - if (++iter == state->children.end()) - return; + if (s == "*") + return std::make_pair (source, true); + + SharedState::Access state (source->m_state); + for (List ::iterator iter (state->children.begin());;) + { + if (iter->source().m_name == s) + { + source = &iter->source(); + break; } + + if (++iter == state->children.end()) + return std::make_pair (nullptr, false); } } } +void PropertyStream::Source::onWrite (Map&) +{ +} + +//------------------------------------------------------------------------------ + +void PropertyStream::Source::remove ( + SharedState::Access& state, SharedState::Access& childState) +{ + bassert (childState->parent == this); + state->children.erase ( + state->children.iterator_to ( + childState->item)); + childState->parent = nullptr; +} + +void PropertyStream::Source::removeAll (SharedState::Access& state) +{ + for (List ::iterator iter (state->children.begin()); + iter != state->children.end();) + { + SharedState::Access childState ((*iter)->m_state); + remove (state, childState); + } +} + +//------------------------------------------------------------------------------ +// +// PropertyStream +// //------------------------------------------------------------------------------ PropertyStream::PropertyStream () - : m_sink (&nullSink()) { } -PropertyStream::PropertyStream (Sink& sink) - : m_sink (&sink) +PropertyStream::~PropertyStream () { } -PropertyStream::PropertyStream (PropertyStream const& other) - : m_sink (other.m_sink) +void PropertyStream::add (std::string const& key, int32 value) { + lexical_add (key, value); } -PropertyStream& PropertyStream::operator= (PropertyStream const& other) +void PropertyStream::add (std::string const& key, uint32 value) { - m_sink = other.m_sink; - return *this; + lexical_add (key, value); } -PropertyStream::Proxy PropertyStream::operator[] (std::string const& key) const +void PropertyStream::add (std::string const& key, int64 value) { - return Proxy (*this, key); -} - -void PropertyStream::begin_object (std::string const& key) const -{ - m_sink->begin_object (key); -} - -void PropertyStream::end_object () const -{ - m_sink->end_object (); -} - -void PropertyStream::begin_array (std::string const& key) const -{ - m_sink->begin_array (key); -} - -void PropertyStream::end_array () const -{ - m_sink->end_array (); -} - -PropertyStream::Sink& PropertyStream::nullSink() -{ - struct NullSink : Sink + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) { - void begin_object (std::string const&) { } - void end_object () { } - void write (std::string const&, std::string const&) { } - void begin_array (std::string const&) { } - void end_array () { } - void write (std::string const&) { } - }; - - static NullSink sink; - - return sink; + add (key, int32(value)); + } + else + { + lexical_add(key, value); + } } +void PropertyStream::add (std::string const& key, uint64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (key, uint32(value)); + } + else + { + lexical_add (key, value); + } +} + +void PropertyStream::add (int32 value) +{ + lexical_add (value); +} + +void PropertyStream::add (uint32 value) +{ + lexical_add (value); +} + +void PropertyStream::add (int64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (int32(value)); + } + else + { + lexical_add (value); + } +} + +void PropertyStream::add (uint64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (uint32(value)); + } + else + { + lexical_add (value); + } +} + + }