2019-11-27 09:39:44 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-12-12 08:57:25 +00:00
|
|
|
#include <Core/Defines.h>
|
2020-09-15 09:55:57 +00:00
|
|
|
#include <common/types.h>
|
2019-11-27 09:39:44 +00:00
|
|
|
#include <Common/CurrentMetrics.h>
|
|
|
|
#include <Common/Exception.h>
|
2020-08-11 19:08:32 +00:00
|
|
|
#include <Disks/Executor.h>
|
2019-11-27 09:39:44 +00:00
|
|
|
|
|
|
|
#include <memory>
|
2019-12-17 13:45:53 +00:00
|
|
|
#include <mutex>
|
2019-11-27 09:39:44 +00:00
|
|
|
#include <utility>
|
|
|
|
#include <boost/noncopyable.hpp>
|
2019-12-27 10:26:23 +00:00
|
|
|
#include <Poco/Path.h>
|
2020-03-05 14:02:15 +00:00
|
|
|
#include <Poco/Timestamp.h>
|
2019-11-27 09:39:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace CurrentMetrics
|
|
|
|
{
|
|
|
|
extern const Metric DiskSpaceReservedForMerge;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2019-12-03 13:37:40 +00:00
|
|
|
class IDiskDirectoryIterator;
|
|
|
|
using DiskDirectoryIteratorPtr = std::unique_ptr<IDiskDirectoryIterator>;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
|
|
|
class IReservation;
|
2020-05-16 20:31:17 +00:00
|
|
|
using ReservationPtr = std::unique_ptr<IReservation>;
|
2020-05-24 16:32:58 +00:00
|
|
|
using Reservations = std::vector<ReservationPtr>;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2020-02-14 14:28:33 +00:00
|
|
|
class ReadBufferFromFileBase;
|
2020-02-20 16:39:32 +00:00
|
|
|
class WriteBufferFromFileBase;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-26 14:28:22 +00:00
|
|
|
/**
|
|
|
|
* Mode of opening a file for write.
|
|
|
|
*/
|
|
|
|
enum class WriteMode
|
|
|
|
{
|
|
|
|
Rewrite,
|
|
|
|
Append
|
|
|
|
};
|
|
|
|
|
2019-11-27 09:39:44 +00:00
|
|
|
/**
|
2019-11-27 15:49:15 +00:00
|
|
|
* Provide interface for reservation.
|
2019-11-27 09:39:44 +00:00
|
|
|
*/
|
|
|
|
class Space : public std::enable_shared_from_this<Space>
|
|
|
|
{
|
|
|
|
public:
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return the name of the space object.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual const String & getName() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Reserve the specified number of bytes.
|
|
|
|
virtual ReservationPtr reserve(UInt64 bytes) = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
|
|
|
virtual ~Space() = default;
|
|
|
|
};
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
using SpacePtr = std::shared_ptr<Space>;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-11-28 19:11:49 +00:00
|
|
|
/**
|
|
|
|
* A unit of storage persisting data and metadata.
|
|
|
|
* Abstract underlying storage technology.
|
|
|
|
* Responsible for:
|
|
|
|
* - file management;
|
|
|
|
* - space accounting and reservation.
|
|
|
|
*/
|
2019-11-27 09:39:44 +00:00
|
|
|
class IDisk : public Space
|
|
|
|
{
|
|
|
|
public:
|
2020-08-11 19:08:32 +00:00
|
|
|
/// Default constructor.
|
|
|
|
explicit IDisk(std::unique_ptr<Executor> executor_ = std::make_unique<SyncExecutor>()) : executor(std::move(executor_)) { }
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Root path for all files stored on the disk.
|
|
|
|
/// It's not required to be a local filesystem path.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual const String & getPath() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Total available space on the disk.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual UInt64 getTotalSpace() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Space currently available on the disk.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual UInt64 getAvailableSpace() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Space available for reservation (available space minus reserved space).
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual UInt64 getUnreservedSpace() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Amount of bytes which should be kept free on the disk.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual UInt64 getKeepingFreeSpace() const { return 0; }
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return `true` if the specified file exists.
|
|
|
|
virtual bool exists(const String & path) const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return `true` if the specified file exists and it's a regular file (not a directory or special file type).
|
|
|
|
virtual bool isFile(const String & path) const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return `true` if the specified file exists and it's a directory.
|
|
|
|
virtual bool isDirectory(const String & path) const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-12 08:57:25 +00:00
|
|
|
/// Return size of the specified file.
|
|
|
|
virtual size_t getFileSize(const String & path) const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Create directory.
|
|
|
|
virtual void createDirectory(const String & path) = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Create directory and all parent directories if necessary.
|
|
|
|
virtual void createDirectories(const String & path) = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2020-01-18 23:18:23 +00:00
|
|
|
/// Remove all files from the directory. Directories are not removed.
|
2019-12-12 08:57:25 +00:00
|
|
|
virtual void clearDirectory(const String & path) = 0;
|
|
|
|
|
|
|
|
/// Move directory from `from_path` to `to_path`.
|
|
|
|
virtual void moveDirectory(const String & from_path, const String & to_path) = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return iterator to the contents of the specified directory.
|
|
|
|
virtual DiskDirectoryIteratorPtr iterateDirectory(const String & path) = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2019-12-12 08:57:25 +00:00
|
|
|
/// Return `true` if the specified directory is empty.
|
|
|
|
bool isDirectoryEmpty(const String & path);
|
|
|
|
|
2020-03-19 16:37:55 +00:00
|
|
|
/// Create empty file at `path`.
|
|
|
|
virtual void createFile(const String & path) = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Move the file from `from_path` to `to_path`.
|
2020-01-02 14:37:31 +00:00
|
|
|
/// If a file with `to_path` path already exists, an exception will be thrown .
|
2019-12-03 13:37:40 +00:00
|
|
|
virtual void moveFile(const String & from_path, const String & to_path) = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2020-01-02 14:37:31 +00:00
|
|
|
/// Move the file from `from_path` to `to_path`.
|
|
|
|
/// If a file with `to_path` path already exists, it will be replaced.
|
|
|
|
virtual void replaceFile(const String & from_path, const String & to_path) = 0;
|
|
|
|
|
2020-03-19 16:37:55 +00:00
|
|
|
/// Recursively copy data containing at `from_path` to `to_path` located at `to_disk`.
|
|
|
|
virtual void copy(const String & from_path, const std::shared_ptr<IDisk> & to_disk, const String & to_path);
|
|
|
|
|
2020-02-28 17:14:55 +00:00
|
|
|
/// List files at `path` and add their names to `file_names`
|
|
|
|
virtual void listFiles(const String & path, std::vector<String> & file_names) = 0;
|
|
|
|
|
2020-02-20 16:39:32 +00:00
|
|
|
/// Open the file for read and return ReadBufferFromFileBase object.
|
|
|
|
virtual std::unique_ptr<ReadBufferFromFileBase> readFile(
|
|
|
|
const String & path,
|
|
|
|
size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE,
|
|
|
|
size_t estimated_size = 0,
|
|
|
|
size_t aio_threshold = 0,
|
|
|
|
size_t mmap_threshold = 0) const = 0;
|
|
|
|
|
|
|
|
/// Open the file for write and return WriteBufferFromFileBase object.
|
|
|
|
virtual std::unique_ptr<WriteBufferFromFileBase> writeFile(
|
|
|
|
const String & path,
|
|
|
|
size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE,
|
|
|
|
WriteMode mode = WriteMode::Rewrite,
|
|
|
|
size_t estimated_size = 0,
|
|
|
|
size_t aio_threshold = 0) = 0;
|
2019-12-17 13:45:53 +00:00
|
|
|
|
2020-01-18 23:18:23 +00:00
|
|
|
/// Remove file or directory. Throws exception if file doesn't exists or if directory is not empty.
|
|
|
|
virtual void remove(const String & path) = 0;
|
|
|
|
|
|
|
|
/// Remove file or directory with all children. Use with extra caution. Throws exception if file doesn't exists.
|
|
|
|
virtual void removeRecursive(const String & path) = 0;
|
2020-03-05 14:02:15 +00:00
|
|
|
|
2020-03-19 16:37:55 +00:00
|
|
|
/// Remove file or directory if it exists.
|
|
|
|
void removeIfExists(const String & path)
|
|
|
|
{
|
|
|
|
if (exists(path))
|
|
|
|
remove(path);
|
|
|
|
}
|
|
|
|
|
2020-03-05 14:02:15 +00:00
|
|
|
/// Set last modified time to file or directory at `path`.
|
|
|
|
virtual void setLastModified(const String & path, const Poco::Timestamp & timestamp) = 0;
|
|
|
|
|
|
|
|
/// Get last modified time of file or directory at `path`.
|
|
|
|
virtual Poco::Timestamp getLastModified(const String & path) = 0;
|
2020-03-19 16:37:55 +00:00
|
|
|
|
|
|
|
/// Set file at `path` as read-only.
|
|
|
|
virtual void setReadOnly(const String & path) = 0;
|
|
|
|
|
|
|
|
/// Create hardlink from `src_path` to `dst_path`.
|
|
|
|
virtual void createHardLink(const String & src_path, const String & dst_path) = 0;
|
2020-06-26 21:55:48 +00:00
|
|
|
|
|
|
|
/// Wrapper for POSIX open
|
|
|
|
virtual int open(const String & path, mode_t mode) const = 0;
|
|
|
|
|
|
|
|
/// Wrapper for POSIX close
|
|
|
|
virtual void close(int fd) const = 0;
|
|
|
|
|
|
|
|
/// Wrapper for POSIX fsync
|
|
|
|
virtual void sync(int fd) const = 0;
|
2020-08-24 09:57:27 +00:00
|
|
|
|
2020-07-12 02:31:58 +00:00
|
|
|
/// Truncate file to specified size.
|
|
|
|
virtual void truncateFile(const String & path, size_t size);
|
|
|
|
|
2020-07-03 12:45:01 +00:00
|
|
|
/// Return disk type - "local", "s3", etc.
|
|
|
|
virtual const String getType() const = 0;
|
2020-08-07 11:40:19 +00:00
|
|
|
|
2020-09-04 14:17:27 +00:00
|
|
|
/// Invoked when Global Context is shutdown.
|
|
|
|
virtual void shutdown() { }
|
|
|
|
|
2020-08-07 11:40:19 +00:00
|
|
|
/// Returns executor to perform asynchronous operations.
|
2020-10-07 11:35:28 +00:00
|
|
|
virtual Executor & getExecutor() { return *executor; }
|
2020-08-11 19:08:32 +00:00
|
|
|
|
2020-10-07 11:35:28 +00:00
|
|
|
private:
|
2020-08-11 19:08:32 +00:00
|
|
|
std::unique_ptr<Executor> executor;
|
2019-11-27 09:39:44 +00:00
|
|
|
};
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
using DiskPtr = std::shared_ptr<IDisk>;
|
|
|
|
using Disks = std::vector<DiskPtr>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterator of directory contents on particular disk.
|
|
|
|
*/
|
|
|
|
class IDiskDirectoryIterator
|
2019-11-27 09:39:44 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Iterate to the next file.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual void next() = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return `true` if the iterator points to a valid element.
|
2019-11-27 09:39:44 +00:00
|
|
|
virtual bool isValid() const = 0;
|
|
|
|
|
2020-01-10 21:42:26 +00:00
|
|
|
/// Path to the file that the iterator currently points to.
|
|
|
|
virtual String path() const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2020-02-27 16:47:40 +00:00
|
|
|
/// Name of the file that the iterator currently points to.
|
|
|
|
virtual String name() const = 0;
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
virtual ~IDiskDirectoryIterator() = default;
|
2019-11-27 09:39:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2019-11-27 15:49:15 +00:00
|
|
|
* Information about reserved size on particular disk.
|
2019-11-27 09:39:44 +00:00
|
|
|
*/
|
2019-12-17 13:45:53 +00:00
|
|
|
class IReservation : boost::noncopyable
|
2019-11-27 09:39:44 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/// Get reservation size.
|
2019-12-03 13:37:40 +00:00
|
|
|
virtual UInt64 getSize() const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
2020-05-09 16:03:22 +00:00
|
|
|
/// Get i-th disk where reservation take place.
|
|
|
|
virtual DiskPtr getDisk(size_t i = 0) const = 0;
|
|
|
|
|
|
|
|
/// Get all disks, used in reservation
|
|
|
|
virtual Disks getDisks() const = 0;
|
2019-11-27 09:39:44 +00:00
|
|
|
|
|
|
|
/// Changes amount of reserved space.
|
|
|
|
virtual void update(UInt64 new_size) = 0;
|
|
|
|
|
|
|
|
/// Unreserves reserved space.
|
|
|
|
virtual ~IReservation() = default;
|
|
|
|
};
|
|
|
|
|
2019-12-03 13:37:40 +00:00
|
|
|
/// Return full path to a file on disk.
|
|
|
|
inline String fullPath(const DiskPtr & disk, const String & path)
|
|
|
|
{
|
|
|
|
return disk->getPath() + path;
|
|
|
|
}
|
2019-12-27 10:26:23 +00:00
|
|
|
|
|
|
|
/// Return parent path for the specified path.
|
|
|
|
inline String parentPath(const String & path)
|
|
|
|
{
|
|
|
|
return Poco::Path(path).parent().toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return file name for the specified path.
|
|
|
|
inline String fileName(const String & path)
|
|
|
|
{
|
|
|
|
return Poco::Path(path).getFileName();
|
|
|
|
}
|
2019-11-27 09:39:44 +00:00
|
|
|
}
|