// See the file "COPYING" in the main distribution directory for copyright. #pragma once #include "WriterBackend.h" ZEEK_FORWARD_DECLARE_NAMESPACED(Manager, zeek, logging); namespace zeek::logging { /** * 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 * runs in a new thread, and it receives messages from the frontend that * correspond to method called by the manager. * */ class WriterFrontend { public: /** * Constructor. * * stream: The logging stream. * * writer: 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. * * info: The meta information struct for the writer. * * local: If true, the writer will instantiate a local backend. * * remote: If true, the writer will forward logs to remote * clients. * * Frontends must only be instantiated by the main thread. */ WriterFrontend(const WriterBackend::WriterInfo& info, zeek::EnumVal* stream, zeek::EnumVal* writer, bool local, bool remote); /** * Destructor. * * Frontends must only be destroyed by the main thread. */ virtual ~WriterFrontend(); /** * Stops all output to this writer. Calling this methods disables all * message forwarding to the backend and will eventually remove the * backend thread. * * This method must only be called from the main thread. */ void Stop(); /** * 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(int num_fields, const threading::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, threading::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. * * @param network_time The network time when the flush was triggered. */ void Flush(double network_time); /** * 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(const char* rotated_path, double open, double close, bool terminating); /** * 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 additional writer information as passed into the constructor. */ const WriterBackend::WriterInfo& Info() const { return *info; } /** * Returns the number of log fields as passed into the constructor. */ int NumFields() const { return num_fields; } /** * Returns a descriptive name for the writer, including the type of * the backend and the path used. * * This method is safe to call from any thread. */ const char* Name() const { return name; } /** * Returns the log fields as passed into the constructor. */ const threading::Field* const * Fields() const { return fields; } protected: friend class Manager; void DeleteVals(int num_fields, threading::Value** vals); zeek::EnumVal* stream; zeek::EnumVal* writer; WriterBackend* backend; // The backend we have instantiated. bool disabled; // True if disabled. bool initialized; // True if initialized. bool buf; // True if buffering is enabled (default). bool local; // True if logging locally. bool remote; // True if loggin remotely. const char* name; // Descriptive name of the WriterBackend::WriterInfo* info; // The writer information. int num_fields; // The number of log fields. const threading::Field* const* fields; // The log fields. // Buffer for bulk writes. static const int WRITER_BUFFER_SIZE = 1000; int write_buffer_pos; // Position of next write in buffer. threading::Value*** write_buffer; // Buffer of size WRITER_BUFFER_SIZE. }; } // namespace zeek::logging namespace logging { using WriterFrontend [[deprecated("Remove in v4.1. Use zeek::logging::WriterFrontend.")]] = zeek::logging::WriterFrontend; } // namespace logging