fault_injection_secondary_cache.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. // This class implements a custom SecondaryCache that randomly injects an
  6. // error status into Inserts/Lookups based on a specified probability.
  7. #include "utilities/fault_injection_secondary_cache.h"
  8. namespace ROCKSDB_NAMESPACE {
  9. void FaultInjectionSecondaryCache::ResultHandle::UpdateHandleValue(
  10. FaultInjectionSecondaryCache::ResultHandle* handle) {
  11. ErrorContext* ctx = handle->cache_->GetErrorContext();
  12. if (!ctx->rand.OneIn(handle->cache_->prob_)) {
  13. handle->value_ = handle->base_->Value();
  14. handle->size_ = handle->base_->Size();
  15. }
  16. handle->base_.reset();
  17. }
  18. bool FaultInjectionSecondaryCache::ResultHandle::IsReady() {
  19. bool ready = true;
  20. if (base_) {
  21. ready = base_->IsReady();
  22. if (ready) {
  23. UpdateHandleValue(this);
  24. }
  25. }
  26. return ready;
  27. }
  28. void FaultInjectionSecondaryCache::ResultHandle::Wait() {
  29. base_->Wait();
  30. UpdateHandleValue(this);
  31. }
  32. Cache::ObjectPtr FaultInjectionSecondaryCache::ResultHandle::Value() {
  33. return value_;
  34. }
  35. size_t FaultInjectionSecondaryCache::ResultHandle::Size() { return size_; }
  36. void FaultInjectionSecondaryCache::ResultHandle::WaitAll(
  37. FaultInjectionSecondaryCache* cache,
  38. std::vector<SecondaryCacheResultHandle*> handles) {
  39. std::vector<SecondaryCacheResultHandle*> base_handles;
  40. for (SecondaryCacheResultHandle* hdl : handles) {
  41. FaultInjectionSecondaryCache::ResultHandle* handle =
  42. static_cast<FaultInjectionSecondaryCache::ResultHandle*>(hdl);
  43. if (!handle->base_) {
  44. continue;
  45. }
  46. base_handles.emplace_back(handle->base_.get());
  47. }
  48. cache->base_->WaitAll(base_handles);
  49. for (SecondaryCacheResultHandle* hdl : handles) {
  50. FaultInjectionSecondaryCache::ResultHandle* handle =
  51. static_cast<FaultInjectionSecondaryCache::ResultHandle*>(hdl);
  52. if (handle->base_) {
  53. UpdateHandleValue(handle);
  54. }
  55. }
  56. }
  57. FaultInjectionSecondaryCache::ErrorContext*
  58. FaultInjectionSecondaryCache::GetErrorContext() {
  59. ErrorContext* ctx = static_cast<ErrorContext*>(thread_local_error_->Get());
  60. if (!ctx) {
  61. ctx = new ErrorContext(seed_);
  62. thread_local_error_->Reset(ctx);
  63. }
  64. return ctx;
  65. }
  66. Status FaultInjectionSecondaryCache::Insert(
  67. const Slice& key, Cache::ObjectPtr value,
  68. const Cache::CacheItemHelper* helper, bool force_insert) {
  69. ErrorContext* ctx = GetErrorContext();
  70. if (ctx->rand.OneIn(prob_)) {
  71. return Status::IOError();
  72. }
  73. return base_->Insert(key, value, helper, force_insert);
  74. }
  75. std::unique_ptr<SecondaryCacheResultHandle>
  76. FaultInjectionSecondaryCache::Lookup(const Slice& key,
  77. const Cache::CacheItemHelper* helper,
  78. Cache::CreateContext* create_context,
  79. bool wait, bool advise_erase,
  80. Statistics* stats,
  81. bool& kept_in_sec_cache) {
  82. ErrorContext* ctx = GetErrorContext();
  83. if (base_is_compressed_sec_cache_) {
  84. if (ctx->rand.OneIn(prob_)) {
  85. return nullptr;
  86. } else {
  87. return base_->Lookup(key, helper, create_context, wait, advise_erase,
  88. stats, kept_in_sec_cache);
  89. }
  90. } else {
  91. std::unique_ptr<SecondaryCacheResultHandle> hdl =
  92. base_->Lookup(key, helper, create_context, wait, advise_erase, stats,
  93. kept_in_sec_cache);
  94. if (wait && ctx->rand.OneIn(prob_)) {
  95. hdl.reset();
  96. }
  97. return std::unique_ptr<FaultInjectionSecondaryCache::ResultHandle>(
  98. new FaultInjectionSecondaryCache::ResultHandle(this, std::move(hdl)));
  99. }
  100. }
  101. void FaultInjectionSecondaryCache::Erase(const Slice& key) {
  102. base_->Erase(key);
  103. }
  104. void FaultInjectionSecondaryCache::WaitAll(
  105. std::vector<SecondaryCacheResultHandle*> handles) {
  106. if (base_is_compressed_sec_cache_) {
  107. ErrorContext* ctx = GetErrorContext();
  108. std::vector<SecondaryCacheResultHandle*> base_handles;
  109. for (SecondaryCacheResultHandle* hdl : handles) {
  110. if (ctx->rand.OneIn(prob_)) {
  111. continue;
  112. }
  113. base_handles.push_back(hdl);
  114. }
  115. base_->WaitAll(base_handles);
  116. } else {
  117. FaultInjectionSecondaryCache::ResultHandle::WaitAll(this, handles);
  118. }
  119. }
  120. } // namespace ROCKSDB_NAMESPACE