Merge branch 'you-complete-me' into we-dont-need-no-backup

Conflicts:
	src/python/src/grpc/_adapter/_c/utility.c
pull/1969/head
Craig Tiller 10 years ago
commit 4b01f6e085
  1. 122
      doc/connectivity-semantics-and-api.md
  2. 4
      include/grpc/grpc.h
  3. 5
      include/grpc/support/slice.h
  4. 3
      src/core/support/log_win32.c
  5. 8
      src/csharp/ext/grpc_csharp_ext.c
  6. 28
      tools/jenkins/run_jenkins.sh

@ -0,0 +1,122 @@
gRPC Connectivity Semantics and API
===================================
This document describes the connectivity semantics for gRPC channels and the
corresponding impact on RPCs. We then discuss an API.
States of Connectivity
----------------------
gRPC Channels provide the abstraction over which clients can communicate with
servers.The client-side channel object can be constructed using little more
than a DNS name. Channels encapsulate a range of functionality including name
resolution, establishing a TCP connection (with retries and backoff) and TLS
handshakes. Channels can also handle errors on established connections and
reconnect, or in the case of HTTP/2 GO_AWAY, re-resolve the name and reconnect.
To hide the details of all this activity from the user of the gRPC API (i.e.,
application code) while exposing meaningful information about the state of a
channel, we use a state machine with four states, defined below:
CONNECTING: The channel is trying to establish a connection and is waiting to
make progress on one of the steps involved in name resolution, TCP connection
establishment or TLS handshake. This is the initial state for all channels upon
creation.
READY: The channel has successfully established a connection all the way
through TLS handshake (or equivalent) and all subsequent attempt to communicate
have succeeded (or are pending without any known failure ).
TRANSIENT_FAILURE: There has been some transient failure (such as a TCP 3-way
handshake timing out or a socket error). Channels in this state will eventually
switch to the CONNECTING state and try to establish a connection again. Since
retries are done with exponential backoff, channels that fail to connect will
start out spending very little time in this state but as the attempts fail
repeatedly, the channel will spend increasingly large amounts of time in this
state. For many non-fatal failures (e.g., TCP connection attempts timing out
because the server is not yet available), the channel may be stuck in this
state for an indefinitely large amount of time.
FATAL_FAILURE: There has been a fatal failure and the channel will never
attempt to establish a connection again. (e.g., a server presenting an invalid
TLS certificate)
Channels that enter this state never leave this state.
The following table lists the legal transitions from one state to another and
corresponding reasons. Empty cells denote disallowed transitions.
<table style='border: 1px solid black'>
<tr>
<th>From/To</th>
<th>CONNECTING</th>
<th>READY</th>
<th>TRANSIENT_FAILURE</th>
<th>FATAL_FAILURE</th>
</tr>
<tr>
<th>CONNECTING</th>
<td>Incremental progress during connection establishment</td>
<td>All steps needed to establish a connection succeeded</td>
<td>Any failure in any of the steps needed to establish connection</td>
<td>Fatal failure encountered while attempting a connection.</td>
</tr>
<tr>
<th>READY</th>
<td></td>
<td>Incremental successful communication on established channel.</td>
<td>Any failure encountered while expecting successful communication on
established channel.</td>
<td></td>
</tr>
<tr>
<th>TRANSIENT_FAILURE</th>
<td>Wait time required to implement (exponential) backoff is over.</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>FATAL_FAILURE</th>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
Channel State API
-----------------
All gRPC libraries will expose a channel-level API method to poll the current
state of a channel. In C++, this method is called GetCurrentState and returns
an enum for one of the four legal states.
All libraries should also expose an API that enables the application (user of
the gRPC API) to be notified when the channel state changes. Since state
changes can be rapid and race with any such notification, the notification
should just inform the user that some state change has happened, leaving it to
the user to poll the channel for the current state.
The synchronous version of this API is:
```cpp
bool WaitForStateChange(gpr_timespec deadline, ChannelState source_state);
```
which returns true when the state changes to something other than the
source_state and false if the deadline expires. Asynchronous and futures based
APIs should have a corresponding method that allows the application to be
notified when the state of a channel changes.
Note that a notification is delivered every time there is a transition from any
state to any *other* state. On the other hand the rules for legal state
transition, require a transition from CONNECTING to TRANSIENT_FAILURE and back
to CONNECTING for every recoverable failure, even if the corresponding
exponential backoff requires no wait before retry. The combined effect is that
the application may receive state change notifications that appear spurious.
e.g., an application waiting for state changes on a channel that is CONNECTING
may receive a state change notification but find the channel in the same
CONNECTING state on polling for current state because the channel may have
spent infinitesimally small amount of time in the TRANSIENT_FAILURE state.

@ -221,7 +221,7 @@ typedef enum {
GRPC_OP_SEND_INITIAL_METADATA = 0,
/* Send a message: 0 or more of these operations can occur for each call */
GRPC_OP_SEND_MESSAGE,
/* Send a close from the server: one and only one instance MUST be sent from
/* Send a close from the client: one and only one instance MUST be sent from
the client,
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_CLOSE_FROM_CLIENT,
@ -240,7 +240,7 @@ typedef enum {
the status will indicate some failure.
*/
GRPC_OP_RECV_STATUS_ON_CLIENT,
/* Receive status on the server: one and only one must be made on the server
/* Receive close on the server: one and only one must be made on the server
*/
GRPC_OP_RECV_CLOSE_ON_SERVER
} grpc_op_type;

@ -110,8 +110,9 @@ gpr_slice gpr_slice_ref(gpr_slice s);
/* Decrement the ref count of s. If the ref count of s reaches zero, all
slices sharing the ref count are destroyed, and considered no longer
initialized. If s is ultimately derived from a call to gpr_slice_new(start,
len, dest) where dest!=NULL , then (*dest)(start, len) is called. Requires
s initialized. */
len, dest) where dest!=NULL , then (*dest)(start) is called, else if s is
ultimately derived from a call to gpr_slice_new_with_len(start, len, dest)
where dest!=NULL , then (*dest)(start, len). Requires s initialized. */
void gpr_slice_unref(gpr_slice s);
/* Create a slice pointing at some data. Calls malloc to allocate a refcount

@ -42,6 +42,7 @@
#include <grpc/support/log_win32.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/string_util.h>
#include "src/core/support/string.h"
#include "src/core/support/string_win32.h"
@ -106,7 +107,7 @@ char *gpr_format_message(DWORD messageid) {
NULL, messageid,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)(&tmessage), 0, NULL);
if (status == 0) return gpr_strdup("Unable to retreive error string");
if (status == 0) return gpr_strdup("Unable to retrieve error string");
message = gpr_tchar_to_char(tmessage);
LocalFree(tmessage);
return message;

@ -65,8 +65,6 @@ grpc_byte_buffer *string_to_byte_buffer(const char *buffer, size_t len) {
return bb;
}
typedef void(GPR_CALLTYPE *callback_funcptr)(gpr_int32 success, void *batch_context);
/*
* Helper to maintain lifetime of batch op inputs and store batch op outputs.
*/
@ -732,10 +730,12 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
gpr_set_log_function(grpcsharp_log_handler);
}
typedef void(GPR_CALLTYPE *test_callback_funcptr)(gpr_int32 success);
/* For testing */
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_callback(callback_funcptr callback) {
callback(1, NULL);
grpcsharp_test_callback(test_callback_funcptr callback) {
callback(1);
}
/* For testing */

@ -41,13 +41,35 @@ if [ "$platform" == "linux" ]
then
echo "building $language on Linux"
if [ "$ghprbPullId" != "" ]
then
# if we are building a pull request, grab corresponding refs.
FETCH_PULL_REQUEST_CMD="&& git fetch $GIT_URL refs/pull/$ghprbPullId/merge refs/pull/$ghprbPullId/head"
fi
# Make sure the CID file is gone.
rm -f docker.cid
# Run tests inside docker
docker run grpc/grpc_jenkins_slave bash -c -l "git clone --recursive $GIT_URL /var/local/git/grpc \
&& cd /var/local/git/grpc && git checkout -f $GIT_COMMIT \
docker run --cidfile=docker.cid grpc/grpc_jenkins_slave bash -c -l "git clone --recursive $GIT_URL /var/local/git/grpc \
&& cd /var/local/git/grpc \
$FETCH_PULL_REQUEST_CMD \
&& git checkout -f $GIT_COMMIT \
&& git submodule update \
&& nvm use 0.12 \
&& rvm use ruby-2.1 \
&& tools/run_tests/run_tests.py -t -l $language"
&& tools/run_tests/run_tests.py -t -l $language" || DOCKER_FAILED="true"
DOCKER_CID=`cat docker.cid`
if [ "$DOCKER_FAILED" == "" ]
then
echo "Docker finished successfully, deleting the container $DOCKER_CID"
docker rm $DOCKER_CID
else
echo "Docker exited with failure, keeping container $DOCKER_CID."
echo "You can SSH to the worker and use 'docker start CID' and 'docker exec -i -t CID bash' to debug the problem."
fi
elif [ "$platform" == "windows" ]
then
echo "building $language on Windows"

Loading…
Cancel
Save