|  | @@ -38,7 +38,7 @@ module GRPC
 | 
	
		
			
				|  |  |    # RpcServer hosts a number of services and makes them available on the
 | 
	
		
			
				|  |  |    # network.
 | 
	
		
			
				|  |  |    class RpcServer
 | 
	
		
			
				|  |  | -    include Core::CompletionType
 | 
	
		
			
				|  |  | +    include Core::CallOps
 | 
	
		
			
				|  |  |      include Core::TimeConsts
 | 
	
		
			
				|  |  |      extend ::Forwardable
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -202,20 +202,14 @@ module GRPC
 | 
	
		
			
				|  |  |        end
 | 
	
		
			
				|  |  |        @pool.start
 | 
	
		
			
				|  |  |        @server.start
 | 
	
		
			
				|  |  | -      server_tag = Object.new
 | 
	
		
			
				|  |  | +      request_call_tag = Object.new
 | 
	
		
			
				|  |  |        until stopped?
 | 
	
		
			
				|  |  | -        @server.request_call(server_tag)
 | 
	
		
			
				|  |  | -        ev = @cq.pluck(server_tag, @poll_period)
 | 
	
		
			
				|  |  | -        next if ev.nil?
 | 
	
		
			
				|  |  | -        if ev.type != SERVER_RPC_NEW
 | 
	
		
			
				|  |  | -          logger.warn("bad evt: got:#{ev.type}, want:#{SERVER_RPC_NEW}")
 | 
	
		
			
				|  |  | -          ev.close
 | 
	
		
			
				|  |  | -          next
 | 
	
		
			
				|  |  | -        end
 | 
	
		
			
				|  |  | -        c = new_active_server_call(ev.call, ev.result)
 | 
	
		
			
				|  |  | +        deadline = from_relative_time(@poll_period)
 | 
	
		
			
				|  |  | +        an_rpc = @server.request_call(@cq, request_call_tag, deadline)
 | 
	
		
			
				|  |  | +        next if an_rpc.nil?
 | 
	
		
			
				|  |  | +        c = new_active_server_call(an_rpc)
 | 
	
		
			
				|  |  |          unless c.nil?
 | 
	
		
			
				|  |  | -          mth = ev.result.method.to_sym
 | 
	
		
			
				|  |  | -          ev.close
 | 
	
		
			
				|  |  | +          mth = an_rpc.method.to_sym
 | 
	
		
			
				|  |  |            @pool.schedule(c) do |call|
 | 
	
		
			
				|  |  |              rpc_descs[mth].run_server_method(call, rpc_handlers[mth])
 | 
	
		
			
				|  |  |            end
 | 
	
	
		
			
				|  | @@ -224,46 +218,49 @@ module GRPC
 | 
	
		
			
				|  |  |        @running = false
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def new_active_server_call(call, new_server_rpc)
 | 
	
		
			
				|  |  | -      # Accept the call.  This is necessary even if a status is to be sent
 | 
	
		
			
				|  |  | -      # back immediately
 | 
	
		
			
				|  |  | -      finished_tag = Object.new
 | 
	
		
			
				|  |  | -      call_queue = Core::CompletionQueue.new
 | 
	
		
			
				|  |  | -      call.metadata = new_server_rpc.metadata  # store the metadata
 | 
	
		
			
				|  |  | -      call.server_accept(call_queue, finished_tag)
 | 
	
		
			
				|  |  | -      call.server_end_initial_metadata
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      # Send UNAVAILABLE if there are too many unprocessed jobs
 | 
	
		
			
				|  |  | +    # Sends UNAVAILABLE if there are too many unprocessed jobs
 | 
	
		
			
				|  |  | +    def available?(an_rpc)
 | 
	
		
			
				|  |  |        jobs_count, max = @pool.jobs_waiting, @max_waiting_requests
 | 
	
		
			
				|  |  |        logger.info("waiting: #{jobs_count}, max: #{max}")
 | 
	
		
			
				|  |  | -      if @pool.jobs_waiting > @max_waiting_requests
 | 
	
		
			
				|  |  | -        logger.warn("NOT AVAILABLE: too many jobs_waiting: #{new_server_rpc}")
 | 
	
		
			
				|  |  | -        noop = proc { |x| x }
 | 
	
		
			
				|  |  | -        c = ActiveCall.new(call, call_queue, noop, noop,
 | 
	
		
			
				|  |  | -                           new_server_rpc.deadline,
 | 
	
		
			
				|  |  | -                           finished_tag: finished_tag)
 | 
	
		
			
				|  |  | -        c.send_status(StatusCodes::UNAVAILABLE, '')
 | 
	
		
			
				|  |  | -        return nil
 | 
	
		
			
				|  |  | -      end
 | 
	
		
			
				|  |  | +      return an_rpc if @pool.jobs_waiting <= @max_waiting_requests
 | 
	
		
			
				|  |  | +      logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}")
 | 
	
		
			
				|  |  | +      noop = proc { |x| x }
 | 
	
		
			
				|  |  | +      c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline)
 | 
	
		
			
				|  |  | +      c.send_status(StatusCodes::UNAVAILABLE, '')
 | 
	
		
			
				|  |  | +      nil
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      # Send NOT_FOUND if the method does not exist
 | 
	
		
			
				|  |  | -      mth = new_server_rpc.method.to_sym
 | 
	
		
			
				|  |  | -      unless rpc_descs.key?(mth)
 | 
	
		
			
				|  |  | -        logger.warn("NOT_FOUND: #{new_server_rpc}")
 | 
	
		
			
				|  |  | -        noop = proc { |x| x }
 | 
	
		
			
				|  |  | -        c = ActiveCall.new(call, call_queue, noop, noop,
 | 
	
		
			
				|  |  | -                           new_server_rpc.deadline,
 | 
	
		
			
				|  |  | -                           finished_tag: finished_tag)
 | 
	
		
			
				|  |  | -        c.send_status(StatusCodes::NOT_FOUND, '')
 | 
	
		
			
				|  |  | -        return nil
 | 
	
		
			
				|  |  | -      end
 | 
	
		
			
				|  |  | +    # Sends NOT_FOUND if the method can't be found
 | 
	
		
			
				|  |  | +    def found?(an_rpc)
 | 
	
		
			
				|  |  | +      mth = an_rpc.method.to_sym
 | 
	
		
			
				|  |  | +      return an_rpc if rpc_descs.key?(mth)
 | 
	
		
			
				|  |  | +      logger.warn("NOT_FOUND: #{an_rpc}")
 | 
	
		
			
				|  |  | +      noop = proc { |x| x }
 | 
	
		
			
				|  |  | +      c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline)
 | 
	
		
			
				|  |  | +      c.send_status(StatusCodes::NOT_FOUND, '')
 | 
	
		
			
				|  |  | +      nil
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def new_active_server_call(an_rpc)
 | 
	
		
			
				|  |  | +      # Accept the call.  This is necessary even if a status is to be sent
 | 
	
		
			
				|  |  | +      # back immediately
 | 
	
		
			
				|  |  | +      return nil if an_rpc.nil? || an_rpc.call.nil?
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      # allow the metadata to be accessed from the call
 | 
	
		
			
				|  |  | +      handle_call_tag = Object.new
 | 
	
		
			
				|  |  | +      an_rpc.call.metadata = an_rpc.metadata
 | 
	
		
			
				|  |  | +      # TODO: add a hook to send md
 | 
	
		
			
				|  |  | +      an_rpc.call.run_batch(@cq, handle_call_tag, INFINITE_FUTURE,
 | 
	
		
			
				|  |  | +                            SEND_INITIAL_METADATA => nil)
 | 
	
		
			
				|  |  | +      return nil unless available?(an_rpc)
 | 
	
		
			
				|  |  | +      return nil unless found?(an_rpc)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        # Create the ActiveCall
 | 
	
		
			
				|  |  | -      rpc_desc = rpc_descs[mth]
 | 
	
		
			
				|  |  | -      logger.info("deadline is #{new_server_rpc.deadline}; (now=#{Time.now})")
 | 
	
		
			
				|  |  | -      ActiveCall.new(call, call_queue,
 | 
	
		
			
				|  |  | +      logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})")
 | 
	
		
			
				|  |  | +      rpc_desc = rpc_descs[an_rpc.method.to_sym]
 | 
	
		
			
				|  |  | +      ActiveCall.new(an_rpc.call, @cq,
 | 
	
		
			
				|  |  |                       rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input),
 | 
	
		
			
				|  |  | -                     new_server_rpc.deadline, finished_tag: finished_tag)
 | 
	
		
			
				|  |  | +                     an_rpc.deadline)
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # Pool is a simple thread pool for running server requests.
 |