Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / src / core / lib / transport / connectivity_state.cc
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 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/transport/connectivity_state.h"
22
23 #include <string.h>
24
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
28
29 grpc_core::TraceFlag grpc_connectivity_state_trace(false, "connectivity_state");
30
31 const char* grpc_connectivity_state_name(grpc_connectivity_state state) {
32   switch (state) {
33     case GRPC_CHANNEL_IDLE:
34       return "IDLE";
35     case GRPC_CHANNEL_CONNECTING:
36       return "CONNECTING";
37     case GRPC_CHANNEL_READY:
38       return "READY";
39     case GRPC_CHANNEL_TRANSIENT_FAILURE:
40       return "TRANSIENT_FAILURE";
41     case GRPC_CHANNEL_SHUTDOWN:
42       return "SHUTDOWN";
43   }
44   GPR_UNREACHABLE_CODE(return "UNKNOWN");
45 }
46
47 void grpc_connectivity_state_init(grpc_connectivity_state_tracker* tracker,
48                                   grpc_connectivity_state init_state,
49                                   const char* name) {
50   gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state);
51   tracker->watchers = nullptr;
52   tracker->name = gpr_strdup(name);
53 }
54
55 void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker* tracker) {
56   grpc_error* error;
57   grpc_connectivity_state_watcher* w;
58   while ((w = tracker->watchers)) {
59     tracker->watchers = w->next;
60
61     if (GRPC_CHANNEL_SHUTDOWN != *w->current) {
62       *w->current = GRPC_CHANNEL_SHUTDOWN;
63       error = GRPC_ERROR_NONE;
64     } else {
65       error =
66           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutdown connectivity owner");
67     }
68     GRPC_CLOSURE_SCHED(w->notify, error);
69     gpr_free(w);
70   }
71   gpr_free(tracker->name);
72 }
73
74 grpc_connectivity_state grpc_connectivity_state_check(
75     grpc_connectivity_state_tracker* tracker) {
76   grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
77       gpr_atm_no_barrier_load(&tracker->current_state_atm));
78   if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
79     gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
80             grpc_connectivity_state_name(cur));
81   }
82   return cur;
83 }
84
85 bool grpc_connectivity_state_has_watchers(
86     grpc_connectivity_state_tracker* connectivity_state) {
87   return connectivity_state->watchers != nullptr;
88 }
89
90 bool grpc_connectivity_state_notify_on_state_change(
91     grpc_connectivity_state_tracker* tracker, grpc_connectivity_state* current,
92     grpc_closure* notify) {
93   grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
94       gpr_atm_no_barrier_load(&tracker->current_state_atm));
95   if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
96     if (current == nullptr) {
97       gpr_log(GPR_INFO, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
98               tracker->name, notify);
99     } else {
100       gpr_log(GPR_INFO, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
101               tracker->name, grpc_connectivity_state_name(*current),
102               grpc_connectivity_state_name(cur), notify);
103     }
104   }
105   if (current == nullptr) {
106     grpc_connectivity_state_watcher* w = tracker->watchers;
107     if (w != nullptr && w->notify == notify) {
108       GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_CANCELLED);
109       tracker->watchers = w->next;
110       gpr_free(w);
111       return false;
112     }
113     while (w != nullptr) {
114       grpc_connectivity_state_watcher* rm_candidate = w->next;
115       if (rm_candidate != nullptr && rm_candidate->notify == notify) {
116         GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_CANCELLED);
117         w->next = w->next->next;
118         gpr_free(rm_candidate);
119         return false;
120       }
121       w = w->next;
122     }
123     return false;
124   } else {
125     if (cur != *current) {
126       *current = cur;
127       GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_NONE);
128     } else {
129       grpc_connectivity_state_watcher* w =
130           static_cast<grpc_connectivity_state_watcher*>(gpr_malloc(sizeof(*w)));
131       w->current = current;
132       w->notify = notify;
133       w->next = tracker->watchers;
134       tracker->watchers = w;
135     }
136     return cur == GRPC_CHANNEL_IDLE;
137   }
138 }
139
140 void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
141                                  grpc_connectivity_state state,
142                                  const char* reason) {
143   grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
144       gpr_atm_no_barrier_load(&tracker->current_state_atm));
145   grpc_connectivity_state_watcher* w;
146   if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
147     gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
148             grpc_connectivity_state_name(cur),
149             grpc_connectivity_state_name(state), reason);
150   }
151   if (cur == state) {
152     return;
153   }
154   GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN);
155   gpr_atm_no_barrier_store(&tracker->current_state_atm, state);
156   while ((w = tracker->watchers) != nullptr) {
157     *w->current = state;
158     tracker->watchers = w->next;
159     if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
160       gpr_log(GPR_INFO, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify);
161     }
162     GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_NONE);
163     gpr_free(w);
164   }
165 }