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/java/src/protocol/TBinaryProtocol.java b/lib/java/src/protocol/TBinaryProtocol.java
index be02a3e..7dff485 100644
--- a/lib/java/src/protocol/TBinaryProtocol.java
+++ b/lib/java/src/protocol/TBinaryProtocol.java
@@ -16,12 +16,30 @@
  */
 public class TBinaryProtocol extends TProtocol {
 
+  protected static final int VERSION_MASK = 0xffff0000;
+  protected static final int VERSION_1 = 0x80010000;
+
+  protected boolean strictRead_ = false;
+  protected boolean strictWrite_ = true;
+
   /**
    * Factory
    */
   public static class Factory implements TProtocolFactory {
+    protected boolean strictRead_ = false;
+    protected boolean strictWrite_ = true;
+    
+    public Factory() {
+      this(false, false);
+    }
+
+    public Factory(boolean strictRead, boolean strictWrite) {
+      strictRead_ = strictRead;
+      strictWrite_ = strictWrite;
+    }
+
     public TProtocol getProtocol(TTransport trans) {
-      return new TBinaryProtocol(trans);
+      return new TBinaryProtocol(trans, strictRead_, strictWrite_);
     }
   }
 
@@ -29,13 +47,27 @@
    * Constructor
    */
   public TBinaryProtocol(TTransport trans) {
-    super(trans);
+    this(trans, false, false);
   }
 
+  public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) {
+    super(trans);
+    strictRead_ = strictRead;
+    strictWrite_ = strictWrite;
+  }
+
+
   public void writeMessageBegin(TMessage message) throws TException {
-    writeString(message.name);
-    writeByte(message.type);
-    writeI32(message.seqid);
+    if (strictWrite_) {
+      int version = VERSION_1 | message.type;
+      writeI32(version);
+      writeString(message.name);
+      writeI32(message.seqid);
+    } else {
+      writeString(message.name);
+      writeByte(message.type);
+      writeI32(message.seqid);
+    }
   }
 
   public void writeMessageEnd() {}
@@ -137,9 +169,24 @@
 
   public TMessage readMessageBegin() throws TException {
     TMessage message = new TMessage();
-    message.name = readString();
-    message.type = readByte();
-    message.seqid = readI32();
+
+    int size = readI32();
+    if (size < 0) {
+      int version = size & VERSION_MASK;
+      if (version != VERSION_1) {
+        throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin");
+      }
+      message.type = (byte)(version & 0x000000ff);
+      message.name = readString();
+      message.seqid = readI32();
+    } else {
+      if (strictRead_) {
+        throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
+      }
+      message.name = readStringBody(size);
+      message.type = readByte();
+      message.seqid = readI32();
+    }
     return message;
   }
 
@@ -239,6 +286,10 @@
 
   public String readString() throws TException {
     int size = readI32();
+    return readStringBody(size);
+  }
+
+  public String readStringBody(int size) throws TException {
     byte[] buf = new byte[size];
     trans_.readAll(buf, 0, size);
     return new String(buf);
diff --git a/lib/java/src/protocol/TProtocolException.java b/lib/java/src/protocol/TProtocolException.java
index efc54b4..783b5be 100644
--- a/lib/java/src/protocol/TProtocolException.java
+++ b/lib/java/src/protocol/TProtocolException.java
@@ -19,6 +19,7 @@
   public static final int INVALID_DATA = 1;
   public static final int NEGATIVE_SIZE = 2;
   public static final int SIZE_LIMIT = 3;
+  public static final int BAD_VERSION = 4;
 
   protected int type_ = UNKNOWN;
 
diff --git a/lib/java/src/server/TThreadPoolServer.java b/lib/java/src/server/TThreadPoolServer.java
index 22930d5..0945fbe 100644
--- a/lib/java/src/server/TThreadPoolServer.java
+++ b/lib/java/src/server/TThreadPoolServer.java
@@ -58,6 +58,15 @@
 
   public TThreadPoolServer(TProcessor processor,
                            TServerTransport serverTransport,
+                           TProtocolFactory protocolFactory) {
+    this(processor, serverTransport,
+         new TTransportFactory(), new TTransportFactory(),
+         protocolFactory, protocolFactory,
+         new Options());
+  }
+
+  public TThreadPoolServer(TProcessor processor,
+                           TServerTransport serverTransport,
                            TTransportFactory transportFactory,
                            TProtocolFactory protocolFactory) {
     this(processor, serverTransport,