aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/php/ext/grpc/channel.c59
-rw-r--r--src/php/ext/grpc/php_grpc.c12
-rwxr-xr-xsrc/php/lib/Grpc/BaseStub.php45
-rwxr-xr-xsrc/php/tests/unit_tests/EndToEndTest.php46
4 files changed, 161 insertions, 1 deletions
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 7d8a6f87ab..447cfc15be 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -51,8 +51,10 @@
#include <grpc/support/log.h>
#include <grpc/grpc_security.h>
-#include "server.h"
+#include "completion_queue.h"
#include "credentials.h"
+#include "server.h"
+#include "timeval.h"
zend_class_entry *grpc_ce_channel;
@@ -205,6 +207,59 @@ PHP_METHOD(Channel, getTarget) {
}
/**
+ * Get the connectivity state of the channel
+ * @param bool (optional) try to connect on the channel
+ * @return long The grpc connectivity state
+ */
+PHP_METHOD(Channel, getConnectivityState) {
+ wrapped_grpc_channel *channel =
+ (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ bool try_to_connect;
+ /* "|b" == 1 optional bool */
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) ==
+ FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "getConnectivityState expects a bool", 1 TSRMLS_CC);
+ return;
+ }
+ RETURN_LONG(grpc_channel_check_connectivity_state(channel->wrapped,
+ (int)try_to_connect));
+}
+
+/**
+ * Watch the connectivity state of the channel until it changed
+ * @param long The previous connectivity state of the channel
+ * @param Timeval The deadline this function should wait until
+ * @return bool If the connectivity state changes from last_state
+ * before deadline
+ */
+PHP_METHOD(Channel, watchConnectivityState) {
+ wrapped_grpc_channel *channel =
+ (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ long last_state;
+ zval *deadline_obj;
+ /* "lO" == 1 long 1 object */
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO",
+ &last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "watchConnectivityState expects 1 long 1 timeval",
+ 1 TSRMLS_CC);
+ return;
+ }
+
+ wrapped_grpc_timeval *deadline =
+ (wrapped_grpc_timeval *)zend_object_store_get_object(
+ deadline_obj TSRMLS_CC);
+ grpc_channel_watch_connectivity_state(
+ channel->wrapped, (grpc_connectivity_state)last_state,
+ deadline->wrapped, completion_queue, NULL);
+ grpc_event event = grpc_completion_queue_pluck(
+ completion_queue, NULL,
+ gpr_inf_future(GPR_CLOCK_REALTIME));
+ RETURN_BOOL(event.success);
+}
+
+/**
* Close the channel
*/
PHP_METHOD(Channel, close) {
@@ -219,6 +274,8 @@ PHP_METHOD(Channel, close) {
static zend_function_entry channel_methods[] = {
PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
PHP_FE_END};
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index fedcf0f539..0f730ea756 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -183,6 +183,18 @@ PHP_MINIT_FUNCTION(grpc) {
REGISTER_LONG_CONSTANT("Grpc\\OP_RECV_CLOSE_ON_SERVER",
GRPC_OP_RECV_CLOSE_ON_SERVER, CONST_CS);
+ /* Register connectivity state constants */
+ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_IDLE",
+ GRPC_CHANNEL_IDLE, CONST_CS);
+ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_CONNECTING",
+ GRPC_CHANNEL_CONNECTING, CONST_CS);
+ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_READY",
+ GRPC_CHANNEL_READY, CONST_CS);
+ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_TRANSIENT_FAILURE",
+ GRPC_CHANNEL_TRANSIENT_FAILURE, CONST_CS);
+ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_FATAL_FAILURE",
+ GRPC_CHANNEL_FATAL_FAILURE, CONST_CS);
+
grpc_init_call(TSRMLS_C);
grpc_init_channel(TSRMLS_C);
grpc_init_server(TSRMLS_C);
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index a0c677908c..9d6a77b855 100755
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -75,6 +75,51 @@ class BaseStub {
}
/**
+ * @param $try_to_connect bool
+ * @return int The grpc connectivity state
+ */
+ public function getConnectivityState($try_to_connect = false) {
+ return $this->channel->getConnectivityState($try_to_connect);
+ }
+
+ /**
+ * @param $timeout in microseconds
+ * @return bool true if channel is ready
+ * @throw Exception if channel is in FATAL_ERROR state
+ */
+ public function waitForReady($timeout) {
+ $new_state = $this->getConnectivityState(true);
+ if ($this->_checkConnectivityState($new_state)) {
+ return true;
+ }
+
+ $now = Timeval::now();
+ $delta = new Timeval($timeout);
+ $deadline = $now->add($delta);
+
+ while ($this->channel->watchConnectivityState($new_state, $deadline)) {
+ // state has changed before deadline
+ $new_state = $this->getConnectivityState();
+ if ($this->_checkConnectivityState($new_state)) {
+ return true;
+ }
+ }
+ // deadline has passed
+ $new_state = $this->getConnectivityState();
+ return $this->_checkConnectivityState($new_state);
+ }
+
+ private function _checkConnectivityState($new_state) {
+ if ($new_state == Grpc\CHANNEL_READY) {
+ return true;
+ }
+ if ($new_state == Grpc\CHANNEL_FATAL_ERROR) {
+ throw new Exception('Failed to connect to server');
+ }
+ return false;
+ }
+
+ /**
* Close the communication channel associated with this stub
*/
public function close() {
diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php
index 27e27cdfdf..4c0cf91d51 100755
--- a/src/php/tests/unit_tests/EndToEndTest.php
+++ b/src/php/tests/unit_tests/EndToEndTest.php
@@ -153,4 +153,50 @@ class EndToEndTest extends PHPUnit_Framework_TestCase{
public function testGetTarget() {
$this->assertTrue(is_string($this->channel->getTarget()));
}
+
+ public function testGetConnectivityState() {
+ $this->assertTrue($this->channel->getConnectivityState() == Grpc\CHANNEL_IDLE);
+ }
+
+ public function testWatchConnectivityStateFailed() {
+ $idle_state = $this->channel->getConnectivityState(true);
+ $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
+
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(1);
+ $deadline = $now->add($delta);
+
+ $this->assertFalse($this->channel->watchConnectivityState(
+ $idle_state, $deadline));
+ }
+
+ public function testWatchConnectivityStateSuccess() {
+ $idle_state = $this->channel->getConnectivityState(true);
+ $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
+
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(3000000); // should finish well before
+ $deadline = $now->add($delta);
+
+ $this->assertTrue($this->channel->watchConnectivityState(
+ $idle_state, $deadline));
+
+ $new_state = $this->channel->getConnectivityState();
+ $this->assertTrue($idle_state != $new_state);
+ }
+
+ public function testWatchConnectivityStateDoNothing() {
+ $idle_state = $this->channel->getConnectivityState();
+ $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
+
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(100000);
+ $deadline = $now->add($delta);
+
+ $this->assertFalse($this->channel->watchConnectivityState(
+ $idle_state, $deadline));
+
+ $new_state = $this->channel->getConnectivityState();
+ $this->assertTrue($new_state == Grpc\CHANNEL_IDLE);
+ }
}