From: David Reiss Date: Fri, 7 Sep 2007 01:26:30 +0000 (+0000) Subject: Thrift: New methods for C++ transports. X-Git-Tag: 0.2.0~1221 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=d8429fcc1020dec143e36dbfc055edbd3009f11b;p=common%2Fthrift.git 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 53d8fd5a..b3d88206 100644 --- a/lib/cpp/src/transport/TTransport.h +++ b/lib/cpp/src/transport/TTransport.h @@ -66,7 +66,7 @@ class TTransport { /** * 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 @@ class TTransport { /** * 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 @@ class TTransport { */ 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 be70f476..b10958cb 100644 --- a/lib/cpp/src/transport/TTransportUtils.cpp +++ b/lib/cpp/src/transport/TTransportUtils.cpp @@ -59,6 +59,26 @@ void TBufferedTransport::write(const uint8_t* buf, uint32_t len) { } } +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 @@ void TFramedTransport::flush() { 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 @@ void TMemoryBuffer::write(const uint8_t* buf, uint32_t len) { 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 1a409752..033e472c 100644 --- a/lib/cpp/src/transport/TTransportUtils.h +++ b/lib/cpp/src/transport/TTransportUtils.h @@ -105,6 +105,10 @@ class TBufferedTransport : public TTransport { void flush(); + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + protected: boost::shared_ptr transport_; uint8_t* rBuf_; @@ -213,6 +217,10 @@ class TFramedTransport : public TTransport { void flush(); + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + protected: boost::shared_ptr transport_; uint8_t* rBuf_; @@ -383,6 +391,10 @@ class TMemoryBuffer : public TTransport { return wPos_ - rPos_; } + bool borrow(uint8_t* buf, uint32_t len); + + void consume(uint32_t len); + private: // Data buffer uint8_t* buffer_;