diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 09c5030fdc..0876b10eb2 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -1279,7 +1279,7 @@ Value** Manager::RecordToFilterVals(Stream* stream, Filter* filter, } WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, string path, - int num_fields, Field** fields) + int num_fields, const Field* const* fields) { Stream* stream = FindStream(id); diff --git a/src/logging/Manager.h b/src/logging/Manager.h index 7fa2c271db..1267a19ca7 100644 --- a/src/logging/Manager.h +++ b/src/logging/Manager.h @@ -15,32 +15,63 @@ class RotationTimer; namespace logging { -// Description of a log field. +/** + * Definition of a log file, i.e., one column of a log stream. + */ struct Field { - string name; - TypeTag type; - // inner type of sets - TypeTag subtype; + string name; //! Name of the field. + TypeTag type; //! Type of the field. + TypeTag subtype; //! Inner type for sets. + /** + * Constructor. + */ Field() { subtype = TYPE_VOID; } + + /** + * Copy constructor. + */ Field(const Field& other) : name(other.name), type(other.type), subtype(other.subtype) { } - // (Un-)serialize. + /** + * Unserializes a field. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ bool Read(SerializationFormat* fmt); + + /** + * Serializes a field. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ bool Write(SerializationFormat* fmt) const; }; -// Values as logged by a writer. +/** + * Definition of a log value, i.e., a entry logged by a stream. + * + * This struct essentialy represents a serialization of a Val instance (for + * those Vals supported). + */ struct Value { - TypeTag type; - bool present; // False for unset fields. + TypeTag type; //! The type of the value. + bool present; //! False for optional record fields that are not set. - // The following union is a subset of BroValUnion, including only the - // types we can log directly. struct set_t { bro_int_t size; Value** vals; }; typedef set_t vec_t; + /** + * This union is a subset of BroValUnion, including only the types we + * can log directly. See IsCompatibleType(). + */ union _val { bro_int_t int_val; bro_uint_t uint_val; @@ -52,42 +83,173 @@ struct Value { vec_t vector_val; } val; + /** + * Constructor. + * + * arg_type: The type of the value. + * + * arg_present: False if the value represents an optional record field + * that is not set. + */ Value(TypeTag arg_type = TYPE_ERROR, bool arg_present = true) : type(arg_type), present(arg_present) {} + + /** + * Destructor. + */ ~Value(); - // (Un-)serialize. + /** + * Unserializes a value. + * + * @param fmt The serialization format to use. The format handles low-level I/O. + * + * @return False if an error occured. + */ bool Read(SerializationFormat* fmt); + + /** + * Serializes a value. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ bool Write(SerializationFormat* fmt) const; - // Returns true if the type can be logged the framework. If - // `atomic_only` is true, will not permit composite types. + /** + * Returns true if the type can be represented by a Value. If + * `atomic_only` is true, will not permit composite types. + */ static bool IsCompatibleType(BroType* t, bool atomic_only=false); private: - Value(const Value& other) { } + Value(const Value& other) { } // Disabled. }; class WriterBackend; class WriterFrontend; class RotationFinishedMessage; +/** + * Singleton class for managing log streams. + */ class Manager { public: + /** + * Constructor. + */ Manager(); + + /** + * Destructor. + */ ~Manager(); - // These correspond to the BiFs visible on the scripting layer. The - // actual BiFs just forward here. + /** + * Creates a new log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param stream A record of script type \c Log::Stream. + * + * This method corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool CreateStream(EnumVal* id, RecordVal* stream); + + /** + * Enables a log log stream. + * + * @param id The enum value corresponding the log stream. + * + * This method corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool EnableStream(EnumVal* id); + + /** + * Disables a log stream. + * + * @param id The enum value corresponding the log stream. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool DisableStream(EnumVal* id); + + /** + * Adds a filter to a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param filter A record of script type \c Log::Filter. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool AddFilter(EnumVal* id, RecordVal* filter); + + /** + * Removes a filter from a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param name The name of the filter to remove. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool RemoveFilter(EnumVal* id, StringVal* name); + + /** + * Removes a filter from a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param name The name of the filter to remove. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool RemoveFilter(EnumVal* id, string name); + + /** + * Write a record to a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param colums A record of the type defined for the stream's + * columns. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ bool Write(EnumVal* id, RecordVal* columns); - bool SetBuf(EnumVal* id, bool enabled); // Adjusts all writers. - bool Flush(EnumVal* id); // Flushes all writers.. + + /** + * Sets log streams buffering state. This adjusts all associated + * writers to the new state. + * + * @param id The enum value corresponding the log stream. + * + * @param enabled False to disable buffering (default is enabled). + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool SetBuf(EnumVal* id, bool enabled); + + /** + * Flushes a log stream. This flushed all associated writers. + * + * @param id The enum value corresponding the log stream. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool Flush(EnumVal* id); protected: friend class WriterFrontend; @@ -103,7 +265,7 @@ protected: // Takes ownership of fields. WriterFrontend* CreateWriter(EnumVal* id, EnumVal* writer, string path, - int num_fields, Field** fields); + int num_fields, const Field* const* fields); // Takes ownership of values.. bool Write(EnumVal* id, EnumVal* writer, string path, @@ -112,8 +274,6 @@ protected: // Announces all instantiated writers to peer. void SendAllWritersTo(RemoteSerializer::PeerID peer); - //// Functions safe to use by writers. - // Signals that a file has been rotated. bool FinishedRotation(WriterFrontend* writer, string new_name, string old_name, double open, double close, bool terminating); diff --git a/src/logging/WriterBackend.cc b/src/logging/WriterBackend.cc index 7c9c1d10ca..e361ca69d3 100644 --- a/src/logging/WriterBackend.cc +++ b/src/logging/WriterBackend.cc @@ -40,6 +40,15 @@ public: virtual bool Process() { Object()->FlushWriteBuffer(); return true; } }; +class DisableMessage : public threading::OutputMessage +{ +public: + DisableMessage(WriterFrontend* writer) + : threading::OutputMessage("Disable", writer) {} + + virtual bool Process() { Object()->SetDisable(); return true; } +}; + } // Backend methods. @@ -86,8 +95,13 @@ bool WriterBackend::FinishedRotation(string new_name, string old_name, return true; } +void WriterBackend::DisableFrontend() + { + SendOut(new DisableMessage(frontend)); + } + bool WriterBackend::Init(WriterFrontend* arg_frontend, string arg_path, int arg_num_fields, - const Field* const * arg_fields) + const Field* const* arg_fields) { frontend = arg_frontend; path = arg_path; @@ -95,7 +109,10 @@ bool WriterBackend::Init(WriterFrontend* arg_frontend, string arg_path, int arg_ fields = arg_fields; if ( ! DoInit(arg_path, arg_num_fields, arg_fields) ) + { + DisableFrontend(); return false; + } return true; } @@ -114,6 +131,7 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals) #endif DeleteVals(num_writes, vals); + DisableFrontend(); return false; } @@ -129,6 +147,7 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals) vals[j][i]->type, fields[i]->type); Debug(DBG_LOGGING, msg); + DisableFrontend(); DeleteVals(num_writes, vals); return false; } @@ -148,6 +167,9 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals) DeleteVals(num_writes, vals); + if ( ! success ) + DisableFrontend(); + return success; } @@ -159,23 +181,47 @@ bool WriterBackend::SetBuf(bool enabled) buffering = enabled; - return DoSetBuf(enabled); + if ( ! DoSetBuf(enabled) ) + { + DisableFrontend(); + return false; + } + + return true; } bool WriterBackend::Rotate(string rotated_path, double open, double close, bool terminating) { - return DoRotate(rotated_path, open, close, terminating); + if ( ! DoRotate(rotated_path, open, close, terminating) ) + { + DisableFrontend(); + return false; + } + + return true; } bool WriterBackend::Flush() { - return DoFlush(); + if ( ! DoFlush() ) + { + DisableFrontend(); + return false; + } + + return true; } bool WriterBackend::Finish() { - return DoFinish(); + if ( ! DoFlush() ) + { + DisableFrontend(); + return false; + } + + return true; } bool WriterBackend::DoHeartbeat(double network_time, double current_time) diff --git a/src/logging/WriterBackend.h b/src/logging/WriterBackend.h index 27f4fe45a5..b5d313a480 100644 --- a/src/logging/WriterBackend.h +++ b/src/logging/WriterBackend.h @@ -11,180 +11,291 @@ namespace logging { -// The backend runs in its own thread, separate from the main process. +/** + * Base class for writer implementation. When the logging::Manager creates a + * new logging filter, it instantiates a WriterFrontend. That then in turn + * creates a WriterBackend of the right type. The frontend then forwards + * message over the backend as its methods are called. + * + * All of this methods must be called only from the corresponding child + * thread (the constructor is the one exception.) + */ class WriterBackend : public threading::MsgThread { public: + /** + * Constructor. + * + * @param name A descriptive name for writer's type (e.g., \c Ascii). + */ WriterBackend(const string& name); + + /** + * Destructor. + */ virtual ~WriterBackend(); - // One-time initialization of the writer to define the logged fields. - // - // "frontend" is the frontend writer that created this backend. The - // *only* purpose of this value is to be passed back via messages as - // a argument to callbacks. One must not otherwise access the - // frontend, it's running in a different thread. - // - // Interpretation of "path" is left to the writer, and will be - // corresponding the value configured on the script-level. - // - // Returns false if an error occured, in which case the writer must - // not be used further. - // - // The new instance takes ownership of "fields", and will delete them - // when done. - bool Init(WriterFrontend* frontend, string path, int num_fields, const Field* const * fields); + /** + * One-time initialization of the writer to define the logged fields. + * + * @param frontend The frontend writer that created this backend. The + * *only* purpose of this value is to be passed back via messages as + * a argument to callbacks. One must not otherwise access the + * frontend, it's running in a different thread. + * + * @param path A string left to the interpretation of the writer + * implementation; it corresponds to the value configured on the + * script-level for the logging filter. + * + * @param num_fields The number of log fields for the stream. + * + * @param fields An array of size \a num_fields with the log fields. + * The methods takes ownership of the array. + * + * @return False if an error occured. + */ + bool Init(WriterFrontend* frontend, string path, int num_fields, const Field* const* fields); - // Writes one log entry. The method takes ownership of "vals" and - // will return immediately after queueing the write request, which is - // potentially before output has actually been written out. - // - // num_fields and the types of the Values must match what was passed - // to Init(). - // - // Returns false if an error occured, in which case the writer must - // not be used any further. + /** + * Writes one log entry. + * + * @param num_fields: The number of log fields for this stream. The + * value must match what was passed to Init(). + * + * @param An array of size \a num_fields with the log values. Their + * types musst match with the field passed to Init(). The method + * takes ownership of \a vals.. + * + * Returns false if an error occured, in which case the writer must + * not be used any further. + * + * @return False if an error occured. + */ bool Write(int num_fields, int num_writes, Value*** vals); - // Sets the buffering status for the writer, if the writer supports - // that. (If not, it will be ignored). + /** + * Sets the buffering status for the writer, assuming the writer + * supports that. (If not, it will be ignored). + * + * @param enabled False if buffering is to be disabled (by default + * it's on). + * + * @return False if an error occured. + */ bool SetBuf(bool enabled); - // Flushes any currently buffered output, if the writer supports - // that. (If not, it will be ignored). + /** + * Flushes any currently buffered output, assuming the writer + * supports that. (If not, it will be ignored). + * + * @return False if an error occured. + */ bool Flush(); - // Triggers rotation, if the writer supports that. (If not, it will - // be ignored). + /** + * Triggers rotation, if the writer supports that. (If not, it will + * be ignored). + * + * @return False if an error occured. + */ bool Rotate(string rotated_path, double open, double close, bool terminating); - // Finishes writing to this logger regularly. Must not be called if - // an error has been indicated earlier. After calling this, no - // further writing must be performed. + /** + * Finishes writing to this logger in a regularl fashion. Must not be + * called if an error has been indicated earlier. After calling this, + * no further writing must be performed. + * + * @return False if an error occured. + */ bool Finish(); - //// Thread-safe methods that may be called from the writer - //// implementation. + /** + * Disables the frontend that has instantiated this backend. Once + * disabled,the frontend will not send any further message over. + */ + void DisableFrontend(); - // The following methods return the information as passed to Init(). + /** + * Returns the log path as passed into the constructor. + */ const string Path() const { return path; } + + /** + * Returns the number of log fields as passed into the constructor. + */ int NumFields() const { return num_fields; } + + /** + * Returns the log fields as passed into the constructor. + */ const Field* const * Fields() const { return fields; } - // Returns the current buffering state. + /** + * Returns the current buffering state. + * + * @return True if buffering is enabled. + */ bool IsBuf() { return buffering; } - // Signals to the log manager that a file has been rotated. - // - // writer: The frontend writer that triggered the rotation. This must - // be the value passed into DoRotate(). - // - // new_name: The filename of the rotated file. old_name: The filename - // of the origina file. - // - // open/close: The timestamps when the original file was opened and - // closed, respectively. - // - // terminating: True if rotation request occured due to the main Bro - // process shutting down. + /** + * Signals that a file has been rotated. This must be called by a + * writer's implementation of DoRotate() once rotation has finished. + * + * Most of the parameters should be passed through from DoRotate(). + * + * @param new_name The filename of the rotated file. + * + * @param old_name The filename of the original file. + * + * @param open: The timestamp when the original file was opened. + * + * @param close: The timestamp when the origina file was closed. + * + * @param terminating: True if the original rotation request occured + * due to the main Bro process shutting down. + */ bool FinishedRotation(string new_name, string old_name, double open, double close, bool terminating); protected: - // Methods for writers to override. If any of these returs false, it - // will be assumed that a fatal error has occured that prevents the - // writer from further operation. It will then be disabled and - // deleted. When returning false, the writer should also report the - // error via Error(). Note that even if a writer does not support the - // functionality for one these methods (like rotation), it must still - // return true if that is not to be considered a fatal error. - // - // Called once for initialization of the writer. + /** + * Writer-specific intialization method. + * + * A writer implementation must override this method. If it returns + * false, it will be assumed that a fatal error has occured that + * prevents the writer from further operation; it will then be + * disabled and eventually deleted. When returning false, an + * implementation should also call Error() to indicate what happened. + */ virtual bool DoInit(string path, int num_fields, - const Field* const * fields) = 0; + const Field* const* fields) = 0; - // Called once per log entry to record. - virtual bool DoWrite(int num_fields, const Field* const * fields, + /** + * Writer-specific output method implementing recording of fone log + * entry. + * + * A writer implementation must override this method. If it returns + * false, it will be assumed that a fatal error has occured that + * prevents the writer from further operation; it will then be + * disabled and eventually deleted. When returning false, an + * implementation should also call Error() to indicate what happened. + */ + virtual bool DoWrite(int num_fields, const Field* const* fields, Value** vals) = 0; - // Called when the buffering status for this writer is changed. If - // buffering is disabled, the writer should attempt to write out - // information as quickly as possible even if doing so may have a - // performance impact. If enabled (which is the default), it may - // buffer data as helpful and write it out later in a way optimized - // for performance. The current buffering state can be queried via - // IsBuf(). - // - // A writer may ignore buffering changes if it doesn't fit with its - // semantics (but must still return true in that case). + /** + * Writer-specific method implementing a change of fthe buffering + * state. If buffering is disabled, the writer should attempt to + * write out information as quickly as possible even if doing so may + * have a performance impact. If enabled (which is the default), it + * may buffer data as helpful and write it out later in a way + * optimized for performance. The current buffering state can be + * queried via IsBuf(). + * + * A writer implementation must override this method but it can just + * ignore calls if buffering doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ virtual bool DoSetBuf(bool enabled) = 0; - // Called to flush any currently buffered output. - // - // A writer may ignore flush requests if it doesn't fit with its - // semantics (but must still return true in that case). + /** + * Writer-specific method implementing flushing of its output. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ virtual bool DoFlush() = 0; - // Called when a log output is to be rotated. Most directly this only - // applies to writers writing into files, which should then close the - // current file and open a new one. However, a writer may also - // trigger other apppropiate actions if semantics are similar. - // - // Once rotation has finished, the implementation should call - // RotationDone() to signal the log manager that potential - // postprocessors can now run. - // - // "rotate_path" reflects the path to where the rotated output is to - // be moved, with specifics depending on the writer. It should - // generally be interpreted in a way consistent with that of "path" - // as passed into DoInit(). As an example, for file-based output, - // "rotate_path" could be the original filename extended with a - // timestamp indicating the time of the rotation. - // - // "open" and "close" are the network time's when the *current* file - // was opened and closed, respectively. - // - // "terminating" indicated whether the rotation request occurs due - // the main Bro prcoess terminating (and not because we've reach a - // regularly scheduled time for rotation). - // - // A writer may ignore rotation requests if it doesn't fit with its - // semantics (but must still return true in that case). + /** + * Writer-specific method implementing log rotation. Most directly + * this only applies to writers writing into files, which should then + * close the current file and open a new one. However, a writer may + * also trigger other apppropiate actions if semantics are similar. * + * Once rotation has finished, the implementation must call + * FinishedRotation() to signal the log manager that potential + * postprocessors can now run. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. It + * still needs to call FinishedRotation() though. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + * + * @param rotate_path Reflects the path to where the rotated output + * is to be moved, with specifics depending on the writer. It should + * generally be interpreted in a way consistent with that of \c path + * as passed into DoInit(). As an example, for file-based output, \c + * rotate_path could be the original filename extended with a + * timestamp indicating the time of the rotation. + * + * @param open The network time when the *current* file was opened. + * + * @param close The network time when the *current* file was closed. + * + * @param terminating Indicates whether the rotation request occurs + * due the main Bro prcoess terminating (and not because we've + * reached a regularly scheduled time for rotation). + */ virtual bool DoRotate(string rotated_path, double open, double close, bool terminating) = 0; - // Called once on termination. Not called when any of the other - // methods has previously signaled an error, i.e., executing this - // method signals a regular shutdown of the writer. + /** + * Writer-specific method implementing log output finalization at + * termination. Not called when any of the other methods has + * previously signaled an error, i.e., executing this method signals + * a regular shutdown of the writer. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ virtual bool DoFinish() = 0; - // Triggered by regular heartbeat messages from the main process. - // - // Note when overriding, you must call WriterBackend::DoHeartbeat(). + /** + * Triggered by regular heartbeat messages from the main thread. + * + * This method can be overridden but once must call + * WriterBackend::DoHeartbeat(). + */ virtual bool DoHeartbeat(double network_time, double current_time); private: friend class Manager; - // When an error occurs, we call this method to set a flag marking - // the writer as disabled. The Manager will check the flag later and - // remove the writer. - bool Disabled() { return disabled; } - - // Deletes the values as passed into Write(). + /** + * Deletes the values as passed into Write(). + */ void DeleteVals(int num_writes, Value*** vals); + // Frontend that instantiated us. This object must not be access from + // this class, it's running in a different thread! WriterFrontend* frontend; - string path; - int num_fields; - const Field* const * fields; - bool buffering; - bool disabled; - // For implementing Fmt(). - char* buf; - unsigned int buf_len; + string path; // Log path. + int num_fields; // Number of log fields. + const Field* const* fields; // Log fields. + bool buffering; // True if buffering is enabled. }; diff --git a/src/logging/WriterFrontend.cc b/src/logging/WriterFrontend.cc index 2f7c1d6e7e..137cdf90ec 100644 --- a/src/logging/WriterFrontend.cc +++ b/src/logging/WriterFrontend.cc @@ -9,7 +9,7 @@ namespace logging { class InitMessage : public threading::InputMessage { public: - InitMessage(WriterBackend* backend, WriterFrontend* frontend, const string path, const int num_fields, const Field* const *fields) + InitMessage(WriterBackend* backend, WriterFrontend* frontend, const string path, const int num_fields, const Field* const* fields) : threading::InputMessage("Init", backend), path(path), num_fields(num_fields), fields(fields) { } diff --git a/src/logging/WriterFrontend.h b/src/logging/WriterFrontend.h index ed1a674842..6f1bb4ea1b 100644 --- a/src/logging/WriterFrontend.h +++ b/src/logging/WriterFrontend.h @@ -1,6 +1,4 @@ // See the file "COPYING" in the main distribution directory for copyright. -// -// Bridge class between main process and writer threads. #ifndef LOGGING_WRITERFRONTEND_H #define LOGGING_WRITERFRONTEND_H @@ -13,57 +11,187 @@ namespace logging { class WriterBackend; +/** + * Bridge class between the logging::Manager and backend writer threads. The + * Manager instantiates one \a WriterFrontend for each open logging filter. + * Each frontend in turns instantiates a WriterBackend-derived class + * internally that's specific to the particular output format. That backend + * spawns a new thread, and it receives messages from the frontend that + * correspond to method called by the manager. + * + */ class WriterFrontend { public: + /** + * Constructor. + * + * type: The backend writer type, with the value corresponding to the + * script-level \c Log::Writer enum (e.g., \a WRITER_ASCII). The + * frontend will internally instantiate a WriterBackend of the + * corresponding type. + * + * Frontends must only be instantiated by the main thread. + */ WriterFrontend(bro_int_t type); + + /** + * Destructor. + * + * Frontends must only be destroyed by the main thread. + */ virtual ~WriterFrontend(); - // Disables the writers and stop the backend thread. + /** + * Stops all output to this writer. Calling this methods disables all + * message forwarding to the backend and stops the backend thread. + * + * This method must only be called from the main thread. + */ void Stop(); - // Interface methods to interact with the writer from the main thread - // (and only from the main thread), typicalli from the log manager. - // All these methods forward (via inter-thread messaging) to the - // corresponding methods of an internally created WriterBackend. See - // there for documentation. - // - // If any of these operations fails, the writer will be automatically - // (but asynchronoulsy) disabled. + /** + * Initializes the writer. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::Init() for arguments. The method takes + * ownership of \a fields. + * + * This method must only be called from the main thread. + */ + void Init(string path, int num_fields, const Field* const* fields); - void Init(string path, int num_fields, const Field* const * fields); + /** + * Write out a record. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * As an optimization, if buffering is enabled (which is the default) + * this method may buffer several writes and send them over to the + * backend in bulk with a single message. An explicit bulk write of + * all currently buffered data can be triggered with + * FlushWriteBuffer(). The backend writer triggers this with a + * message at every heartbeat. + * + * See WriterBackend::Writer() for arguments (except that this method + * takes only a single record, not an array). The method takes + * ownership of \a vals. + * + * This method must only be called from the main thread. + */ void Write(int num_fields, Value** vals); + + /** + * Sets the buffering state. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::SetBuf() for arguments. + * + * This method must only be called from the main thread. + */ void SetBuf(bool enabled); + + /** + * Flushes the output. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. In addition, it also triggers + * FlushWriteBuffer(). If the backend method fails, it sends a + * message back that will asynchronously call Disable(). + * + * This method must only be called from the main thread. + */ void Flush(); - void FlushWriteBuffer(); + + /** + * Triggers log rotation. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::Rotate() for arguments. + * + * This method must only be called from the main thread. + */ void Rotate(string rotated_path, double open, double close, bool terminating); + + /** + * Finalizes writing to this tream. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * This method must only be called from the main thread. + */ void Finish(); - // Calling this disable the writer. All methods calls will be no-ops - // from now on. The Manager will eventually remove disabled writers. + /** + * Explicitly triggers a transfer of all potentially buffered Write() + * operations over to the backend. + * + * This method must only be called from the main thread. + */ + void FlushWriteBuffer(); + + /** + * Disables the writer frontend. From now on, all method calls that + * would normally send message over to the backend, turn into no-ops. + * Note though that it does not stop the backend itself, use Stop() + * to do thast as well (this method is primarily for use as callback + * when the backend wants to disable the frontend). + * + * Disabled frontend will eventually be discarded by the + * logging::Manager. + * + * This method must only be called from the main thread. + */ void SetDisable() { disabled = true; } + + /** + * Returns true if the writer frontend has been disabled with SetDisable(). + */ bool Disabled() { return disabled; } + /** + * Returns the log path as passed into the constructor. + */ const string Path() const { return path; } + + /** + * Returns the number of log fields as passed into the constructor. + */ int NumFields() const { return num_fields; } + + /** + * Returns the log fields as passed into the constructor. + */ const Field* const * Fields() const { return fields; } protected: friend class Manager; - WriterBackend* backend; - bool disabled; - bool initialized; - bool buf; + WriterBackend* backend; // The backend we have instanatiated. + bool disabled; // True if disabled. + bool initialized; // True if initialized. + bool buf; // True if buffering is enabled (default). - string path; - int num_fields; - const Field* const * fields; + string path; // The log path. + int num_fields; // The number of log fields. + const Field* const* fields; // The log fields. // Buffer for bulk writes. static const int WRITER_BUFFER_SIZE = 50; - - int write_buffer_pos; - Value*** write_buffer; + int write_buffer_pos; // Position of next write in buffer. + Value*** write_buffer; // Buffer of size WRITER_BUFFER_SIZE. }; } diff --git a/src/logging/writers/Ascii.h b/src/logging/writers/Ascii.h index 0c627c68e9..4a9dea4950 100644 --- a/src/logging/writers/Ascii.h +++ b/src/logging/writers/Ascii.h @@ -19,8 +19,8 @@ public: protected: virtual bool DoInit(string path, int num_fields, - const Field* const * fields); - virtual bool DoWrite(int num_fields, const Field* const * fields, + const Field* const* fields); + virtual bool DoWrite(int num_fields, const Field* const* fields, Value** vals); virtual bool DoSetBuf(bool enabled); virtual bool DoRotate(string rotated_path, double open, diff --git a/src/logging/writers/None.h b/src/logging/writers/None.h index 9360ef44f6..b25bb09348 100644 --- a/src/logging/writers/None.h +++ b/src/logging/writers/None.h @@ -20,7 +20,7 @@ protected: virtual bool DoInit(string path, int num_fields, const Field* const * fields) { return true; } - virtual bool DoWrite(int num_fields, const Field* const * fields, + virtual bool DoWrite(int num_fields, const Field* const* fields, Value** vals) { return true; } virtual bool DoSetBuf(bool enabled) { return true; } virtual bool DoRotate(string rotated_path, double open,