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:
Dario Casalinuovo 2016-06-22 21:33:22 +02:00
parent ad89985e7e
commit 6903cf9bda
2 changed files with 96 additions and 67 deletions

View File

@ -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;

View File

@ -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;
// This is an endless stream, we don't know off_t size = 0;
// how much data will come and when, we could if (fOwner->GetSize(&size) != B_OK)
// block on that.
if (fTotalSize == 0)
return B_WOULD_BLOCK;
if (position >= fTotalSize)
return B_ERROR; return B_ERROR;
off_t size = 0; if (position > size) {
fBuffer->GetSize(&size); // This is an endless stream, we don't know
if (position >= size) // how much data will come and when, we could
// block on that.
if (IsMutable())
return B_WOULD_BLOCK;
else
return B_ERROR;
}
off_t bufSize = 0;
if (GetSize(&bufSize) != B_OK)
return B_ERROR;
if (position > bufSize)
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;
} }
off_t fStartOffset; BAdapterIO* fOwner;
off_t fTotalSize; off_t fBackPosition;
off_t fStartOffset;
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)
{ {