Reviewers: teon.banek, buda Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1974
100 lines
3.8 KiB
C++
100 lines
3.8 KiB
C++
/**
|
|
* @file
|
|
*
|
|
* This file contains utilities for operations with files. Other than utility
|
|
* functions, a `File` class is provided which emulates a `fstream`.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <filesystem>
|
|
|
|
namespace utils {
|
|
|
|
/// Reads all lines from the file specified by path. If the file doesn't exist
|
|
/// or there is an access error the function returns an empty list.
|
|
std::vector<std::string> ReadLines(const std::filesystem::path &path) noexcept;
|
|
|
|
/// Ensures that the given directory either exists after this call. If the
|
|
/// directory didn't exist prior to the call it is created, if it existed prior
|
|
/// to the call it is left as is.
|
|
bool EnsureDir(const std::filesystem::path &dir) noexcept;
|
|
|
|
/// Calls `EnsureDir` and terminates the program if the call failed. It prints
|
|
/// an error message for which directory the ensuring failed.
|
|
void EnsureDirOrDie(const std::filesystem::path &dir);
|
|
|
|
/// Deletes everything from the given directory including the directory.
|
|
bool DeleteDir(const std::filesystem::path &dir) noexcept;
|
|
|
|
/// Copies the file from `src` to `dst`.
|
|
bool CopyFile(const std::filesystem::path &src,
|
|
const std::filesystem::path &dst) noexcept;
|
|
|
|
/// This class implements a file handler that is used for mission critical files
|
|
/// that need to be written and synced to permanent storage. Typical usage for
|
|
/// this class is in implementation of write-ahead logging or anything similar
|
|
/// that requires that data that is written *must* be stored in permanent
|
|
/// storage.
|
|
///
|
|
/// If any of the methods fails with a critical error *they will crash* the
|
|
/// whole program. The reasoning is that if you have some data that is mission
|
|
/// critical to be written to permanent storage and you fail in doing so you
|
|
/// aren't safe to continue your operation. The errors that can occur are mainly
|
|
/// EIO (unrecoverable underlying storage error) or ENOSPC (the underlying
|
|
/// storage has no more space).
|
|
///
|
|
/// The typical usage for this class when writing data to the file is that you
|
|
/// call `Write` as many times as necessary to write one logical part of your
|
|
/// data and only then you call `Sync`. For the write-ahead log example that
|
|
/// would mean that you call `Write` until you write a whole single state delta
|
|
/// and only after that you call `Sync` to ensure that the whole delta was
|
|
/// written to permanent storage.
|
|
///
|
|
/// This class *isn't* thread safe. It is implemented as a wrapper around low
|
|
/// level system calls used for file manipulation.
|
|
class LogFile {
|
|
public:
|
|
LogFile() = default;
|
|
~LogFile();
|
|
|
|
LogFile(const LogFile &) = delete;
|
|
LogFile &operator=(const LogFile &) = delete;
|
|
|
|
LogFile(LogFile &&other);
|
|
LogFile &operator=(LogFile &&other);
|
|
|
|
/// This method opens a new file used for writing. If the file doesn't exist
|
|
/// it is created and if the file exists data is appended to the file to
|
|
/// ensure that no data is ever lost. Files are created with a restrictive
|
|
/// permission mask (0640). On failure and misuse it crashes the program.
|
|
void Open(const std::filesystem::path &path);
|
|
|
|
/// Returns a boolean indicating whether a file is opened.
|
|
bool IsOpen() const;
|
|
|
|
/// Returns the path to the currently opened file. If a file isn't opened the
|
|
/// path is empty.
|
|
const std::filesystem::path &path() const;
|
|
|
|
/// Writes data to the currently opened file. On failure and misuse it crashes
|
|
/// the program.
|
|
void Write(const char *data, size_t size);
|
|
void Write(const uint8_t *data, size_t size);
|
|
void Write(const std::string &data);
|
|
|
|
/// Syncs currently pending data to the currently opened file. On failure
|
|
/// and misuse it crashes the program.
|
|
void Sync();
|
|
|
|
/// Closes the currently opened file. It doesn't perform a `Sync` on the
|
|
/// file. On failure and misuse it crashes the program.
|
|
void Close();
|
|
|
|
private:
|
|
int fd_{-1};
|
|
size_t written_since_last_sync_{0};
|
|
std::filesystem::path path_;
|
|
};
|
|
|
|
} // namespace utils
|