Skip to content
Snippets Groups Projects
Commit 93ef0a90 authored by g0dil's avatar g0dil
Browse files

Console: Add log support to network client (every client is a log target)

parent 916c9493
No related branches found
No related tags found
No related merge requests found
...@@ -7,4 +7,5 @@ ALPHABETICAL_INDEX = NO ...@@ -7,4 +7,5 @@ ALPHABETICAL_INDEX = NO
TAGFILES = \ TAGFILES = \
"$(TOPDIR)/Socket/doc/Socket.tag" \ "$(TOPDIR)/Socket/doc/Socket.tag" \
"$(TOPDIR)/Scheduler/doc/Scheduler.tag" \ "$(TOPDIR)/Scheduler/doc/Scheduler.tag" \
"$(TOPDIR)/Utils/doc/Utils.tag" "$(TOPDIR)/Utils/doc/Utils.tag" \
"$(TOPDIR)/Utils/Logger/doc/Logger.tag"
...@@ -65,7 +65,8 @@ namespace console { ...@@ -65,7 +65,8 @@ namespace console {
typedef boost::iterator_range< ParseCommandInfo::argument_iterator> Arguments; typedef boost::iterator_range< ParseCommandInfo::argument_iterator> Arguments;
struct ExitException {}; ///< Thrown by built-in 'exit' command /// Thrown by built-in 'exit' command
struct ExitException {};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
//\/name Structors and default members //\/name Structors and default members
......
...@@ -143,6 +143,7 @@ namespace console { ...@@ -143,6 +143,7 @@ namespace console {
typedef typename boost::remove_reference<result_type>::type NodeType; typedef typename boost::remove_reference<result_type>::type NodeType;
/// Internal
struct Creator { struct Creator {
static NodeType & create(DirectoryNode & node, std::string const & name, static NodeType & create(DirectoryNode & node, std::string const & name,
Object const & ob); Object const & ob);
......
...@@ -53,6 +53,7 @@ namespace console { ...@@ -53,6 +53,7 @@ namespace console {
typedef typename boost::remove_reference<result_type>::type NodeType; typedef typename boost::remove_reference<result_type>::type NodeType;
/// Internal
struct Creator { struct Creator {
static NodeType & create(DirectoryNode & node, Owner & owner, static NodeType & create(DirectoryNode & node, Owner & owner,
std::string const & name, Object const & ob); std::string const & name, Object const & ob);
......
...@@ -41,6 +41,8 @@ namespace senf { ...@@ -41,6 +41,8 @@ namespace senf {
namespace console { namespace console {
namespace detail { namespace detail {
#ifndef DOXYGEN
struct ParserAccess struct ParserAccess
{ {
static void init(ParseCommandInfo & info) static void init(ParseCommandInfo & info)
...@@ -149,11 +151,15 @@ namespace detail { ...@@ -149,11 +151,15 @@ namespace detail {
} }
}; };
#endif
}}} }}}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// senf::console::ParseCommandInfo // senf::console::ParseCommandInfo
#ifndef DOXYGEN
struct senf::console::ParseCommandInfo::MakeRange struct senf::console::ParseCommandInfo::MakeRange
{ {
typedef ParseCommandInfo::argument_value_type result_type; typedef ParseCommandInfo::argument_value_type result_type;
...@@ -168,6 +174,8 @@ struct senf::console::ParseCommandInfo::MakeRange ...@@ -168,6 +174,8 @@ struct senf::console::ParseCommandInfo::MakeRange
} }
}; };
#endif
prefix_ void senf::console::ParseCommandInfo::finalize() prefix_ void senf::console::ParseCommandInfo::finalize()
{ {
arguments_.resize( tempArguments_.size() ); arguments_.resize( tempArguments_.size() );
...@@ -211,6 +219,8 @@ prefix_ std::ostream & senf::console::operator<<(std::ostream & stream, ...@@ -211,6 +219,8 @@ prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// senf::console::CommandParser // senf::console::CommandParser
#ifndef DOXYGEN
struct senf::console::CommandParser::Impl struct senf::console::CommandParser::Impl
{ {
typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar; typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar;
...@@ -222,6 +232,8 @@ struct senf::console::CommandParser::Impl ...@@ -222,6 +232,8 @@ struct senf::console::CommandParser::Impl
Impl() : dispatcher(), context(), grammar(dispatcher, context) {} Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
}; };
#endif
prefix_ senf::console::CommandParser::CommandParser() prefix_ senf::console::CommandParser::CommandParser()
: impl_ (new Impl()) : impl_ (new Impl())
{} {}
......
...@@ -102,11 +102,13 @@ prefix_ void senf::console::Server::removeClient(Client & client) ...@@ -102,11 +102,13 @@ prefix_ void senf::console::Server::removeClient(Client & client)
// senf::console::Client // senf::console::Client
prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name) prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
: handle_ (handle), name_ (name), out_(::dup(handle.fd())) : out_t(::dup(handle.fd())), senf::log::IOStreamTarget(out_t::member),
handle_ (handle), name_ (name), promptLen_(0)
{ {
showPrompt(); showPrompt();
ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"), ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
senf::membind(&Client::clientData, this) ); senf::membind(&Client::clientData, this) );
route< senf::SenfLog, senf::log::NOTICE >();
} }
prefix_ senf::console::Client::~Client() prefix_ senf::console::Client::~Client()
...@@ -120,6 +122,7 @@ prefix_ void senf::console::Client::stopClient() ...@@ -120,6 +122,7 @@ prefix_ void senf::console::Client::stopClient()
prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper) prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
{ {
promptLen_ = 0;
if (helper->error() || handle_.eof()) { if (helper->error() || handle_.eof()) {
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
stopClient(); stopClient();
...@@ -131,8 +134,9 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel ...@@ -131,8 +134,9 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel
boost::trim(data); // Gets rid of superfluous \r or \n characters boost::trim(data); // Gets rid of superfluous \r or \n characters
try { try {
if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1, boost::ref(out_)))) if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1,
out_ << "syntax error" << std::endl; boost::ref(out_t::member))))
out_t::member << "syntax error" << std::endl;
} }
catch (Executor::ExitException &) { catch (Executor::ExitException &) {
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
...@@ -140,10 +144,10 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel ...@@ -140,10 +144,10 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel
return; return;
} }
catch (std::exception & ex) { catch (std::exception & ex) {
out_ << ex.what() << std::endl; out_t::member << ex.what() << std::endl;
} }
catch (...) { catch (...) {
out_ << "unidentified error (unknown exception thrown)" << std::endl; out_t::member << "unidentified error (unknown exception thrown)" << std::endl;
} }
showPrompt(); showPrompt();
...@@ -153,7 +157,21 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel ...@@ -153,7 +157,21 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel
prefix_ void senf::console::Client::showPrompt() prefix_ void senf::console::Client::showPrompt()
{ {
out_ << name_ << ":" << executor_.cwd().path() << "# " << std::flush; std::string path (executor_.cwd().path());
out_t::member << name_ << ":" << path << "# " << std::flush;
promptLen_ = name_.size() + 1 + path.size() + 1;
}
prefix_ void senf::console::Client::v_write(boost::posix_time::ptime timestamp,
std::string const & stream,
std::string const & area, unsigned level,
std::string const & message)
{
if (promptLen_)
out_t::member << '\r' << std::string(' ', promptLen_) << '\r';
IOStreamTarget::v_write(timestamp, stream, area, level, message);
if (promptLen_)
showPrompt();
} }
///////////////////////////////cc.e//////////////////////////////////////// ///////////////////////////////cc.e////////////////////////////////////////
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "Parse.hh" #include "Parse.hh"
#include "Executor.hh" #include "Executor.hh"
#include "../Socket/Protocols/INet/INetAddressing.hh" #include "../Socket/Protocols/INet/INetAddressing.hh"
#include "../Utils/Logger.hh"
//#include "Server.mpp" //#include "Server.mpp"
///////////////////////////////hh.p//////////////////////////////////////// ///////////////////////////////hh.p////////////////////////////////////////
...@@ -113,10 +114,17 @@ namespace console { ...@@ -113,10 +114,17 @@ namespace console {
\fixme Make output non-blocking (use a non-blocking/discarding streambuf) and possibly set \fixme Make output non-blocking (use a non-blocking/discarding streambuf) and possibly set
socket send buffer size socket send buffer size
\fixme Don't register a new ReadHelper every round \fixme Don't register a new ReadHelper every round
\fixme Ensure, that output errors (or any errors) in the console don't terminate the
application
*/ */
class Client class Client
: public senf::intrusive_refcount : public senf::intrusive_refcount,
private boost::base_from_member< boost::iostreams::stream<boost::iostreams::file_descriptor_sink> >,
public senf::log::IOStreamTarget
{ {
typedef boost::base_from_member<
boost::iostreams::stream<boost::iostreams::file_descriptor_sink> > out_t;
SENF_LOG_CLASS_AREA(); SENF_LOG_CLASS_AREA();
SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE ); SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
public: public:
...@@ -134,15 +142,17 @@ namespace console { ...@@ -134,15 +142,17 @@ namespace console {
void clientData(ReadHelper<ClientHandle>::ptr helper); void clientData(ReadHelper<ClientHandle>::ptr helper);
void showPrompt(); void showPrompt();
virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
std::string const & area, unsigned level,
std::string const & message);
ClientHandle handle_; ClientHandle handle_;
std::string tail_; std::string tail_;
CommandParser parser_; CommandParser parser_;
Executor executor_; Executor executor_;
std::string name_; std::string name_;
unsigned promptLen_;
typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
fdostream out_;
friend class Server; friend class Server;
}; };
......
...@@ -73,8 +73,8 @@ prefix_ void senf::log::IOStreamTarget::v_write(boost::posix_time::ptime timesta ...@@ -73,8 +73,8 @@ prefix_ void senf::log::IOStreamTarget::v_write(boost::posix_time::ptime timesta
stream_ << timestamp << sep; stream_ << timestamp << sep;
stream_ << "[" << LEVELNAMES_[level] << "]"; stream_ << "[" << LEVELNAMES_[level] << "]";
if (area != "senf::log::DefaultArea") if (area != "senf::log::DefaultArea")
stream_ << "[" << area << "] "; stream_ << "[" << area << "]";
stream_ << *i << "\n"; stream_ << " " << *i << "\n";
sep = '-'; sep = '-';
} }
stream_ << std::flush; stream_ << std::flush;
......
...@@ -73,12 +73,11 @@ namespace log { ...@@ -73,12 +73,11 @@ namespace log {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
protected: protected:
private:
void v_write(boost::posix_time::ptime timestamp, std::string const & stream, void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
std::string const & area, unsigned level, std::string const & area, unsigned level,
std::string const & message); std::string const & message);
private:
std::ostream & stream_; std::ostream & stream_;
static char const * const LEVELNAMES_[8]; static char const * const LEVELNAMES_[8];
}; };
......
...@@ -45,8 +45,8 @@ prefix_ senf::log::Target::Target() ...@@ -45,8 +45,8 @@ prefix_ senf::log::Target::Target()
prefix_ senf::log::Target::~Target() prefix_ senf::log::Target::~Target()
{ {
while( ! rib_.empty()) { while( ! rib_.empty()) {
// This is terribly slow but simplifies the area cache handling and removing a target should // This is slow but simplifies the area cache handling and removing a target should be
// be quite seldom // relatively seldom
RIB::reverse_iterator i (rib_.rbegin()); RIB::reverse_iterator i (rib_.rbegin());
unroute(i->stream_, i->area_, i->level_, i->action_); unroute(i->stream_, i->area_, i->level_, i->action_);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment