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;
|
||||
bigtime_t fTimeout;
|
||||
|
||||
off_t fBackPosition;
|
||||
mutable RWLocker fLock;
|
||||
|
||||
RelativePositionIO* fBuffer;
|
||||
off_t fTotalSize;
|
||||
|
||||
BInputAdapter* fInputAdapter;
|
||||
|
||||
|
@ -14,36 +14,31 @@
|
||||
class RelativePositionIO : public BPositionIO
|
||||
{
|
||||
public:
|
||||
RelativePositionIO(BPositionIO* buffer)
|
||||
RelativePositionIO(BAdapterIO* owner, BPositionIO* buffer)
|
||||
:
|
||||
BPositionIO(),
|
||||
fOwner(owner),
|
||||
fBackPosition(0),
|
||||
fStartOffset(0),
|
||||
fTotalSize(0),
|
||||
fBuffer(buffer)
|
||||
{}
|
||||
{
|
||||
fOwner->GetFlags(&fFlags);
|
||||
}
|
||||
|
||||
virtual ~RelativePositionIO()
|
||||
{
|
||||
delete fBuffer;
|
||||
}
|
||||
|
||||
void SetTotalSize(size_t size)
|
||||
{
|
||||
fTotalSize = size;
|
||||
}
|
||||
|
||||
size_t TotalSize() const
|
||||
{
|
||||
return fTotalSize;
|
||||
}
|
||||
|
||||
status_t ResetStartOffset(off_t offset)
|
||||
{
|
||||
status_t ret = fBuffer->SetSize(0);
|
||||
if (ret == B_OK)
|
||||
fStartOffset = offset;
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
fBackPosition = offset;
|
||||
fStartOffset = offset;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t EvaluatePosition(off_t position)
|
||||
@ -54,18 +49,25 @@ public:
|
||||
if (position < fStartOffset)
|
||||
return B_RESOURCE_UNAVAILABLE;
|
||||
|
||||
// This is an endless stream, we don't know
|
||||
// how much data will come and when, we could
|
||||
// block on that.
|
||||
if (fTotalSize == 0)
|
||||
return B_WOULD_BLOCK;
|
||||
|
||||
if (position >= fTotalSize)
|
||||
off_t size = 0;
|
||||
if (fOwner->GetSize(&size) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
off_t size = 0;
|
||||
fBuffer->GetSize(&size);
|
||||
if (position >= size)
|
||||
if (position > size) {
|
||||
// This is an endless stream, we don't know
|
||||
// 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_OK;
|
||||
@ -74,15 +76,13 @@ public:
|
||||
status_t WaitForData(off_t position)
|
||||
{
|
||||
off_t bufferSize = 0;
|
||||
position = _PositionToRelative(position);
|
||||
|
||||
status_t ret = fBuffer->GetSize(&bufferSize);
|
||||
status_t ret = GetSize(&bufferSize);
|
||||
if (ret != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
while(bufferSize < position) {
|
||||
snooze(100000);
|
||||
fBuffer->GetSize(&bufferSize);
|
||||
GetSize(&bufferSize);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
@ -90,6 +90,8 @@ public:
|
||||
virtual ssize_t ReadAt(off_t position, void* buffer,
|
||||
size_t size)
|
||||
{
|
||||
AutoReadLocker _(fLock);
|
||||
|
||||
return fBuffer->ReadAt(
|
||||
_PositionToRelative(position), buffer, size);
|
||||
|
||||
@ -98,31 +100,36 @@ public:
|
||||
virtual ssize_t WriteAt(off_t position,
|
||||
const void* buffer, size_t size)
|
||||
{
|
||||
AutoWriteLocker _(fLock);
|
||||
|
||||
return fBuffer->WriteAt(
|
||||
_PositionToRelative(position), buffer, size);
|
||||
}
|
||||
|
||||
virtual off_t Seek(off_t position, uint32 seekMode)
|
||||
{
|
||||
AutoWriteLocker _(fLock);
|
||||
|
||||
return fBuffer->Seek(_PositionToRelative(position), seekMode);
|
||||
}
|
||||
|
||||
virtual off_t Position() const
|
||||
{
|
||||
AutoReadLocker _(fLock);
|
||||
|
||||
return _RelativeToPosition(fBuffer->Position());
|
||||
}
|
||||
|
||||
virtual status_t SetSize(off_t size)
|
||||
{
|
||||
AutoWriteLocker _(fLock);
|
||||
|
||||
return fBuffer->SetSize(_PositionToRelative(size));
|
||||
}
|
||||
|
||||
virtual status_t GetSize(off_t* size) const
|
||||
{
|
||||
if (fTotalSize > 0) {
|
||||
*size = fTotalSize;
|
||||
return B_OK;
|
||||
}
|
||||
AutoReadLocker _(fLock);
|
||||
|
||||
off_t bufferSize;
|
||||
status_t ret = fBuffer->GetSize(&bufferSize);
|
||||
@ -132,6 +139,31 @@ public:
|
||||
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:
|
||||
|
||||
off_t _PositionToRelative(off_t position) const
|
||||
@ -144,10 +176,14 @@ private:
|
||||
return position + fStartOffset;
|
||||
}
|
||||
|
||||
off_t fStartOffset;
|
||||
off_t fTotalSize;
|
||||
BAdapterIO* fOwner;
|
||||
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),
|
||||
fTimeout(timeout),
|
||||
fBackPosition(0),
|
||||
fBuffer(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)
|
||||
return ret;
|
||||
|
||||
AutoReadLocker _(fLock);
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
AutoWriteLocker _(fLock);
|
||||
|
||||
return fBuffer->WriteAt(position, buffer, size);
|
||||
}
|
||||
|
||||
@ -217,8 +248,6 @@ BAdapterIO::Seek(off_t position, uint32 seekMode)
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
|
||||
AutoWriteLocker _(fLock);
|
||||
|
||||
return fBuffer->Seek(position, seekMode);
|
||||
}
|
||||
|
||||
@ -226,8 +255,6 @@ BAdapterIO::Seek(off_t position, uint32 seekMode)
|
||||
off_t
|
||||
BAdapterIO::Position() const
|
||||
{
|
||||
AutoReadLocker _(fLock);
|
||||
|
||||
return fBuffer->Position();
|
||||
}
|
||||
|
||||
@ -235,7 +262,10 @@ BAdapterIO::Position() const
|
||||
status_t
|
||||
BAdapterIO::SetSize(off_t size)
|
||||
{
|
||||
AutoWriteLocker _(fLock);
|
||||
if (!fBuffer->IsMutable()) {
|
||||
fTotalSize = size;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return fBuffer->SetSize(size);
|
||||
}
|
||||
@ -244,19 +274,32 @@ BAdapterIO::SetSize(off_t size)
|
||||
status_t
|
||||
BAdapterIO::GetSize(off_t* size) const
|
||||
{
|
||||
AutoReadLocker _(fLock);
|
||||
if (!fBuffer->IsMutable()) {
|
||||
*size = fTotalSize;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return fBuffer->GetSize(size);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BAdapterIO::BackWrite(const void* buffer, size_t size)
|
||||
{
|
||||
return fBuffer->BackWrite(buffer, size);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BAdapterIO::_EvaluateWait(off_t pos)
|
||||
{
|
||||
status_t err = fBuffer->EvaluatePosition(pos);
|
||||
if (err == B_ERROR && err != B_WOULD_BLOCK)
|
||||
return B_ERROR;
|
||||
else if (err == B_RESOURCE_UNAVAILABLE) {
|
||||
|
||||
if (err != B_RESOURCE_UNAVAILABLE && err != B_OK)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
if (err == B_RESOURCE_UNAVAILABLE && fBuffer->IsStreaming()
|
||||
&& fBuffer->IsSeekable()) {
|
||||
if (SeekRequested(pos) != B_OK)
|
||||
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
|
||||
BAdapterIO::SeekRequested(off_t position)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user