#include "Route.hh"
#include "Module.hh"
#include "ModuleManager.hh"
+#include "../Utils/Console/Console.hh"
//#include "Connectors.mpp"
#define prefix_
peer().enqueueInitializable();
}
+senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::traceState_ (
+ senf::ppi::connector::Connector::NO_TRACING);
+
+prefix_ void senf::ppi::connector::Connector::trace(Packet const & p, char const * label)
+{
+ if (traceState_ == NO_TRACING)
+ return;
+ SENF_LOG_BLOCK(({
+ std::string type (prettyName(p.typeId().id()));
+ log << "PPI trace: 0x" << std::hex << p.id() << " "
+ << type.substr(21, type.size()-22) << " " << label
+ << " on " << & module() << " " << prettyName(typeid(module()))
+ << " connector 0x" << this << "\n";
+ if (traceState_ == TRACE_CONTENTS)
+ p.dump(log);
+ }));
+}
+
+namespace senf { namespace ppi { namespace connector {
+
+ SENF_CONSOLE_REGISTER_ENUM_MEMBER(
+ Connector, TraceState, (NO_TRACING)(TRACE_IDS)(TRACE_CONTENTS) );
+
+}}}
+
+namespace {
+
+ struct ConsoleRegister
+ {
+ ConsoleRegister();
+ };
+
+ ConsoleRegister::ConsoleRegister()
+ {
+ senf::console::sysdir()
+ .add("ppiTracing", SENF_FNP(senf::ppi::connector::Connector::TraceState,
+ senf::ppi::connector::Connector::tracing, ()))
+ .doc("Log every packet sent or received by any module.\n"
+ "There are three different tracing levels:\n"
+ "\n"
+ " NO_TRACING don't output any tracing information\n"
+ " TRACE_IDS trace packet id's but do not show packet contents\n"
+ " TRACE_CONTENTS trace complete packet contents\n"
+ "\n"
+ "A log message is generated whenever the packet traverses a connector. The\n"
+ "TRACE_IDS log message has the following format:\n"
+ "\n"
+ " PPI trace: <packet-id> <packet-type> <direction>\n"
+ " on <module-id> <module-type> connector <connector-id>\n"
+ "\n"
+ "The fields are:\n"
+ "\n"
+ " packet-id Numeric unique packet id. This value is unique for packets\n"
+ " alive at the same time, packets at different times may (and\n"
+ " will) share id's\n"
+ " packet-type The type of the packet header\n"
+ " direction 'INCOMING' for packets entering the module, 'OUTGOING' for\n"
+ " packets leaving it\n"
+ " module-id Unique module id\n"
+ " module-type Type of the module the packet is sent to/from\n"
+ " connector-id Unique connector id\n");
+
+ senf::console::sysdir()
+ .add("ppiTracing", SENF_FNP(void, senf::ppi::connector::Connector::tracing,
+ (senf::ppi::connector::Connector::TraceState)))
+ .arg("state", "new tracing state");
+ }
+
+ ConsoleRegister consoleRegister;
+
+}
+
prefix_ void senf::ppi::connector::Connector::disconnect()
{
// Cannot disconnected a non-connected connector
queue_.pop_back();
v_dequeueEvent();
}
+ trace(p, "INCOMING");
return p;
}
return *module_;
}
+prefix_ void senf::ppi::connector::Connector::tracing(TraceState state)
+{
+ traceState_ = state;
+}
+
+prefix_ senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::tracing()
+{
+ return traceState_;
+}
+
////////////////////////////////////////
// protected members
prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet const & p)
{
+ trace(p, "OUTGOING");
if (connected())
peer().enqueue(p);
}
class Connector
: ModuleManager::Initializable, boost::noncopyable
{
+ SENF_LOG_CLASS_AREA();
+ SENF_LOG_DEFAULT_LEVEL(senf::log::NOTICE);
public:
Connector & peer() const; ///< Get peer connected to this connector
module::Module & module() const; ///< Get this connectors containing module
void disconnect(); ///< Disconnect connector from peer
+ enum TraceState { NO_TRACING, TRACE_IDS, TRACE_CONTENTS };
+
+ static void tracing(TraceState state);
+ static TraceState tracing();
+
protected:
Connector();
virtual ~Connector();
void connect(Connector & target);
+
+ void trace(Packet const & p, char const * label);
private:
virtual std::type_info const & packetTypeID();
Connector * peer_;
module::Module * module_;
+ static TraceState traceState_;
+
friend class module::Module;
};
return ptr()->factory();
}
+prefix_ unsigned long senf::Packet::id()
+ const
+{
+ return reinterpret_cast<unsigned long>(&ptr()->impl());
+}
+
prefix_ bool senf::Packet::boolean_test()
const
{
///@{
bool operator==(Packet const & other) const; ///< Check for packet identity
- /**< Two packet handles compare equal if they really are the
- same packet header in the same packet chain. */
+ /**< Two packet handles compare equal if they really are the
+ same packet header in the same packet chain. */
bool boolean_test() const; ///< Check, whether the packet is valid()
/**< \see valid() */
bool valid() const; ///< Check, whether the packet is valid()
\endcode */
void finalizeTo(Packet const & other); ///< Update calculated fields
- /**< The finalize() fammily of members will update
- calculated packet fields: checksums, size fields and so
- on. This includes any field, which can be set from
- other information in the packet. Each concrete packet
- type should document, which fields are set by
- finalize().
-
- finalizeTo(other) will automatically process all
- packets/headers/interpreters beginning at \a other
- backwards towards outer packets up to \c this. */
+ /**< The finalize() fammily of members will update
+ calculated packet fields: checksums, size fields and so
+ on. This includes any field, which can be set from
+ other information in the packet. Each concrete packet
+ type should document, which fields are set by
+ finalize().
+
+ finalizeTo(other) will automatically process all
+ packets/headers/interpreters beginning at \a other
+ backwards towards outer packets up to \c this. */
void finalizeAll(); ///< Update calculated fields
/**< The finalize() fammily of members will update
headers. */
void dump(std::ostream & os) const; ///< Write out a printable packet representation
- /**< This method is provided mostly to help debugging packet
- problems. Each concrete packet should implement a dump
- method writing out all fields of the packet in a
- readable representation. dump() will call this member
- for each packet/header/interpreter in the chain from \c
- this packet up to the end of the chain. */
-
- TypeIdValue typeId() const; ///< Get id of \c this packet
- /**< This value is used e.g. in the packet registry to
- associate packet types with other information.
- \returns A type holding the same information as a
- type_info object, albeit assignable */
+ /**< This method is provided mostly to help debugging packet
+ problems. Each concrete packet should implement a dump
+ method writing out all fields of the packet in a
+ readable representation. dump() will call this member
+ for each packet/header/interpreter in the chain from \c
+ this packet up to the end of the chain. */
+
+ TypeIdValue typeId() const; ///< Get type of \c this packet
+ /**< This value is used e.g. in the packet registry to
+ associate packet types with other information.
+ \returns A type holding the same information as a
+ type_info object, albeit assignable */
factory_t factory() const; ///< Return factory instance of \c this packet
- /**< The returned factory instance can be used to create new
- packets of the given type without knowing the concrete
- type of the packet. The value may be stored away for
- later use if needed. */
+ /**< The returned factory instance can be used to create new
+ packets of the given type without knowing the concrete
+ type of the packet. The value may be stored away for
+ later use if needed. */
+
+ unsigned long id() const; ///< Unique packet id
+ /**< Get a unique packet id. If two packets have the same
+ id, they share the internal data representation.. */
///@}