Thrift: New methods for C++ transports.
Summary:
To support the upcoming variable-length encoding of integers in
TDenseProtocol, augment Thrift transports with two new methods:
borrow and consume. Borrow copies some data out of the transport
without consuming it, and consume... consumes it.
Reviewed By: mcslee
Test Plan:
Thrift compiles.
Should check in variable-length integer code for TDenseProtocol
right after this (git ruulz).
Revert Plan: revert stuff that uses these methods also.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665251 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/transport/TTransport.h b/lib/cpp/src/transport/TTransport.h
index 53d8fd5..b3d8820 100644
--- a/lib/cpp/src/transport/TTransport.h
+++ b/lib/cpp/src/transport/TTransport.h
@@ -66,7 +66,7 @@
/**
* Attempt to read up to the specified number of bytes into the string.
*
- * @param s Reference to the location to append the read data
+ * @param buf Reference to the location to write the data
* @param len How many bytes to read
* @return How many bytes were actually read
* @throws TTransportException If an error occurs
@@ -112,7 +112,7 @@
/**
* Writes the string in its entirety to the buffer.
*
- * @param s The string to write out
+ * @param buf The data to write out
* @throws TTransportException if an error occurs
*/
virtual void write(const uint8_t* buf, uint32_t len) {
@@ -138,6 +138,37 @@
*/
virtual void flush() {}
+ /**
+ * Attempts to copy len bytes from the transport into buf. Does not consume
+ * the bytes read (i.e.: a later read will return the same data). This
+ * method is meant to support protocols that need to read variable-length
+ * fields. They can attempt to borrow the maximum amount of data that they
+ * will need, then consume (see next method) what they actually use. Some
+ * transports will not support this method and others will fail occasionally,
+ * so protocols must be prepared to use read if borrow fails.
+ *
+ * @oaram buf The buffer to store the data
+ * @param len How much data to borrow
+ * @return true if the requested data has been borrowed, false otherwise
+ * @throws TTransportException if an error occurs
+ */
+ virtual bool borrow(uint8_t* buf, uint32_t len) {
+ return false;
+ }
+
+ /**
+ * Remove len bytes from the transport. This should always follow a borrow
+ * of at least len bytes, and should always succeed.
+ * TODO(dreiss): Is there any transport that could borrow but fail to
+ * consume, or that would require a buffer to dump the consumed data?
+ *
+ * @param len How many bytes to consume
+ * @throws TTransportException If an error occurs
+ */
+ virtual void consume(uint32_t len) {
+ throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume.");
+ }
+
protected:
/**
* Simple constructor.
diff --git a/lib/cpp/src/transport/TTransportUtils.cpp b/lib/cpp/src/transport/TTransportUtils.cpp
index be70f47..b10958c 100644
--- a/lib/cpp/src/transport/TTransportUtils.cpp
+++ b/lib/cpp/src/transport/TTransportUtils.cpp
@@ -59,6 +59,26 @@
}
}
+bool TBufferedTransport::borrow(uint8_t* buf, uint32_t len) {
+ // Don't try to be clever with shifting buffers.
+ // If we have enough data, give it, otherwise
+ // let the protcol use its slow path.
+ if (rLen_-rPos_ >= len) {
+ memcpy(buf, rBuf_+rPos_, len);
+ return true;
+ }
+ return false;
+}
+
+void TBufferedTransport::consume(uint32_t len) {
+ if (rLen_-rPos_ >= len) {
+ rPos_ += len;
+ } else {
+ throw TTransportException(TTransportException::BAD_ARGS,
+ "consume did not follow a borrow.");
+ }
+}
+
void TBufferedTransport::flush() {
// Write out any data waiting in the write buffer
if (wLen_ > 0) {
@@ -183,6 +203,26 @@
transport_->flush();
}
+bool TFramedTransport::borrow(uint8_t* buf, uint32_t len) {
+ // Don't try to be clever with shifting buffers.
+ // If we have enough data, give it, otherwise
+ // let the protcol use its slow path.
+ if (read_ && (rLen_-rPos_ >= len)) {
+ memcpy(buf, rBuf_+rPos_, len);
+ return true;
+ }
+ return false;
+}
+
+void TFramedTransport::consume(uint32_t len) {
+ if (rLen_-rPos_ >= len) {
+ rPos_ += len;
+ } else {
+ throw TTransportException(TTransportException::BAD_ARGS,
+ "consume did not follow a borrow.");
+ }
+}
+
uint32_t TMemoryBuffer::read(uint8_t* buf, uint32_t len) {
// Check avaible data for reading
uint32_t avail = wPos_ - rPos_;
@@ -253,6 +293,26 @@
wPos_ += len;
}
+bool TMemoryBuffer::borrow(uint8_t* buf, uint32_t len) {
+ // Don't try to be clever with shifting buffers.
+ // If we have enough data, give it, otherwise
+ // let the protcol use its slow path.
+ if (wPos_-rPos_ >= len) {
+ memcpy(buf, buffer_ + rPos_, len);
+ return true;
+ }
+ return false;
+}
+
+void TMemoryBuffer::consume(uint32_t len) {
+ if (wPos_-rPos_ >= len) {
+ rPos_ += len;
+ } else {
+ throw TTransportException(TTransportException::BAD_ARGS,
+ "consume did not follow a borrow.");
+ }
+}
+
uint32_t TPipedTransport::read(uint8_t* buf, uint32_t len) {
uint32_t need = len;
diff --git a/lib/cpp/src/transport/TTransportUtils.h b/lib/cpp/src/transport/TTransportUtils.h
index 1a40975..033e472 100644
--- a/lib/cpp/src/transport/TTransportUtils.h
+++ b/lib/cpp/src/transport/TTransportUtils.h
@@ -105,6 +105,10 @@
void flush();
+ bool borrow(uint8_t* buf, uint32_t len);
+
+ void consume(uint32_t len);
+
protected:
boost::shared_ptr<TTransport> transport_;
uint8_t* rBuf_;
@@ -213,6 +217,10 @@
void flush();
+ bool borrow(uint8_t* buf, uint32_t len);
+
+ void consume(uint32_t len);
+
protected:
boost::shared_ptr<TTransport> transport_;
uint8_t* rBuf_;
@@ -383,6 +391,10 @@
return wPos_ - rPos_;
}
+ bool borrow(uint8_t* buf, uint32_t len);
+
+ void consume(uint32_t len);
+
private:
// Data buffer
uint8_t* buffer_;