|  | @@ -275,15 +275,99 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
 | 
	
		
			
				|  |  |    grpc_completion_queue* cq_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +class Server::SyncRequestManager : public GrpcRpcManager {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  SyncRequestManager(Server* server, CompletionQueue* server_cq,
 | 
	
		
			
				|  |  | +                     std::shared_ptr<GlobalCallbacks> global_callbacks,
 | 
	
		
			
				|  |  | +                     int min_pollers, int max_pollers)
 | 
	
		
			
				|  |  | +      : GrpcRpcManager(min_pollers, max_pollers),
 | 
	
		
			
				|  |  | +        server_(server),
 | 
	
		
			
				|  |  | +        server_cq_(server_cq),
 | 
	
		
			
				|  |  | +        global_callbacks_(global_callbacks) {}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  static const int kRpcPollingTimeoutMsec = 500;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  WorkStatus PollForWork(void** tag, bool* ok) GRPC_OVERRIDE {
 | 
	
		
			
				|  |  | +    *tag = nullptr;
 | 
	
		
			
				|  |  | +    gpr_timespec deadline =
 | 
	
		
			
				|  |  | +        gpr_time_from_millis(kRpcPollingTimeoutMsec, GPR_TIMESPAN);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    switch (server_cq_->AsyncNext(tag, ok, deadline)) {
 | 
	
		
			
				|  |  | +      case CompletionQueue::TIMEOUT:
 | 
	
		
			
				|  |  | +        return TIMEOUT;
 | 
	
		
			
				|  |  | +      case CompletionQueue::SHUTDOWN:
 | 
	
		
			
				|  |  | +        return SHUTDOWN;
 | 
	
		
			
				|  |  | +      case CompletionQueue::GOT_EVENT:
 | 
	
		
			
				|  |  | +        return WORK_FOUND;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    GPR_UNREACHABLE_CODE(return TIMEOUT);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void DoWork(void* tag, bool ok) GRPC_OVERRIDE {
 | 
	
		
			
				|  |  | +    SyncRequest* sync_req = static_cast<SyncRequest*>(tag);
 | 
	
		
			
				|  |  | +    if (ok && sync_req) {
 | 
	
		
			
				|  |  | +      SyncRequest::CallData cd(server_, sync_req);
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        sync_req->SetupRequest();
 | 
	
		
			
				|  |  | +        if (!IsShutdown()) {
 | 
	
		
			
				|  |  | +          sync_req->Request(server_->c_server(), server_cq_->cq());
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          sync_req->TeardownRequest();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      GPR_TIMER_SCOPE("cd.Run()", 0);
 | 
	
		
			
				|  |  | +      cd.Run(global_callbacks_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // TODO (sreek): If ok == false, log an error
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void AddSyncMethod(RpcServiceMethod* method, void* tag) {
 | 
	
		
			
				|  |  | +    sync_methods_.emplace_back(method, tag);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void AddUnknownSyncMethod() {
 | 
	
		
			
				|  |  | +    // TODO (sreek) - Check if !sync_methods_.empty() is really needed here
 | 
	
		
			
				|  |  | +    if (!sync_methods_.empty()) {
 | 
	
		
			
				|  |  | +      unknown_method_.reset(new RpcServiceMethod(
 | 
	
		
			
				|  |  | +          "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
 | 
	
		
			
				|  |  | +      // Use of emplace_back with just constructor arguments is not accepted
 | 
	
		
			
				|  |  | +      // here by gcc-4.4 because it can't match the anonymous nullptr with a
 | 
	
		
			
				|  |  | +      // proper constructor implicitly. Construct the object and use push_back.
 | 
	
		
			
				|  |  | +      sync_methods_.push_back(SyncRequest(unknown_method_.get(), nullptr));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void Start() {
 | 
	
		
			
				|  |  | +    if (!sync_methods_.empty()) {
 | 
	
		
			
				|  |  | +      for (auto m = sync_methods_.begin(); m != sync_methods_.end(); m++) {
 | 
	
		
			
				|  |  | +        m->SetupRequest();
 | 
	
		
			
				|  |  | +        m->Request(server_->c_server(), server_cq_->cq());
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      GrpcRpcManager::Initialize();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | + private:
 | 
	
		
			
				|  |  | +  Server* server_;
 | 
	
		
			
				|  |  | +  CompletionQueue* server_cq_;
 | 
	
		
			
				|  |  | +  std::vector<SyncRequest> sync_methods_;
 | 
	
		
			
				|  |  | +  std::unique_ptr<RpcServiceMethod> unknown_method_;
 | 
	
		
			
				|  |  | +  std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static internal::GrpcLibraryInitializer g_gli_initializer;
 | 
	
		
			
				|  |  | -Server::Server(bool has_sync_methods, int max_message_size,
 | 
	
		
			
				|  |  | -               ChannelArguments* args)
 | 
	
		
			
				|  |  | -    : GrpcRpcManager(3, 5, 8),
 | 
	
		
			
				|  |  | -      max_message_size_(max_message_size),
 | 
	
		
			
				|  |  | +Server::Server(
 | 
	
		
			
				|  |  | +    std::shared_ptr<std::vector<ServerCompletionQueue>> sync_server_cqs,
 | 
	
		
			
				|  |  | +    int max_message_size, ChannelArguments* args, int min_pollers,
 | 
	
		
			
				|  |  | +    int max_pollers)
 | 
	
		
			
				|  |  | +    : max_message_size_(max_message_size),
 | 
	
		
			
				|  |  | +      sync_server_cqs_(sync_server_cqs),
 | 
	
		
			
				|  |  |        started_(false),
 | 
	
		
			
				|  |  |        shutdown_(false),
 | 
	
		
			
				|  |  |        shutdown_notified_(false),
 | 
	
		
			
				|  |  | -      sync_methods_(new std::list<SyncRequest>),
 | 
	
		
			
				|  |  |        has_generic_service_(false),
 | 
	
		
			
				|  |  |        server_(nullptr),
 | 
	
		
			
				|  |  |        server_initializer_(new ServerInitializer(this)) {
 | 
	
	
		
			
				|  | @@ -291,16 +375,17 @@ Server::Server(bool has_sync_methods, int max_message_size,
 | 
	
		
			
				|  |  |    gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
 | 
	
		
			
				|  |  |    global_callbacks_ = g_callbacks;
 | 
	
		
			
				|  |  |    global_callbacks_->UpdateArguments(args);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for (auto it = sync_server_cqs_->begin(); it != sync_server_cqs_->end();
 | 
	
		
			
				|  |  | +       it++) {
 | 
	
		
			
				|  |  | +    sync_req_mgrs_.emplace_back(new SyncRequestManager(
 | 
	
		
			
				|  |  | +        this, &(*it), global_callbacks_, min_pollers, max_pollers));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    grpc_channel_args channel_args;
 | 
	
		
			
				|  |  |    args->SetChannelArgs(&channel_args);
 | 
	
		
			
				|  |  | -  server_ = grpc_server_create(&channel_args, nullptr);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (!has_sync_methods) {
 | 
	
		
			
				|  |  | -    grpc_server_register_non_listening_completion_queue(server_, cq_.cq(),
 | 
	
		
			
				|  |  | -                                                        nullptr);
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  server_ = grpc_server_create(&channel_args, nullptr);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  Server::~Server() {
 | 
	
	
		
			
				|  | @@ -310,15 +395,20 @@ Server::~Server() {
 | 
	
		
			
				|  |  |        lock.unlock();
 | 
	
		
			
				|  |  |        Shutdown();
 | 
	
		
			
				|  |  |      } else if (!started_) {
 | 
	
		
			
				|  |  | +      // TODO (sreek): Shutdown all cqs
 | 
	
		
			
				|  |  | +      /*
 | 
	
		
			
				|  |  |        cq_.Shutdown();
 | 
	
		
			
				|  |  | +      */
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // TODO(sreek) Do thisfor all cqs ?
 | 
	
		
			
				|  |  | +  /*
 | 
	
		
			
				|  |  |    void* got_tag;
 | 
	
		
			
				|  |  |    bool ok;
 | 
	
		
			
				|  |  |    GPR_ASSERT(!cq_.Next(&got_tag, &ok));
 | 
	
		
			
				|  |  | +  */
 | 
	
		
			
				|  |  |    grpc_server_destroy(server_);
 | 
	
		
			
				|  |  | -  delete sync_methods_;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
 | 
	
	
		
			
				|  | @@ -329,8 +419,6 @@ void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_server* Server::c_server() { return server_; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -CompletionQueue* Server::completion_queue() { return &cq_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
 | 
	
		
			
				|  |  |      RpcServiceMethod* method) {
 | 
	
		
			
				|  |  |    switch (method->method_type()) {
 | 
	
	
		
			
				|  | @@ -351,6 +439,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
 | 
	
		
			
				|  |  |                 "Can only register an asynchronous service against one server.");
 | 
	
		
			
				|  |  |      service->server_ = this;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    const char* method_name = nullptr;
 | 
	
		
			
				|  |  |    for (auto it = service->methods_.begin(); it != service->methods_.end();
 | 
	
		
			
				|  |  |         ++it) {
 | 
	
	
		
			
				|  | @@ -369,7 +458,9 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
 | 
	
		
			
				|  |  |      if (method->handler() == nullptr) {
 | 
	
		
			
				|  |  |        method->set_server_tag(tag);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      sync_methods_->emplace_back(method, tag);
 | 
	
		
			
				|  |  | +      for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
 | 
	
		
			
				|  |  | +        (*it)->AddSyncMethod(method, tag);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      method_name = method->name();
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -405,13 +496,8 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
 | 
	
		
			
				|  |  |    grpc_server_start(server_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!has_generic_service_) {
 | 
	
		
			
				|  |  | -    if (!sync_methods_->empty()) {
 | 
	
		
			
				|  |  | -      unknown_method_.reset(new RpcServiceMethod(
 | 
	
		
			
				|  |  | -          "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
 | 
	
		
			
				|  |  | -      // Use of emplace_back with just constructor arguments is not accepted
 | 
	
		
			
				|  |  | -      // here by gcc-4.4 because it can't match the anonymous nullptr with a
 | 
	
		
			
				|  |  | -      // proper constructor implicitly. Construct the object and use push_back.
 | 
	
		
			
				|  |  | -      sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr));
 | 
	
		
			
				|  |  | +    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
 | 
	
		
			
				|  |  | +      (*it)->AddUnknownSyncMethod();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for (size_t i = 0; i < num_cqs; i++) {
 | 
	
	
		
			
				|  | @@ -421,6 +507,12 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
 | 
	
		
			
				|  |  | +    (*it)->Start();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* TODO (Sreek) - Do this for all cqs */
 | 
	
		
			
				|  |  | +  /*
 | 
	
		
			
				|  |  |    // Start processing rpcs.
 | 
	
		
			
				|  |  |    if (!sync_methods_->empty()) {
 | 
	
		
			
				|  |  |      for (auto m = sync_methods_->begin(); m != sync_methods_->end(); m++) {
 | 
	
	
		
			
				|  | @@ -430,26 +522,73 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      GrpcRpcManager::Initialize();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// TODO (sreek) - Reimplement this
 | 
	
		
			
				|  |  |  void Server::ShutdownInternal(gpr_timespec deadline) {
 | 
	
		
			
				|  |  |    grpc::unique_lock<grpc::mutex> lock(mu_);
 | 
	
		
			
				|  |  |    if (started_ && !shutdown_) {
 | 
	
		
			
				|  |  |      shutdown_ = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    int shutdown_tag = 0;  // Dummy shutdown tag
 | 
	
		
			
				|  |  | +    grpc_server_shutdown_and_notify(server_, shutdown_cq_.cq(), &shutdown_tag);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Shutdown all RpcManagers. This will try to gracefully stop all the
 | 
	
		
			
				|  |  | +    // threads in the RpcManagers (once they process any inflight requests)
 | 
	
		
			
				|  |  | +    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
 | 
	
		
			
				|  |  | +      (*it)->ShutdownRpcManager();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    shutdown_cq_.Shutdown();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void* tag;
 | 
	
		
			
				|  |  | +    bool ok;
 | 
	
		
			
				|  |  | +    CompletionQueue::NextStatus status =
 | 
	
		
			
				|  |  | +        shutdown_cq_.AsyncNext(&tag, &ok, deadline);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If this timed out, it means we are done with the grace-period for
 | 
	
		
			
				|  |  | +    // a clean shutdown. We should force a shutdown now by cancelling all
 | 
	
		
			
				|  |  | +    // inflight calls
 | 
	
		
			
				|  |  | +    if (status == CompletionQueue::NextStatus::TIMEOUT) {
 | 
	
		
			
				|  |  | +      grpc_server_cancel_all_calls(server_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has
 | 
	
		
			
				|  |  | +    // successfully shutdown
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Wait for threads in all RpcManagers to terminate
 | 
	
		
			
				|  |  | +    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
 | 
	
		
			
				|  |  | +      (*it)->Wait();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Shutdown the completion queues
 | 
	
		
			
				|  |  | +    // TODO (sreek) Move this into SyncRequestManager
 | 
	
		
			
				|  |  | +    for (auto it = sync_server_cqs_->begin(); it != sync_server_cqs_->end();
 | 
	
		
			
				|  |  | +         it++) {
 | 
	
		
			
				|  |  | +      (*it).Shutdown();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  |      grpc_server_shutdown_and_notify(server_, cq_.cq(), new ShutdownRequest());
 | 
	
		
			
				|  |  |      cq_.Shutdown();
 | 
	
		
			
				|  |  |      lock.unlock();
 | 
	
		
			
				|  |  | +    */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    // TODO (sreek) Delete this
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  |      GrpcRpcManager::ShutdownRpcManager();
 | 
	
		
			
				|  |  |      GrpcRpcManager::Wait();
 | 
	
		
			
				|  |  | +    */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Spin, eating requests until the completion queue is completely shutdown.
 | 
	
		
			
				|  |  |      // If the deadline expires then cancel anything that's pending and keep
 | 
	
		
			
				|  |  |      // spinning forever until the work is actually drained.
 | 
	
		
			
				|  |  |      // Since nothing else needs to touch state guarded by mu_, holding it
 | 
	
		
			
				|  |  |      // through this loop is fine.
 | 
	
		
			
				|  |  | +    //
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  |      SyncRequest* request;
 | 
	
		
			
				|  |  |      bool ok;
 | 
	
		
			
				|  |  |      while (SyncRequest::AsyncWait(&cq_, &request, &ok, deadline)) {
 | 
	
	
		
			
				|  | @@ -461,6 +600,7 @@ void Server::ShutdownInternal(gpr_timespec deadline) {
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      lock.lock();
 | 
	
		
			
				|  |  | +    */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* TODO (sreek) - Remove this block */
 | 
	
		
			
				|  |  |      // Wait for running callbacks to finish.
 | 
	
	
		
			
				|  | @@ -642,6 +782,8 @@ void Server::RunRpc() {
 | 
	
		
			
				|  |  |      */
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* TODO (sreek) Move this to SyncRequestManager */
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  |  void Server::PollForWork(bool& is_work_found, void** tag) {
 | 
	
		
			
				|  |  |    is_work_found = true;
 | 
	
		
			
				|  |  |    *tag = nullptr;
 | 
	
	
		
			
				|  | @@ -651,6 +793,7 @@ void Server::PollForWork(bool& is_work_found, void** tag) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void Server::DoWork(void* tag) {
 | 
	
		
			
				|  |  |    auto* mrd = static_cast<SyncRequest*>(tag);
 | 
	
		
			
				|  |  |    if (mrd) {
 | 
	
	
		
			
				|  | @@ -669,6 +812,7 @@ void Server::DoWork(void* tag) {
 | 
	
		
			
				|  |  |      cd.Run(global_callbacks_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +*/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ServerInitializer* Server::initializer() { return server_initializer_.get(); }
 | 
	
		
			
				|  |  |  
 |