blob: 87765b9799d6c6e782ba220e2b8a04ee86919ce1 [file] [log] [blame]
Craig Tillerc7b5f762015-06-27 11:48:42 -07001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, Google Inc.
Craig Tillerc7b5f762015-06-27 11:48:42 -07004 * 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
Craig Tiller08a1cf82015-06-29 09:37:52 -070034#include "src/core/transport/connectivity_state.h"
Craig Tiller5795da72015-09-17 15:27:13 -070035
36#include <string.h>
37
Craig Tillerc7b5f762015-06-27 11:48:42 -070038#include <grpc/support/alloc.h>
Craig Tiller98465032015-06-29 14:36:42 -070039#include <grpc/support/log.h>
Craig Tiller1ada6ad2015-07-16 16:19:14 -070040#include <grpc/support/string_util.h>
41
42int grpc_connectivity_state_trace = 0;
43
Craig Tillera82950e2015-09-22 12:33:20 -070044const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
45 switch (state) {
Craig Tiller03dc6552015-07-17 23:12:34 -070046 case GRPC_CHANNEL_IDLE:
47 return "IDLE";
48 case GRPC_CHANNEL_CONNECTING:
49 return "CONNECTING";
50 case GRPC_CHANNEL_READY:
51 return "READY";
52 case GRPC_CHANNEL_TRANSIENT_FAILURE:
53 return "TRANSIENT_FAILURE";
54 case GRPC_CHANNEL_FATAL_FAILURE:
55 return "FATAL_FAILURE";
Craig Tillera82950e2015-09-22 12:33:20 -070056 }
Craig Tiller179e6fe2015-12-09 11:09:47 -080057 GPR_UNREACHABLE_CODE(return "UNKNOWN");
Craig Tiller1ada6ad2015-07-16 16:19:14 -070058}
Craig Tillerc7b5f762015-06-27 11:48:42 -070059
Craig Tillera82950e2015-09-22 12:33:20 -070060void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
61 grpc_connectivity_state init_state,
62 const char *name) {
Craig Tiller08a1cf82015-06-29 09:37:52 -070063 tracker->current_state = init_state;
64 tracker->watchers = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -070065 tracker->name = gpr_strdup(name);
Craig Tillerc7b5f762015-06-27 11:48:42 -070066}
67
Craig Tillera82950e2015-09-22 12:33:20 -070068void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
69 grpc_connectivity_state_tracker *tracker) {
Craig Tiller47a708e2015-09-15 16:16:06 -070070 int success;
Craig Tillerc7b5f762015-06-27 11:48:42 -070071 grpc_connectivity_state_watcher *w;
Craig Tillera82950e2015-09-22 12:33:20 -070072 while ((w = tracker->watchers)) {
73 tracker->watchers = w->next;
Craig Tillerc7b5f762015-06-27 11:48:42 -070074
Craig Tillera82950e2015-09-22 12:33:20 -070075 if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) {
76 *w->current = GRPC_CHANNEL_FATAL_FAILURE;
77 success = 1;
78 } else {
79 success = 0;
Craig Tiller08a1cf82015-06-29 09:37:52 -070080 }
Craig Tiller6c396862016-01-28 13:53:40 -080081 grpc_exec_ctx_enqueue(exec_ctx, w->notify, success, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -070082 gpr_free(w);
83 }
84 gpr_free(tracker->name);
Craig Tillerc7b5f762015-06-27 11:48:42 -070085}
86
Craig Tillera82950e2015-09-22 12:33:20 -070087grpc_connectivity_state grpc_connectivity_state_check(
88 grpc_connectivity_state_tracker *tracker) {
89 if (grpc_connectivity_state_trace) {
Craig Tiller53ee0402015-11-25 09:07:09 -080090 gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
Craig Tillera82950e2015-09-22 12:33:20 -070091 grpc_connectivity_state_name(tracker->current_state));
92 }
Craig Tiller08a1cf82015-06-29 09:37:52 -070093 return tracker->current_state;
Craig Tillerc7b5f762015-06-27 11:48:42 -070094}
95
Craig Tillera82950e2015-09-22 12:33:20 -070096int 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 if (grpc_connectivity_state_trace) {
Craig Tiller48613042015-11-29 14:45:11 -0800100 if (current == NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800101 gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
102 tracker->name, notify);
Craig Tiller48613042015-11-29 14:45:11 -0800103 } else {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800104 gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
105 tracker->name, grpc_connectivity_state_name(*current),
Craig Tiller48613042015-11-29 14:45:11 -0800106 grpc_connectivity_state_name(tracker->current_state), notify);
David Garcia Quintas3b147812015-09-30 15:59:52 -0700107 }
David Garcia Quintas3b147812015-09-30 15:59:52 -0700108 }
Craig Tiller48613042015-11-29 14:45:11 -0800109 if (current == NULL) {
110 grpc_connectivity_state_watcher *w = tracker->watchers;
111 if (w != NULL && w->notify == notify) {
Craig Tiller6c396862016-01-28 13:53:40 -0800112 grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
Craig Tiller48613042015-11-29 14:45:11 -0800113 tracker->watchers = w->next;
114 gpr_free(w);
115 return 0;
116 }
117 while (w != NULL) {
118 grpc_connectivity_state_watcher *rm_candidate = w->next;
119 if (rm_candidate != NULL && rm_candidate->notify == notify) {
Craig Tiller6c396862016-01-28 13:53:40 -0800120 grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
Craig Tiller48613042015-11-29 14:45:11 -0800121 w->next = w->next->next;
122 gpr_free(rm_candidate);
123 return 0;
124 }
125 w = w->next;
126 }
127 return 0;
128 } else {
129 if (tracker->current_state != *current) {
130 *current = tracker->current_state;
Craig Tiller6c396862016-01-28 13:53:40 -0800131 grpc_exec_ctx_enqueue(exec_ctx, notify, true, NULL);
Craig Tiller48613042015-11-29 14:45:11 -0800132 } else {
133 grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
134 w->current = current;
135 w->notify = notify;
136 w->next = tracker->watchers;
137 tracker->watchers = w;
138 }
139 return tracker->current_state == GRPC_CHANNEL_IDLE;
140 }
David Garcia Quintas3b147812015-09-30 15:59:52 -0700141}
142
Craig Tillera82950e2015-09-22 12:33:20 -0700143void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
144 grpc_connectivity_state_tracker *tracker,
145 grpc_connectivity_state state,
146 const char *reason) {
Craig Tiller000cd8f2015-09-18 07:20:29 -0700147 grpc_connectivity_state_watcher *w;
Craig Tillera82950e2015-09-22 12:33:20 -0700148 if (grpc_connectivity_state_trace) {
Craig Tiller53ee0402015-11-25 09:07:09 -0800149 gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
Craig Tillera82950e2015-09-22 12:33:20 -0700150 grpc_connectivity_state_name(tracker->current_state),
151 grpc_connectivity_state_name(state), reason);
152 }
153 if (tracker->current_state == state) {
154 return;
155 }
156 GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700157 tracker->current_state = state;
Craig Tillera82950e2015-09-22 12:33:20 -0700158 while ((w = tracker->watchers) != NULL) {
159 *w->current = tracker->current_state;
160 tracker->watchers = w->next;
Craig Tiller6c396862016-01-28 13:53:40 -0800161 grpc_exec_ctx_enqueue(exec_ctx, w->notify, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700162 gpr_free(w);
163 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700164}