blob: 9156b4af97ce6db24ee47b271bbcb08769fe87aa [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#ifndef KUDU_RPC_SERVICE_IF_H
#define KUDU_RPC_SERVICE_IF_H
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <google/protobuf/message.h>
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/metrics.h"
namespace kudu {
namespace rpc {
class InboundCall;
class RemoteMethod;
class ResultTracker;
class RpcContext;
// Generated services define an instance of this class for each
// method that they implement. The generic server code implemented
// by GeneratedServiceIf look up the RpcMethodInfo in order to handle
// each RPC.
struct RpcMethodInfo : public RefCountedThreadSafe<RpcMethodInfo> {
// Prototype protobufs for requests and responses.
// These are empty protobufs which are cloned in order to provide an
// instance for each request.
std::unique_ptr<google::protobuf::Message> req_prototype;
std::unique_ptr<google::protobuf::Message> resp_prototype;
scoped_refptr<Histogram> handler_latency_histogram;
// Whether we should track this method's result, using ResultTracker.
bool track_result;
// The authorization function for this RPC. If this function
// returns false, the RPC has already been handled (i.e. rejected)
// by the authorization function.
std::function<bool(const google::protobuf::Message* req,
google::protobuf::Message* resp,
RpcContext* ctx)> authz_method;
// The actual function to be called.
std::function<void(const google::protobuf::Message* req,
google::protobuf::Message* resp,
RpcContext* ctx)> func;
};
// Handles incoming messages that initiate an RPC.
class ServiceIf {
public:
virtual ~ServiceIf();
virtual void Handle(InboundCall* incoming) = 0;
virtual void Shutdown();
virtual std::string service_name() const = 0;
// The service should return true if it supports the provided application
// specific feature flag.
virtual bool SupportsFeature(uint32_t feature) const;
// Look up the method being requested by the remote call.
//
// If this returns nullptr, then certain functionality like
// metrics collection will not be performed for this call.
virtual RpcMethodInfo* LookupMethod(const RemoteMethod& method) {
return nullptr;
}
// Default authorization method, which just allows all RPCs.
//
// See docs/design-docs/rpc.md for details on how to add custom
// authorization checks to a service.
bool AuthorizeAllowAll(const google::protobuf::Message* /*req*/,
google::protobuf::Message* /*resp*/,
RpcContext* /*ctx*/) {
return true;
}
protected:
bool ParseParam(InboundCall* call, google::protobuf::Message* message);
void RespondBadMethod(InboundCall* call);
};
// Base class for code-generated service classes.
class GeneratedServiceIf : public ServiceIf {
public:
virtual ~GeneratedServiceIf();
// Looks up the appropriate method in 'methods_by_name_' and executes
// it on the current thread.
//
// If no such method is found, responds with an error.
void Handle(InboundCall* incoming) override;
RpcMethodInfo* LookupMethod(const RemoteMethod& method) override;
// Returns the mapping from method names to method infos.
typedef std::unordered_map<std::string, scoped_refptr<RpcMethodInfo>> MethodInfoMap;
const MethodInfoMap& methods_by_name() const { return methods_by_name_; }
protected:
// For each method, stores the relevant information about how to handle the
// call. Methods are inserted by the constructor of the generated subclass.
// After construction, this map is accessed by multiple threads and therefore
// must not be modified.
MethodInfoMap methods_by_name_;
// The result tracker for this service's methods.
scoped_refptr<ResultTracker> result_tracker_;
};
} // namespace rpc
} // namespace kudu
#endif