Skip to content

Commit 7cd36cb

Browse files
authored
Merge pull request ClickHouse#77406 from jkartseva/plain-rw-imitate-hardlink
Support ALTER TABLE ATTACH|DETACH|MOVE|REPLACE PARTITION for plain_rewritable disk
2 parents 0f73421 + 81aff72 commit 7cd36cb

22 files changed

+373
-30
lines changed

src/Disks/IDisk.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
#include "IDisk.h"
2+
#include <Core/Field.h>
3+
#include <Core/ServerUUID.h>
4+
#include <Disks/FakeDiskTransaction.h>
25
#include <IO/ReadBufferFromFileBase.h>
36
#include <IO/WriteBufferFromFileBase.h>
47
#include <IO/copyData.h>
8+
#include <Interpreters/Context.h>
9+
#include <Storages/PartitionCommands.h>
510
#include <Poco/Logger.h>
611
#include <Poco/Util/AbstractConfiguration.h>
7-
#include <Interpreters/Context.h>
812
#include <Common/ThreadPool.h>
9-
#include <Common/threadPoolCallbackRunner.h>
1013
#include <Common/logger_useful.h>
1114
#include <Common/setThreadName.h>
12-
#include <Core/Field.h>
13-
#include <Core/ServerUUID.h>
14-
#include <Disks/FakeDiskTransaction.h>
15+
#include <Common/threadPoolCallbackRunner.h>
1516

1617
namespace CurrentMetrics
1718
{
@@ -191,6 +192,11 @@ void IDisk::truncateFile(const String &, size_t)
191192
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Truncate operation is not implemented for disk of type {}", getDataSourceDescription().type);
192193
}
193194

195+
bool IDisk::supportsPartitionCommand(const PartitionCommand & /*command*/) const
196+
{
197+
return true;
198+
}
199+
194200
SyncGuardPtr IDisk::getDirectorySyncGuard(const String & /* path */) const
195201
{
196202
return nullptr;

src/Disks/IDisk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ using DiskObjectStoragePtr = std::shared_ptr<DiskObjectStorage>;
7272

7373
using ObjectAttributes = std::map<std::string, std::string>;
7474

75+
struct PartitionCommand;
76+
7577
/**
7678
* Provide interface for reservation.
7779
*/
@@ -444,6 +446,8 @@ class IDisk : public Space
444446

445447
virtual bool supportsHardLinks() const { return true; }
446448

449+
virtual bool supportsPartitionCommand(const PartitionCommand & command) const;
450+
447451
/// Check if disk is broken. Broken disks will have 0 space and cannot be used.
448452
virtual bool isBroken() const { return false; }
449453

src/Disks/ObjectStorages/DiskObjectStorage.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,11 @@ bool DiskObjectStorage::supportsHardLinks() const
643643
return !isWriteOnce() && !object_storage->isPlain();
644644
}
645645

646+
bool DiskObjectStorage::supportsPartitionCommand(const PartitionCommand & command) const
647+
{
648+
return !isWriteOnce() && metadata_storage->supportsPartitionCommand(command);
649+
}
650+
646651
DiskObjectStoragePtr DiskObjectStorage::createDiskObjectStorage()
647652
{
648653
const auto config_prefix = "storage_configuration.disks." + name;

src/Disks/ObjectStorages/DiskObjectStorage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ friend class DiskObjectStorageRemoteMetadataRestoreHelper;
215215

216216
bool supportsHardLinks() const override;
217217

218+
bool supportsPartitionCommand(const PartitionCommand & command) const override;
219+
218220
/// Get structure of object storage this disk works with. Examples:
219221
/// DiskObjectStorage(S3ObjectStorage)
220222
/// DiskObjectStorage(CachedObjectStorage(S3ObjectStorage))

src/Disks/ObjectStorages/IMetadataStorage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace ErrorCodes
2424
}
2525

2626
class IMetadataStorage;
27+
struct PartitionCommand;
2728

2829
/// Return the result of operation to the caller.
2930
/// It is used in `IDiskObjectStorageOperation::finalize` after metadata transaction executed to make decision on blob removal.
@@ -225,6 +226,8 @@ class IMetadataStorage : private boost::noncopyable
225226
throwNotImplemented();
226227
}
227228

229+
virtual bool supportsPartitionCommand(const PartitionCommand & /* command */) const = 0;
230+
228231
virtual std::vector<std::string> listDirectory(const std::string & path) const = 0;
229232

230233
virtual DirectoryIteratorPtr iterateDirectory(const std::string & path) const = 0;

src/Disks/ObjectStorages/InMemoryDirectoryPathMap.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ class InMemoryDirectoryPathMap
7979
return res;
8080
}
8181

82+
bool existsFile(const std::string & local_path) const
83+
{
84+
auto path = std::filesystem::path(local_path);
85+
auto dir = path.parent_path();
86+
auto filename = path.filename();
87+
88+
std::lock_guard lock(mutex);
89+
auto it = map.find(dir);
90+
if (it == map.end())
91+
return false;
92+
93+
return it->second.files.contains(filename);
94+
}
95+
8296
bool addFile(const std::string & local_path)
8397
{
8498
auto path = std::filesystem::path(local_path);

src/Disks/ObjectStorages/MetadataStorageFromDisk.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
#include <Disks/ObjectStorages/MetadataStorageFromDisk.h>
21
#include <Disks/ObjectStorages/IMetadataStorage.h>
3-
#include <IO/WriteHelpers.h>
2+
#include <Disks/ObjectStorages/MetadataStorageFromDisk.h>
43
#include <IO/ReadHelpers.h>
4+
#include <IO/WriteHelpers.h>
5+
#include <Storages/PartitionCommands.h>
6+
57
#include <ranges>
68
#include <shared_mutex>
79

@@ -44,6 +46,11 @@ time_t MetadataStorageFromDisk::getLastChanged(const std::string & path) const
4446
return disk->getLastChanged(path);
4547
}
4648

49+
bool MetadataStorageFromDisk::supportsPartitionCommand(const PartitionCommand & /*command*/) const
50+
{
51+
return true;
52+
}
53+
4754
uint64_t MetadataStorageFromDisk::getFileSize(const String & path) const
4855
{
4956
auto metadata = readMetadata(path);

src/Disks/ObjectStorages/MetadataStorageFromDisk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class MetadataStorageFromDisk final : public IMetadataStorage
5454

5555
bool supportsStat() const override { return disk->supportsStat(); }
5656

57+
bool supportsPartitionCommand(const PartitionCommand & command) const override;
58+
5759
struct stat stat(const String & path) const override { return disk->stat(path); }
5860

5961
std::vector<std::string> listDirectory(const std::string & path) const override;

src/Disks/ObjectStorages/MetadataStorageFromPlainObjectStorage.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <Disks/ObjectStorages/MetadataStorageFromPlainObjectStorageOperations.h>
55
#include <Disks/ObjectStorages/StaticDirectoryIterator.h>
66
#include <Disks/ObjectStorages/StoredObject.h>
7+
#include <Storages/PartitionCommands.h>
78
#include <Common/ObjectStorageKey.h>
89
#include <Common/SipHash.h>
910
#include <Common/logger_useful.h>
@@ -109,6 +110,11 @@ std::optional<Poco::Timestamp> MetadataStorageFromPlainObjectStorage::getLastMod
109110
return std::nullopt;
110111
}
111112

113+
bool MetadataStorageFromPlainObjectStorage::supportsPartitionCommand(const PartitionCommand & /*command*/) const
114+
{
115+
return false;
116+
}
117+
112118
std::vector<std::string> MetadataStorageFromPlainObjectStorage::listDirectory(const std::string & path) const
113119
{
114120
auto key_prefix = object_storage->generateObjectKeyForPath(path, std::nullopt /* key_prefix */).serialize();
@@ -215,6 +221,26 @@ void MetadataStorageFromPlainObjectStorageTransaction::removeDirectory(const std
215221
}
216222
}
217223

224+
void MetadataStorageFromPlainObjectStorageTransaction::createHardLink(const std::string & path_from, const std::string & path_to)
225+
{
226+
if (metadata_storage.object_storage->isWriteOnce())
227+
throwNotImplemented();
228+
229+
addOperation(std::make_unique<MetadataStorageFromPlainObjectStorageCopyFileOperation>(
230+
path_from, path_to, *metadata_storage.getPathMap(), object_storage));
231+
}
232+
233+
void MetadataStorageFromPlainObjectStorageTransaction::moveFile(const std::string & path_from, const std::string & path_to)
234+
{
235+
if (metadata_storage.object_storage->isWriteOnce())
236+
throwNotImplemented();
237+
238+
if (metadata_storage.existsDirectory(path_from))
239+
moveDirectory(path_from, path_to);
240+
else
241+
throwNotImplemented();
242+
}
243+
218244
void MetadataStorageFromPlainObjectStorageTransaction::createEmptyMetadataFile(const std::string & path)
219245
{
220246
if (metadata_storage.object_storage->isWriteOnce())

src/Disks/ObjectStorages/MetadataStorageFromPlainObjectStorage.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class MetadataStorageFromPlainObjectStorage : public IMetadataStorage
8787

8888
bool supportsChmod() const override { return false; }
8989
bool supportsStat() const override { return false; }
90+
bool supportsPartitionCommand(const PartitionCommand & command) const override;
9091

9192
protected:
9293
/// Get the object storage prefix for storing metadata files.
@@ -117,14 +118,20 @@ class MetadataStorageFromPlainObjectStorageTransaction : public IMetadataTransac
117118

118119
void addBlobToMetadata(const std::string & /* path */, ObjectStorageKey /* object_key */, uint64_t /* size_in_bytes */) override
119120
{
120-
// Noop
121+
/// Noop
121122
}
122123

123124
void setLastModified(const String &, const Poco::Timestamp &) override
124125
{
125126
/// Noop
126127
}
127128

129+
/// Required for MergeTree backups.
130+
void setReadOnly(const std::string & /*path*/) override
131+
{
132+
/// Noop
133+
}
134+
128135
void createEmptyMetadataFile(const std::string & /* path */) override;
129136

130137
void createMetadataFile(const std::string & /* path */, ObjectStorageKey /* object_key */, uint64_t /* size_in_bytes */) override;
@@ -138,6 +145,11 @@ class MetadataStorageFromPlainObjectStorageTransaction : public IMetadataTransac
138145
void unlinkFile(const std::string & path) override;
139146
void removeDirectory(const std::string & path) override;
140147

148+
/// Hard links are simulated using server-side copying.
149+
void createHardLink(const std::string & path_from, const std::string & path_to) override;
150+
151+
void moveFile(const std::string & path_from, const std::string & path_to) override;
152+
141153
UnlinkMetadataFileOperationOutcomePtr unlinkMetadata(const std::string & path) override;
142154

143155
void commit() override;

0 commit comments

Comments
 (0)