Skip to content

Commit e5aa957

Browse files
authored
feat(operation): introduce cleanup operations (#128)
1 parent 6b9eb68 commit e5aa957

10 files changed

Lines changed: 1874 additions & 0 deletions
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include <cstdint>
22+
#include <functional>
23+
#include <map>
24+
#include <memory>
25+
#include <set>
26+
#include <string>
27+
28+
#include "paimon/result.h"
29+
#include "paimon/type_fwd.h"
30+
#include "paimon/visibility.h"
31+
32+
namespace paimon {
33+
class Executor;
34+
class MemoryPool;
35+
36+
/// `CleanContext` is some configuration for orphan files clean operations.
37+
///
38+
/// Please do not use this class directly, use `CleanContextBuilder` to build a `CleanContext` which
39+
/// has input validation.
40+
/// @see CleanContextBuilder
41+
class PAIMON_EXPORT CleanContext {
42+
public:
43+
CleanContext(const std::string& root_path, const std::map<std::string, std::string>& options,
44+
int64_t older_than_ms, const std::shared_ptr<MemoryPool>& pool,
45+
const std::shared_ptr<Executor>& executor,
46+
const std::shared_ptr<FileSystem>& specific_file_system,
47+
std::function<bool(const std::string&)> should_be_retained);
48+
~CleanContext();
49+
50+
const std::string& GetRootPath() const {
51+
return root_path_;
52+
}
53+
54+
const std::map<std::string, std::string>& GetOptions() const {
55+
return options_;
56+
}
57+
58+
int64_t GetOlderThanMs() const {
59+
return older_than_ms_;
60+
}
61+
62+
std::shared_ptr<MemoryPool> GetMemoryPool() const {
63+
return memory_pool_;
64+
}
65+
66+
std::shared_ptr<Executor> GetExecutor() const {
67+
return executor_;
68+
}
69+
70+
std::shared_ptr<FileSystem> GetSpecificFileSystem() const {
71+
return specific_file_system_;
72+
}
73+
74+
std::function<bool(const std::string&)> GetFileRetainCondition() const {
75+
return should_be_retained_;
76+
}
77+
78+
private:
79+
std::string root_path_;
80+
std::map<std::string, std::string> options_;
81+
int64_t older_than_ms_;
82+
std::shared_ptr<MemoryPool> memory_pool_;
83+
std::shared_ptr<Executor> executor_;
84+
std::shared_ptr<FileSystem> specific_file_system_;
85+
std::function<bool(const std::string&)> should_be_retained_;
86+
};
87+
88+
/// `CleanContextBuilder` used to build a `CleanContext`, has input validation.
89+
class PAIMON_EXPORT CleanContextBuilder {
90+
public:
91+
/// Constructs a `CleanContextBuilder` with required parameters.
92+
/// @param root_path The root path of the table.
93+
explicit CleanContextBuilder(const std::string& root_path);
94+
95+
~CleanContextBuilder();
96+
97+
/// Set a configuration options map to set some option entries which are not defined in the
98+
/// table schema or whose values you want to overwrite.
99+
/// @note The options map will clear the options added by `AddOption()` before.
100+
/// @param options The configuration options map.
101+
/// @return Reference to this builder for method chaining.
102+
CleanContextBuilder& SetOptions(const std::map<std::string, std::string>& options);
103+
104+
/// Add a single configuration option which is not defined in the table schema or whose value
105+
/// you want to overwrite.
106+
///
107+
/// If you want to add multiple options, call `AddOption()` multiple times or use `SetOptions()`
108+
/// instead.
109+
/// @param key The option key.
110+
/// @param value The option value.
111+
/// @return Reference to this builder for method chaining.
112+
CleanContextBuilder& AddOption(const std::string& key, const std::string& value);
113+
114+
/// An optional time threshold in milliseconds for filtering. If not provided, defaults to the
115+
/// current time minus one day.
116+
CleanContextBuilder& WithOlderThanMs(int64_t older_than_ms);
117+
118+
/// Specifies a custom condition to determine which files should be retained.
119+
/// @param should_be_retained A callable object that takes a filename and returns `true` if the
120+
/// file should be kept, or `false` if it can be deleted.
121+
/// @return Reference to this builder for method chaining.
122+
CleanContextBuilder& WithFileRetainCondition(
123+
std::function<bool(const std::string&)> should_be_retained);
124+
125+
/// Set custom memory pool for memory management.
126+
/// @param pool The memory pool to use.
127+
/// @return Reference to this builder for method chaining.
128+
CleanContextBuilder& WithMemoryPool(const std::shared_ptr<MemoryPool>& pool);
129+
130+
/// Set custom executor for task execution.
131+
/// @param executor The executor to use.
132+
/// @return Reference to this builder for method chaining.
133+
CleanContextBuilder& WithExecutor(const std::shared_ptr<Executor>& executor);
134+
135+
/// Sets a custom file system instance to be used for all file operations in this clean context.
136+
/// This bypasses the global file system registry and uses the provided implementation directly.
137+
///
138+
/// @param file_system The file system to use.
139+
/// @return Reference to this builder for method chaining.
140+
/// @note If not set, use default file system (configured in `Options::FILE_SYSTEM`)
141+
CleanContextBuilder& WithFileSystem(const std::shared_ptr<FileSystem>& file_system);
142+
143+
/// Build and return a `CleanContext` instance with input validation.
144+
/// @return Result containing the constructed `CleanContext` or an error status.
145+
Result<std::unique_ptr<CleanContext>> Finish();
146+
147+
private:
148+
class Impl;
149+
150+
std::unique_ptr<Impl> impl_;
151+
};
152+
153+
/// To remove the data files and metadata files that are not used by table (so-called "orphan
154+
/// files").
155+
///
156+
/// It will ignore exception when listing all files because it's OK to not delete unread files.
157+
///
158+
/// To avoid deleting newly written files, it only deletes orphan files older than `olderThanMillis`
159+
/// (1 day by default).
160+
///
161+
/// To avoid deleting files that are used but not read by mistaken, it will stop removing process
162+
/// when failed to read used files.
163+
///
164+
/// To avoid deleting files that were newly added to the Paimon Java protocol but are unrecognized
165+
/// by Paimon C++, we implemented a strong pattern-matching validation, deleting only files in
166+
/// patterns we recognize.
167+
///
168+
/// @note `OrphanFilesCleaner` in Paimon C++ only support cleaning append table, do not support
169+
/// cleaning table with tag, table with external paths, table with branch, table with index, table
170+
/// with changelog, and primary key table.
171+
class PAIMON_EXPORT OrphanFilesCleaner {
172+
public:
173+
virtual ~OrphanFilesCleaner() = default;
174+
175+
/// Create an instance of `OrphanFilesCleaner`.
176+
///
177+
/// @param context A unique pointer to the `CleanContext` used for cleanup tasks.
178+
///
179+
/// @return A Result containing a unique pointer to the `OrphanFilesCleaner` instance.
180+
static Result<std::unique_ptr<OrphanFilesCleaner>> Create(
181+
std::unique_ptr<CleanContext>&& context);
182+
183+
/// Cleans orphan files.
184+
///
185+
/// @return A Result object containing a set of strings representing the paths of the cleaned
186+
/// files.
187+
virtual Result<std::set<std::string>> Clean() = 0;
188+
189+
/// Retrieve metrics related to orphan files cleaning operations.
190+
///
191+
/// @return A shared pointer to a `Metrics` object containing cleaning metrics.
192+
virtual std::shared_ptr<Metrics> GetMetrics() const = 0;
193+
194+
protected:
195+
OrphanFilesCleaner() = default;
196+
};
197+
} // namespace paimon
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "paimon/core/operation/metrics/commit_metrics.h"
20+
21+
#include <memory>
22+
#include <string>
23+
24+
#include "gtest/gtest.h"
25+
#include "paimon/common/metrics/metrics_impl.h"
26+
#include "paimon/testing/utils/testharness.h"
27+
28+
namespace paimon::test {
29+
30+
TEST(CommitMetricsTest, TestSimple) {
31+
auto commit_metrics = std::make_shared<MetricsImpl>();
32+
commit_metrics->SetCounter("some_metric", 100);
33+
commit_metrics->SetCounter(CommitMetrics::LAST_COMMIT_ATTEMPTS, 30);
34+
ASSERT_OK_AND_ASSIGN(uint64_t counter,
35+
commit_metrics->GetCounter(CommitMetrics::LAST_COMMIT_ATTEMPTS));
36+
ASSERT_EQ(30, counter);
37+
ASSERT_OK_AND_ASSIGN(counter, commit_metrics->GetCounter("some_metric"));
38+
ASSERT_EQ(100, counter);
39+
auto other = std::make_shared<MetricsImpl>();
40+
other->SetCounter("some_metric_2", 200);
41+
other->SetCounter(CommitMetrics::LAST_COMMIT_ATTEMPTS, 50);
42+
commit_metrics->Merge(other);
43+
ASSERT_OK_AND_ASSIGN(counter, commit_metrics->GetCounter(CommitMetrics::LAST_COMMIT_ATTEMPTS));
44+
ASSERT_EQ(80, counter);
45+
ASSERT_OK_AND_ASSIGN(counter, commit_metrics->GetCounter("some_metric"));
46+
ASSERT_EQ(100, counter);
47+
ASSERT_OK_AND_ASSIGN(counter, commit_metrics->GetCounter("some_metric_2"));
48+
ASSERT_EQ(200, counter);
49+
}
50+
51+
} // namespace paimon::test

0 commit comments

Comments
 (0)