Skip to content
Snippets Groups Projects
Commit 49cfb353 authored by g0dil's avatar g0dil
Browse files

Utils: Add DiscardStream

Utils/Console: Allow adding additional config sources to a config bundle while parsing
Utils/Console: Redirect non error console output during configuration to a DiscardStream
Utils/Console: Add more information to path/directory console errors
Utils/Logger: Fix reference to destroyed areas in global destructors
parent 33a24ec4
No related branches found
No related tags found
No related merge requests found
Showing
with 244 additions and 23 deletions
...@@ -120,9 +120,8 @@ prefix_ void senf::console::ConfigBundle::parse(DirectoryNode & restrict) ...@@ -120,9 +120,8 @@ prefix_ void senf::console::ConfigBundle::parse(DirectoryNode & restrict)
prefix_ void senf::console::ConfigBundle::parseInternal() prefix_ void senf::console::ConfigBundle::parseInternal()
{ {
Sources::const_iterator i (sources_.begin()); // It is valid to add additional sources at the end while parsing ...
Sources::const_iterator const i_end (sources_.end()); for (Sources::const_iterator i (sources_.begin()); i != sources_.end(); ++i)
for (; i != i_end; ++i)
(*i)->parse(executor_); (*i)->parse(executor_);
} }
......
...@@ -53,6 +53,11 @@ prefix_ senf::console::DirectoryNode & senf::console::detail::RestrictedExecutor ...@@ -53,6 +53,11 @@ prefix_ senf::console::DirectoryNode & senf::console::detail::RestrictedExecutor
return executor_.chroot(); return executor_.chroot();
} }
prefix_ std::ostream & senf::console::detail::RestrictedExecutor::stream()
{
return stream_;
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// senf::console::ConfigBundle // senf::console::ConfigBundle
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
// Custom includes // Custom includes
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <list>
#include "Parse.hh" #include "Parse.hh"
#include "Executor.hh" #include "Executor.hh"
...@@ -94,7 +95,7 @@ namespace console { ...@@ -94,7 +95,7 @@ namespace console {
private: private:
void parseInternal(); void parseInternal();
typedef std::vector<detail::ConfigSource::ptr> Sources; typedef std::list<detail::ConfigSource::ptr> Sources;
Sources sources_; Sources sources_;
detail::RestrictedExecutor executor_; detail::RestrictedExecutor executor_;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include "Executor.hh" #include "Executor.hh"
#include "../../Utils/intrusive_refcount.hh" #include "../../Utils/intrusive_refcount.hh"
#include "../../Utils/DiscardStream.hh"
///////////////////////////////ih.p//////////////////////////////////////// ///////////////////////////////ih.p////////////////////////////////////////
...@@ -77,6 +78,8 @@ namespace detail { ...@@ -77,6 +78,8 @@ namespace detail {
DirectoryNode & root() const; DirectoryNode & root() const;
std::ostream & stream();
class RestrictGuard; class RestrictGuard;
protected: protected:
...@@ -90,6 +93,7 @@ namespace detail { ...@@ -90,6 +93,7 @@ namespace detail {
Executor executor_; Executor executor_;
ParsedNodes parsedNodes_; ParsedNodes parsedNodes_;
DirectoryNode::ptr restrict_; DirectoryNode::ptr restrict_;
DiscardStream stream_;
friend class RestrictGuard; friend class RestrictGuard;
}; };
......
...@@ -39,7 +39,7 @@ prefix_ void senf::console::detail::ConfigFileSource::v_parse(RestrictedExecutor ...@@ -39,7 +39,7 @@ prefix_ void senf::console::detail::ConfigFileSource::v_parse(RestrictedExecutor
{ {
try { try {
parser_.parseFile(filename_, boost::bind( boost::ref(executor), parser_.parseFile(filename_, boost::bind( boost::ref(executor),
boost::ref(std::cerr), boost::ref(executor.stream()),
_1 )); _1 ));
} }
catch (SystemException & ex) { catch (SystemException & ex) {
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
namespace { namespace {
struct TraverseTokens { struct TraversTokens {
typedef std::string const & result_type; typedef std::string const & result_type;
result_type operator()(senf::console::Token const & token) const { result_type operator()(senf::console::Token const & token) const {
return token.value(); return token.value();
...@@ -140,11 +140,11 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, ...@@ -140,11 +140,11 @@ prefix_ void senf::console::Executor::execute(std::ostream & output,
} }
} }
catch (InvalidPathException &) { catch (InvalidPathException & ex) {
throw SyntaxErrorException("invalid path"); throw SyntaxErrorException("invalid path") << " '" << ex.path << "'";
} }
catch (InvalidDirectoryException &) { catch (InvalidDirectoryException & ex) {
throw SyntaxErrorException("invalid directory"); throw SyntaxErrorException("invalid directory") << " '" << ex.path << "'";
} }
catch (InvalidCommandException &) { catch (InvalidCommandException &) {
throw SyntaxErrorException("invalid command"); throw SyntaxErrorException("invalid command");
...@@ -297,7 +297,12 @@ senf::console::Executor::traverseNode(ParseCommandInfo::TokensRange const & path ...@@ -297,7 +297,12 @@ senf::console::Executor::traverseNode(ParseCommandInfo::TokensRange const & path
return dir.back().lock()->get(name); return dir.back().lock()->get(name);
} }
catch (UnknownNodeNameException &) { catch (UnknownNodeNameException &) {
throw InvalidPathException(); throw InvalidPathException(
senf::stringJoin(
senf::make_transform_range(
boost::make_iterator_range(path.begin(), path.end()),
boost::bind(&Token::value, _1)),
"/"));
} }
} }
...@@ -305,10 +310,14 @@ prefix_ void ...@@ -305,10 +310,14 @@ prefix_ void
senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const & path, senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const & path,
Path & dir) Path & dir)
{ {
std::string errorPath;
try { try {
ParseCommandInfo::TokensRange::const_iterator i (path.begin()); ParseCommandInfo::TokensRange::const_iterator i (path.begin());
ParseCommandInfo::TokensRange::const_iterator const i_end (path.end()); ParseCommandInfo::TokensRange::const_iterator const i_end (path.end());
for (; i != i_end; ++i) { for (; i != i_end; ++i) {
if (i != path.begin())
errorPath += "/";
errorPath += i->value();
if (*i == NoneToken()) { if (*i == NoneToken()) {
if (i == path.begin()) { if (i == path.begin()) {
dir.clear(); dir.clear();
......
...@@ -148,8 +148,17 @@ namespace console { ...@@ -148,8 +148,17 @@ namespace console {
Path & dir); Path & dir);
std::string complete(DirectoryNode & dir, std::string const & name); std::string complete(DirectoryNode & dir, std::string const & name);
struct InvalidPathException {}; struct InvalidPathException {
struct InvalidDirectoryException {}; std::string path;
InvalidPathException() : path() {}
InvalidPathException(std::string path_) : path(path_) {}
};
struct InvalidDirectoryException {
std::string path;
InvalidDirectoryException() : path() {}
InvalidDirectoryException(std::string path_) : path(path_) {}
};
struct InvalidCommandException {}; struct InvalidCommandException {};
DirectoryNode::ptr root_; DirectoryNode::ptr root_;
......
...@@ -85,7 +85,7 @@ BOOST_AUTO_UNIT_TEST(commandGrammar) ...@@ -85,7 +85,7 @@ BOOST_AUTO_UNIT_TEST(commandGrammar)
{ {
static char text[] = static char text[] =
"# Comment\n" "# Comment\n"
"doo / bii / doo arg" "doo/bii/doo arg/two/three"
" flab::blub" " flab::blub"
" 123.434>a" " 123.434>a"
" (a,b;c (huhu/{haha}))" " (a,b;c (huhu/{haha}))"
...@@ -99,7 +99,7 @@ BOOST_AUTO_UNIT_TEST(commandGrammar) ...@@ -99,7 +99,7 @@ BOOST_AUTO_UNIT_TEST(commandGrammar)
grammar.use_parser<Grammar::SkipParser>() ) . full ); grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), BOOST_CHECK_EQUAL( ss.str(),
"beginCommand( Word('doo')/Word('bii')/Word('doo') )\n" "beginCommand( Word('doo')/Word('bii')/Word('doo') )\n"
"pushToken( Word('arg') )\n" "pushToken( Word('arg/two/three') )\n"
"pushToken( Word('flab::blub') )\n" "pushToken( Word('flab::blub') )\n"
"pushToken( Word('123.434>a') )\n" "pushToken( Word('123.434>a') )\n"
"pushToken( ArgumentGroupOpen('(') )\n" "pushToken( ArgumentGroupOpen('(') )\n"
......
...@@ -152,7 +152,7 @@ senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & ...@@ -152,7 +152,7 @@ senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const &
cmd.command(path); cmd.command(path);
parser_.parseArguments(value, cmd); parser_.parseArguments(value, cmd);
executor(std::cerr, cmd); executor(executor.stream(), cmd);
} }
prefix_ void prefix_ void
......
...@@ -70,11 +70,6 @@ namespace detail { ...@@ -70,11 +70,6 @@ namespace detail {
: public boost::iostreams::sink : public boost::iostreams::sink
{ {
public: public:
typedef ClientSocketHandle<
senf::MakeSocketPolicy<StreamFramingPolicy,
WriteablePolicy,
ConnectedCommunicationPolicy>::policy > Handle;
NonblockingSocketSink(Client & client); NonblockingSocketSink(Client & client);
std::streamsize write(const char * s, std::streamsize n); std::streamsize write(const char * s, std::streamsize n);
......
// $Id$
//
// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
\brief DiscardStream inline non-template implementation */
//#include "DiscardStream.ih"
// Custom includes
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
prefix_ std::streamsize senf::DiscardSink::write(char const * s, std::streamsize n)
{
return n;
}
prefix_ senf::DiscardStream::DiscardStream()
{
open(DiscardSink());
}
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// End:
// $Id$
//
// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
\brief DiscardStream public header */
#ifndef HH_SENF_Utils_DiscardStream_
#define HH_SENF_Utils_DiscardStream_ 1
// Custom includes
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
//#include "DiscardStream.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
class DiscardSink
: public boost::iostreams::sink
{
public:
std::streamsize write(char const * s, std::streamsize n);
};
class DiscardStream
: public boost::iostreams::stream<DiscardSink>
{
public:
DiscardStream();
};
}
///////////////////////////////hh.e////////////////////////////////////////
#include "DiscardStream.cci"
//#include "DiscardStream.ct"
//#include "DiscardStream.cti"
#endif
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// End:
// $Id$
//
// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
\brief DiscardStream.test unit tests */
//#include "DiscardStream.test.hh"
//#include "DiscardStream.test.ih"
// Custom includes
#include "DiscardStream.hh"
#include "../Utils/auto_unit_test.hh"
#include <boost/test/test_tools.hpp>
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
BOOST_AUTO_UNIT_TEST(discardStream)
{
senf::DiscardStream stream;
SENF_CHECK_NO_THROW( stream << "discard me" );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
// Local Variables:
// mode: c++
// fill-column: 100
// comment-column: 40
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// End:
...@@ -36,9 +36,15 @@ ...@@ -36,9 +36,15 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// senf::log::detail::AreaBase // senf::log::detail::AreaBase
prefix_ senf::log::detail::AreaBase::~AreaBase() prefix_ senf::log::detail::AreaBase::AreaBase()
: alive_ (true)
{} {}
prefix_ senf::log::detail::AreaBase::~AreaBase()
{
alive_ = false;
}
prefix_ void senf::log::detail::AreaBase::updateRoutingCache(Target & target, prefix_ void senf::log::detail::AreaBase::updateRoutingCache(Target & target,
StreamBase const & stream, StreamBase const & stream,
unsigned limit) unsigned limit)
......
...@@ -88,6 +88,12 @@ prefix_ void senf::log::detail::AreaBase::init() ...@@ -88,6 +88,12 @@ prefix_ void senf::log::detail::AreaBase::init()
senf::log::AreaRegistry::instance().registerArea(*this); senf::log::AreaRegistry::instance().registerArea(*this);
} }
prefix_ bool senf::log::detail::AreaBase::alive()
const
{
return alive_;
}
prefix_ unsigned senf::log::detail::AreaBase::limit(StreamBase const & stream) prefix_ unsigned senf::log::detail::AreaBase::limit(StreamBase const & stream)
const const
{ {
......
...@@ -47,12 +47,14 @@ namespace detail { ...@@ -47,12 +47,14 @@ namespace detail {
/** \brief Internal: Area base class */ /** \brief Internal: Area base class */
struct AreaBase struct AreaBase
{ {
AreaBase();
virtual ~AreaBase(); virtual ~AreaBase();
std::string fullName() const; std::string fullName() const;
virtual std::string v_name() const; virtual std::string v_name() const;
void init(); void init();
bool alive() const;
unsigned limit(StreamBase const & stream) const; unsigned limit(StreamBase const & stream) const;
void updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) const; void updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) const;
...@@ -74,6 +76,7 @@ namespace detail { ...@@ -74,6 +76,7 @@ namespace detail {
}; };
typedef std::vector<CacheEntry> RoutingCache; typedef std::vector<CacheEntry> RoutingCache;
mutable RoutingCache routingCache_; mutable RoutingCache routingCache_;
bool alive_;
}; };
}}} }}}
......
...@@ -272,6 +272,9 @@ prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * st ...@@ -272,6 +272,9 @@ prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * st
updateRoutingCache(stream, i->second); updateRoutingCache(stream, i->second);
return; return;
} }
if (! area->alive())
// We are globally destructing and the area is gone already ...
return;
unsigned limit (DISABLED::value); unsigned limit (DISABLED::value);
RIB::iterator i (rib_.begin()); RIB::iterator i (rib_.begin());
RIB::iterator const i_end (rib_.end()); RIB::iterator const i_end (rib_.end());
...@@ -415,7 +418,7 @@ prefix_ senf::log::detail::TargetRegistry::TargetRegistry() ...@@ -415,7 +418,7 @@ prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
" <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n" " <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n"
"\n" "\n"
"Route all messages to the currently connected client\n" "Route all messages to the currently connected client\n"
" $ /sys/log/self { route (); }"); " $ /sys/log/self { route (); }");
} }
prefix_ senf::log::detail::TargetRegistry::~TargetRegistry() prefix_ senf::log::detail::TargetRegistry::~TargetRegistry()
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define HH_SENF_Utils_auto_unit_test_ 1 #define HH_SENF_Utils_auto_unit_test_ 1
// Custom includes // Custom includes
#include <iostream>
#include <boost/version.hpp> #include <boost/version.hpp>
//#include "auto_unit_test.mpp" //#include "auto_unit_test.mpp"
......
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