Thrift TBinaryProtocol change
Summary: New Thrift TBinaryProtocol with a version identifier
Reviewed By: aditya, eugene
Test Plan: Modify your services to have strictRead_ and strictWrite_ both set to FALSE. Then redeploy your services and test running clients against them. Once you have clients and servers running stably on this new code, you should redploy versions with strictWrite_ set to TRUE. Once that's all good, we can set strictRead_ to TRUE as well, and eventually deprecate the old protocol code entirely.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665138 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/php/src/protocol/TBinaryProtocol.php b/lib/php/src/protocol/TBinaryProtocol.php
index 962fcfe..69723da 100644
--- a/lib/php/src/protocol/TBinaryProtocol.php
+++ b/lib/php/src/protocol/TBinaryProtocol.php
@@ -19,15 +19,31 @@
*/
class TBinaryProtocol extends TProtocol {
- public function __construct($trans) {
+ const VERSION_MASK = 0xffff0000;
+ const VERSION_1 = 0x80010000;
+
+ private $strictRead_ = false;
+ private $strictWrite_ = true;
+
+ public function __construct($trans, $strictRead=false, $strictWrite=true) {
parent::__construct($trans);
+ $this->strictRead_ = $strictRead;
+ $this->strictWrite_ = $strictWrite;
}
public function writeMessageBegin($name, $type, $seqid) {
- return
- $this->writeString($name) +
- $this->writeByte($type) +
- $this->writeI32($seqid);
+ if ($this->strictWrite_) {
+ $version = self::VERSION_1 | $type;
+ return
+ $this->writeI32($version) +
+ $this->writeString($name) +
+ $this->writeI32($seqid);
+ } else {
+ return
+ $this->writeString($name) +
+ $this->writeByte($type) +
+ $this->writeI32($seqid);
+ }
}
public function writeMessageEnd() {
@@ -50,7 +66,7 @@
public function writeFieldEnd() {
return 0;
- }
+ }
public function writeFieldStop() {
return
@@ -115,29 +131,29 @@
public function writeI64($value) {
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
- // as signed and any int over 2^31 - 1 as a float
+ // as signed and any int over 2^31 - 1 as a float
if (PHP_INT_SIZE == 4) {
$neg = $value < 0;
if ($neg) {
- $value *= -1;
+ $value *= -1;
}
-
+
$hi = (int)($value / 4294967296);
$lo = (int)$value;
-
+
if ($neg) {
- $hi = ~$hi;
- $lo = ~$lo;
- if (($lo & (int)0xffffffff) == (int)0xffffffff) {
- $lo = 0;
- $hi++;
- } else {
- $lo++;
- }
+ $hi = ~$hi;
+ $lo = ~$lo;
+ if (($lo & (int)0xffffffff) == (int)0xffffffff) {
+ $lo = 0;
+ $hi++;
+ } else {
+ $lo++;
+ }
}
$data = pack('N2', $hi, $lo);
-
+
} else {
$hi = $value >> 32;
$lo = $value & 0xFFFFFFFF;
@@ -164,10 +180,29 @@
}
public function readMessageBegin(&$name, &$type, &$seqid) {
- return
- $this->readString($name) +
- $this->readByte($type) +
- $this->readI32($seqid);
+ $result = $this->readI32($sz);
+ if ($sz < 0) {
+ $version = $sz & self::VERSION_MASK;
+ if ($version != self::VERSION_1) {
+ throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
+ }
+ $type = $sz & 0x000000ff;
+ $result +=
+ $this->readString($name) +
+ $this->readI32($seqid);
+ } else {
+ if ($this->strictRead_) {
+ throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
+ } else {
+ // Handle pre-versioned input
+ $name = $this->trans_->readAll($sz);
+ $result +=
+ $sz +
+ $this->readByte($type) +
+ $this->readI32($seqid);
+ }
+ }
+ return $result;
}
public function readMessageEnd() {
@@ -266,7 +301,7 @@
$data = $this->trans_->readAll(8);
$arr = unpack('N2', $data);
-
+
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
@@ -350,8 +385,16 @@
* Binary Protocol Factory
*/
class TBinaryProtocolFactory implements TProtocolFactory {
+ private $strictRead_ = false;
+ private $strictWrite_ = false;
+
+ public function __construct($strictRead=false, $strictWrite=false) {
+ $this->strictRead_ = $strictRead;
+ $this->strictWrite_ = $strictWrite;
+ }
+
public function getProtocol($trans) {
- return new TBinaryProtocol($trans);
+ return new TBinaryProtocol($trans, $this->strictRead, $this->strictWrite);
}
}