TBufferedTransport.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. * @package thrift.transport
  21. */
  22. namespace Thrift\Transport;
  23. use Thrift\Factory\TStringFuncFactory;
  24. /**
  25. * Buffered transport. Stores data to an internal buffer that it doesn't
  26. * actually write out until flush is called. For reading, we do a greedy
  27. * read and then serve data out of the internal buffer.
  28. *
  29. * @package thrift.transport
  30. */
  31. class TBufferedTransport extends TTransport
  32. {
  33. /**
  34. * Constructor. Creates a buffered transport around an underlying transport
  35. */
  36. public function __construct($transport=null, $rBufSize=512, $wBufSize=512)
  37. {
  38. $this->transport_ = $transport;
  39. $this->rBufSize_ = $rBufSize;
  40. $this->wBufSize_ = $wBufSize;
  41. }
  42. /**
  43. * The underlying transport
  44. *
  45. * @var TTransport
  46. */
  47. protected $transport_ = null;
  48. /**
  49. * The receive buffer size
  50. *
  51. * @var int
  52. */
  53. protected $rBufSize_ = 512;
  54. /**
  55. * The write buffer size
  56. *
  57. * @var int
  58. */
  59. protected $wBufSize_ = 512;
  60. /**
  61. * The write buffer.
  62. *
  63. * @var string
  64. */
  65. protected $wBuf_ = '';
  66. /**
  67. * The read buffer.
  68. *
  69. * @var string
  70. */
  71. protected $rBuf_ = '';
  72. public function isOpen()
  73. {
  74. return $this->transport_->isOpen();
  75. }
  76. public function open()
  77. {
  78. $this->transport_->open();
  79. }
  80. public function close()
  81. {
  82. $this->transport_->close();
  83. }
  84. public function putBack($data)
  85. {
  86. if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
  87. $this->rBuf_ = $data;
  88. } else {
  89. $this->rBuf_ = ($data . $this->rBuf_);
  90. }
  91. }
  92. /**
  93. * The reason that we customize readAll here is that the majority of PHP
  94. * streams are already internally buffered by PHP. The socket stream, for
  95. * example, buffers internally and blocks if you call read with $len greater
  96. * than the amount of data available, unlike recv() in C.
  97. *
  98. * Therefore, use the readAll method of the wrapped transport inside
  99. * the buffered readAll.
  100. */
  101. public function readAll($len)
  102. {
  103. $have = TStringFuncFactory::create()->strlen($this->rBuf_);
  104. if ($have == 0) {
  105. $data = $this->transport_->readAll($len);
  106. } elseif ($have < $len) {
  107. $data = $this->rBuf_;
  108. $this->rBuf_ = '';
  109. $data .= $this->transport_->readAll($len - $have);
  110. } elseif ($have == $len) {
  111. $data = $this->rBuf_;
  112. $this->rBuf_ = '';
  113. } elseif ($have > $len) {
  114. $data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
  115. $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
  116. }
  117. return $data;
  118. }
  119. public function read($len)
  120. {
  121. if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
  122. $this->rBuf_ = $this->transport_->read($this->rBufSize_);
  123. }
  124. if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) {
  125. $ret = $this->rBuf_;
  126. $this->rBuf_ = '';
  127. return $ret;
  128. }
  129. $ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
  130. $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
  131. return $ret;
  132. }
  133. public function write($buf)
  134. {
  135. $this->wBuf_ .= $buf;
  136. if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) {
  137. $out = $this->wBuf_;
  138. // Note that we clear the internal wBuf_ prior to the underlying write
  139. // to ensure we're in a sane state (i.e. internal buffer cleaned)
  140. // if the underlying write throws up an exception
  141. $this->wBuf_ = '';
  142. $this->transport_->write($out);
  143. }
  144. }
  145. public function flush()
  146. {
  147. if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) {
  148. $out = $this->wBuf_;
  149. // Note that we clear the internal wBuf_ prior to the underlying write
  150. // to ensure we're in a sane state (i.e. internal buffer cleaned)
  151. // if the underlying write throws up an exception
  152. $this->wBuf_ = '';
  153. $this->transport_->write($out);
  154. }
  155. $this->transport_->flush();
  156. }
  157. }