| 97 | } |
| 98 | |
| 99 | void SsdCache::write(std::vector<CachePin> pins) { |
| 100 | BOLT_CHECK_LE(numShards_, writesInProgress_); |
| 101 | |
| 102 | BOLT_TEST_ADJUST("bytedance::bolt::cache::SsdCache::write", this); |
| 103 | |
| 104 | const auto startTimeUs = getCurrentTimeMicro(); |
| 105 | |
| 106 | uint64_t bytes = 0; |
| 107 | std::vector<std::vector<CachePin>> shards(numShards_); |
| 108 | for (auto& pin : pins) { |
| 109 | bytes += pin.checkedEntry()->size(); |
| 110 | const auto& target = file(pin.checkedEntry()->key().fileNum.id()); |
| 111 | shards[target.shardId()].push_back(std::move(pin)); |
| 112 | } |
| 113 | |
| 114 | int32_t numNoStore = 0; |
| 115 | for (auto i = 0; i < numShards_; ++i) { |
| 116 | if (shards[i].empty()) { |
| 117 | ++numNoStore; |
| 118 | continue; |
| 119 | } |
| 120 | struct PinHolder { |
| 121 | std::vector<CachePin> pins; |
| 122 | |
| 123 | explicit PinHolder(std::vector<CachePin>&& _pins) |
| 124 | : pins(std::move(_pins)) {} |
| 125 | }; |
| 126 | |
| 127 | // We move the mutable vector of pins to the executor. These must |
| 128 | // be wrapped in a shared struct to be passed via lambda capture. |
| 129 | auto pinHolder = std::make_shared<PinHolder>(std::move(shards[i])); |
| 130 | executor_->add([this, i, pinHolder, bytes, startTimeUs]() { |
| 131 | try { |
| 132 | files_[i]->write(pinHolder->pins); |
| 133 | } catch (const std::exception& e) { |
| 134 | // Catch so as not to miss updating 'writesInProgress_'. Could |
| 135 | // theoretically happen for std::bad_alloc or such. |
| 136 | BOLT_SSD_CACHE_LOG(WARNING) |
| 137 | << "Ignoring error in SsdFile::write: " << e.what(); |
| 138 | } |
| 139 | pinHolder->pins.clear(); |
| 140 | if (--writesInProgress_ == 0) { |
| 141 | // Typically occurs every few GB. Allows detecting unusually slow rates |
| 142 | // from failing devices. |
| 143 | BOLT_SSD_CACHE_LOG(INFO) << fmt::format( |
| 144 | "Wrote {}MB, {} MB/s", |
| 145 | bytes >> 20, |
| 146 | static_cast<float>(bytes) / (getCurrentTimeMicro() - startTimeUs)); |
| 147 | } |
| 148 | }); |
| 149 | } |
| 150 | writesInProgress_.fetch_sub(numNoStore); |
| 151 | } |
| 152 | |
| 153 | bool SsdCache::removeFileEntries( |
| 154 | const folly::F14FastSet<uint64_t>& filesToRemove, |