memgraph/src/utils/file.hpp
Matej Ferencevic 9291a5fc4d Migrate to C++17
Reviewers: teon.banek, buda

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1974
2019-04-23 14:46:44 +02:00

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