41.6 LazyFlusher

LSS::Flush() needs to be called on a regular basis in order to flush the log to avoid data loss if there is a system failure (such as loss of power). This is a synchronous call - i.e. it won't return until the log has been flushed.

LSS::Flush() is threadsafe, so it is permissible for a worker thread to call this function.

LazyFlusher employs a low priority background thread in order to make repeated calls to LSS::Flush(). The rate at which it will flush the log is determined by the int variable LssSettings::flushTimeMilliSec which defaults to 1000 milliseconds.

When the system is I/O bound writing to disk, we don't want to waste time flushing partially full segments to disk. To support this concept, LazyFlusher::SignalDontNeedToFlush() is called each time a full segment is written to disk by the lazy writer. When this is called repeatedly, the TimeOutTask will be prevented from timing out and therefore the LazyFlusher avoids flushing the log. This ensures that auto-flushing has no impact on the maximum write performance.

LazyFlusher previously used a TimeOutTask but that was using a dedicated thread, so instead an AsyncPeriodicTimer is used.

Note that it is important that Reset() on the AsyncPeriodicTimer can be called from within the timeout task - i.e. without creating a dead-lock. This is because LSS::Flush() will very often synchronously call LazyFlusher::SignalDontNeedToFlush().

Code


class LazyFlusher
{
public:
    LazyFlusher(LSS& lss);
    void Start();
    void Stop();
    void SignalDontNeedToFlush();

private:
    LSS& lss_;
    std::shared_ptr<AsyncPeriodicTimer> timer_;
};