aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/filters/client_channel/resolver.h
blob: 9da849a10173af58190a6c434759b59523fe1880 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed 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 GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H

#include <grpc/support/port_platform.h>

#include <grpc/impl/codegen/grpc_types.h>

#include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h"

extern grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount;

namespace grpc_core {

/// Interface for name resolution.
///
/// This interface is designed to support both push-based and pull-based
/// mechanisms.  A push-based mechanism is one where the resolver will
/// subscribe to updates for a given name, and the name service will
/// proactively send new data to the resolver whenever the data associated
/// with the name changes.  A pull-based mechanism is one where the resolver
/// needs to query the name service again to get updated information (e.g.,
/// DNS).
///
/// Note: All methods with a "Locked" suffix must be called from the
/// combiner passed to the constructor.
class Resolver : public InternallyRefCounted<Resolver> {
 public:
  // Not copyable nor movable.
  Resolver(const Resolver&) = delete;
  Resolver& operator=(const Resolver&) = delete;

  /// Requests a callback when a new result becomes available.
  /// When the new result is available, sets \a *result to the new result
  /// and schedules \a on_complete for execution.
  /// Upon transient failure, sets \a *result to nullptr and schedules
  /// \a on_complete with no error.
  /// If resolution is fatally broken, sets \a *result to nullptr and
  /// schedules \a on_complete with an error.
  /// TODO(roth): When we have time, improve the way this API represents
  /// transient failure vs. shutdown.
  ///
  /// Note that the client channel will almost always have a request
  /// to \a NextLocked() pending.  When it gets the callback, it will
  /// process the new result and then immediately make another call to
  /// \a NextLocked().  This allows push-based resolvers to provide new
  /// data as soon as it becomes available.
  virtual void NextLocked(grpc_channel_args** result,
                          grpc_closure* on_complete) GRPC_ABSTRACT;

  /// Asks the resolver to obtain an updated resolver result, if
  /// applicable.
  ///
  /// This is useful for pull-based implementations to decide when to
  /// re-resolve.  However, the implementation is not required to
  /// re-resolve immediately upon receiving this call; it may instead
  /// elect to delay based on some configured minimum time between
  /// queries, to avoid hammering the name service with queries.
  ///
  /// For push-based implementations, this may be a no-op.
  ///
  /// If this causes new data to become available, then the currently
  /// pending call to \a NextLocked() will return the new result.
  virtual void RequestReresolutionLocked() {}

  /// Resets the re-resolution backoff, if any.
  /// This needs to be implemented only by pull-based implementations;
  /// for push-based implementations, it will be a no-op.
  /// TODO(roth): Pull the backoff code out of resolver and into
  /// client_channel, so that it can be shared across resolver
  /// implementations.  At that point, this method can go away.
  virtual void ResetBackoffLocked() {}

  void Orphan() override {
    // Invoke ShutdownAndUnrefLocked() inside of the combiner.
    GRPC_CLOSURE_SCHED(
        GRPC_CLOSURE_CREATE(&Resolver::ShutdownAndUnrefLocked, this,
                            grpc_combiner_scheduler(combiner_)),
        GRPC_ERROR_NONE);
  }

  GRPC_ABSTRACT_BASE_CLASS

 protected:
  GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE

  /// Does NOT take ownership of the reference to \a combiner.
  // TODO(roth): Once we have a C++-like interface for combiners, this
  // API should change to take a RefCountedPtr<>, so that we always take
  // ownership of a new ref.
  explicit Resolver(grpc_combiner* combiner);

  virtual ~Resolver();

  /// Shuts down the resolver.  If there is a pending call to
  /// NextLocked(), the callback will be scheduled with an error.
  virtual void ShutdownLocked() GRPC_ABSTRACT;

  grpc_combiner* combiner() const { return combiner_; }

 private:
  static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) {
    Resolver* resolver = static_cast<Resolver*>(arg);
    resolver->ShutdownLocked();
    resolver->Unref();
  }

  grpc_combiner* combiner_;
};

}  // namespace grpc_core

#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H */