AdapterIO: Increase consistency
* Moved data locking in the internal buffer class, includes handling of backend writes. * Takes advantage of inheritance for getting the size. The choice is made depending on the flags. This allow the implementer to easily return a custom size by reimplementing GetSize. At the same time a plain BAdapterIO can still have it's total size set, but the behavior will change depending it's mutable or not. * Some decisions are now made by considering everything in absolute values. * Other minor fixes.
This commit is contained in:
parent
ad89985e7e
commit
6903cf9bda
@ -72,10 +72,8 @@ private:
|
|||||||
int32 fFlags;
|
int32 fFlags;
|
||||||
bigtime_t fTimeout;
|
bigtime_t fTimeout;
|
||||||
|
|
||||||
off_t fBackPosition;
|
|
||||||
mutable RWLocker fLock;
|
|
||||||
|
|
||||||
RelativePositionIO* fBuffer;
|
RelativePositionIO* fBuffer;
|
||||||
|
off_t fTotalSize;
|
||||||
|
|
||||||
BInputAdapter* fInputAdapter;
|
BInputAdapter* fInputAdapter;
|
||||||
|
|
||||||
|
@ -14,36 +14,31 @@
|
|||||||
class RelativePositionIO : public BPositionIO
|
class RelativePositionIO : public BPositionIO
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RelativePositionIO(BPositionIO* buffer)
|
RelativePositionIO(BAdapterIO* owner, BPositionIO* buffer)
|
||||||
:
|
:
|
||||||
BPositionIO(),
|
BPositionIO(),
|
||||||
|
fOwner(owner),
|
||||||
|
fBackPosition(0),
|
||||||
fStartOffset(0),
|
fStartOffset(0),
|
||||||
fTotalSize(0),
|
|
||||||
fBuffer(buffer)
|
fBuffer(buffer)
|
||||||
{}
|
{
|
||||||
|
fOwner->GetFlags(&fFlags);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~RelativePositionIO()
|
virtual ~RelativePositionIO()
|
||||||
{
|
{
|
||||||
delete fBuffer;
|
delete fBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTotalSize(size_t size)
|
|
||||||
{
|
|
||||||
fTotalSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t TotalSize() const
|
|
||||||
{
|
|
||||||
return fTotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t ResetStartOffset(off_t offset)
|
status_t ResetStartOffset(off_t offset)
|
||||||
{
|
{
|
||||||
status_t ret = fBuffer->SetSize(0);
|
status_t ret = fBuffer->SetSize(0);
|
||||||
if (ret == B_OK)
|
if (ret != B_OK)
|
||||||
fStartOffset = offset;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
fBackPosition = offset;
|
||||||
|
fStartOffset = offset;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t EvaluatePosition(off_t position)
|
status_t EvaluatePosition(off_t position)
|
||||||
@ -54,18 +49,25 @@ public:
|
|||||||
if (position < fStartOffset)
|
if (position < fStartOffset)
|
||||||
return B_RESOURCE_UNAVAILABLE;
|
return B_RESOURCE_UNAVAILABLE;
|
||||||
|
|
||||||
|
off_t size = 0;
|
||||||
|
if (fOwner->GetSize(&size) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (position > size) {
|
||||||
// This is an endless stream, we don't know
|
// This is an endless stream, we don't know
|
||||||
// how much data will come and when, we could
|
// how much data will come and when, we could
|
||||||
// block on that.
|
// block on that.
|
||||||
if (fTotalSize == 0)
|
if (IsMutable())
|
||||||
return B_WOULD_BLOCK;
|
return B_WOULD_BLOCK;
|
||||||
|
else
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (position >= fTotalSize)
|
off_t bufSize = 0;
|
||||||
|
if (GetSize(&bufSize) != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
off_t size = 0;
|
if (position > bufSize)
|
||||||
fBuffer->GetSize(&size);
|
|
||||||
if (position >= size)
|
|
||||||
return B_RESOURCE_UNAVAILABLE;
|
return B_RESOURCE_UNAVAILABLE;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@ -74,15 +76,13 @@ public:
|
|||||||
status_t WaitForData(off_t position)
|
status_t WaitForData(off_t position)
|
||||||
{
|
{
|
||||||
off_t bufferSize = 0;
|
off_t bufferSize = 0;
|
||||||
position = _PositionToRelative(position);
|
status_t ret = GetSize(&bufferSize);
|
||||||
|
|
||||||
status_t ret = fBuffer->GetSize(&bufferSize);
|
|
||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
while(bufferSize < position) {
|
while(bufferSize < position) {
|
||||||
snooze(100000);
|
snooze(100000);
|
||||||
fBuffer->GetSize(&bufferSize);
|
GetSize(&bufferSize);
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -90,6 +90,8 @@ public:
|
|||||||
virtual ssize_t ReadAt(off_t position, void* buffer,
|
virtual ssize_t ReadAt(off_t position, void* buffer,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
|
AutoReadLocker _(fLock);
|
||||||
|
|
||||||
return fBuffer->ReadAt(
|
return fBuffer->ReadAt(
|
||||||
_PositionToRelative(position), buffer, size);
|
_PositionToRelative(position), buffer, size);
|
||||||
|
|
||||||
@ -98,31 +100,36 @@ public:
|
|||||||
virtual ssize_t WriteAt(off_t position,
|
virtual ssize_t WriteAt(off_t position,
|
||||||
const void* buffer, size_t size)
|
const void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
|
AutoWriteLocker _(fLock);
|
||||||
|
|
||||||
return fBuffer->WriteAt(
|
return fBuffer->WriteAt(
|
||||||
_PositionToRelative(position), buffer, size);
|
_PositionToRelative(position), buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual off_t Seek(off_t position, uint32 seekMode)
|
virtual off_t Seek(off_t position, uint32 seekMode)
|
||||||
{
|
{
|
||||||
|
AutoWriteLocker _(fLock);
|
||||||
|
|
||||||
return fBuffer->Seek(_PositionToRelative(position), seekMode);
|
return fBuffer->Seek(_PositionToRelative(position), seekMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual off_t Position() const
|
virtual off_t Position() const
|
||||||
{
|
{
|
||||||
|
AutoReadLocker _(fLock);
|
||||||
|
|
||||||
return _RelativeToPosition(fBuffer->Position());
|
return _RelativeToPosition(fBuffer->Position());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t SetSize(off_t size)
|
virtual status_t SetSize(off_t size)
|
||||||
{
|
{
|
||||||
|
AutoWriteLocker _(fLock);
|
||||||
|
|
||||||
return fBuffer->SetSize(_PositionToRelative(size));
|
return fBuffer->SetSize(_PositionToRelative(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t GetSize(off_t* size) const
|
virtual status_t GetSize(off_t* size) const
|
||||||
{
|
{
|
||||||
if (fTotalSize > 0) {
|
AutoReadLocker _(fLock);
|
||||||
*size = fTotalSize;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t bufferSize;
|
off_t bufferSize;
|
||||||
status_t ret = fBuffer->GetSize(&bufferSize);
|
status_t ret = fBuffer->GetSize(&bufferSize);
|
||||||
@ -132,6 +139,31 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t BackWrite(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
AutoWriteLocker _(fLock);
|
||||||
|
|
||||||
|
off_t currentPos = Position();
|
||||||
|
off_t ret = fBuffer->WriteAt(fBackPosition, buffer, size);
|
||||||
|
fBackPosition += ret;
|
||||||
|
return fBuffer->Seek(currentPos, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsStreaming() const
|
||||||
|
{
|
||||||
|
return (fFlags & B_MEDIA_STREAMING) == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsMutable() const
|
||||||
|
{
|
||||||
|
return (fFlags & B_MEDIA_MUTABLE_SIZE) == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSeekable() const
|
||||||
|
{
|
||||||
|
return (fFlags & B_MEDIA_SEEKABLE) == true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
off_t _PositionToRelative(off_t position) const
|
off_t _PositionToRelative(off_t position) const
|
||||||
@ -144,10 +176,14 @@ private:
|
|||||||
return position + fStartOffset;
|
return position + fStartOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAdapterIO* fOwner;
|
||||||
|
off_t fBackPosition;
|
||||||
off_t fStartOffset;
|
off_t fStartOffset;
|
||||||
off_t fTotalSize;
|
|
||||||
|
|
||||||
BPositionIO* fBuffer;
|
BPositionIO* fBuffer;
|
||||||
|
int32 fFlags;
|
||||||
|
|
||||||
|
mutable RWLocker fLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -155,11 +191,10 @@ BAdapterIO::BAdapterIO(int32 flags, bigtime_t timeout)
|
|||||||
:
|
:
|
||||||
fFlags(flags),
|
fFlags(flags),
|
||||||
fTimeout(timeout),
|
fTimeout(timeout),
|
||||||
fBackPosition(0),
|
|
||||||
fBuffer(NULL),
|
fBuffer(NULL),
|
||||||
fInputAdapter(NULL)
|
fInputAdapter(NULL)
|
||||||
{
|
{
|
||||||
fBuffer = new RelativePositionIO(new BMallocIO());
|
fBuffer = new RelativePositionIO(this, new BMallocIO());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -191,8 +226,6 @@ BAdapterIO::ReadAt(off_t position, void* buffer, size_t size)
|
|||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
AutoReadLocker _(fLock);
|
|
||||||
|
|
||||||
return fBuffer->ReadAt(position, buffer, size);
|
return fBuffer->ReadAt(position, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,8 +237,6 @@ BAdapterIO::WriteAt(off_t position, const void* buffer, size_t size)
|
|||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
AutoWriteLocker _(fLock);
|
|
||||||
|
|
||||||
return fBuffer->WriteAt(position, buffer, size);
|
return fBuffer->WriteAt(position, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +248,6 @@ BAdapterIO::Seek(off_t position, uint32 seekMode)
|
|||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
AutoWriteLocker _(fLock);
|
|
||||||
|
|
||||||
return fBuffer->Seek(position, seekMode);
|
return fBuffer->Seek(position, seekMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,8 +255,6 @@ BAdapterIO::Seek(off_t position, uint32 seekMode)
|
|||||||
off_t
|
off_t
|
||||||
BAdapterIO::Position() const
|
BAdapterIO::Position() const
|
||||||
{
|
{
|
||||||
AutoReadLocker _(fLock);
|
|
||||||
|
|
||||||
return fBuffer->Position();
|
return fBuffer->Position();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +262,10 @@ BAdapterIO::Position() const
|
|||||||
status_t
|
status_t
|
||||||
BAdapterIO::SetSize(off_t size)
|
BAdapterIO::SetSize(off_t size)
|
||||||
{
|
{
|
||||||
AutoWriteLocker _(fLock);
|
if (!fBuffer->IsMutable()) {
|
||||||
|
fTotalSize = size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return fBuffer->SetSize(size);
|
return fBuffer->SetSize(size);
|
||||||
}
|
}
|
||||||
@ -244,19 +274,32 @@ BAdapterIO::SetSize(off_t size)
|
|||||||
status_t
|
status_t
|
||||||
BAdapterIO::GetSize(off_t* size) const
|
BAdapterIO::GetSize(off_t* size) const
|
||||||
{
|
{
|
||||||
AutoReadLocker _(fLock);
|
if (!fBuffer->IsMutable()) {
|
||||||
|
*size = fTotalSize;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return fBuffer->GetSize(size);
|
return fBuffer->GetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
BAdapterIO::BackWrite(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
return fBuffer->BackWrite(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BAdapterIO::_EvaluateWait(off_t pos)
|
BAdapterIO::_EvaluateWait(off_t pos)
|
||||||
{
|
{
|
||||||
status_t err = fBuffer->EvaluatePosition(pos);
|
status_t err = fBuffer->EvaluatePosition(pos);
|
||||||
if (err == B_ERROR && err != B_WOULD_BLOCK)
|
|
||||||
return B_ERROR;
|
if (err != B_RESOURCE_UNAVAILABLE && err != B_OK)
|
||||||
else if (err == B_RESOURCE_UNAVAILABLE) {
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (err == B_RESOURCE_UNAVAILABLE && fBuffer->IsStreaming()
|
||||||
|
&& fBuffer->IsSeekable()) {
|
||||||
if (SeekRequested(pos) != B_OK)
|
if (SeekRequested(pos) != B_OK)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
@ -276,18 +319,6 @@ BAdapterIO::BuildInputAdapter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
BAdapterIO::BackWrite(const void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
AutoWriteLocker _(fLock);
|
|
||||||
|
|
||||||
off_t currentPos = Position();
|
|
||||||
off_t ret = fBuffer->WriteAt(fBackPosition, buffer, size);
|
|
||||||
fBackPosition += ret;
|
|
||||||
return fBuffer->Seek(currentPos, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BAdapterIO::SeekRequested(off_t position)
|
BAdapterIO::SeekRequested(off_t position)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user