1 //
2 // Copyright 2021 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef GRPC_SRC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H
18 #define GRPC_SRC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H
19 #include <grpc/support/port_platform.h>
20 
21 #include <memory>
22 
23 #include "absl/strings/string_view.h"
24 
25 #include "src/core/ext/xds/xds_client.h"
26 #include "src/core/ext/xds/xds_resource_type.h"
27 #include "src/core/lib/gprpp/ref_counted_ptr.h"
28 
29 namespace grpc_core {
30 
31 // Base class for XdsResourceType implementations.
32 // Handles all down-casting logic for a particular resource type struct.
33 // ResourceTypeStruct must inherit from XdsResourceType::ResourceData,
34 // must be copy-constructible, and must implement operator==().
35 template <typename Subclass, typename ResourceTypeStruct>
36 class XdsResourceTypeImpl : public XdsResourceType {
37  public:
38   using ResourceType = ResourceTypeStruct;
39 
40   // XdsClient watcher that handles down-casting.
41   class WatcherInterface : public XdsClient::ResourceWatcherInterface {
42    public:
43     virtual void OnResourceChanged(ResourceType listener) = 0;
44 
45    private:
46     // Get result from XdsClient generic watcher interface, perform
47     // down-casting, and invoke the caller's OnResourceChanged() method.
OnGenericResourceChanged(const XdsResourceType::ResourceData * resource)48     void OnGenericResourceChanged(
49         const XdsResourceType::ResourceData* resource) override {
50       OnResourceChanged(*static_cast<const ResourceType*>(resource));
51     }
52   };
53 
Get()54   static const Subclass* Get() {
55     static const Subclass* g_instance = new Subclass();
56     return g_instance;
57   }
58 
59   // Convenient wrappers around XdsClient generic watcher API that provide
60   // type-safety.
StartWatch(XdsClient * xds_client,absl::string_view resource_name,RefCountedPtr<WatcherInterface> watcher)61   static void StartWatch(XdsClient* xds_client, absl::string_view resource_name,
62                          RefCountedPtr<WatcherInterface> watcher) {
63     xds_client->WatchResource(Get(), resource_name, std::move(watcher));
64   }
65   static void CancelWatch(XdsClient* xds_client,
66                           absl::string_view resource_name,
67                           WatcherInterface* watcher,
68                           bool delay_unsubscription = false) {
69     xds_client->CancelResourceWatch(Get(), resource_name, watcher,
70                                     delay_unsubscription);
71   }
72 
ResourcesEqual(const ResourceData * r1,const ResourceData * r2)73   bool ResourcesEqual(const ResourceData* r1,
74                       const ResourceData* r2) const override {
75     return *static_cast<const ResourceType*>(r1) ==
76            *static_cast<const ResourceType*>(r2);
77   }
78 
CopyResource(const ResourceData * resource)79   std::unique_ptr<ResourceData> CopyResource(
80       const ResourceData* resource) const override {
81     return std::make_unique<ResourceType>(
82         *static_cast<const ResourceType*>(resource));
83   }
84 };
85 
86 }  // namespace grpc_core
87 
88 #endif  // GRPC_SRC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H
89