| 1420 | } |
| 1421 | |
| 1422 | void TabletNodeImpl::PersistentCacheGarbageCollect(const std::set<std::string>& inherited_files, |
| 1423 | const std::set<std::string>& active_tablets) { |
| 1424 | std::shared_ptr<leveldb::PersistentCache> p_cache; |
| 1425 | if (!io::GetPersistentCache(&p_cache).ok() || !p_cache) { |
| 1426 | return; |
| 1427 | } |
| 1428 | leveldb::StopWatchMicro timer(leveldb::Env::Default(), true); |
| 1429 | std::vector<std::string> all_keys{p_cache->GetAllKeys()}; |
| 1430 | /* |
| 1431 | * all cached tablets/files: |
| 1432 | * ------------------------------------------ |
| 1433 | * | active tablets | inactive tablets | |
| 1434 | * | | | |
| 1435 | * | | all | to | |
| 1436 | * | | inherited | *DELETE* | |
| 1437 | * | | files | | |
| 1438 | * ------------------------------------------ |
| 1439 | * We need to save active tablets' files and inherited files. |
| 1440 | * Try remove files of tablets not on this tabletserver. |
| 1441 | * Here is the gc rule: |
| 1442 | * |
| 1443 | * Key format in persistent cache: |table_name/tablet_name/lg_num/xxxxxxxx.sst| |
| 1444 | * | 1 | | |
| 1445 | * string in active_tablets |table_name/tablet_name| | |
| 1446 | * | 2 | |
| 1447 | * string in inherited_files |table_name/tablet_name/lg_num/xxxxxxxx.sst| |
| 1448 | * |
| 1449 | * If part 1 of persistent cache key doesn't match any string in active tablets, |
| 1450 | * and part 2 of it doesn't match any one in inherited_files, we'll remove it. |
| 1451 | */ |
| 1452 | std::unordered_set<std::string> new_delayed_gc_files; |
| 1453 | for (auto& key : all_keys) { |
| 1454 | if (inherited_files.find(key) != inherited_files.end()) { |
| 1455 | // 1. If file name in inherited_files, skip it. |
| 1456 | continue; |
| 1457 | } |
| 1458 | std::vector<std::string> splited_terms; |
| 1459 | SplitString(key, "/", &splited_terms); |
| 1460 | assert(splited_terms.size() > 2); |
| 1461 | // 2. Extract table_name/tablet_name from persistent key. |
| 1462 | std::string tablet_name = splited_terms[0] + "/" + splited_terms[1]; |
| 1463 | if (active_tablets.find(tablet_name) != active_tablets.end()) { |
| 1464 | // 3. Skip active tablets' file. |
| 1465 | continue; |
| 1466 | } |
| 1467 | if (delayed_gc_files_.find(key) != delayed_gc_files_.end()) { |
| 1468 | LOG(INFO) << "[Persistent Cache GC] Remove unused file: " << key << "."; |
| 1469 | // 4. If this key has already be delayed for one gc period, remove it. |
| 1470 | p_cache->ForceEvict(key); |
| 1471 | } else { |
| 1472 | LOG(INFO) << "[Persistent Cache GC] Add file: " << key << " to delayed gc files."; |
| 1473 | // 5. Otherwise, it'll be add to delayed_gc_files, waiting for next gc process. |
| 1474 | new_delayed_gc_files.emplace(key); |
| 1475 | } |
| 1476 | } |
| 1477 | |
| 1478 | std::swap(delayed_gc_files_, new_delayed_gc_files); |
| 1479 | p_cache->GarbageCollect(); |
nothing calls this directly
no test coverage detected