Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include "src/core/transport/connectivity_state.h"
35 :
36 : #include <string.h>
37 :
38 : #include <grpc/support/alloc.h>
39 : #include <grpc/support/log.h>
40 : #include <grpc/support/string_util.h>
41 :
42 : int grpc_connectivity_state_trace = 0;
43 :
44 1325 : const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
45 1325 : switch (state) {
46 : case GRPC_CHANNEL_IDLE:
47 165 : return "IDLE";
48 : case GRPC_CHANNEL_CONNECTING:
49 1 : return "CONNECTING";
50 : case GRPC_CHANNEL_READY:
51 821 : return "READY";
52 : case GRPC_CHANNEL_TRANSIENT_FAILURE:
53 1 : return "TRANSIENT_FAILURE";
54 : case GRPC_CHANNEL_FATAL_FAILURE:
55 337 : return "FATAL_FAILURE";
56 : }
57 0 : GPR_UNREACHABLE_CODE(return "UNKNOWN");
58 0 : }
59 :
60 15309 : void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
61 : grpc_connectivity_state init_state,
62 : const char *name) {
63 15309 : tracker->current_state = init_state;
64 15309 : tracker->watchers = NULL;
65 15309 : tracker->name = gpr_strdup(name);
66 15307 : }
67 :
68 15080 : void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
69 : grpc_connectivity_state_tracker *tracker) {
70 : int success;
71 : grpc_connectivity_state_watcher *w;
72 30160 : while ((w = tracker->watchers)) {
73 0 : tracker->watchers = w->next;
74 :
75 0 : if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) {
76 0 : *w->current = GRPC_CHANNEL_FATAL_FAILURE;
77 0 : success = 1;
78 : } else {
79 0 : success = 0;
80 : }
81 0 : grpc_exec_ctx_enqueue(exec_ctx, w->notify, success);
82 0 : gpr_free(w);
83 : }
84 15080 : gpr_free(tracker->name);
85 15081 : }
86 :
87 2938 : grpc_connectivity_state grpc_connectivity_state_check(
88 : grpc_connectivity_state_tracker *tracker) {
89 2938 : if (grpc_connectivity_state_trace) {
90 0 : gpr_log(GPR_DEBUG, "CONWATCH: %s: get %s", tracker->name,
91 : grpc_connectivity_state_name(tracker->current_state));
92 : }
93 2938 : return tracker->current_state;
94 : }
95 :
96 26077 : int grpc_connectivity_state_notify_on_state_change(
97 : grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
98 : grpc_connectivity_state *current, grpc_closure *notify) {
99 26077 : if (grpc_connectivity_state_trace) {
100 328 : gpr_log(GPR_DEBUG, "CONWATCH: %s: from %s [cur=%s] notify=%p",
101 : tracker->name, grpc_connectivity_state_name(*current),
102 : grpc_connectivity_state_name(tracker->current_state), notify);
103 : }
104 26078 : if (tracker->current_state != *current) {
105 4510 : *current = tracker->current_state;
106 4510 : grpc_exec_ctx_enqueue(exec_ctx, notify, 1);
107 : } else {
108 21568 : grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
109 21569 : w->current = current;
110 21569 : w->notify = notify;
111 21569 : w->next = tracker->watchers;
112 21569 : tracker->watchers = w;
113 : }
114 26079 : return tracker->current_state == GRPC_CHANNEL_IDLE;
115 : }
116 :
117 246 : int grpc_connectivity_state_change_unsubscribe(
118 : grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
119 : grpc_closure *subscribed_notify) {
120 246 : grpc_connectivity_state_watcher *w = tracker->watchers;
121 246 : if (w != NULL && w->notify == subscribed_notify) {
122 0 : tracker->watchers = w->next;
123 0 : gpr_free(w);
124 0 : return 1;
125 : }
126 736 : while (w != NULL) {
127 246 : grpc_connectivity_state_watcher *rm_candidate = w->next;
128 246 : if (rm_candidate != NULL && rm_candidate->notify == subscribed_notify) {
129 2 : w->next = w->next->next;
130 2 : gpr_free(rm_candidate);
131 2 : return 1;
132 : }
133 244 : w = w->next;
134 : }
135 244 : return 0;
136 : }
137 :
138 44082 : void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
139 : grpc_connectivity_state_tracker *tracker,
140 : grpc_connectivity_state state,
141 : const char *reason) {
142 : grpc_connectivity_state_watcher *w;
143 44082 : if (grpc_connectivity_state_trace) {
144 332 : gpr_log(GPR_DEBUG, "SET: %s: %s --> %s [%s]", tracker->name,
145 : grpc_connectivity_state_name(tracker->current_state),
146 : grpc_connectivity_state_name(state), reason);
147 : }
148 44084 : if (tracker->current_state == state) {
149 53452 : return;
150 : }
151 34622 : GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
152 34622 : tracker->current_state = state;
153 90735 : while ((w = tracker->watchers) != NULL) {
154 21490 : *w->current = tracker->current_state;
155 21490 : tracker->watchers = w->next;
156 21490 : grpc_exec_ctx_enqueue(exec_ctx, w->notify, 1);
157 21490 : gpr_free(w);
158 : }
159 : }
|