/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/delete_scheduler_test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | |
21 | | #ifndef __STDC_FORMAT_MACROS |
22 | | #define __STDC_FORMAT_MACROS |
23 | | #endif |
24 | | |
25 | | #include <inttypes.h> |
26 | | #include <atomic> |
27 | | #include <thread> |
28 | | #include <vector> |
29 | | |
30 | | #include "yb/rocksdb/env.h" |
31 | | #include "yb/rocksdb/util/delete_scheduler.h" |
32 | | #include "yb/rocksdb/util/sync_point.h" |
33 | | #include "yb/rocksdb/util/testharness.h" |
34 | | #include "yb/rocksdb/util/testutil.h" |
35 | | |
36 | | #include "yb/util/string_util.h" |
37 | | #include "yb/util/test_util.h" |
38 | | |
39 | | namespace rocksdb { |
40 | | |
41 | | class DeleteSchedulerTest : public RocksDBTest { |
42 | | public: |
43 | 8 | DeleteSchedulerTest() : env_(Env::Default()) { |
44 | 8 | dummy_files_dir_ = test::TmpDir(env_) + "/dummy_data_dir"; |
45 | 8 | DestroyAndCreateDir(dummy_files_dir_); |
46 | 8 | trash_dir_ = test::TmpDir(env_) + "/trash"; |
47 | 8 | DestroyAndCreateDir(trash_dir_); |
48 | 8 | } |
49 | | |
50 | 8 | ~DeleteSchedulerTest() { |
51 | 8 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
52 | 8 | rocksdb::SyncPoint::GetInstance()->LoadDependency({}); |
53 | 8 | rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks(); |
54 | 8 | DestroyDir(dummy_files_dir_); |
55 | 8 | } |
56 | | |
57 | 35 | void DestroyDir(const std::string& dir) { |
58 | 35 | if (env_->FileExists(dir).IsNotFound()) { |
59 | 16 | return; |
60 | 16 | } |
61 | 19 | std::vector<std::string> files_in_dir; |
62 | 19 | EXPECT_OK(env_->GetChildren(dir, &files_in_dir)); |
63 | 38 | for (auto& file_in_dir : files_in_dir) { |
64 | 38 | if (file_in_dir == "." || file_in_dir == "..") { |
65 | 38 | continue; |
66 | 38 | } |
67 | 0 | EXPECT_OK(env_->DeleteFile(dir + "/" + file_in_dir)); |
68 | 0 | } |
69 | 19 | EXPECT_OK(env_->DeleteDir(dir)); |
70 | 19 | } |
71 | | |
72 | 26 | void DestroyAndCreateDir(const std::string& dir) { |
73 | 26 | DestroyDir(dir); |
74 | 26 | EXPECT_OK(env_->CreateDir(dir)); |
75 | 26 | } |
76 | | |
77 | 57 | int CountFilesInDir(const std::string& dir) { |
78 | 57 | std::vector<std::string> files_in_dir; |
79 | 57 | EXPECT_OK(env_->GetChildren(dir, &files_in_dir)); |
80 | | // Ignore "." and ".." |
81 | 57 | return static_cast<int>(files_in_dir.size()) - 2; |
82 | 57 | } |
83 | | |
84 | 1.19k | std::string NewDummyFile(const std::string& file_name, uint64_t size = 1024) { |
85 | 1.19k | std::string file_path = dummy_files_dir_ + "/" + file_name; |
86 | 1.19k | std::unique_ptr<WritableFile> f; |
87 | 1.19k | EXPECT_OK(env_->NewWritableFile(file_path, &f, EnvOptions())); |
88 | 1.19k | std::string data(size, 'A'); |
89 | 1.19k | EXPECT_OK(f->Append(data)); |
90 | 1.19k | EXPECT_OK(f->Close()); |
91 | 1.19k | return file_path; |
92 | 1.19k | } |
93 | | |
94 | 16 | void NewDeleteScheduler() { |
95 | 16 | ASSERT_OK(env_->CreateDirIfMissing(trash_dir_)); |
96 | 16 | delete_scheduler_.reset(new DeleteScheduler( |
97 | 16 | env_, trash_dir_, rate_bytes_per_sec_, nullptr, nullptr)); |
98 | 16 | } |
99 | | |
100 | | Env* env_; |
101 | | std::string dummy_files_dir_; |
102 | | std::string trash_dir_; |
103 | | int64_t rate_bytes_per_sec_; |
104 | | std::shared_ptr<DeleteScheduler> delete_scheduler_; |
105 | | }; |
106 | | |
107 | | // Test the basic functionality of DeleteScheduler (Rate Limiting). |
108 | | // 1- Create 100 dummy files |
109 | | // 2- Delete the 100 dummy files using DeleteScheduler |
110 | | // --- Hold DeleteScheduler::BackgroundEmptyTrash --- |
111 | | // 3- Wait for DeleteScheduler to delete all files in trash |
112 | | // 4- Verify that BackgroundEmptyTrash used to correct penlties for the files |
113 | | // 5- Make sure that all created files were completely deleted |
114 | 1 | TEST_F(DeleteSchedulerTest, BasicRateLimiting) { |
115 | 1 | rocksdb::SyncPoint::GetInstance()->LoadDependency({ |
116 | 1 | {"DeleteSchedulerTest::BasicRateLimiting:1", |
117 | 1 | "DeleteScheduler::BackgroundEmptyTrash"}, |
118 | 1 | }); |
119 | | |
120 | 1 | std::vector<uint64_t> penalties; |
121 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
122 | 1 | "DeleteScheduler::BackgroundEmptyTrash:Wait", |
123 | 500 | [&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); }); |
124 | | |
125 | 1 | int num_files = 100; // 100 files |
126 | 1 | uint64_t file_size = 1024; // every file is 1 kb |
127 | 1 | std::vector<uint64_t> delete_kbs_per_sec = {512, 200, 100, 50, 25}; |
128 | | |
129 | 6 | for (size_t t = 0; t < delete_kbs_per_sec.size(); t++) { |
130 | 5 | penalties.clear(); |
131 | 5 | rocksdb::SyncPoint::GetInstance()->ClearTrace(); |
132 | 5 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
133 | | |
134 | 5 | DestroyAndCreateDir(dummy_files_dir_); |
135 | 5 | rate_bytes_per_sec_ = delete_kbs_per_sec[t] * 1024; |
136 | 5 | NewDeleteScheduler(); |
137 | | |
138 | | // Create 100 dummy files, every file is 1 Kb |
139 | 5 | std::vector<std::string> generated_files; |
140 | 505 | for (int i = 0; i < num_files; i++) { |
141 | 500 | std::string file_name = "file" + ToString(i) + ".data"; |
142 | 500 | generated_files.push_back(NewDummyFile(file_name, file_size)); |
143 | 500 | } |
144 | | |
145 | | // Delete dummy files and measure time spent to empty trash |
146 | 505 | for (int i = 0; i < num_files; i++) { |
147 | 500 | ASSERT_OK(delete_scheduler_->DeleteFile(generated_files[i])); |
148 | 500 | } |
149 | 5 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
150 | | |
151 | 5 | uint64_t delete_start_time = env_->NowMicros(); |
152 | 5 | TEST_SYNC_POINT("DeleteSchedulerTest::BasicRateLimiting:1"); |
153 | 5 | delete_scheduler_->WaitForEmptyTrash(); |
154 | 5 | uint64_t time_spent_deleting = env_->NowMicros() - delete_start_time; |
155 | | |
156 | 5 | auto bg_errors = delete_scheduler_->GetBackgroundErrors(); |
157 | 5 | ASSERT_EQ(bg_errors.size(), 0); |
158 | | |
159 | 5 | uint64_t total_files_size = 0; |
160 | 5 | uint64_t expected_penlty = 0; |
161 | 5 | ASSERT_EQ(penalties.size(), num_files); |
162 | 505 | for (int i = 0; i < num_files; i++) { |
163 | 500 | total_files_size += file_size; |
164 | 500 | expected_penlty = ((total_files_size * 1000000) / rate_bytes_per_sec_); |
165 | 500 | ASSERT_EQ(expected_penlty, penalties[i]); |
166 | 500 | } |
167 | 5 | ASSERT_GT(time_spent_deleting, expected_penlty * 0.9); |
168 | | |
169 | 5 | ASSERT_EQ(CountFilesInDir(trash_dir_), 0); |
170 | 5 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
171 | 5 | } |
172 | 1 | } |
173 | | |
174 | | // Same as the BasicRateLimiting test but delete files in multiple threads. |
175 | | // 1- Create 100 dummy files |
176 | | // 2- Delete the 100 dummy files using DeleteScheduler using 10 threads |
177 | | // --- Hold DeleteScheduler::BackgroundEmptyTrash --- |
178 | | // 3- Wait for DeleteScheduler to delete all files in queue |
179 | | // 4- Verify that BackgroundEmptyTrash used to correct penlties for the files |
180 | | // 5- Make sure that all created files were completely deleted |
181 | 1 | TEST_F(DeleteSchedulerTest, RateLimitingMultiThreaded) { |
182 | 1 | rocksdb::SyncPoint::GetInstance()->LoadDependency({ |
183 | 1 | {"DeleteSchedulerTest::RateLimitingMultiThreaded:1", |
184 | 1 | "DeleteScheduler::BackgroundEmptyTrash"}, |
185 | 1 | }); |
186 | | |
187 | 1 | std::vector<uint64_t> penalties; |
188 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
189 | 1 | "DeleteScheduler::BackgroundEmptyTrash:Wait", |
190 | 500 | [&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); }); |
191 | | |
192 | 1 | int thread_cnt = 10; |
193 | 1 | int num_files = 10; // 10 files per thread |
194 | 1 | uint64_t file_size = 1024; // every file is 1 kb |
195 | | |
196 | 1 | std::vector<uint64_t> delete_kbs_per_sec = {512, 200, 100, 50, 25}; |
197 | 6 | for (size_t t = 0; t < delete_kbs_per_sec.size(); t++) { |
198 | 5 | penalties.clear(); |
199 | 5 | rocksdb::SyncPoint::GetInstance()->ClearTrace(); |
200 | 5 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
201 | | |
202 | 5 | DestroyAndCreateDir(dummy_files_dir_); |
203 | 5 | rate_bytes_per_sec_ = delete_kbs_per_sec[t] * 1024; |
204 | 5 | NewDeleteScheduler(); |
205 | | |
206 | | // Create 100 dummy files, every file is 1 Kb |
207 | 5 | std::vector<std::string> generated_files; |
208 | 505 | for (int i = 0; i < num_files * thread_cnt; i++) { |
209 | 500 | std::string file_name = "file" + ToString(i) + ".data"; |
210 | 500 | generated_files.push_back(NewDummyFile(file_name, file_size)); |
211 | 500 | } |
212 | | |
213 | | // Delete dummy files using 10 threads and measure time spent to empty trash |
214 | 5 | std::atomic<int> thread_num(0); |
215 | 5 | std::vector<std::thread> threads; |
216 | 50 | std::function<void()> delete_thread = [&]() { |
217 | 50 | int idx = thread_num.fetch_add(1); |
218 | 50 | int range_start = idx * num_files; |
219 | 50 | int range_end = range_start + num_files; |
220 | 550 | for (int j = range_start; j < range_end; j++) { |
221 | 500 | ASSERT_OK(delete_scheduler_->DeleteFile(generated_files[j])); |
222 | 500 | } |
223 | 50 | }; |
224 | | |
225 | 55 | for (int i = 0; i < thread_cnt; i++) { |
226 | 50 | threads.emplace_back(delete_thread); |
227 | 50 | } |
228 | | |
229 | 55 | for (size_t i = 0; i < threads.size(); i++) { |
230 | 50 | threads[i].join(); |
231 | 50 | } |
232 | | |
233 | 5 | uint64_t delete_start_time = env_->NowMicros(); |
234 | 5 | TEST_SYNC_POINT("DeleteSchedulerTest::RateLimitingMultiThreaded:1"); |
235 | 5 | delete_scheduler_->WaitForEmptyTrash(); |
236 | 5 | uint64_t time_spent_deleting = env_->NowMicros() - delete_start_time; |
237 | | |
238 | 5 | auto bg_errors = delete_scheduler_->GetBackgroundErrors(); |
239 | 5 | ASSERT_EQ(bg_errors.size(), 0); |
240 | | |
241 | 5 | uint64_t total_files_size = 0; |
242 | 5 | uint64_t expected_penlty = 0; |
243 | 5 | ASSERT_EQ(penalties.size(), num_files * thread_cnt); |
244 | 505 | for (int i = 0; i < num_files * thread_cnt; i++) { |
245 | 500 | total_files_size += file_size; |
246 | 500 | expected_penlty = ((total_files_size * 1000000) / rate_bytes_per_sec_); |
247 | 500 | ASSERT_EQ(expected_penlty, penalties[i]); |
248 | 500 | } |
249 | 5 | ASSERT_GT(time_spent_deleting, expected_penlty * 0.9); |
250 | | |
251 | 5 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
252 | 5 | ASSERT_EQ(CountFilesInDir(trash_dir_), 0); |
253 | 5 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
254 | 5 | } |
255 | 1 | } |
256 | | |
257 | | // Disable rate limiting by setting rate_bytes_per_sec_ to 0 and make sure |
258 | | // that when DeleteScheduler delete a file it delete it immediately and dont |
259 | | // move it to trash |
260 | 1 | TEST_F(DeleteSchedulerTest, DisableRateLimiting) { |
261 | 1 | int bg_delete_file = 0; |
262 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
263 | 1 | "DeleteScheduler::DeleteTrashFile:DeleteFile", |
264 | 0 | [&](void* arg) { bg_delete_file++; }); |
265 | | |
266 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
267 | | |
268 | 1 | rate_bytes_per_sec_ = 0; |
269 | 1 | NewDeleteScheduler(); |
270 | | |
271 | 11 | for (int i = 0; i < 10; i++) { |
272 | | // Every file we delete will be deleted immediately |
273 | 10 | std::string dummy_file = NewDummyFile("dummy.data"); |
274 | 10 | ASSERT_OK(delete_scheduler_->DeleteFile(dummy_file)); |
275 | 10 | ASSERT_TRUE(env_->FileExists(dummy_file).IsNotFound()); |
276 | 10 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
277 | 10 | ASSERT_EQ(CountFilesInDir(trash_dir_), 0); |
278 | 10 | } |
279 | | |
280 | 1 | ASSERT_EQ(bg_delete_file, 0); |
281 | | |
282 | 1 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
283 | 1 | } |
284 | | |
285 | | // Testing that moving files to trash with the same name is not a problem |
286 | | // 1- Create 10 files with the same name "conflict.data" |
287 | | // 2- Delete the 10 files using DeleteScheduler |
288 | | // 3- Make sure that trash directory contain 10 files ("conflict.data" x 10) |
289 | | // --- Hold DeleteScheduler::BackgroundEmptyTrash --- |
290 | | // 4- Make sure that files are deleted from trash |
291 | 1 | TEST_F(DeleteSchedulerTest, ConflictNames) { |
292 | 1 | rocksdb::SyncPoint::GetInstance()->LoadDependency({ |
293 | 1 | {"DeleteSchedulerTest::ConflictNames:1", |
294 | 1 | "DeleteScheduler::BackgroundEmptyTrash"}, |
295 | 1 | }); |
296 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
297 | | |
298 | 1 | rate_bytes_per_sec_ = 1024 * 1024; // 1 Mb/sec |
299 | 1 | NewDeleteScheduler(); |
300 | | |
301 | | // Create "conflict.data" and move it to trash 10 times |
302 | 11 | for (int i = 0; i < 10; i++) { |
303 | 10 | std::string dummy_file = NewDummyFile("conflict.data"); |
304 | 10 | ASSERT_OK(delete_scheduler_->DeleteFile(dummy_file)); |
305 | 10 | } |
306 | 1 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
307 | | // 10 files ("conflict.data" x 10) in trash |
308 | 1 | ASSERT_EQ(CountFilesInDir(trash_dir_), 10); |
309 | | |
310 | | // Hold BackgroundEmptyTrash |
311 | 1 | TEST_SYNC_POINT("DeleteSchedulerTest::ConflictNames:1"); |
312 | 1 | delete_scheduler_->WaitForEmptyTrash(); |
313 | 1 | ASSERT_EQ(CountFilesInDir(trash_dir_), 0); |
314 | | |
315 | 1 | auto bg_errors = delete_scheduler_->GetBackgroundErrors(); |
316 | 1 | ASSERT_EQ(bg_errors.size(), 0); |
317 | | |
318 | 1 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
319 | 1 | } |
320 | | |
321 | | // 1- Create 10 dummy files |
322 | | // 2- Delete the 10 files using DeleteScheduler (move them to trsah) |
323 | | // 3- Delete the 10 files directly (using env_->DeleteFile) |
324 | | // --- Hold DeleteScheduler::BackgroundEmptyTrash --- |
325 | | // 4- Make sure that DeleteScheduler failed to delete the 10 files and |
326 | | // reported 10 background errors |
327 | 1 | TEST_F(DeleteSchedulerTest, BackgroundError) { |
328 | 1 | rocksdb::SyncPoint::GetInstance()->LoadDependency({ |
329 | 1 | {"DeleteSchedulerTest::BackgroundError:1", |
330 | 1 | "DeleteScheduler::BackgroundEmptyTrash"}, |
331 | 1 | }); |
332 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
333 | | |
334 | 1 | rate_bytes_per_sec_ = 1024 * 1024; // 1 Mb/sec |
335 | 1 | NewDeleteScheduler(); |
336 | | |
337 | | // Generate 10 dummy files and move them to trash |
338 | 11 | for (int i = 0; i < 10; i++) { |
339 | 10 | std::string file_name = "data_" + ToString(i) + ".data"; |
340 | 10 | ASSERT_OK(delete_scheduler_->DeleteFile(NewDummyFile(file_name))); |
341 | 10 | } |
342 | 1 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
343 | 1 | ASSERT_EQ(CountFilesInDir(trash_dir_), 10); |
344 | | |
345 | | // Delete 10 files from trash, this will cause background errors in |
346 | | // BackgroundEmptyTrash since we already deleted the files it was |
347 | | // goind to delete |
348 | 11 | for (int i = 0; i < 10; i++) { |
349 | 10 | std::string file_name = "data_" + ToString(i) + ".data"; |
350 | 10 | ASSERT_OK(env_->DeleteFile(trash_dir_ + "/" + file_name)); |
351 | 10 | } |
352 | | |
353 | | // Hold BackgroundEmptyTrash |
354 | 1 | TEST_SYNC_POINT("DeleteSchedulerTest::BackgroundError:1"); |
355 | 1 | delete_scheduler_->WaitForEmptyTrash(); |
356 | 1 | auto bg_errors = delete_scheduler_->GetBackgroundErrors(); |
357 | 1 | ASSERT_EQ(bg_errors.size(), 10); |
358 | | |
359 | 1 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
360 | 1 | } |
361 | | |
362 | | // 1- Create 10 dummy files |
363 | | // 2- Delete 10 dummy files using DeleteScheduler |
364 | | // 3- Wait for DeleteScheduler to delete all files in queue |
365 | | // 4- Make sure all files in trash directory were deleted |
366 | | // 5- Repeat previous steps 5 times |
367 | 1 | TEST_F(DeleteSchedulerTest, StartBGEmptyTrashMultipleTimes) { |
368 | 1 | int bg_delete_file = 0; |
369 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
370 | 1 | "DeleteScheduler::DeleteTrashFile:DeleteFile", |
371 | 50 | [&](void* arg) { bg_delete_file++; }); |
372 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
373 | | |
374 | 1 | rate_bytes_per_sec_ = 1024 * 1024; // 1 MB / sec |
375 | 1 | NewDeleteScheduler(); |
376 | | |
377 | | // Move files to trash, wait for empty trash, start again |
378 | 6 | for (int run = 1; run <= 5; run++) { |
379 | | // Generate 10 dummy files and move them to trash |
380 | 55 | for (int i = 0; i < 10; i++) { |
381 | 50 | std::string file_name = "data_" + ToString(i) + ".data"; |
382 | 50 | ASSERT_OK(delete_scheduler_->DeleteFile(NewDummyFile(file_name))); |
383 | 50 | } |
384 | 5 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
385 | 5 | delete_scheduler_->WaitForEmptyTrash(); |
386 | 5 | ASSERT_EQ(bg_delete_file, 10 * run); |
387 | 5 | ASSERT_EQ(CountFilesInDir(trash_dir_), 0); |
388 | | |
389 | 5 | auto bg_errors = delete_scheduler_->GetBackgroundErrors(); |
390 | 5 | ASSERT_EQ(bg_errors.size(), 0); |
391 | 5 | } |
392 | | |
393 | 1 | ASSERT_EQ(bg_delete_file, 50); |
394 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
395 | 1 | } |
396 | | |
397 | | // 1- Create a DeleteScheduler with very slow rate limit (1 Byte / sec) |
398 | | // 2- Delete 100 files using DeleteScheduler |
399 | | // 3- Delete the DeleteScheduler (call the destructor while queue is not empty) |
400 | | // 4- Make sure that not all files were deleted from trash and that |
401 | | // DeleteScheduler background thread did not delete all files |
402 | 1 | TEST_F(DeleteSchedulerTest, DestructorWithNonEmptyQueue) { |
403 | 1 | int bg_delete_file = 0; |
404 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
405 | 1 | "DeleteScheduler::DeleteTrashFile:DeleteFile", |
406 | 1 | [&](void* arg) { bg_delete_file++; }); |
407 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
408 | | |
409 | 1 | rate_bytes_per_sec_ = 1; // 1 Byte / sec |
410 | 1 | NewDeleteScheduler(); |
411 | | |
412 | 101 | for (int i = 0; i < 100; i++) { |
413 | 100 | std::string file_name = "data_" + ToString(i) + ".data"; |
414 | 100 | ASSERT_OK(delete_scheduler_->DeleteFile(NewDummyFile(file_name))); |
415 | 100 | } |
416 | | |
417 | | // Deleting 100 files will need >28 hours to delete |
418 | | // we will delete the DeleteScheduler while delete queue is not empty |
419 | 1 | delete_scheduler_.reset(); |
420 | | |
421 | 1 | ASSERT_LT(bg_delete_file, 100); |
422 | 1 | ASSERT_GT(CountFilesInDir(trash_dir_), 0); |
423 | | |
424 | 1 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
425 | 1 | } |
426 | | |
427 | | // 1- Delete the trash directory |
428 | | // 2- Delete 10 files using DeleteScheduler |
429 | | // 3- Make sure that the 10 files were deleted immediately since DeleteScheduler |
430 | | // failed to move them to trash directory |
431 | 1 | TEST_F(DeleteSchedulerTest, MoveToTrashError) { |
432 | 1 | int bg_delete_file = 0; |
433 | 1 | rocksdb::SyncPoint::GetInstance()->SetCallBack( |
434 | 1 | "DeleteScheduler::DeleteTrashFile:DeleteFile", |
435 | 0 | [&](void* arg) { bg_delete_file++; }); |
436 | 1 | rocksdb::SyncPoint::GetInstance()->EnableProcessing(); |
437 | | |
438 | 1 | rate_bytes_per_sec_ = 1024; // 1 Kb / sec |
439 | 1 | NewDeleteScheduler(); |
440 | | |
441 | | // We will delete the trash directory, that mean that DeleteScheduler wont |
442 | | // be able to move files to trash and will delete files them immediately. |
443 | 1 | DestroyDir(trash_dir_); |
444 | 11 | for (int i = 0; i < 10; i++) { |
445 | 10 | std::string file_name = "data_" + ToString(i) + ".data"; |
446 | 10 | ASSERT_OK(delete_scheduler_->DeleteFile(NewDummyFile(file_name))); |
447 | 10 | } |
448 | | |
449 | 1 | ASSERT_EQ(CountFilesInDir(dummy_files_dir_), 0); |
450 | 1 | ASSERT_EQ(bg_delete_file, 0); |
451 | | |
452 | 1 | rocksdb::SyncPoint::GetInstance()->DisableProcessing(); |
453 | 1 | } |
454 | | } // namespace rocksdb |
455 | | |
456 | 13.2k | int main(int argc, char** argv) { |
457 | 13.2k | ::testing::InitGoogleTest(&argc, argv); |
458 | 13.2k | return RUN_ALL_TESTS(); |
459 | 13.2k | } |