339 lines
14 KiB
C++
339 lines
14 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license.
|
|
// (https://developers.google.com/open-source/licenses/bsd)
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "common/status.h"
|
|
#include "util/slice.h"
|
|
|
|
namespace starrocks {
|
|
|
|
class RandomAccessFile;
|
|
class RandomRWFile;
|
|
class WritableFile;
|
|
class SequentialFile;
|
|
struct WritableFileOptions;
|
|
struct RandomAccessFileOptions;
|
|
struct RandomRWFileOptions;
|
|
|
|
class Env {
|
|
public:
|
|
// Governs if/how the file is created.
|
|
//
|
|
// enum value | file exists | file does not exist
|
|
// -----------------------------+-------------------+--------------------
|
|
// CREATE_OR_OPEN_WITH_TRUNCATE | opens + truncates | creates
|
|
// CREATE_OR_OPEN | opens | creates
|
|
// MUST_CREATE | fails | creates
|
|
// MUST_EXIST | opens | fails
|
|
enum OpenMode { CREATE_OR_OPEN_WITH_TRUNCATE, CREATE_OR_OPEN, MUST_CREATE, MUST_EXIST };
|
|
|
|
Env() = default;
|
|
virtual ~Env() = default;
|
|
|
|
// Return a default environment suitable for the current operating
|
|
// system. Sophisticated users may wish to provide their own Env
|
|
// implementation instead of relying on this default environment.
|
|
static Env* Default();
|
|
|
|
// Create a brand new sequentially-readable file with the specified name.
|
|
// On success, stores a pointer to the new file in *result and returns OK.
|
|
// On failure stores NULL in *result and returns non-OK. If the file does
|
|
// not exist, returns a non-OK status.
|
|
//
|
|
// The returned file will only be accessed by one thread at a time.
|
|
virtual Status new_sequential_file(const std::string& fname, std::unique_ptr<SequentialFile>* result) = 0;
|
|
|
|
// Create a brand new random access read-only file with the
|
|
// specified name. On success, stores a pointer to the new file in
|
|
// *result and returns OK. On failure stores nullptr in *result and
|
|
// returns non-OK. If the file does not exist, returns a non-OK
|
|
// status.
|
|
//
|
|
// The returned file may be concurrently accessed by multiple threads.
|
|
virtual Status new_random_access_file(const std::string& fname, std::unique_ptr<RandomAccessFile>* result) = 0;
|
|
|
|
virtual Status new_random_access_file(const RandomAccessFileOptions& opts, const std::string& fname,
|
|
std::unique_ptr<RandomAccessFile>* result) = 0;
|
|
|
|
// Create an object that writes to a new file with the specified
|
|
// name. Deletes any existing file with the same name and creates a
|
|
// new file. On success, stores a pointer to the new file in
|
|
// *result and returns OK. On failure stores NULL in *result and
|
|
// returns non-OK.
|
|
//
|
|
// The returned file will only be accessed by one thread at a time.
|
|
virtual Status new_writable_file(const std::string& fname, std::unique_ptr<WritableFile>* result) = 0;
|
|
|
|
// Like the previous new_writable_file, but allows options to be
|
|
// specified.
|
|
virtual Status new_writable_file(const WritableFileOptions& opts, const std::string& fname,
|
|
std::unique_ptr<WritableFile>* result) = 0;
|
|
|
|
// Creates a new readable and writable file. If a file with the same name
|
|
// already exists on disk, it is deleted.
|
|
//
|
|
// Some of the methods of the new file may be accessed concurrently,
|
|
// while others are only safe for access by one thread at a time.
|
|
virtual Status new_random_rw_file(const std::string& fname, std::unique_ptr<RandomRWFile>* result) = 0;
|
|
|
|
// Like the previous new_random_rw_file, but allows options to be specified.
|
|
virtual Status new_random_rw_file(const RandomRWFileOptions& opts, const std::string& fname,
|
|
std::unique_ptr<RandomRWFile>* result) = 0;
|
|
|
|
// Returns OK if the path exists.
|
|
// NotFound if the named file does not exist,
|
|
// the calling process does not have permission to determine
|
|
// whether this file exists, or if the path is invalid.
|
|
// IOError if an IO Error was encountered
|
|
virtual Status path_exists(const std::string& fname) = 0;
|
|
|
|
// Store in *result the names of the children of the specified directory.
|
|
// The names are relative to "dir".
|
|
// Original contents of *results are dropped.
|
|
// Returns OK if "dir" exists and "*result" contains its children.
|
|
// NotFound if "dir" does not exist, the calling process does not have
|
|
// permission to access "dir", or if "dir" is invalid.
|
|
// IOError if an IO Error was encountered
|
|
virtual Status get_children(const std::string& dir, std::vector<std::string>* result) = 0;
|
|
|
|
// Iterate the specified directory and call given callback function with child's
|
|
// name. This function continues execution until all children have been iterated
|
|
// or callback function return false.
|
|
// The names are relative to "dir".
|
|
//
|
|
// The function call extra cost is acceptable. Compared with returning all children
|
|
// into a given vector, the performance of this method is 5% worse. However this
|
|
// approach is more flexiable and efficient in fulfilling other requirements.
|
|
//
|
|
// Returns OK if "dir" exists.
|
|
// NotFound if "dir" does not exist, the calling process does not have
|
|
// permission to access "dir", or if "dir" is invalid.
|
|
// IOError if an IO Error was encountered
|
|
virtual Status iterate_dir(const std::string& dir, const std::function<bool(const char*)>& cb) = 0;
|
|
|
|
// Delete the named file.
|
|
virtual Status delete_file(const std::string& fname) = 0;
|
|
|
|
// Create the specified directory.
|
|
// NOTE: It will return error if the path already exist(not necessarily as a directory)
|
|
virtual Status create_dir(const std::string& dirname) = 0;
|
|
|
|
// Creates directory if missing.
|
|
// Return OK if it exists, or successful in Creating.
|
|
virtual Status create_dir_if_missing(const std::string& dirname, bool* created = nullptr) = 0;
|
|
|
|
// Delete the specified directory.
|
|
// NOTE: The dir must be empty.
|
|
virtual Status delete_dir(const std::string& dirname) = 0;
|
|
|
|
// Synchronize the entry for a specific directory.
|
|
virtual Status sync_dir(const std::string& dirname) = 0;
|
|
|
|
// Checks if the file is a directory. Returns an error if it doesn't
|
|
// exist, otherwise writes true or false into 'is_dir' appropriately.
|
|
virtual Status is_directory(const std::string& path, bool* is_dir) = 0;
|
|
|
|
// Canonicalize 'path' by applying the following conversions:
|
|
// - Converts a relative path into an absolute one using the cwd.
|
|
// - Converts '.' and '..' references.
|
|
// - Resolves all symbolic links.
|
|
//
|
|
// All directory entries in 'path' must exist on the filesystem.
|
|
virtual Status canonicalize(const std::string& path, std::string* result) = 0;
|
|
|
|
virtual Status get_file_size(const std::string& fname, uint64_t* size) = 0;
|
|
|
|
// Store the last modification time of fname in *file_mtime.
|
|
virtual Status get_file_modified_time(const std::string& fname, uint64_t* file_mtime) = 0;
|
|
// Rename file src to target.
|
|
virtual Status rename_file(const std::string& src, const std::string& target) = 0;
|
|
|
|
// create a hard-link
|
|
virtual Status link_file(const std::string& /*old_path*/, const std::string& /*new_path*/) = 0;
|
|
};
|
|
|
|
struct RandomAccessFileOptions {
|
|
RandomAccessFileOptions() {}
|
|
};
|
|
|
|
// Creation-time options for WritableFile
|
|
struct WritableFileOptions {
|
|
// Call Sync() during Close().
|
|
bool sync_on_close = false;
|
|
// See OpenMode for details.
|
|
Env::OpenMode mode = Env::CREATE_OR_OPEN_WITH_TRUNCATE;
|
|
};
|
|
|
|
// Creation-time options for RWFile
|
|
struct RandomRWFileOptions {
|
|
// Call Sync() during Close().
|
|
bool sync_on_close = false;
|
|
// See OpenMode for details.
|
|
Env::OpenMode mode = Env::CREATE_OR_OPEN_WITH_TRUNCATE;
|
|
};
|
|
|
|
// A file abstraction for reading sequentially through a file
|
|
class SequentialFile {
|
|
public:
|
|
SequentialFile() = default;
|
|
virtual ~SequentialFile() = default;
|
|
|
|
// Read up to "result.size" bytes from the file.
|
|
// Copies the resulting data into "result.data".
|
|
//
|
|
// If an error was encountered, returns a non-OK status
|
|
// and the contents of "result" are invalid.
|
|
//
|
|
// Return OK if reached the end of file.
|
|
//
|
|
// REQUIRES: External synchronization
|
|
virtual Status read(Slice* result) = 0;
|
|
|
|
// Skip "n" bytes from the file. This is guaranteed to be no
|
|
// slower that reading the same data, but may be faster.
|
|
//
|
|
// If end of file is reached, skipping will stop at the end of the
|
|
// file, and Skip will return OK.
|
|
//
|
|
// REQUIRES: External synchronization
|
|
virtual Status skip(uint64_t n) = 0;
|
|
|
|
// Returns the filename provided when the SequentialFile was constructed.
|
|
virtual const std::string& filename() const = 0;
|
|
};
|
|
|
|
class RandomAccessFile {
|
|
public:
|
|
RandomAccessFile() = default;
|
|
virtual ~RandomAccessFile() = default;
|
|
|
|
// Read up to "result.size" bytes from the file.
|
|
// Copies the resulting data into "result.data".
|
|
//
|
|
// Return OK if reached the end of file.
|
|
virtual Status read(uint64_t offset, Slice* res) const = 0;
|
|
|
|
// Read "result.size" bytes from the file starting at "offset".
|
|
// Copies the resulting data into "result.data".
|
|
//
|
|
// If an error was encountered, returns a non-OK status.
|
|
//
|
|
// This method will internally retry on EINTR and "short reads" in order to
|
|
// fully read the requested number of bytes. In the event that it is not
|
|
// possible to read exactly 'length' bytes, an IOError is returned.
|
|
//
|
|
// Safe for concurrent use by multiple threads.
|
|
virtual Status read_at(uint64_t offset, const Slice& result) const = 0;
|
|
|
|
// Reads up to the "results" aggregate size, based on each Slice's "size",
|
|
// from the file starting at 'offset'. The Slices must point to already-allocated
|
|
// buffers for the data to be written to.
|
|
//
|
|
// If an error was encountered, returns a non-OK status.
|
|
//
|
|
// This method will internally retry on EINTR and "short reads" in order to
|
|
// fully read the requested number of bytes. In the event that it is not
|
|
// possible to read exactly 'length' bytes, an IOError is returned.
|
|
//
|
|
// Safe for concurrent use by multiple threads.
|
|
virtual Status readv_at(uint64_t offset, const Slice* res, size_t res_cnt) const = 0;
|
|
|
|
// Return the size of this file
|
|
virtual Status size(uint64_t* size) const = 0;
|
|
|
|
// Return name of this file
|
|
virtual const std::string& file_name() const = 0;
|
|
};
|
|
|
|
// A file abstraction for sequential writing. The implementation
|
|
// must provide buffering since callers may append small fragments
|
|
// at a time to the file.
|
|
// Note: To avoid user misuse, WritableFile's API should support only
|
|
// one of Append or PositionedAppend. We support only Append here.
|
|
class WritableFile {
|
|
public:
|
|
enum FlushMode { FLUSH_SYNC, FLUSH_ASYNC };
|
|
|
|
WritableFile() = default;
|
|
virtual ~WritableFile() = default;
|
|
|
|
// Append data to the end of the file
|
|
virtual Status append(const Slice& data) = 0;
|
|
|
|
// If possible, uses scatter-gather I/O to efficiently append
|
|
// multiple buffers to a file. Otherwise, falls back to regular I/O.
|
|
//
|
|
// For implementation specific quirks and details, see comments in
|
|
// implementation source code (e.g., env_posix.cc)
|
|
virtual Status appendv(const Slice* data, size_t cnt) = 0;
|
|
|
|
// Pre-allocates 'size' bytes for the file in the underlying filesystem.
|
|
// size bytes are added to the current pre-allocated size or to the current
|
|
// offset, whichever is bigger. In no case is the file truncated by this
|
|
// operation.
|
|
//
|
|
// On some implementations, preallocation is done without initializing the
|
|
// contents of the data blocks (as opposed to writing zeroes), requiring no
|
|
// IO to the data blocks.
|
|
//
|
|
// In no case is the file truncated by this operation.
|
|
virtual Status pre_allocate(uint64_t size) = 0;
|
|
|
|
virtual Status close() = 0;
|
|
|
|
// Flush all dirty data (not metadata) to disk.
|
|
//
|
|
// If the flush mode is synchronous, will wait for flush to finish and
|
|
// return a meaningful status.
|
|
virtual Status flush(FlushMode mode) = 0;
|
|
|
|
virtual Status sync() = 0;
|
|
|
|
virtual uint64_t size() const = 0;
|
|
|
|
// Returns the filename provided when the WritableFile was constructed.
|
|
virtual const std::string& filename() const = 0;
|
|
|
|
private:
|
|
// No copying allowed
|
|
WritableFile(const WritableFile&);
|
|
void operator=(const WritableFile&);
|
|
};
|
|
|
|
// A file abstraction for random reading and writing.
|
|
class RandomRWFile {
|
|
public:
|
|
enum FlushMode { FLUSH_SYNC, FLUSH_ASYNC };
|
|
RandomRWFile() = default;
|
|
virtual ~RandomRWFile() = default;
|
|
|
|
virtual Status read_at(uint64_t offset, const Slice& result) const = 0;
|
|
|
|
virtual Status readv_at(uint64_t offset, const Slice* res, size_t res_cnt) const = 0;
|
|
|
|
virtual Status write_at(uint64_t offset, const Slice& data) = 0;
|
|
|
|
virtual Status writev_at(uint64_t offset, const Slice* data, size_t data_cnt) = 0;
|
|
|
|
virtual Status flush(FlushMode mode, uint64_t offset, size_t length) = 0;
|
|
|
|
virtual Status sync() = 0;
|
|
|
|
virtual Status close() = 0;
|
|
|
|
virtual Status size(uint64_t* size) const = 0;
|
|
virtual const std::string& filename() const = 0;
|
|
};
|
|
|
|
} // namespace starrocks
|