1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #ifndef GRPC_SRC_CPP_SERVER_HEALTH_DEFAULT_HEALTH_CHECK_SERVICE_H
20 #define GRPC_SRC_CPP_SERVER_HEALTH_DEFAULT_HEALTH_CHECK_SERVICE_H
21 
22 #include <stddef.h>
23 
24 #include <map>
25 #include <memory>
26 #include <string>
27 
28 #include "absl/base/thread_annotations.h"
29 
30 #include <grpcpp/grpcpp.h>
31 #include <grpcpp/health_check_service_interface.h>
32 #include <grpcpp/impl/service_type.h>
33 #include <grpcpp/impl/sync.h>
34 #include <grpcpp/support/byte_buffer.h>
35 #include <grpcpp/support/server_callback.h>
36 #include <grpcpp/support/status.h>
37 
38 #include "src/core/lib/gprpp/ref_counted.h"
39 #include "src/core/lib/gprpp/ref_counted_ptr.h"
40 
41 namespace grpc {
42 
43 // Default implementation of HealthCheckServiceInterface. Server will create and
44 // own it.
45 class DefaultHealthCheckService final : public HealthCheckServiceInterface {
46  public:
47   enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING };
48 
49   // The service impl to register with the server.
50   class HealthCheckServiceImpl : public Service {
51    public:
52     // Reactor for handling Watch streams.
53     class WatchReactor : public ServerWriteReactor<ByteBuffer>,
54                          public grpc_core::RefCounted<WatchReactor> {
55      public:
56       WatchReactor(HealthCheckServiceImpl* service, const ByteBuffer* request);
57 
58       void SendHealth(ServingStatus status);
59 
60       void OnWriteDone(bool ok) override;
61       void OnCancel() override;
62       void OnDone() override;
63 
64      private:
65       void SendHealthLocked(ServingStatus status)
66           ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_);
67 
68       void MaybeFinishLocked(Status status) ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_);
69 
70       HealthCheckServiceImpl* service_;
71       std::string service_name_;
72       ByteBuffer response_;
73 
74       grpc::internal::Mutex mu_;
75       bool write_pending_ ABSL_GUARDED_BY(mu_) = false;
76       ServingStatus pending_status_ ABSL_GUARDED_BY(mu_) = NOT_FOUND;
77       bool finish_called_ ABSL_GUARDED_BY(mu_) = false;
78     };
79 
80     explicit HealthCheckServiceImpl(DefaultHealthCheckService* database);
81 
82     ~HealthCheckServiceImpl() override;
83 
84    private:
85     // Request handler for Check method.
86     static ServerUnaryReactor* HandleCheckRequest(
87         DefaultHealthCheckService* database, CallbackServerContext* context,
88         const ByteBuffer* request, ByteBuffer* response);
89 
90     // Returns true on success.
91     static bool DecodeRequest(const ByteBuffer& request,
92                               std::string* service_name);
93     static bool EncodeResponse(ServingStatus status, ByteBuffer* response);
94 
95     DefaultHealthCheckService* database_;
96 
97     grpc::internal::Mutex mu_;
98     grpc::internal::CondVar shutdown_condition_;
99     bool shutdown_ ABSL_GUARDED_BY(mu_) = false;
100     size_t num_watches_ ABSL_GUARDED_BY(mu_) = 0;
101   };
102 
103   DefaultHealthCheckService();
104 
105   void SetServingStatus(const std::string& service_name, bool serving) override;
106   void SetServingStatus(bool serving) override;
107 
108   void Shutdown() override;
109 
110   ServingStatus GetServingStatus(const std::string& service_name) const;
111 
112   HealthCheckServiceImpl* GetHealthCheckService();
113 
114  private:
115   // Stores the current serving status of a service and any call
116   // handlers registered for updates when the service's status changes.
117   class ServiceData {
118    public:
119     void SetServingStatus(ServingStatus status);
GetServingStatus()120     ServingStatus GetServingStatus() const { return status_; }
121     void AddWatch(
122         grpc_core::RefCountedPtr<HealthCheckServiceImpl::WatchReactor> watcher);
123     void RemoveWatch(HealthCheckServiceImpl::WatchReactor* watcher);
Unused()124     bool Unused() const { return watchers_.empty() && status_ == NOT_FOUND; }
125 
126    private:
127     ServingStatus status_ = NOT_FOUND;
128     std::map<HealthCheckServiceImpl::WatchReactor*,
129              grpc_core::RefCountedPtr<HealthCheckServiceImpl::WatchReactor>>
130         watchers_;
131   };
132 
133   void RegisterWatch(
134       const std::string& service_name,
135       grpc_core::RefCountedPtr<HealthCheckServiceImpl::WatchReactor> watcher);
136 
137   void UnregisterWatch(const std::string& service_name,
138                        HealthCheckServiceImpl::WatchReactor* watcher);
139 
140   mutable grpc::internal::Mutex mu_;
141   bool shutdown_ ABSL_GUARDED_BY(&mu_) = false;
142   std::map<std::string, ServiceData> services_map_ ABSL_GUARDED_BY(&mu_);
143   std::unique_ptr<HealthCheckServiceImpl> impl_;
144 };
145 
146 }  // namespace grpc
147 
148 #endif  // GRPC_SRC_CPP_SERVER_HEALTH_DEFAULT_HEALTH_CHECK_SERVICE_H
149