1 /* 2 * 3 * Copyright 2015 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_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H 20 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <grpc/impl/codegen/grpc_types.h> 25 26 #include "src/core/lib/gprpp/abstract.h" 27 #include "src/core/lib/gprpp/orphanable.h" 28 #include "src/core/lib/iomgr/combiner.h" 29 #include "src/core/lib/iomgr/iomgr.h" 30 31 extern grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount; 32 33 namespace grpc_core { 34 35 /// Interface for name resolution. 36 /// 37 /// This interface is designed to support both push-based and pull-based 38 /// mechanisms. A push-based mechanism is one where the resolver will 39 /// subscribe to updates for a given name, and the name service will 40 /// proactively send new data to the resolver whenever the data associated 41 /// with the name changes. A pull-based mechanism is one where the resolver 42 /// needs to query the name service again to get updated information (e.g., 43 /// DNS). 44 /// 45 /// Note: All methods with a "Locked" suffix must be called from the 46 /// combiner passed to the constructor. 47 class Resolver : public InternallyRefCountedWithTracing<Resolver> { 48 public: 49 // Not copyable nor movable. 50 Resolver(const Resolver&) = delete; 51 Resolver& operator=(const Resolver&) = delete; 52 53 /// Requests a callback when a new result becomes available. 54 /// When the new result is available, sets \a *result to the new result 55 /// and schedules \a on_complete for execution. 56 /// Upon transient failure, sets \a *result to nullptr and schedules 57 /// \a on_complete with no error. 58 /// If resolution is fatally broken, sets \a *result to nullptr and 59 /// schedules \a on_complete with an error. 60 /// TODO(roth): When we have time, improve the way this API represents 61 /// transient failure vs. shutdown. 62 /// 63 /// Note that the client channel will almost always have a request 64 /// to \a NextLocked() pending. When it gets the callback, it will 65 /// process the new result and then immediately make another call to 66 /// \a NextLocked(). This allows push-based resolvers to provide new 67 /// data as soon as it becomes available. 68 virtual void NextLocked(grpc_channel_args** result, 69 grpc_closure* on_complete) GRPC_ABSTRACT; 70 71 /// Asks the resolver to obtain an updated resolver result, if 72 /// applicable. 73 /// 74 /// This is useful for pull-based implementations to decide when to 75 /// re-resolve. However, the implementation is not required to 76 /// re-resolve immediately upon receiving this call; it may instead 77 /// elect to delay based on some configured minimum time between 78 /// queries, to avoid hammering the name service with queries. 79 /// 80 /// For push-based implementations, this may be a no-op. 81 /// 82 /// If this causes new data to become available, then the currently 83 /// pending call to \a NextLocked() will return the new result. 84 virtual void RequestReresolutionLocked() {} 85 86 /// Resets the re-resolution backoff, if any. 87 /// This needs to be implemented only by pull-based implementations; 88 /// for push-based implementations, it will be a no-op. 89 /// TODO(roth): Pull the backoff code out of resolver and into 90 /// client_channel, so that it can be shared across resolver 91 /// implementations. At that point, this method can go away. 92 virtual void ResetBackoffLocked() {} 93 94 void Orphan() override { 95 // Invoke ShutdownAndUnrefLocked() inside of the combiner. 96 GRPC_CLOSURE_SCHED( 97 GRPC_CLOSURE_CREATE(&Resolver::ShutdownAndUnrefLocked, this, 98 grpc_combiner_scheduler(combiner_)), 99 GRPC_ERROR_NONE); 100 } 101 102 GRPC_ABSTRACT_BASE_CLASS 103 104 protected: 105 GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE 106 107 /// Does NOT take ownership of the reference to \a combiner. 108 // TODO(roth): Once we have a C++-like interface for combiners, this 109 // API should change to take a RefCountedPtr<>, so that we always take 110 // ownership of a new ref. 111 explicit Resolver(grpc_combiner* combiner); 112 113 virtual ~Resolver(); 114 115 /// Shuts down the resolver. If there is a pending call to 116 /// NextLocked(), the callback will be scheduled with an error. 117 virtual void ShutdownLocked() GRPC_ABSTRACT; 118 119 grpc_combiner* combiner() const { return combiner_; } 120 121 private: 122 static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) { 123 Resolver* resolver = static_cast<Resolver*>(arg); 124 resolver->ShutdownLocked(); 125 resolver->Unref(); 126 } 127 128 grpc_combiner* combiner_; 129 }; 130 131 } // namespace grpc_core 132 133 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H */ 134