aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Disks/ObjectStorages/DiskObjectStorageTransaction.h
blob: a4cb0ed37395f9b35da391e9d0a2851499aad8d1 (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
#pragma once

#include <Disks/IDiskTransaction.h>
#include <Disks/ObjectStorages/DiskObjectStorage.h>
#include <Disks/ObjectStorages/IMetadataStorage.h>

namespace DB
{


/// Basic operation inside disk object storage transaction.
struct IDiskObjectStorageOperation
{
    /// useful for operations with blobs in object storage
    IObjectStorage & object_storage;
    /// useful for some read operations
    IMetadataStorage & metadata_storage;
public:
    IDiskObjectStorageOperation(IObjectStorage & object_storage_, IMetadataStorage & metadata_storage_)
        : object_storage(object_storage_)
        , metadata_storage(metadata_storage_)
    {}

    /// Execute operation and something to metadata transaction
    virtual void execute(MetadataTransactionPtr transaction) = 0;
    /// Revert operation if possible
    virtual void undo() = 0;
    /// Action to execute after metadata transaction successfully committed.
    /// Useful when it's impossible to revert operation
    /// like removal of blobs. Such implementation can lead to garbage.
    virtual void finalize() = 0;
    virtual ~IDiskObjectStorageOperation() = default;

    virtual std::string getInfoForLog() const = 0;
};

using DiskObjectStorageOperation = std::unique_ptr<IDiskObjectStorageOperation>;

using DiskObjectStorageOperations = std::vector<DiskObjectStorageOperation>;


/// Disk object storage transaction, actually implement some part of disk object storage
/// logic. Works on top of non atomic operations with blobs and possibly atomic implementation
/// of metadata storage.
///
/// Commit works like:
/// 1. Execute all accumulated operations in loop.
/// 2. Commit metadata transaction.
/// 3. Finalize all accumulated operations in loop.
///
/// If something wrong happen on step 1 or 2 reverts all applied operations.
/// If finalize failed -- nothing is reverted, garbage is left in blob storage.
struct DiskObjectStorageTransaction final : public IDiskTransaction, std::enable_shared_from_this<DiskObjectStorageTransaction>
{
private:
    IObjectStorage & object_storage;
    IMetadataStorage & metadata_storage;

    MetadataTransactionPtr metadata_transaction;

    /// TODO we can get rid of this params
    DiskObjectStorageRemoteMetadataRestoreHelper * metadata_helper;

    DiskObjectStorageOperations operations_to_execute;

public:
    DiskObjectStorageTransaction(
        IObjectStorage & object_storage_,
        IMetadataStorage & metadata_storage_,
        DiskObjectStorageRemoteMetadataRestoreHelper * metadata_helper_);

    void commit() override;
    void undo() override;

    void createDirectory(const std::string & path) override;

    void createDirectories(const std::string & path) override;

    void clearDirectory(const std::string & path) override;

    void moveDirectory(const std::string & from_path, const std::string & to_path) override;

    void moveFile(const String & from_path, const String & to_path) override;

    void replaceFile(const std::string & from_path, const std::string & to_path) override;

    void createFile(const String & path) override;

    void copyFile(const std::string & from_file_path, const std::string & to_file_path) override;

    /// writeFile is a difficult function for transactions.
    /// Now it's almost noop because metadata added to transaction in finalize method
    /// of write buffer. Autocommit means that transaction will be immediately committed
    /// after returned buffer will be finalized.
    std::unique_ptr<WriteBufferFromFileBase> writeFile( /// NOLINT
        const std::string & path,
        size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE,
        WriteMode mode = WriteMode::Rewrite,
        const WriteSettings & settings = {},
        bool autocommit = true) override;

    /// Write a file using a custom function to write an object to the disk's object storage.
    void writeFileUsingBlobWritingFunction(const String & path, WriteMode mode, WriteBlobFunction && write_blob_function) override;

    void removeFile(const std::string & path) override;
    void removeFileIfExists(const std::string & path) override;
    void removeDirectory(const std::string & path) override;
    void removeRecursive(const std::string & path) override;

    void removeSharedFile(const std::string & path, bool keep_shared_data) override;
    void removeSharedRecursive(const std::string & path, bool keep_all_shared_data, const NameSet & file_names_remove_metadata_only) override;
    void removeSharedFileIfExists(const std::string & path, bool keep_shared_data) override;
    void removeSharedFiles(const RemoveBatchRequest & files, bool keep_all_batch_data, const NameSet & file_names_remove_metadata_only) override;

    void setLastModified(const std::string & path, const Poco::Timestamp & timestamp) override;
    void chmod(const String & path, mode_t mode) override;
    void setReadOnly(const std::string & path) override;
    void createHardLink(const std::string & src_path, const std::string & dst_path) override;
};

using DiskObjectStorageTransactionPtr = std::shared_ptr<DiskObjectStorageTransaction>;

}