TAGFILES = \
"$(TOPDIR)/Socket/doc/Socket.tag" \
"$(TOPDIR)/Scheduler/doc/Scheduler.tag" \
- "$(TOPDIR)/Utils/doc/Utils.tag"
+ "$(TOPDIR)/Utils/doc/Utils.tag" \
+ "$(TOPDIR)/Utils/Logger/doc/Logger.tag"
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
typedef typename boost::remove_reference<result_type>::type NodeType;
+ /// Internal
struct Creator {
static NodeType & create(DirectoryNode & node, std::string const & name,
Object const & ob);
typedef typename boost::remove_reference<result_type>::type NodeType;
+ /// Internal
struct Creator {
static NodeType & create(DirectoryNode & node, Owner & owner,
std::string const & name, Object const & ob);
namespace console {
namespace detail {
+#ifndef DOXYGEN
+
struct ParserAccess
{
static void init(ParseCommandInfo & info)
}
};
+#endif
+
}}}
///////////////////////////////////////////////////////////////////////////
// senf::console::ParseCommandInfo
+#ifndef DOXYGEN
+
struct senf::console::ParseCommandInfo::MakeRange
{
typedef ParseCommandInfo::argument_value_type result_type;
}
};
+#endif
+
prefix_ void senf::console::ParseCommandInfo::finalize()
{
arguments_.resize( tempArguments_.size() );
///////////////////////////////////////////////////////////////////////////
// senf::console::CommandParser
+#ifndef DOXYGEN
+
struct senf::console::CommandParser::Impl
{
typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar;
Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
};
+#endif
+
prefix_ senf::console::CommandParser::CommandParser()
: impl_ (new Impl())
{}
// senf::console::Client
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();
ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
senf::membind(&Client::clientData, this) );
+ route< senf::SenfLog, senf::log::NOTICE >();
}
prefix_ senf::console::Client::~Client()
prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
{
+ promptLen_ = 0;
if (helper->error() || handle_.eof()) {
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
stopClient();
boost::trim(data); // Gets rid of superfluous \r or \n characters
try {
- if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1, boost::ref(out_))))
- out_ << "syntax error" << std::endl;
+ if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1,
+ boost::ref(out_t::member))))
+ out_t::member << "syntax error" << std::endl;
}
catch (Executor::ExitException &) {
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
return;
}
catch (std::exception & ex) {
- out_ << ex.what() << std::endl;
+ out_t::member << ex.what() << std::endl;
}
catch (...) {
- out_ << "unidentified error (unknown exception thrown)" << std::endl;
+ out_t::member << "unidentified error (unknown exception thrown)" << std::endl;
}
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////////////////////////////////////////
#include "Parse.hh"
#include "Executor.hh"
#include "../Socket/Protocols/INet/INetAddressing.hh"
+#include "../Utils/Logger.hh"
//#include "Server.mpp"
///////////////////////////////hh.p////////////////////////////////////////
\fixme Make output non-blocking (use a non-blocking/discarding streambuf) and possibly set
socket send buffer size
\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
- : 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_DEFAULT_LEVEL( senf::log::NOTICE );
public:
void clientData(ReadHelper<ClientHandle>::ptr helper);
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_;
std::string tail_;
CommandParser parser_;
Executor executor_;
std::string name_;
-
- typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
- fdostream out_;
+ unsigned promptLen_;
friend class Server;
};
stream_ << timestamp << sep;
stream_ << "[" << LEVELNAMES_[level] << "]";
if (area != "senf::log::DefaultArea")
- stream_ << "[" << area << "] ";
- stream_ << *i << "\n";
+ stream_ << "[" << area << "]";
+ stream_ << " " << *i << "\n";
sep = '-';
}
stream_ << std::flush;
///////////////////////////////////////////////////////////////////////////
protected:
-
- private:
void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
std::string const & area, unsigned level,
std::string const & message);
+ private:
std::ostream & stream_;
static char const * const LEVELNAMES_[8];
};
prefix_ senf::log::Target::~Target()
{
while( ! rib_.empty()) {
- // This is terribly slow but simplifies the area cache handling and removing a target should
- // be quite seldom
+ // This is slow but simplifies the area cache handling and removing a target should be
+ // relatively seldom
RIB::reverse_iterator i (rib_.rbegin());
unroute(i->stream_, i->area_, i->level_, i->action_);
}