| 64 | : env_(env), refresh_rate_secs_(refresh_rate_secs) {} |
| 65 | |
| 66 | void GcsDnsCache::AnnotateRequest(HttpRequest* request) { |
| 67 | // TODO(saeta): Blacklist failing IP addresses. |
| 68 | mutex_lock l(mu_); |
| 69 | if (!started_) { |
| 70 | VLOG(1) << "Starting GCS DNS cache."; |
| 71 | DCHECK(!worker_) << "Worker thread already exists!"; |
| 72 | // Perform DNS resolutions to warm the cache. |
| 73 | addresses_ = ResolveNames(kCachedDomainNames); |
| 74 | |
| 75 | // Note: we opt to use a thread instead of a delayed closure. |
| 76 | worker_.reset(env_->StartThread({}, "gcs_dns_worker", |
| 77 | [this]() { return WorkerThread(); })); |
| 78 | started_ = true; |
| 79 | } |
| 80 | |
| 81 | CHECK_EQ(kCachedDomainNames.size(), addresses_.size()); |
| 82 | for (size_t i = 0; i < kCachedDomainNames.size(); ++i) { |
| 83 | const string& name = kCachedDomainNames[i]; |
| 84 | const std::vector<string>& addresses = addresses_[i]; |
| 85 | if (!addresses.empty()) { |
| 86 | const string& chosen_address = |
| 87 | SelectRandomItemUniform(&random_, addresses); |
| 88 | request->AddResolveOverride(name, 443, chosen_address); |
| 89 | VLOG(1) << "Annotated DNS mapping: " << name << " --> " << chosen_address; |
| 90 | } else { |
| 91 | LOG(WARNING) << "No IP addresses available for " << name; |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | /* static */ std::vector<string> GcsDnsCache::ResolveName(const string& name) { |
| 97 | VLOG(1) << "Resolving DNS name: " << name; |