aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Backups/BackupImpl.h
blob: 5b0254c22bfe26e06ad824864173e38aab350386 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#pragma once

#include <Backups/IBackup.h>
#include <Backups/IBackupCoordination.h>
#include <Backups/BackupInfo.h>
#include <map>
#include <mutex>


namespace DB
{
class IBackupCoordination;
class IBackupReader;
class IBackupWriter;
class SeekableReadBuffer;
class IArchiveReader;
class IArchiveWriter;
class Context;
using ContextPtr = std::shared_ptr<const Context>;

/// Implementation of IBackup.
/// Along with passed files it also stores backup metadata - a single file named ".backup" in XML format
/// which contains a list of all files in the backup with their sizes and checksums and information
/// whether the base backup should be used for each entry.
class BackupImpl : public IBackup
{
public:
    struct ArchiveParams
    {
        String archive_name;
        String password;
        String compression_method;
        int compression_level = 0;
        size_t max_volume_size = 0;
    };

    BackupImpl(
        const BackupInfo & backup_info_,
        const ArchiveParams & archive_params_,
        const std::optional<BackupInfo> & base_backup_info_,
        std::shared_ptr<IBackupReader> reader_,
        const ContextPtr & context_,
        bool use_same_s3_credentials_for_base_backup_);

    BackupImpl(
        const BackupInfo & backup_info_,
        const ArchiveParams & archive_params_,
        const std::optional<BackupInfo> & base_backup_info_,
        std::shared_ptr<IBackupWriter> writer_,
        const ContextPtr & context_,
        bool is_internal_backup_,
        const std::shared_ptr<IBackupCoordination> & coordination_,
        const std::optional<UUID> & backup_uuid_,
        bool deduplicate_files_,
        bool use_same_s3_credentials_for_base_backup_);

    ~BackupImpl() override;

    const String & getNameForLogging() const override { return backup_name_for_logging; }
    OpenMode getOpenMode() const override { return open_mode; }
    time_t getTimestamp() const override { return timestamp; }
    UUID getUUID() const override { return *uuid; }
    BackupPtr getBaseBackup() const override { return base_backup; }
    size_t getNumFiles() const override;
    UInt64 getTotalSize() const override;
    size_t getNumEntries() const override;
    UInt64 getSizeOfEntries() const override;
    UInt64 getUncompressedSize() const override;
    UInt64 getCompressedSize() const override;
    size_t getNumReadFiles() const override;
    UInt64 getNumReadBytes() const override;
    Strings listFiles(const String & directory, bool recursive) const override;
    bool hasFiles(const String & directory) const override;
    bool fileExists(const String & file_name) const override;
    bool fileExists(const SizeAndChecksum & size_and_checksum) const override;
    UInt64 getFileSize(const String & file_name) const override;
    UInt128 getFileChecksum(const String & file_name) const override;
    SizeAndChecksum getFileSizeAndChecksum(const String & file_name) const override;
    std::unique_ptr<SeekableReadBuffer> readFile(const String & file_name) const override;
    std::unique_ptr<SeekableReadBuffer> readFile(const SizeAndChecksum & size_and_checksum) const override;
    size_t copyFileToDisk(const String & file_name, DiskPtr destination_disk, const String & destination_path, WriteMode write_mode) const override;
    size_t copyFileToDisk(const SizeAndChecksum & size_and_checksum, DiskPtr destination_disk, const String & destination_path, WriteMode write_mode) const override;
    void writeFile(const BackupFileInfo & info, BackupEntryPtr entry) override;
    void finalizeWriting() override;
    bool supportsWritingInMultipleThreads() const override { return !use_archive; }

private:
    void open(const ContextPtr & context);
    void close();

    void openArchive();
    void closeArchive();

    /// Writes the file ".backup" containing backup's metadata.
    void writeBackupMetadata() TSA_REQUIRES(mutex);
    void readBackupMetadata() TSA_REQUIRES(mutex);

    /// Checks that a new backup doesn't exist yet.
    void checkBackupDoesntExist() const;

    /// Lock file named ".lock" and containing the UUID of a backup is used to own the place where we're writing the backup.
    /// Thus it will not be allowed to put any other backup to the same place (even if the BACKUP command is executed on a different node).
    void createLockFile();
    bool checkLockFile(bool throw_if_failed) const;
    void removeLockFile();

    void removeAllFilesAfterFailure();

    /// Calculates and sets `compressed_size`.
    void setCompressedSize();

    std::unique_ptr<SeekableReadBuffer> readFileImpl(const SizeAndChecksum & size_and_checksum, bool read_encrypted) const;

    BackupInfo backup_info;
    const String backup_name_for_logging;
    const bool use_archive;
    const ArchiveParams archive_params;
    const OpenMode open_mode;
    std::shared_ptr<IBackupWriter> writer;
    std::shared_ptr<IBackupReader> reader;
    const bool is_internal_backup;
    std::shared_ptr<IBackupCoordination> coordination;

    mutable std::mutex mutex;

    using SizeAndChecksum = std::pair<UInt64, UInt128>;
    std::map<String /* file_name */, SizeAndChecksum> file_names TSA_GUARDED_BY(mutex); /// Should be ordered alphabetically, see listFiles(). For empty files we assume checksum = 0.
    std::map<SizeAndChecksum, BackupFileInfo> file_infos TSA_GUARDED_BY(mutex); /// Information about files. Without empty files.

    std::optional<UUID> uuid;
    time_t timestamp = 0;
    size_t num_files = 0;
    UInt64 total_size = 0;
    size_t num_entries = 0;
    UInt64 size_of_entries = 0;
    UInt64 uncompressed_size = 0;
    UInt64 compressed_size = 0;
    mutable size_t num_read_files = 0;
    mutable UInt64 num_read_bytes = 0;
    int version;
    std::optional<BackupInfo> base_backup_info;
    std::shared_ptr<const IBackup> base_backup;
    std::optional<UUID> base_backup_uuid;
    std::shared_ptr<IArchiveReader> archive_reader;
    std::shared_ptr<IArchiveWriter> archive_writer;
    String lock_file_name;
    std::atomic<bool> lock_file_before_first_file_checked = false;

    bool writing_finalized = false;
    bool deduplicate_files = true;
    bool use_same_s3_credentials_for_base_backup = false;
    const Poco::Logger * log;
};

}