diff --git a/repos/os/include/os/reporter.h b/repos/os/include/os/reporter.h index 10a6619968..ad631b1811 100644 --- a/repos/os/include/os/reporter.h +++ b/repos/os/include/os/reporter.h @@ -14,16 +14,19 @@ #ifndef _INCLUDE__OS__REPORTER_H_ #define _INCLUDE__OS__REPORTER_H_ +#include #include #include #include #include - -namespace Genode { class Reporter; } +namespace Genode { + class Reporter; + class Expanding_reporter; +} -class Genode::Reporter : Noncopyable +class Genode::Reporter { public: @@ -152,4 +155,63 @@ class Genode::Reporter : Noncopyable }; }; + +/** + * Reporter that increases the report buffer capacity on demand + * + * This convenience wrapper of the 'Reporter' alleviates the need to handle + * 'Xml_generator::Buffer_exceeded' exceptions manually. In most cases, the + * only reasonable way to handle such an exception is upgrading the report + * buffer as done by this class. Furthermore, in contrast to the regular + * 'Reporter', which needs to be 'enabled', the 'Expanding_reporter' is + * implicitly enabled at construction time. + */ +class Genode::Expanding_reporter +{ + public: + + typedef Session_label Label; + typedef String<64> Node_type; + + private: + + Env &_env; + + Node_type const _type; + Label const _label; + + Constructible _reporter { }; + + size_t _buffer_size = 4096; + + void _construct() + { + _reporter.construct(_env, _type.string(), _label.string(), _buffer_size); + _reporter->enabled(true); + } + + public: + + Expanding_reporter(Env &env, Node_type const &type, Label const &label) + : _env(env), _type(type), _label(label) { _construct(); } + + template + void generate(FN const &fn) + { + retry( + + /* attempt to generate a report, may throw */ + [&] () { + Reporter::Xml_generator + xml(*_reporter, [&] () { fn(xml); }); }, + + /* respond to exception by successively increasing the buffer */ + [&] () { + _buffer_size += 4096; + _construct(); + } + ); + } +}; + #endif /* _INCLUDE__OS__REPORTER_H_ */