/** \file
 *
 *  Contains the LogEngine class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

/** \defgroup logging Logging
 *
 *  Logging subsystem.
 *
 *  The Logging subsystem has four layers
 *   - Log entries (LogEntry, SyslogEntry, DataEntry, etc)
 *   - Queuing, aka the public interface (Logger and LogQueue)
 *   - Processing and decimation (LogEngine)
 *   - Output (LogWriter)
 *
 *  Under normal operation, there is a singleton LogQueue object.
 *  Objects have instances of the Logger, which
 *  handles "writing" to the queue.  They create instances of LogEntry
 *  (typically handled by the Logger), and drop them
 *  in the queue.
 *
 *  The backend is handled by the LogEngine, which is a Component and may run either
 *  synchronously with the rest of the software, or asynchronously (in its own
 *  thread), but _It must be run_ for anything to happen logging-wise.  In
 *  the current implementation LogEngine is run synchronously with the rest of
 *  the software
 *
 *  When run, the LogEngine extracts available LogEntries from the queue,
 *  and uses a set of recipes (LoggerAssociations) to match entries
 *  to output devices (LogWriter), which may be a binary or plain-text file,
 *  the console, etc.
 */

#ifndef _LOGENGINE_H
#define _LOGENGINE_H

#include "LogAssociation.h"
#include "LogWriter.h"
#include "LogQueue.h"
#include "LoggerRules.h"
#include "utils/Mutex.h"

// Foward declarations
class LogAssociation;
class Rule;

/**
 *  Component responsible for handling the contents of the LogQueue.  Typically,
 *  logEngine is called at the end of the computation cycle, although it could
 *  be run in its own thread.
 *
 *  When run, LogEngine extracts available LogEntries from the queue,
 *  and uses a set of recipes (LoggerAssociations) to match entries
 *  to output devices (LogWriter), which may be a binary or plain-text file,
 *  the console, etc.
 *
 *  \ingroup logging
 */
class LogEngine
{

public:
    /// Constructor for Logger.
    LogEngine();

    /// Allows specification of the non-singleton queue
    LogEngine( LogQueue& queue );

    /// Destructor for Logger.
    virtual ~LogEngine();

    /// Reset cached input settings associated with LogWriters
    virtual void resetInputs();

    /// Initialize the component.
    virtual void initialize( void );

    /// Deal with an entry as appropriate
    void processEntry( LogEntry* thisEntry );

    /// Pop log entries from the queue and deal with them as appropriate.
    /// If a non-zero timeout is specified, stop after that much time has passed
    void processQueue( const Timespan& timeout );

    /// Deinitialize the component
    virtual void uninitialize( void );

    /// Add an entry to the LoggerAssociations table
    virtual LogAssociation* addAssociation( LogWriter* writer, Rule* rule );

    /// Remove an entry from the LoggerAssociations table
    virtual void removeAssociation( LogWriter* writer );

    /// Configure logWriters
    void configAssociatedLogWriters( Logger& sysLogger );

    /// Stop processing
    void lockProcessing()
    {
        mutex_.lock();
    }

    /// Continue processing
    void unlockProcessing()
    {
        mutex_.unlock();
    }


protected:

    /// For convenience, more than anything else
    LogQueue &queue_;

    /// Allows the supervisor to shut down log processing.
    Mutex mutex_;

    ///
    void cleanupAll( void );

    /// Stores all of the associations as a list
    LoggerAssociationDeque associations_;

};

#endif // LOGENGINE_H
