* BBufferIO did not implement Seek() and Position() correctly; it just passed
it to the stream. This caused Read()/Write() to need two syscalls for nothing (this only caused the actual stream to share the same position with the BBufferIO, something you just cannot rely on when using buffered I/O). * Anyway, this reduces the time VirtualBox needs to open some RAW test images from over 4 minutes to less than 15 seconds... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28662 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2007-2008, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _BUFFER_IO_H
|
#ifndef _BUFFER_IO_H
|
||||||
@@ -40,7 +40,8 @@ class BBufferIO : public BPositionIO {
|
|||||||
char* fBuffer;
|
char* fBuffer;
|
||||||
size_t fBufferSize;
|
size_t fBufferSize;
|
||||||
size_t fBufferUsed;
|
size_t fBufferUsed;
|
||||||
uint32 _reserved_ints[6];
|
off_t fPosition;
|
||||||
|
uint32 _reserved_ints[4];
|
||||||
bool fBufferIsDirty;
|
bool fBufferIsDirty;
|
||||||
bool fOwnsStream;
|
bool fOwnsStream;
|
||||||
bool _reserved_bools[6];
|
bool _reserved_bools[6];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2007, Haiku
|
* Copyright (c) 2001-2008, Haiku
|
||||||
* Distributed under the terms of the MIT license
|
* Distributed under the terms of the MIT license
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
BBufferIO::BBufferIO(BPositionIO *stream, size_t bufferSize, bool ownsStream)
|
BBufferIO::BBufferIO(BPositionIO* stream, size_t bufferSize, bool ownsStream)
|
||||||
:
|
:
|
||||||
fBufferStart(0),
|
fBufferStart(0),
|
||||||
fStream(stream),
|
fStream(stream),
|
||||||
@@ -22,18 +22,16 @@ BBufferIO::BBufferIO(BPositionIO *stream, size_t bufferSize, bool ownsStream)
|
|||||||
fBufferUsed(0),
|
fBufferUsed(0),
|
||||||
fBufferIsDirty(false),
|
fBufferIsDirty(false),
|
||||||
fOwnsStream(ownsStream)
|
fOwnsStream(ownsStream)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (bufferSize < 512)
|
fBufferSize = max_c(bufferSize, 512);
|
||||||
bufferSize = 512;
|
fPosition = stream->Position();
|
||||||
|
|
||||||
fBufferSize = bufferSize;
|
|
||||||
|
|
||||||
// What can we do if this malloc fails ?
|
// What can we do if this malloc fails ?
|
||||||
// I think R5 uses new, but doesn't catch the thrown exception
|
// I think R5 uses new, but doesn't catch the thrown exception
|
||||||
// (if you specify a very big buffer, the application just
|
// (if you specify a very big buffer, the application just
|
||||||
// terminates with abort).
|
// terminates with abort).
|
||||||
fBuffer = (char *)malloc(fBufferSize);
|
fBuffer = (char*)malloc(fBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -52,27 +50,26 @@ BBufferIO::~BBufferIO()
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BBufferIO::ReadAt(off_t pos, void *buffer, size_t size)
|
BBufferIO::ReadAt(off_t pos, void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
// We refuse to crash, even if
|
// We refuse to crash, even if
|
||||||
// you were lazy and didn't give a valid
|
// you were lazy and didn't give a valid
|
||||||
// stream on construction.
|
// stream on construction.
|
||||||
if (fStream == NULL)
|
if (fStream == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// If the amount of data we want doesn't fit in the buffer, just
|
// If the amount of data we want doesn't fit in the buffer, just
|
||||||
// read it directly from the disk (and don't touch the buffer).
|
// read it directly from the disk (and don't touch the buffer).
|
||||||
if (size > fBufferSize) {
|
if (size > fBufferSize || fBuffer == NULL) {
|
||||||
if (fBufferIsDirty)
|
if (fBufferIsDirty)
|
||||||
Flush();
|
Flush();
|
||||||
return fStream->ReadAt(pos, buffer, size);
|
return fStream->ReadAt(pos, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the data we are looking for is not in the buffer...
|
// If the data we are looking for is not in the buffer...
|
||||||
if (size > fBufferUsed
|
if (size > fBufferUsed
|
||||||
|| pos < fBufferStart
|
|| pos < fBufferStart
|
||||||
|| pos > fBufferStart + fBufferUsed
|
|| pos > fBufferStart + fBufferUsed
|
||||||
|| pos + size > fBufferStart + fBufferUsed) {
|
|| pos + size > fBufferStart + fBufferUsed) {
|
||||||
@@ -86,7 +83,7 @@ BBufferIO::ReadAt(off_t pos, void *buffer, size_t size)
|
|||||||
fBufferStart = pos; // The data is buffered starting from this offset
|
fBufferStart = pos; // The data is buffered starting from this offset
|
||||||
}
|
}
|
||||||
|
|
||||||
size = min_c(size, fBufferUsed);
|
size = min_c(size, fBufferUsed);
|
||||||
|
|
||||||
// copy data from the cache to the given buffer
|
// copy data from the cache to the given buffer
|
||||||
memcpy(buffer, fBuffer + pos - fBufferStart, size);
|
memcpy(buffer, fBuffer + pos - fBufferStart, size);
|
||||||
@@ -96,16 +93,15 @@ BBufferIO::ReadAt(off_t pos, void *buffer, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BBufferIO::WriteAt(off_t pos, const void *buffer, size_t size)
|
BBufferIO::WriteAt(off_t pos, const void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
if (fStream == NULL)
|
if (fStream == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// If data doesn't fit into the buffer, write it directly to the stream
|
// If data doesn't fit into the buffer, write it directly to the stream
|
||||||
if (size > fBufferSize)
|
if (size > fBufferSize || fBuffer == NULL)
|
||||||
return fStream->WriteAt(pos, buffer, size);
|
return fStream->WriteAt(pos, buffer, size);
|
||||||
|
|
||||||
// If we have cached data in the buffer, whose offset into the stream
|
// If we have cached data in the buffer, whose offset into the stream
|
||||||
@@ -113,7 +109,7 @@ BBufferIO::WriteAt(off_t pos, const void *buffer, size_t size)
|
|||||||
if (!fBufferIsDirty && fBufferStart > pos) {
|
if (!fBufferIsDirty && fBufferStart > pos) {
|
||||||
fBufferStart = 0;
|
fBufferStart = 0;
|
||||||
fBufferUsed = 0;
|
fBufferUsed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we want to write beyond the cached data...
|
// If we want to write beyond the cached data...
|
||||||
if (pos > fBufferStart + fBufferUsed
|
if (pos > fBufferStart + fBufferUsed
|
||||||
@@ -132,7 +128,7 @@ BBufferIO::WriteAt(off_t pos, const void *buffer, size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fBuffer + pos - fBufferStart, buffer, size);
|
memcpy(fBuffer + pos - fBufferStart, buffer, size);
|
||||||
|
|
||||||
fBufferIsDirty = true;
|
fBufferIsDirty = true;
|
||||||
fBufferUsed = max_c((size + pos), fBufferUsed);
|
fBufferUsed = max_c((size + pos), fBufferUsed);
|
||||||
@@ -147,17 +143,40 @@ BBufferIO::Seek(off_t position, uint32 seekMode)
|
|||||||
if (fStream == NULL)
|
if (fStream == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
return fStream->Seek(position, seekMode);
|
switch (seekMode) {
|
||||||
|
case SEEK_CUR:
|
||||||
|
fPosition += position;
|
||||||
|
if (fPosition < 0)
|
||||||
|
fPosition = 0;
|
||||||
|
break;
|
||||||
|
case SEEK_SET:
|
||||||
|
if (position < 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
fPosition = position;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
{
|
||||||
|
off_t size;
|
||||||
|
status_t status = fStream->GetSize(&size);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
fPosition = size - position;
|
||||||
|
if (fPosition < 0)
|
||||||
|
fPosition = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
BBufferIO::Position() const
|
BBufferIO::Position() const
|
||||||
{
|
{
|
||||||
if (fStream == NULL)
|
return fPosition;
|
||||||
return B_NO_INIT;
|
|
||||||
|
|
||||||
return fStream->Position();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -186,7 +205,7 @@ BBufferIO::Flush()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BPositionIO *
|
BPositionIO*
|
||||||
BBufferIO::Stream() const
|
BBufferIO::Stream() const
|
||||||
{
|
{
|
||||||
return fStream;
|
return fStream;
|
||||||
@@ -208,9 +227,9 @@ BBufferIO::OwnsStream() const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BBufferIO::SetOwnsStream(bool owns_stream)
|
BBufferIO::SetOwnsStream(bool ownsStream)
|
||||||
{
|
{
|
||||||
fOwnsStream = owns_stream;
|
fOwnsStream = ownsStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -231,9 +250,9 @@ BBufferIO::PrintToStream() const
|
|||||||
|
|
||||||
|
|
||||||
// These functions are here to maintain future binary
|
// These functions are here to maintain future binary
|
||||||
// compatibility.
|
// compatibility.
|
||||||
status_t BBufferIO::_Reserved_BufferIO_0(void *) { return B_ERROR; }
|
status_t BBufferIO::_Reserved_BufferIO_0(void*) { return B_ERROR; }
|
||||||
status_t BBufferIO::_Reserved_BufferIO_1(void *) { return B_ERROR; }
|
status_t BBufferIO::_Reserved_BufferIO_1(void*) { return B_ERROR; }
|
||||||
status_t BBufferIO::_Reserved_BufferIO_2(void *) { return B_ERROR; }
|
status_t BBufferIO::_Reserved_BufferIO_2(void*) { return B_ERROR; }
|
||||||
status_t BBufferIO::_Reserved_BufferIO_3(void *) { return B_ERROR; }
|
status_t BBufferIO::_Reserved_BufferIO_3(void*) { return B_ERROR; }
|
||||||
status_t BBufferIO::_Reserved_BufferIO_4(void *) { return B_ERROR; }
|
status_t BBufferIO::_Reserved_BufferIO_4(void*) { return B_ERROR; }
|
||||||
|
|||||||
Reference in New Issue
Block a user