| 68 | } |
| 69 | |
| 70 | Status ClientCacheHelper::ReopenClient( |
| 71 | const ClientFactory& factory_method, ClientKey* client_key) { |
| 72 | // Clients are not ordinarily removed from the cache completely (in the future, they may |
| 73 | // be); this is the only method where a client may be deleted and replaced with another. |
| 74 | shared_ptr<ThriftClientImpl> client_impl; |
| 75 | ClientMap::iterator client; |
| 76 | { |
| 77 | lock_guard<mutex> lock(client_map_lock_); |
| 78 | client = client_map_.find(*client_key); |
| 79 | DCHECK(client != client_map_.end()); |
| 80 | client_impl = client->second; |
| 81 | } |
| 82 | VLOG(1) << "ReopenClient(): re-creating client for " << |
| 83 | TNetworkAddressToString(client_impl->address()); |
| 84 | |
| 85 | client_impl->Close(); |
| 86 | |
| 87 | // TODO: Thrift TBufferedTransport cannot be re-opened after Close() because it does not |
| 88 | // clean up internal buffers it reopens. To work around this issue, create a new client |
| 89 | // instead. |
| 90 | ClientKey old_client_key = *client_key; |
| 91 | Status status = CreateClient(client_impl->address(), factory_method, client_key); |
| 92 | // Only erase the existing client from the map if creation of the new one succeeded. |
| 93 | // This helps to ensure the proper accounting of metrics in the presence of |
| 94 | // re-connection failures (the original client should be released as usual). |
| 95 | if (status.ok()) { |
| 96 | // CreateClient() will increment total_clients_metric_ if succeed. |
| 97 | if (metrics_enabled_) { |
| 98 | total_clients_metric_->Increment(-1); |
| 99 | DCHECK_GE(total_clients_metric_->GetValue(), 0); |
| 100 | } |
| 101 | lock_guard<mutex> lock(client_map_lock_); |
| 102 | client_map_.erase(client); |
| 103 | } else { |
| 104 | // Restore the client used before the failed re-opening attempt, so the caller can |
| 105 | // properly release it. |
| 106 | *client_key = old_client_key; |
| 107 | } |
| 108 | return status; |
| 109 | } |
| 110 | |
| 111 | Status ClientCacheHelper::CreateClient(const TNetworkAddress& address, |
| 112 | const ClientFactory& factory_method, ClientKey* client_key) { |