×


FileHelper
- Found In File: FileHelper.h





This class aids Serenity's targets in file related operations. This includes things such as: opening and closing the file, writing to the buffer, setting the file buffer size, flushing the buffer to the file, controlling the background flush thread, and renaming the log file.

This class is composed from the following classes:
Click here for a file snippet:

This class is found under the namespace serenity::target::helpers in file FileHelper.h

   constexpr size_t max_size_size_t { (size_t)-1 };
   constexpr size_t pageSize =
   #if defined(_WIN32) && not defined(_WIN64)
     static_cast<size_t>(2 * MB);
   #elif defined _WIN64
     static_cast<size_t>(4 * MB);
   #else
     static_cast<size_t>(DEFAULT_BUFFER_SIZE);
   #endif    // _WIN32 && !_WIN64
   class FileHelper
   {
     public:
       explicit FileHelper(const std::string_view fpath);
       FileHelper(FileHelper&)            = delete;
       FileHelper& operator=(FileHelper&) = delete;
       ~FileHelper()                      = default;
       bool OpenFile(bool truncate = false);
       void WriteToFile(size_t writeLimit = max_size_size_t, bool truncateRest = false);
       void Flush();
       bool CloseFile(bool onRotation = false);
       std::vector<char>& FileBuffer();
       size_t FileBufferSize();
       void SetBufferCapacity(size_t value);
       void InitializeFilePath(std::string_view fileName = "");
       virtual bool RenameFile(utf_utils::InputSource newFileName);
       void BackgroundFlushThread(std::stop_token stopToken);
       void StopBackgroundThread();
       void StartBackgroundThread();
       void PauseBackgroundThread();
       void ResumeBackgroundThread();
       void SyncTargetHelpers(std::shared_ptr<BaseTargetHelper>& syncToHelper);
       const std::unique_ptr<FileCache>& FileCacheHelper() const;
       const std::unique_ptr<BackgroundThread>& BackgoundThreadInfo() const;
     private:
       void OpenImpl(bool truncate);
       void WriteImpl();
       void WriteImpl(size_t writeLimit, bool truncateRest = false);
       void FlushImpl();
       void CloseImpl();
     private:
       int retryAttempt;
       bool fileOpen;
       int file;
       std::vector<char> buffer;
       std::mutex fileHelperMutex;
       std::unique_ptr<FileCache> fileCache;
       std::shared_ptr<BaseTargetHelper> targetHelper;
       std::unique_ptr<BackgroundThread> flushWorker;
   };
            

Namespace Constexpr Globals
constexpr size_t max_size_size_t
This constexpr variable is set to the max size that type size_t can store and is simply used in checks in WriteToFile()
constexpr size_t pageSize
This constexpr variable is used in initially reserving the file buffer size and is used in writes to disk for chunking operations.

Public Functions
explicit FileHelper(const std::string_view fpath);
This is the only constructor available for this class.
bool OpenFile(bool truncate);
This function opens the file that was cached from the constructor.
void WriteToFile(size_t writeLimit, bool truncateRest);
This function is what's in charge of writing the log messages from the file buffer to disk.
void Flush();
This function is in charge of flushing the file buffer to the disk.
bool CloseFile(bool onRotation);
This function is in control of closing the file that was cached.
std::vector<char>& FileBuffer();
This function simply returns a reference to the file buffer being used.
size_t FileBufferSize();
This function returns the file buffer's current size.
void SetBufferCapacity(size_t value);
This function is used to set the file buffer's capacity.
void InitializeFilePath(std::string_view fileName);
This function is mainly used in the default constructors of the in-house targets, as well as the constructors that don't take in a file path, but do take a file name as a parameter.
virtual bool RenameFile(utf_utils::InputSource newFileName);
This virtual function is in charge of renaming the log file. This function is made virtual so that the targets may override the default behavior of this function if desired.
void BackgroundFlushThread(std::stop_token stopToken);
This function is the workload of the background thread in charge of flushing the file buffer to disk after some set interval has elapsed.
void StopBackgroundThread();
This function is in charge of stopping the background thread in charge of flushing the file buffer to disk.
void StartBackgroundThread();
This function is in charge of starting the background thread in charge of flushing the file buffer to disk.
void PauseBackgroundThread();
This function temporarily pauses the background thread in charge of flushing until it's notified that it can resume again.
void ResumeBackgroundThread();
void SyncTargetHelpers(std::shared_ptr<BaseTargetHelper>& syncToHelper);
This function simply points the member variable targetHelper to `syncToHelper` in order for this class to utilize the logging target's settings.
const std::unique_ptr<FileCache>& FileCacheHelper() const;
This function simply returns a const reference to the smart pointer member variable fileCache
const std::unique_ptr<BackgroundThread>& BackgoundThreadInfo() const;
This function simply returns a const reference to the smart pointer member variable flushWorker

Private Functions
void OpenImpl(bool truncate);
This function is called in OpenFile().
void WriteImpl();
This function is called in WriteToFile() and is the implementation block that writes bytes to disk.
void WriteImpl(size_t writeLimit, bool truncateRest);
This function is called in WriteToFile() and is the implementation block that writes bytes to disk.
void FlushImpl();
This function is called in Flush() and is in charge of flushing the entire file buffer to disk in an efficient manner using page size chunks to write.
void CloseImpl();
This function is in charge of the actual file close logic and is called from CloseFile()

More Information About Class FileHelper


constexpr size_t max_size_size_t
This constexpr variable is set to the max size that type size_t can store and is simply used in checks in WriteToFile()



constexpr size_t pageSize
This constexpr variable is used in initially reserving the file buffer size and is used in writes to disk for chunking operations.
  • This variable is set to:
    • x86-32: 2MB
    • x86-64: 4MB
    • default: DEFAULT_BUFFER_SIZE (this is set to 64KB)


explicit FileHelper(const std::string_view fpath);
This is the only constructor available for this class.
  • Parameter `fpath` is the path to the file, whether absolute or relative to the currently running process's directory.

  • This class constructor:
    • Instantiates a smart pointer to FileCache stored in member variable fileCache
    • Instantiates a smart pointer to BaseTargetHelper stored in member variable targetHelper
    • Instantiates a smart pointer to BackgroundThread stored in member variable flushWorker
    • Initially reserves the file buffer size to the platform's page size
      • x86-32: 2MB
      • x86-64: 4MB
      • default: DEFAULT_BUFFER_SIZE (this is set to 64KB)
      • NOTE: This size can be changed via the `void SetBufferCapacity(size_t value)` function
    This function takes a string_view as a file path to cache and passes this path to the member variable `fileCache`, which will break up the path into pieces to store. This is how the FileHelper class will refer to the file for open/close operations, renaming the file, etc.

    The member variable `targetHelper` is what is used to set the flush policy as well as what determines whether or not multi-threading support is enabled or disabled. This class is merely a link-step for the targets that use FileHelper in their composition and the values/handles are synced from the target side by calling this class's function `void SyncTargetHelpers(std::shared_ptr& syncToHelper)`. This allows the target itself to control multi-thread support and flush policy while this class uses those options for any background thread operations that take place.

    The member variable `flushWorker` is what is used for thread cooperation between the logging thread(s) and the background flushing thread when multi-thread support is enabled and/or when the flush policy is set to an interval based flush option. The relevant thread-related functions in this class use this smart pointer as well as `targetHelper` to minimize thread contention while logs are being written..



    bool OpenFile(bool truncate = false);
    This function opens the file that was cached from the constructor.
  • Parameter `truncate` is used to control whether or not the file is truncated on open if it already exists on disk
    • If multi-thread support is enabled, this function will :
      • Lock this class's mutex `fileHelperMutex`
      • Call PauseBackgroundThread() - this call does nothing if a background flush thread isn't active
      • Call OpenImpl(truncate) - the actual file open implementation
      • Call ResumeBackgroundThread() - this call does nothing if a background flush thread isn't active
      • returns true on success and false on failure

    • Otherwise, if multi-thread support is disabled, this function will effectively:
      • Call OpenImpl(truncate) - the actual file open implementation
      • returns true on success and false on failure


    void WriteToFile(size_t writeLimit = max_size_size_t, bool truncateRest = false);
    This function is what's in charge of writing the log messages from the file buffer to disk.
  • Parameter `writeLimit` is used to control how many bytes are written
  • Parameter `truncateRest` is used to control whether or not the rest of the buffer is ignored and erased after writeLimit bytes have been written to the file.
    • If writeLimit is equal to max_size_size_t:
      • Calls WriteImpl()
        - effectively only writes the file buffer to disk if the file buffer's size is greater than or equal to the page size

    • Otherwise if writeLimit is less than max_size_size_t:
      • Calls WriteImpl(writeLimit, truncateRest)
        - writes out the number of bytes specified by writeLimit and erases the rest dependant on whether or not truncateRest = true


    void Flush();
    This function is in charge of flushing the file buffer to the disk.
    • This function will:
      • Check if the background flush thread is active
      • If the thread is active, this function will:
        • Notify the thread that a manual flush is being called from the logger thread
        • Lock the FileHelper mutex
        • Call FlushImpl()
        • Unlock The Mutex
        • Notify the background thread that the manual flush is done
      • Otherwise, this function will simply call FlushImpl()


    bool CloseFile(bool onRotation = false);
    This function is in control of closing the file that was cached.
  • Parameter `onRotation` is used to control whether the buffer is flushed to disk before close or not.
  • As the name implies, this is mostly just used for the RotatingTarget and is why this parameter's default value is false.
    • If multi-thread support is enabled, this function will:
      • Lock FileHelper's mutex
      • Call PauseBackgroundThread() - this call does nothing if a background flush thread isn't active
      • If onRotation=false, calls Flush()
      • Call CloseImpl()
      • return true if the file was successfully closed and false if it wasn't

    • Otherwise, this function will:
      • Call PauseBackgroundThread() - this call does nothing if a background flush thread isn't active
      • If onRotation=false, calls Flush()
      • Call CloseImpl()
      • return true if the file was successfully closed and false if it wasn't


    std::vector<char>& FileBuffer();
    This function simply returns a reference to the file buffer being used.



    size_t FileBufferSize();
    This function returns the file buffer's current size.



    void SetBufferCapacity(size_t value);
    This function is used to set the file buffer's capacity.
  • Parameter `value` is used to set the new size of the file buffer.
    • NOTE: The default sizes for the file buffer are listed below:
      • x86-32: 2MB
      • x86-64: 4MB
      • Everything else: DEFAULT_BUFFER_SIZE (this is set to 64KB)


    void InitializeFilePath(std::string_view fileName = "");
    This function is mainly used in the default constructors of the in-house targets, as well as the constructors that don't take in a file path, but do take a file name as a parameter.
  • Parameter `fileName` is used to set the name of the log file.

  • This function will:
    • Initialize the file path to the currently running process's directory + "Logs" + `fileName`
    • If parameter `fileName` is empty:
      • The log file will be named "Generic_Log.txt"
      • Otherwise the log file will be named `fileName`
    • Call `CacheFile()` to store the relevant segments of the file path


    virtual bool RenameFile(utf_utils::InputSource newFileName);
    This virtual function is in charge of renaming the log file. This function is made virtual so that the targets may override the default behavior of this function if desired. An example of this is in RotateTarget's `RenameFile()` override.
  • Parameter `newFileName` is used to set the new name of the log file.

  • This function's default behavior will:
    • Close the file if the file is open
    • Retrieve the current file path
    • Try to rename the file
    • Sets the new file path with the newly named file
    • Opens the file
    • This function returns true if the below conditions are met:
      • The file was successfully closed
      • The file was successfully renamed
      • The file was successfully re-opened
    • Otherwise, this function returns false


    void BackgroundFlushThread(std::stop_token stopToken);
    This function is the workload of the background thread in charge of flushing the file buffer to disk after some set interval has elapsed.
  • Parameter `stopToken` is used from the logger thread as a signal for gracefully terminating this worker thread.
    • This function simply:
      • Iterates in a while loop until the atomic cleanUpThreads=true
      • While the atomic cleanUpThreads=false, this function:
        • Checks if a request for stopping the workload has been issued
          • If not, continues
          • If so, returns from this function, joining the background thread
        • Checks if a request to temporarily pause the thread has been issued
          • If not, calls Flush()
          • If so, first waits for the logger thread to notify when this thread can continue, then calls Flush()
        • This thread is then put to sleep for the interval specified by the flush policy before the next iteration continues.
    Both the stop_token used in this function and the atomic cleanUpThreads are located in the struct BackgroundThread



    void StopBackgroundThread();
    This function is in charge of stopping the background thread in charge of flushing the file buffer to disk.

    This function will:
    • If the background thread isn't active, does nothing and returns
    • Request the background thread to stop
    • Set the atomic cleanUpThreads to true
    • Notify the background thread that cleanUpThreads has been changed
    • Join the background thread
    • Set the flush policy to never
      • this is to stop a thread instantiation occurring when the targets check the flush policy on the next log call
    • Set the atomic flushThreadEnabled to false
    Both the atomic cleanUpThreads and the atomic flushThreadEnabled are located in the struct BackgroundThread



    void StartBackgroundThread();
    This function is in charge of starting the background thread in charge of flushing the file buffer to disk.

    This function will:
    • If the background thread is already active, does nothing and returns
    • Sets the flush policy to FlushSetting::periodically
      • This is to ensure that the flush thread isn't wasting time and resources
    • Set the atomic cleanUpThreads to false if not already
    • Initializes and kicks off the background thread in charge of flushing
    • Set the atomic flushThreadEnabled to true
    Both the atomic cleanUpThreads and the atomic flushThreadEnabled are located in the struct BackgroundThread



    void PauseBackgroundThread();
    This function temporarily pauses the background thread in charge of flushing until it's notified that it can resume again.

  • This function sets the atomic pauseThread to true and then notifies the background thread of this change
  • This essentially puts the thread into indefinite sleep until the atomic changes again

  • The atomic pauseThread is located in the struct BackgroundThread



    void ResumeBackgroundThread();
    This function resumes the background thread in charge of flushing.

  • This function sets the atomic pauseThread to false and then notifies the background thread of this change
  • This essentially resumes the flush loop in BackgroundThread()
  • This function does nothing if
  • The background thread was never launched
  • The background thread was never paused

  • The atomic pauseThread is located in the struct BackgroundThread



    void SyncTargetHelpers(std::shared_ptr<BaseTargetHelper>& syncToHelper);
    This function simply points the member variable targetHelper to `syncToHelper` in order for this class to utilize the logging target's settings.
  • Parameter `syncToHelper` is a shared_ptr to a BaseTargetHelper object from the target logger.



  • const std::unique_ptr<FileCache>& FileCacheHelper() const;
    This function simply returns a const reference to the smart pointer member variable fileCache



    const std::unique_ptr<BackgroundThread>& BackgoundThreadInfo() const;
    This function simply returns a const reference to the smart pointer member variable flushWorker



    private: void OpenImpl(bool truncate);
    This function is called in OpenFile().
    • This function will:
      • Retrieve the cached file path
      • Create the appropriate directories if they aren't present
      • If the file itself doesn't already exist, this function will create the file
      • Open the file
      • If truncate is set to true, this will truncate the file on open
      • Sets the member variable fileOpen to:
        • true on successful open
        • false otherwise.


    private: void WriteImpl();
    This function is called in WriteToFile() and is the implementation block that writes bytes to disk.
  • This function is used to effectively only write to disk when it's efficient to do so as to avoid the overhead of constant write calls.
  • To bypass this behavior and manually write to disk, please refer to the function, Flush()
    • This function will :
      • Do nothing and return if the file buffer's size is less than the page size
      • Write one page sized chunk from the file buffer to disk
      • Erase the same page sized chunk from the file buffer


    private: void WriteImpl(size_t writeLimit, bool truncateRest = false);
    This function is called in WriteToFile() and is the implementation block that writes bytes to disk.
  • Parameter `writeLimit` is used to control how many bytes are written
  • Parameter `truncateRest` is used to control whether or not the rest of the buffer is ignored and erased after writeLimit bytes have been written to the file.
    • This function will:
      • Do nothing and return if the file buffer size is less than the writeLimit bytes specified
      • Write the specified number of bytes from the file buffer to disk
      • Erase the specified number of bytes from the file buffer after writing them to disk
        • If truncateRest = true, this will clear the entire buffer after the write instead


    private: void FlushImpl();
    This function is called in Flush() and is in charge of flushing the entire file buffer to disk in an efficient manner using page size chunks to write.
    • If the file buffer size is greater than the page size, this function will:
      • Calculate how many chunks the file buffer needs to be broken up into
      • In a loop, write out the number of chunks to disk, erasing them from the buffer afterwards
      • Writes out the remaining bytes left over that didn't fit the chunk size earlier before clearing the buffer
    • Otherwise, if the file buffer size is less than the page size, this function will:
      • Simply write the whole file buffer contents to disk in one chunk
      • Clear the file buffer


    private: void CloseImpl();
    This function is in charge of the actual file close logic and is called from CloseFile()
    • This function will:
      • Do nothing and return if the file is already closed
      • Close the file
      • Sets the member variable fileOpen to:
        • false on successful close
        • true otherwise to indicate file close was unsuccessful.