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 1192 : const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
45 1192 : switch (state) {
46 : case GRPC_CHANNEL_IDLE:
47 148 : return "IDLE";
48 : case GRPC_CHANNEL_CONNECTING:
49 0 : return "CONNECTING";
50 : case GRPC_CHANNEL_READY:
51 740 : return "READY";
52 : case GRPC_CHANNEL_TRANSIENT_FAILURE:
53 0 : return "TRANSIENT_FAILURE";
54 : case GRPC_CHANNEL_FATAL_FAILURE:
55 304 : return "FATAL_FAILURE";
56 : }
57 0 : abort();
58 : return "UNKNOWN";
59 : }
60 :
61 8690 : void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
62 : grpc_connectivity_state init_state,
63 : const char *name) {
64 8690 : tracker->current_state = init_state;
65 8690 : tracker->watchers = NULL;
66 8690 : tracker->name = gpr_strdup(name);
67 8690 : }
68 :
69 8690 : void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
70 : grpc_connectivity_state_tracker *tracker) {
71 : int success;
72 : grpc_connectivity_state_watcher *w;
73 17380 : while ((w = tracker->watchers)) {
74 0 : tracker->watchers = w->next;
75 :
76 0 : if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) {
77 0 : *w->current = GRPC_CHANNEL_FATAL_FAILURE;
78 0 : success = 1;
79 : } else {
80 0 : success = 0;
81 : }
82 0 : grpc_exec_ctx_enqueue(exec_ctx, w->notify, success);
83 0 : gpr_free(w);
84 : }
85 8690 : gpr_free(tracker->name);
86 8690 : }
87 :
88 1585 : grpc_connectivity_state grpc_connectivity_state_check(
89 : grpc_connectivity_state_tracker *tracker) {
90 1585 : if (grpc_connectivity_state_trace) {
91 0 : gpr_log(GPR_DEBUG, "CONWATCH: %s: get %s", tracker->name,
92 : grpc_connectivity_state_name(tracker->current_state));
93 : }
94 1585 : return tracker->current_state;
95 : }
96 :
97 17102 : int grpc_connectivity_state_notify_on_state_change(
98 : grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
99 : grpc_connectivity_state *current, grpc_closure *notify) {
100 17102 : if (grpc_connectivity_state_trace) {
101 296 : gpr_log(GPR_DEBUG, "CONWATCH: %s: from %s [cur=%s] notify=%p",
102 : tracker->name, grpc_connectivity_state_name(*current),
103 : grpc_connectivity_state_name(tracker->current_state), notify);
104 : }
105 17105 : if (tracker->current_state != *current) {
106 3002 : *current = tracker->current_state;
107 3002 : grpc_exec_ctx_enqueue(exec_ctx, notify, 1);
108 : } else {
109 14103 : grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
110 14102 : w->current = current;
111 14102 : w->notify = notify;
112 14102 : w->next = tracker->watchers;
113 14102 : tracker->watchers = w;
114 : }
115 17101 : return tracker->current_state == GRPC_CHANNEL_IDLE;
116 : }
117 :
118 0 : int grpc_connectivity_state_change_unsubscribe(
119 : grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
120 : grpc_closure *subscribed_notify) {
121 0 : grpc_connectivity_state_watcher *w = tracker->watchers;
122 0 : if (w != NULL && w->notify == subscribed_notify) {
123 0 : tracker->watchers = w->next;
124 0 : gpr_free(w);
125 0 : return 1;
126 : }
127 0 : while (w != NULL) {
128 0 : grpc_connectivity_state_watcher *rm_candidate = w->next;
129 0 : if (rm_candidate != NULL && rm_candidate->notify == subscribed_notify) {
130 0 : w->next = w->next->next;
131 0 : gpr_free(rm_candidate);
132 0 : return 1;
133 : }
134 0 : w = w->next;
135 : }
136 0 : return 0;
137 : }
138 :
139 27631 : void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
140 : grpc_connectivity_state_tracker *tracker,
141 : grpc_connectivity_state state,
142 : const char *reason) {
143 : grpc_connectivity_state_watcher *w;
144 27631 : if (grpc_connectivity_state_trace) {
145 300 : gpr_log(GPR_DEBUG, "SET: %s: %s --> %s [%s]", tracker->name,
146 : grpc_connectivity_state_name(tracker->current_state),
147 : grpc_connectivity_state_name(state), reason);
148 : }
149 27632 : if (tracker->current_state == state) {
150 33568 : return;
151 : }
152 21697 : GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
153 21697 : tracker->current_state = state;
154 57498 : while ((w = tracker->watchers) != NULL) {
155 14103 : *w->current = tracker->current_state;
156 14103 : tracker->watchers = w->next;
157 14103 : grpc_exec_ctx_enqueue(exec_ctx, w->notify, 1);
158 14103 : gpr_free(w);
159 : }
160 : }
|