Skip to content

Commit ec223d3

Browse files
committed
PHPLIB-252: Allow seeking to advance chunk iterator instead of always re-querying
1 parent 0d3496d commit ec223d3

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

src/GridFS/ReadableStream.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,26 @@ public function seek($offset)
186186
$this->chunkOffset = (integer) floor($offset / $this->chunkSize);
187187
$this->bufferOffset = $offset % $this->chunkSize;
188188

189-
if ($lastChunkOffset !== $this->chunkOffset) {
189+
/* If we are seeking to a previous chunk, we need to reinitialize the
190+
* chunk iterator.
191+
*/
192+
if ($lastChunkOffset > $this->chunkOffset) {
190193
$this->buffer = null;
191194
$this->chunksIterator = null;
195+
return;
196+
}
197+
198+
/* If we are seeking to a subsequent chunk, we do not need to
199+
* reinitalize the chunk iterator. Instead, we can simply move forward
200+
* to $this->chunkOffset.
201+
*/
202+
$numChunks = $this->chunkOffset - $lastChunkOffset;
203+
$i = 0;
204+
if ($this->chunksIterator !== null) {
205+
while ($i < $numChunks) {
206+
$this->chunksIterator->next();
207+
$i++;
208+
}
192209
}
193210
}
194211

tests/GridFS/ReadableStreamFunctionalTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,32 @@ public function testSeekOutOfRange()
199199

200200
$stream->seek(11);
201201
}
202+
203+
public function testSeekPreviousChunk()
204+
{
205+
$fileDocument = $this->collectionWrapper->findFileById('length-10');
206+
$stream = new ReadableStream($this->collectionWrapper, $fileDocument);
207+
208+
$stream->readBytes(1);
209+
$stream->seek(5);
210+
$stream->seek(2);
211+
$stream->readBytes(1);
212+
}
213+
214+
public function testSeekSubsequentChunk()
215+
{
216+
$fileDocument = $this->collectionWrapper->findFileById('length-10');
217+
218+
$observer = $this->getMockBuilder(ReadableStream::class)
219+
->setConstructorArgs(array($this->collectionWrapper, $fileDocument))
220+
->getMock();
221+
222+
$observer->expects($this->never())
223+
->method('initChunksIterator');
224+
225+
$observer->readBytes(1);
226+
$observer->seek(5);
227+
$observer->seek(2);
228+
$observer->readBytes(1);
229+
}
202230
}

0 commit comments

Comments
 (0)