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_XDS_XDS_CLIENT_XDS_RESOURCE_TYPE_IMPL_H 18 #define GRPC_SRC_CORE_XDS_XDS_CLIENT_XDS_RESOURCE_TYPE_IMPL_H 19 #include <grpc/support/port_platform.h> 20 21 #include <memory> 22 #include <utility> 23 24 #include "absl/strings/string_view.h" 25 #include "src/core/util/ref_counted_ptr.h" 26 #include "src/core/xds/xds_client/xds_client.h" 27 #include "src/core/xds/xds_client/xds_resource_type.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 // 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( 44 absl::StatusOr<std::shared_ptr<const ResourceType>> resource, 45 RefCountedPtr<XdsClient::ReadDelayHandle> read_delay_handle) = 0; 46 47 private: 48 // Get result from XdsClient generic watcher interface, perform 49 // down-casting, and invoke the caller's OnResourceChanged() method. OnGenericResourceChanged(absl::StatusOr<std::shared_ptr<const XdsResourceType::ResourceData>> resource,RefCountedPtr<XdsClient::ReadDelayHandle> read_delay_handle)50 void OnGenericResourceChanged( 51 absl::StatusOr<std::shared_ptr<const XdsResourceType::ResourceData>> 52 resource, 53 RefCountedPtr<XdsClient::ReadDelayHandle> read_delay_handle) override { 54 if (!resource.ok()) { 55 OnResourceChanged(resource.status(), std::move(read_delay_handle)); 56 } else { 57 OnResourceChanged( 58 std::static_pointer_cast<const ResourceType>(std::move(*resource)), 59 std::move(read_delay_handle)); 60 } 61 } 62 }; 63 Get()64 static const Subclass* Get() { 65 static const Subclass* g_instance = new Subclass(); 66 return g_instance; 67 } 68 69 // Convenient wrappers around XdsClient generic watcher API that provide 70 // type-safety. StartWatch(XdsClient * xds_client,absl::string_view resource_name,RefCountedPtr<WatcherInterface> watcher)71 static void StartWatch(XdsClient* xds_client, absl::string_view resource_name, 72 RefCountedPtr<WatcherInterface> watcher) { 73 xds_client->WatchResource(Get(), resource_name, std::move(watcher)); 74 } 75 static void CancelWatch(XdsClient* xds_client, 76 absl::string_view resource_name, 77 WatcherInterface* watcher, 78 bool delay_unsubscription = false) { 79 xds_client->CancelResourceWatch(Get(), resource_name, watcher, 80 delay_unsubscription); 81 } 82 ResourcesEqual(const ResourceData * r1,const ResourceData * r2)83 bool ResourcesEqual(const ResourceData* r1, 84 const ResourceData* r2) const override { 85 return *static_cast<const ResourceType*>(r1) == 86 *static_cast<const ResourceType*>(r2); 87 } 88 }; 89 90 } // namespace grpc_core 91 92 #endif // GRPC_SRC_CORE_XDS_XDS_CLIENT_XDS_RESOURCE_TYPE_IMPL_H 93