blob: 74fa2c200954b73cbaf46d78f4dc1bf570553ad0 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*
* ============================================================================
* Name : oscl_async_file.h
* Part of : osclio
* Interface :
* Description :
* Version :
* ==============================================================================
*/
#ifndef OSCL_FILE_ASYNC_READ_H_INCLUDED
#define OSCL_FILE_ASYNC_READ_H_INCLUDED
#include "oscl_base.h"
#include "osclconfig_io.h"
#include "oscl_vector.h"
#include "oscl_mem.h"
#include "oscl_scheduler_ao.h"
#include "oscl_file_io.h"
#ifndef OSCL_SEMAPHORE_H_INCLUDED
#include "oscl_semaphore.h"
#endif
class OsclNativeFile;
//non-modifiable buffer pointer container
class OsclPtrC: public HeapBase
{
public:
OsclPtrC(const uint8* ptr, int32 len, int32 max): iPtr(ptr), iMaxLength(max), iLength(len)
{}
OsclPtrC(const OsclPtrC& d): HeapBase(d), iPtr(d.iPtr), iMaxLength(d.iMaxLength), iLength(d.iLength)
{}
const uint8* Ptr()
{
return iPtr;
}
void SetLength(int32 l)
{
OSCL_ASSERT(l <= iMaxLength);
iLength = l;
}
int32 Length()
{
return iLength;
}
void Zero()
{
iLength = 0;
}
void Set(OsclPtrC* v)
{
iPtr = v->iPtr;
iMaxLength = v->iMaxLength;
iLength = v->iLength;
}
void Set(uint8* ptr, int32 len, int32 max)
{
iPtr = ptr;
iLength = len;
iMaxLength = max;
}
//extract the right-most data
OsclPtrC Right(int32 size)
{
OSCL_ASSERT(iLength >= size);
OsclPtrC des(iPtr + iLength - size, size, size);
return des;
}
//extract the left-most data
OsclPtrC Left(int32 size)
{
OSCL_ASSERT(iLength >= size);
OsclPtrC des(iPtr, size, size);
return des;
}
private:
const uint8* iPtr;
int32 iMaxLength;
int32 iLength;
};
//modifiable buffer pointer container
class OsclPtr: public HeapBase
{
public:
OsclPtr(uint8* ptr, int32& len, int32 max): iPtr(ptr), iMaxLength(max), iLength(len)
{}
OsclPtr(const OsclPtr& d): HeapBase(d), iPtr(d.iPtr), iMaxLength(d.iMaxLength), iLength(d.iLength)
{}
uint8* Ptr()
{
return iPtr;
}
void SetLength(int32 l)
{
OSCL_ASSERT(l <= iMaxLength);
iLength = l;
}
int32 Length()
{
return iLength;
}
void Zero()
{
iLength = 0;
}
void Set(OsclPtr &v)
{
iPtr = v.iPtr;
iMaxLength = v.iMaxLength;
iLength = v.iLength;
}
void Set(uint8* ptr, int32 len, int32 max)
{
iPtr = ptr;
iLength = len;
iMaxLength = max;
}
void Append(OsclPtrC &v)
{
OSCL_ASSERT(iLength + v.Length() <= iMaxLength);
oscl_memmove(iPtr + iLength, v.Ptr(), v.Length());
iLength += v.Length();
}
private:
uint8* iPtr;
int32 iMaxLength;
int32& iLength;
};
//buffer container that allocates from the heap
class OsclBuf: public HeapBase
{
public:
static OsclBuf* NewL(int32 size)
{
OsclBuf* self = OSCL_NEW(OsclBuf, (size));
self->iBuffer = (uint8*)OSCL_MALLOC(self->iMaxLength);
if (!self->iBuffer)
{
OSCL_DELETE(self);
OsclError::Leave(OsclErrNoMemory);
}
return self;
}
static void Delete(OsclBuf* a)
{
if (a)
{
if (a->iBuffer)
OSCL_FREE(a->iBuffer);
OSCL_DELETE(a);
}
}
OsclBuf(int32 size): iBuffer(NULL), iMaxLength(size), iLength(0)
{}
int32 Length()
{
return iLength;
}
OsclPtr Des()
{
OsclPtr des(iBuffer, iLength, iMaxLength);
return des;
}
OsclPtrC DesC()
{
OsclPtrC des(iBuffer, iLength, iMaxLength);
return des;
}
uint8* iBuffer;
int32 iMaxLength;
int32 iLength;
};
/*!
** Buffer class used with async read. We keep an array of these, covering
** consecutive areas of the file. This allows for some seeking without requiring
** a full flush & refill each time.
*/
class OsclAsyncFileBuffer: public HeapBase
{
public:
static OsclAsyncFileBuffer* NewL(int32 aBufferSize, int32 aId);
~OsclAsyncFileBuffer();
public:
void CleanInUse()
{
iInUse = false;
}
void SetInUse()
{
iInUse = true;
}
bool IsInUse()
{
return iInUse;
}
bool IsValid()
{
return iValid;
}
int32 Offset()
{
return iOffset;
}
void SetOffset(int32 aOffset)
{
iOffset = aOffset;
}
int32 Length()
{
return iLength;
}
bool HasThisOffset(int32 aOffset);
int32 Id()
{
return iId;
}
OsclBuf* Buffer();
void UpdateData();
void StartAsyncRead(bool aStartAsyncRead);
private:
OsclAsyncFileBuffer(int32 aBufferSize, int32 aId);
void ConstructL();
private:
OsclBuf* iBuffer;
int32 iOffset;
bool iInUse;
int32 iLength;
bool iValid;
int32 iBufferSize;
int32 iId;
};
/**
* OsclAsyncFile
*/
class OsclAsyncFile : public OsclActiveObject
{
public:
/**
* Two-phased constructor.
*
* @param aAsyncFile: open handle for async file read.
* Note: it is the caller's job to open/close this file handle.
*
* @param aSyncFile: duplicate open handle for sync file read.
* Note: it is the caller's job to open this file handle, but this
* class will close the handle.
*
* @param aCacheSize: size of one of the individual cache buffers. The total
* cached data size will be larger, since multiple buffers are used.
*
* @param aStartAsyncRead: When true, async file read will start immediately.
* When false, read will not begin until StartAsyncRead is called.
*
*/
static OsclAsyncFile* NewL(OsclNativeFile& aAsyncFile, int32 aCacheSize, PVLogger*);
static void Delete(OsclAsyncFile*);
/**
* Destructor.
*/
~OsclAsyncFile();
private:
//From OsclActiveObject
void Run();
void DoCancel();
public:
////////////////////////
// File IO methods.
////////////////////////
int32 Open(const oscl_wchar *filename, uint32 mode
, const OsclNativeFileParams& params
, Oscl_FileServer& fileserv);
int32 Open(const char *filename, uint32 mode
, const OsclNativeFileParams& params
, Oscl_FileServer& fileserv);
int32 Seek(int32 offset, Oscl_File::seek_type origin);
int32 Tell();
uint32 Read(OsclAny* aBuffer1, uint32 aDataSize, uint32 aNumElements);
int32 EndOfFile();
int32 Size();
int32 Close();
uint32 Write(const OsclAny* aBuffer1, uint32 aDataSize, uint32 aNumElements)
{
OSCL_UNUSED_ARG(aBuffer1);
OSCL_UNUSED_ARG(aDataSize);
OSCL_UNUSED_ARG(aNumElements);
return 0;//not supported
}
uint32 Flush()
{
return ((uint32) - 1);//not supported
}
private:
OsclAsyncFile(OsclNativeFile& aAsyncFile, int32 aCacheSize, PVLogger*);
/**
* Second-phase constructor.
*/
void ConstructL();
private:
// private utility methods
void StartAsyncRead(bool aStartAsyncRead);
bool FindDataBuffer(OsclAsyncFileBuffer*& aDataBuffer, int32& aBufferId, int32 aOffset, int32 aSize);
void UpdateReading();
int32 BytesReadAhead(int32 aOffset);
int32 SortDataBuffers();
bool GetNextDataBuffer(OsclAsyncFileBuffer*& aDataBuffer, int32 aFilePointerToReadFrom);
void StartNextRead(int32 aPosToReadFrom);
void ReOrderBuffersQueue(int32 aOffset, int32 aFirstBufferId);
bool IsLinkedDataBuffer(OsclAsyncFileBuffer* aDataBuffer);
bool CanBeLinked(OsclAsyncFileBuffer* aDataBuffer);
uint32 doRead(uint8*& aBuffer1, uint32 aDataSize, uint32 aNumElements, int32 aOffset);
private:
int32 iFileSize;
// File object to do async read from
OsclNativeFile& iNativeFile;
// File position for async reads.
int32 iAsyncFilePosition;
// For verification
OsclNativeFile* iNativeFileVerify;
int32 iVerifyCount;
// Duplicate file handle for sync read
OsclNativeFile* iNativeFileDuplicate;
// File position for sync reads.
int32 iSyncFilePosition;
// Arrays of data buffers
Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iDataBufferArray;
Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iSortedDataBufferArray;
Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iLinkedDataBufferArray;
// Local data buffer
OsclAsyncFileBuffer* iDataBuffer;
OsclAsyncFileBuffer* iDataBufferInUse;
// Buffer for synchronous read
OsclBuf* iSyncBuffer;
// Initialized in constructor. Determines the size of each data buffer
uint32 iTotalCacheSize;
// Logical File Position (as seen by the client of this class)
int32 iFilePosition;
// Last offset after a user read operation
int32 iLastUserFileRead;
// Start async read enable flag
bool iStartAsyncRead;
// Pointer to buffer for asynchronous read
int32 iReadPtrDummyLen;
OsclPtr iReadPtr;
// For profiling
PVLogger* iLogger;
////////////////////////
// Configuration parameters.
////////////////////////
// Number of buffers in the linked list
int32 iKCacheBufferCount ;
// This defines the limit on how much data we will
// read ahead of the current position
int32 iKMinBytesReadAhead ;
// This defines the size of the individual async read operations.
int32 iKAsyncReadBufferSize ;
////////////////////////
// The non-native async read implementation.
////////////////////////
// Keeps track of whether we have native async read or not
bool iHasNativeAsyncRead;
// Thread control sems
OsclSemaphore iAsyncReadSem;
OsclSemaphore iAsyncReadExitSem;
// To keep track of the tread state:
// EAsyncReadNotActive - the thread is not created or the thread is stopped
// EAsyncReadActive - the thread is running
enum TAsyncReadThreadState {EAsyncReadNotActive, EAsyncReadActive};
TAsyncReadThreadState iAsyncReadThreadState;
// To signal the thread to exit
bool iAsyncReadThreadExitFlag;
// Number of bytes read in the last call
int32 iAsyncReadNumBytes;
// Thread routine
void InThread();
static TOsclThreadFuncRet OSCL_THREAD_DECL iAsyncReadThreadFunc(TOsclThreadFuncArg);
// Thread start/stop.
void LaunchAsyncReadThread();
void StopAsyncReadThread();
// Request an async read.
void StartNonNativeAsyncRead();
public:
// for test&stat
uint32 iNumOfRun;
uint32 iNumOfRunErr;
};
#endif