| Index: ceee/ie/broker/broker_rpc_client.cc
 | 
| ===================================================================
 | 
| --- ceee/ie/broker/broker_rpc_client.cc	(revision 67905)
 | 
| +++ ceee/ie/broker/broker_rpc_client.cc	(working copy)
 | 
| @@ -9,17 +9,60 @@
 | 
|  #include <atlbase.h>
 | 
|  #include "base/lock.h"
 | 
|  #include "base/logging.h"
 | 
| +#include "base/tuple.h"
 | 
|  #include "base/win/scoped_comptr.h"
 | 
|  #include "broker_lib.h"  // NOLINT
 | 
|  #include "broker_rpc_lib.h"  // NOLINT
 | 
|  #include "ceee/common/com_utils.h"
 | 
|  #include "ceee/ie/broker/broker_rpc_utils.h"
 | 
|  
 | 
| -BrokerRpcClient::BrokerRpcClient() : context_(0), binding_handle_(NULL) {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +void LogRpcException(const char* str, unsigned int exception_code) {
 | 
| +  LOG(ERROR) << str << com::LogWe(exception_code);
 | 
|  }
 | 
|  
 | 
| -BrokerRpcClient::~BrokerRpcClient() {
 | 
| -  Disconnect();
 | 
| +HRESULT BindRpc(std::wstring endpoint, RPC_BINDING_HANDLE* binding_handle) {
 | 
| +  DCHECK(binding_handle != NULL);
 | 
| +  std::wstring protocol = kRpcProtocol;
 | 
| +  DCHECK(!protocol.empty());
 | 
| +  DCHECK(!endpoint.empty());
 | 
| +  if (protocol.empty() || endpoint.empty() || binding_handle == NULL)
 | 
| +    return E_INVALIDARG;
 | 
| +
 | 
| +  RPC_BINDING_HANDLE tmp_binding_handle = NULL;
 | 
| +
 | 
| +  // TODO(vitalybuka@google.com): There's no guarantee (aside from name
 | 
| +  // uniqueness) that it will connect to an endpoint created by the same user.
 | 
| +  // Hint: The missing invocation is RpcBindingSetAuthInfoEx.
 | 
| +  VLOG(1) << "Connecting to RPC server. Endpoint: " << endpoint;
 | 
| +  RPC_WSTR string_binding = NULL;
 | 
| +  // Create binding string for given end point.
 | 
| +  RPC_STATUS status = ::RpcStringBindingCompose(
 | 
| +      NULL,
 | 
| +      reinterpret_cast<RPC_WSTR>(&protocol[0]),
 | 
| +      NULL,
 | 
| +      reinterpret_cast<RPC_WSTR>(&endpoint[0]),
 | 
| +      NULL,
 | 
| +      &string_binding);
 | 
| +
 | 
| +  if (RPC_S_OK == status) {
 | 
| +    // Create binding from just generated binding string. Binding handle should
 | 
| +    // be used for PRC calls.
 | 
| +    status = ::RpcBindingFromStringBinding(string_binding, &tmp_binding_handle);
 | 
| +    ::RpcStringFree(&string_binding);
 | 
| +    if (RPC_S_OK == status) {
 | 
| +      VLOG(1) << "RPC client is connected. Endpoint: " << endpoint;
 | 
| +      *binding_handle = tmp_binding_handle;
 | 
| +      return S_OK;
 | 
| +    } else {
 | 
| +      LogRpcException("Failed to bind. RPC_STATUS:", status);
 | 
| +    }
 | 
| +  } else {
 | 
| +    LogRpcException("Failed to compose binding string. RPC_STATUS:", status);
 | 
| +  }
 | 
| +  return RPC_E_FAULT;
 | 
|  }
 | 
|  
 | 
|  int HandleRpcException(unsigned int rpc_exception_code) {
 | 
| @@ -38,10 +81,18 @@
 | 
|    return EXCEPTION_EXECUTE_HANDLER;
 | 
|  }
 | 
|  
 | 
| -static void LogRpcException(const char* str, unsigned int exception_code) {
 | 
| -  LOG(ERROR) << str << com::LogWe(exception_code);
 | 
| +}  // namespace
 | 
| +
 | 
| +BrokerRpcClient::BrokerRpcClient(bool allow_restarts)
 | 
| +    : context_(0),
 | 
| +      binding_handle_(NULL),
 | 
| +      allow_restarts_(allow_restarts) {
 | 
|  }
 | 
|  
 | 
| +BrokerRpcClient::~BrokerRpcClient() {
 | 
| +  Disconnect();
 | 
| +}
 | 
| +
 | 
|  void BrokerRpcClient::LockContext() {
 | 
|    RpcTryExcept {
 | 
|      context_ = BrokerRpcClient_Connect(binding_handle_);
 | 
| @@ -58,56 +109,33 @@
 | 
|    } RpcEndExcept
 | 
|  }
 | 
|  
 | 
| +HRESULT BrokerRpcClient::StartServer(IUnknown** server) {
 | 
| +  base::win::ScopedComPtr<IUnknown> broker;
 | 
| +  // TODO(vitalybuka@google.com): Start broker without COM after the last
 | 
| +  // COM interface is removed.
 | 
| +  HRESULT hr = broker.CreateInstance(CLSID_CeeeBroker);
 | 
| +  LOG_IF(ERROR, FAILED(hr)) << "Failed to create broker. " << com::LogHr(hr);
 | 
| +  if (FAILED(hr))
 | 
| +    return hr;
 | 
| +  *server = broker.Detach();
 | 
| +  return S_OK;
 | 
| +}
 | 
| +
 | 
|  HRESULT BrokerRpcClient::Connect(bool start_server) {
 | 
|    if (is_connected())
 | 
|      return S_OK;
 | 
|  
 | 
|    // Keep alive until RPC is connected.
 | 
| -  base::win::ScopedComPtr<ICeeeBrokerRegistrar> broker;
 | 
| +  base::win::ScopedComPtr<IUnknown> broker;
 | 
|    if (start_server) {
 | 
| -    // TODO(vitalybuka@google.com): Start broker without COM after the last
 | 
| -    // COM interface is removed.
 | 
| -    HRESULT hr = broker.CreateInstance(CLSID_CeeeBroker);
 | 
| -    LOG_IF(ERROR, FAILED(hr)) << "Failed to create broker. " << com::LogHr(hr);
 | 
| +    HRESULT hr = StartServer(broker.Receive());
 | 
|      if (FAILED(hr))
 | 
|        return hr;
 | 
|    }
 | 
|  
 | 
| -  std::wstring end_point = GetRpcEndPointAddress();
 | 
| -  std::wstring protocol = kRpcProtocol;
 | 
| -  DCHECK(!protocol.empty());
 | 
| -  DCHECK(!end_point.empty());
 | 
| -  if (protocol.empty() || end_point.empty())
 | 
| -    return RPC_E_FAULT;
 | 
| +  if (SUCCEEDED(BindRpc(GetRpcEndpointAddress(), &binding_handle_)))
 | 
| +    LockContext();
 | 
|  
 | 
| -  // TODO(vitalybuka@google.com): There's no guarantee (aside from name
 | 
| -  // uniqueness) that it will connect to an endpoint created by the same user.
 | 
| -  // Hint: The missing invocation is RpcBindingSetAuthInfoEx.
 | 
| -  LOG(INFO) << "Connecting to RPC server. Endpoint: " << end_point;
 | 
| -  RPC_WSTR string_binding = NULL;
 | 
| -  // Create binding string with given protocol and end point.
 | 
| -  RPC_STATUS status = ::RpcStringBindingCompose(
 | 
| -      NULL,
 | 
| -      reinterpret_cast<RPC_WSTR>(&protocol[0]),
 | 
| -      NULL,
 | 
| -      reinterpret_cast<RPC_WSTR>(&end_point[0]),
 | 
| -      NULL,
 | 
| -      &string_binding);
 | 
| -  LOG_IF(ERROR, RPC_S_OK != status) <<
 | 
| -      "Failed to compose binding string. RPC_STATUS=0x" << com::LogWe(status);
 | 
| -
 | 
| -  if (RPC_S_OK == status) {
 | 
| -    // Create binding from just generated binding string. Binding handle should
 | 
| -    // used for PRC calls.
 | 
| -    status = ::RpcBindingFromStringBinding(string_binding, &binding_handle_);
 | 
| -    LOG_IF(ERROR, RPC_S_OK != status) <<
 | 
| -        "Failed to bind. RPC_STATUS=0x" << com::LogWe(status);
 | 
| -    ::RpcStringFree(&string_binding);
 | 
| -    if (RPC_S_OK == status) {
 | 
| -      LOG(INFO) << "RPC client is connected. Endpoint: " << end_point;
 | 
| -      LockContext();
 | 
| -    }
 | 
| -  }
 | 
|    if (!is_connected()) {
 | 
|      Disconnect();
 | 
|      return RPC_E_FAULT;
 | 
| @@ -125,26 +153,42 @@
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -HRESULT BrokerRpcClient::FireEvent(const char* event_name,
 | 
| -                                   const char* event_args) {
 | 
| +template<class Function, class Params>
 | 
| +HRESULT BrokerRpcClient::RunRpc(bool allow_restart,
 | 
| +                                Function rpc_function,
 | 
| +                                const Params& params) {
 | 
| +  DCHECK(rpc_function);
 | 
| +  if (!is_connected())
 | 
| +    return RPC_E_FAULT;
 | 
|    RpcTryExcept {
 | 
| -    BrokerRpcClient_FireEvent(binding_handle_, context_, event_name,
 | 
| -                              event_args);
 | 
| +    DispatchToFunction(rpc_function, params);
 | 
|      return S_OK;
 | 
|    } RpcExcept(HandleRpcException(RpcExceptionCode())) {
 | 
| -    LogRpcException("RPC error in FireEvent", RpcExceptionCode());
 | 
| +    LogRpcException("RPC error in RunRpc", RpcExceptionCode());
 | 
| +
 | 
| +    if (allow_restart &&
 | 
| +        RPC_S_OK != ::RpcMgmtIsServerListening(binding_handle_)) {
 | 
| +      Disconnect();
 | 
| +      if (SUCCEEDED(Connect(true))) {
 | 
| +        return RunRpc(false, rpc_function, params);
 | 
| +      }
 | 
| +    }
 | 
|      return RPC_E_FAULT;
 | 
|    } RpcEndExcept
 | 
|  }
 | 
|  
 | 
| +HRESULT BrokerRpcClient::FireEvent(const char* event_name,
 | 
| +                                   const char* event_args) {
 | 
| +  return RunRpc(allow_restarts_,
 | 
| +                &BrokerRpcClient_FireEvent,
 | 
| +                MakeRefTuple(binding_handle_, context_, event_name,
 | 
| +                             event_args));
 | 
| +}
 | 
| +
 | 
|  HRESULT BrokerRpcClient::SendUmaHistogramTimes(const char* name, int sample) {
 | 
| -  RpcTryExcept {
 | 
| -    BrokerRpcClient_SendUmaHistogramTimes(binding_handle_, name, sample);
 | 
| -    return S_OK;
 | 
| -  } RpcExcept(HandleRpcException(RpcExceptionCode())) {
 | 
| -    LogRpcException("RPC error in SendUmaHistogramTimes", RpcExceptionCode());
 | 
| -    return RPC_E_FAULT;
 | 
| -  } RpcEndExcept
 | 
| +  return RunRpc(allow_restarts_,
 | 
| +                &BrokerRpcClient_SendUmaHistogramTimes,
 | 
| +                MakeRefTuple(binding_handle_, name, sample));
 | 
|  }
 | 
|  
 | 
|  HRESULT BrokerRpcClient::SendUmaHistogramData(const char* name,
 | 
| @@ -152,12 +196,8 @@
 | 
|                                                int min,
 | 
|                                                int max,
 | 
|                                                int bucket_count) {
 | 
| -  RpcTryExcept {
 | 
| -    BrokerRpcClient_SendUmaHistogramData(
 | 
| -        binding_handle_, name, sample, min, max, bucket_count);
 | 
| -    return S_OK;
 | 
| -  } RpcExcept(HandleRpcException(RpcExceptionCode())) {
 | 
| -    LogRpcException("RPC error in SendUmaHistogramData", RpcExceptionCode());
 | 
| -    return RPC_E_FAULT;
 | 
| -  } RpcEndExcept
 | 
| +  return RunRpc(allow_restarts_,
 | 
| +                &BrokerRpcClient_SendUmaHistogramData,
 | 
| +                MakeRefTuple(binding_handle_, name, sample, min, max,
 | 
| +                          bucket_count));
 | 
|  }
 | 
| 
 |