}
m_ThreadGroup.join_all();
+
+ m_Stopped = false;
}
/**
static bool Daemonize(void)
{
#ifndef _WIN32
+ Application::GetTP().Stop();
+
pid_t pid = fork();
if (pid == -1) {
return false;
Application::Exit(0);
}
+
+ Application::GetTP().Start();
#endif /* _WIN32 */
return true;
do { \
result = yyextra->ReadInput(buf, max_size); \
} while (0)
-
-extern int ignore_newlines;
-
-struct lex_buf {
- char *buf;
- size_t size;
-};
-
-static void lb_init(lex_buf *lb)
-{
- lb->buf = NULL;
- lb->size = 0;
-}
-
-/*static void lb_cleanup(lex_buf *lb)
-{
- free(lb->buf);
-}*/
-
-static void lb_append_char(lex_buf *lb, char new_char)
-{
- const size_t block_size = 64;
-
- size_t old_blocks = (lb->size + (block_size - 1)) / block_size;
- size_t new_blocks = ((lb->size + 1) + (block_size - 1)) / block_size;
-
- if (old_blocks != new_blocks) {
- char *new_buf = (char *)realloc(lb->buf, new_blocks * block_size);
-
- if (new_buf == NULL && new_blocks > 0)
- throw std::bad_alloc();
-
- lb->buf = new_buf;
- }
-
- lb->size++;
- lb->buf[lb->size - 1] = new_char;
-}
-
-static char *lb_steal(lex_buf *lb)
-{
- lb_append_char(lb, '\0');
-
- char *buf = lb->buf;
- lb->buf = NULL;
- lb->size = 0;
- return buf;
-}
%}
%option reentrant noyywrap yylineno
%x HEREDOC
%%
- lex_buf string_buf;
-
-\" { lb_init(&string_buf); BEGIN(STRING); }
+\" { yyextra->m_LexBuffer.str(""); yyextra->m_LexBuffer.clear(); BEGIN(STRING); }
<STRING>\" {
BEGIN(INITIAL);
- lb_append_char(&string_buf, '\0');
-
- yylval->text = lb_steal(&string_buf);
+ std::string str = yyextra->m_LexBuffer.str();
+ yylval->text = strdup(str.c_str());
return T_STRING;
}
<STRING>\n {
- std::ostringstream msgbuf;
- msgbuf << "Unterminated string found: " << *yylloc;
- ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
- BEGIN(INITIAL);
+ BOOST_THROW_EXCEPTION(ConfigError("Unterminated string literal") << errinfo_debuginfo(*yylloc));
}
<STRING>\\[0-7]{1,3} {
if (result > 0xff) {
/* error, constant is out-of-bounds */
- std::ostringstream msgbuf;
- msgbuf << "Constant is out-of-bounds: " << yytext << " " << *yylloc;
- ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
+ BOOST_THROW_EXCEPTION(ConfigError("Constant is out of bounds: " + String(yytext)) << errinfo_debuginfo(*yylloc));
}
- lb_append_char(&string_buf, result);
+ yyextra->m_LexBuffer << static_cast<char>(result);
}
<STRING>\\[0-9]+ {
/* generate error - bad escape sequence; something
* like '\48' or '\0777777'
*/
- std::ostringstream msgbuf;
- msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
- ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
+ BOOST_THROW_EXCEPTION(ConfigError("Bad escape sequence found: " + String(yytext)) << errinfo_debuginfo(*yylloc));
}
-<STRING>\\n { lb_append_char(&string_buf, '\n'); }
-<STRING>\\t { lb_append_char(&string_buf, '\t'); }
-<STRING>\\r { lb_append_char(&string_buf, '\r'); }
-<STRING>\\b { lb_append_char(&string_buf, '\b'); }
-<STRING>\\f { lb_append_char(&string_buf, '\f'); }
-<STRING>\\(.|\n) { lb_append_char(&string_buf, yytext[1]); }
+<STRING>\\n { yyextra->m_LexBuffer << "\n"; }
+<STRING>\\t { yyextra->m_LexBuffer << "\t"; }
+<STRING>\\r { yyextra->m_LexBuffer << "\r"; }
+<STRING>\\b { yyextra->m_LexBuffer << "\b"; }
+<STRING>\\f { yyextra->m_LexBuffer << "\f"; }
+<STRING>\\(.|\n) { yyextra->m_LexBuffer << yytext[1]; }
<STRING>[^\\\n\"]+ {
char *yptr = yytext;
while (*yptr)
- lb_append_char(&string_buf, *yptr++);
+ yyextra->m_LexBuffer << *yptr++;
}
-\{\{\{ { lb_init(&string_buf); BEGIN(HEREDOC); }
+\{\{\{ { yyextra->m_LexBuffer.str(""); yyextra->m_LexBuffer.clear(); BEGIN(HEREDOC); }
<HEREDOC>\}\}\} {
BEGIN(INITIAL);
- lb_append_char(&string_buf, '\0');
-
- yylval->text = lb_steal(&string_buf);
+ std::string str = yyextra->m_LexBuffer.str();
+ yylval->text = strdup(str.c_str());
return T_STRING;
}
-<HEREDOC>(.|\n) { lb_append_char(&string_buf, yytext[0]); }
+<HEREDOC>(.|\n) { yyextra->m_LexBuffer << yytext[0]; }
<INITIAL>{
"/*" BEGIN(C_COMMENT);
}
<C_COMMENT><<EOF>> {
- std::ostringstream msgbuf;
- msgbuf << "End-of-file while in comment: " << yytext << " " << *yylloc;
- ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
- yyterminate();
+ BOOST_THROW_EXCEPTION(ConfigError("End-of-file while in comment") << errinfo_debuginfo(*yylloc));
}
\> return T_GREATER_THAN;
}
-[\r\n]+ { yycolumn -= strlen(yytext) - 1; if (!ignore_newlines) return T_NEWLINE; }
+[\r\n]+ { yycolumn -= strlen(yytext) - 1; if (!yyextra->m_IgnoreNewlines) return T_NEWLINE; }
<<EOF>> { if (!yyextra->m_Eof) { yyextra->m_Eof = true; return T_NEWLINE; } else { yyterminate(); } }
. return yytext[0];
using namespace icinga;
-int ignore_newlines = 0;
-
template<typename T>
static void MakeRBinaryOp(Expression** result, Expression *left, Expression *right, DebugInfo& diLeft, DebugInfo& diRight)
{
void yyerror(YYLTYPE *locp, std::vector<Expression *> *, ConfigCompiler *, const char *err)
{
- std::ostringstream message;
- message << *locp << ": " << err;
- ConfigCompilerContext::GetInstance()->AddMessage(true, message.str(), *locp);
+ BOOST_THROW_EXCEPTION(ConfigError(err) << errinfo_debuginfo(*locp));
}
int yyparse(std::vector<Expression *> *elist, ConfigCompiler *context);
Expression *ConfigCompiler::Compile(void)
{
- try {
- std::vector<Expression *> elist;
-
- if (yyparse(&elist, this) != 0)
- return NULL;
+ std::vector<Expression *> elist;
- DictExpression *expr = new DictExpression(elist);
- expr->MakeInline();
- return expr;
- } catch (const ConfigError& ex) {
- const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
- ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
- } catch (const std::exception& ex) {
- ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
- }
+ if (yyparse(&elist, this) != 0)
+ return NULL;
- return NULL;
+ DictExpression *expr = new DictExpression(elist);
+ expr->MakeInline();
+ return expr;
}
#define scanner (context->GetScanner())
}
| '('
{
- ignore_newlines++;
+ context->m_IgnoreNewlines++;
}
rterm ')'
{
- ignore_newlines--;
+ context->m_IgnoreNewlines--;
$$ = $3;
}
| rterm T_LOGICAL_OR rterm { MakeRBinaryOp<LogicalOrExpression>(&$$, $1, $3, @1, @3); }
* @param zone The zone.
*/
ConfigCompiler::ConfigCompiler(const String& path, std::istream *input, const String& zone)
- : m_Path(path), m_Input(input), m_Zone(zone), m_Eof(false)
+ : m_Path(path), m_Input(input), m_Zone(zone), m_Eof(false), m_IgnoreNewlines(0)
{
InitializeScanner();
}
ConfigCompiler::~ConfigCompiler(void)
{
DestroyScanner();
+ delete m_Input;
}
/**
(void) Utility::LoadExtensionLibrary(library);
}
+void ConfigCompiler::CompileHelper(void)
+{
+ try {
+ m_Promise.set_value(boost::shared_ptr<Expression>(Compile()));
+ } catch (...) {
+ m_Promise.set_exception(boost::current_exception());
+ }
+
+ delete this;
+}
+
/**
* Compiles a stream.
*
stream->exceptions(std::istream::badbit);
- ConfigCompiler ctx(path, stream, zone);
- return ctx.Compile();
+ ConfigCompiler* ctx = new ConfigCompiler(path, stream, zone);
+
+ boost::shared_future<boost::shared_ptr<Expression> > ftr = boost::shared_future<boost::shared_ptr<Expression> >(ctx->m_Promise.get_future());
+
+ Utility::QueueAsyncCallback(boost::bind(&ConfigCompiler::CompileHelper, ctx));
+ return new FutureExpression(ftr);
}
/**
{
CONTEXT("Compiling configuration file '" + path + "'");
- std::ifstream stream;
- stream.open(path.CStr(), std::ifstream::in);
+ std::ifstream *stream = new std::ifstream();
+ stream->open(path.CStr(), std::ifstream::in);
- if (!stream)
+ if (!*stream)
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("std::ifstream::open")
<< boost::errinfo_errno(errno)
Log(LogInformation, "ConfigCompiler")
<< "Compiling config file: " << path;
- return CompileStream(path, &stream, zone);
+ return CompileStream(path, stream, zone);
}
/**
*/
Expression *ConfigCompiler::CompileText(const String& path, const String& text, const String& zone)
{
- std::stringstream stream(text);
- return CompileStream(path, &stream, zone);
+ std::stringstream *stream = new std::stringstream(text);
+ return CompileStream(path, stream, zone);
}
/**
void *GetScanner(void) const;
private:
+ boost::promise<boost::shared_ptr<Expression> > m_Promise;
+
String m_Path;
std::istream *m_Input;
String m_Zone;
void *m_Scanner;
bool m_Eof;
+ int m_IgnoreNewlines;
+ std::ostringstream m_LexBuffer;
+
std::stack<TypeRuleList::Ptr> m_RuleLists;
ConfigType::Ptr m_Type;
void InitializeScanner(void);
void DestroyScanner(void);
+ void CompileHelper(void);
+
friend int ::yylex(YYSTYPE *context, icinga::DebugInfo *di, yyscan_t scanner);
friend int ::yyparse(std::vector<icinga::Expression *> *elist, ConfigCompiler *context);
};
#include "base/configerror.hpp"
#include "base/convert.hpp"
#include <boost/foreach.hpp>
+#include <boost/thread/future.hpp>
#include <map>
namespace icinga
boost::shared_ptr<Expression> m_Expression;
};
+class I2_CONFIG_API FutureExpression : public Expression
+{
+public:
+ FutureExpression(const boost::shared_future<boost::shared_ptr<Expression> >& future)
+ : m_Future(future)
+ { }
+
+protected:
+ virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const
+ {
+ return m_Future.get()->DoEvaluate(frame, dhint);
+ }
+
+ virtual const DebugInfo& GetDebugInfo(void) const
+ {
+ return m_Future.get()->GetDebugInfo();
+ }
+
+private:
+ mutable boost::shared_future<boost::shared_ptr<Expression> > m_Future;
+};
+
class I2_CONFIG_API LiteralExpression : public Expression
{
public: