• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /*
19 * ============================================================================
20 *  Name        : oscl_async_file.h
21 *  Part of     : osclio
22 *  Interface   :
23 *  Description :
24 *  Version     :
25 * ==============================================================================
26 */
27 
28 #ifndef OSCL_FILE_ASYNC_READ_H_INCLUDED
29 #define OSCL_FILE_ASYNC_READ_H_INCLUDED
30 
31 
32 #include "oscl_base.h"
33 #include "osclconfig_io.h"
34 #include "oscl_vector.h"
35 #include "oscl_mem.h"
36 #include "oscl_scheduler_ao.h"
37 #include "oscl_file_io.h"
38 
39 #ifndef OSCL_SEMAPHORE_H_INCLUDED
40 #include "oscl_semaphore.h"
41 #endif
42 
43 class OsclNativeFile;
44 
45 //non-modifiable buffer pointer container
46 class OsclPtrC: public HeapBase
47 {
48     public:
OsclPtrC(const uint8 * ptr,int32 len,int32 max)49         OsclPtrC(const uint8* ptr, int32 len, int32 max): iPtr(ptr), iMaxLength(max), iLength(len)
50         {}
OsclPtrC(const OsclPtrC & d)51         OsclPtrC(const OsclPtrC& d): HeapBase(d), iPtr(d.iPtr), iMaxLength(d.iMaxLength), iLength(d.iLength)
52         {}
Ptr()53         const uint8* Ptr()
54         {
55             return iPtr;
56         }
SetLength(int32 l)57         void SetLength(int32 l)
58         {
59             OSCL_ASSERT(l <= iMaxLength);
60             iLength = l;
61         }
Length()62         int32 Length()
63         {
64             return iLength;
65         }
Zero()66         void Zero()
67         {
68             iLength = 0;
69         }
Set(OsclPtrC * v)70         void Set(OsclPtrC* v)
71         {
72             iPtr = v->iPtr;
73             iMaxLength = v->iMaxLength;
74             iLength = v->iLength;
75         }
Set(uint8 * ptr,int32 len,int32 max)76         void Set(uint8* ptr, int32 len, int32 max)
77         {
78             iPtr = ptr;
79             iLength = len;
80             iMaxLength = max;
81         }
82         //extract the right-most data
Right(int32 size)83         OsclPtrC Right(int32 size)
84         {
85             OSCL_ASSERT(iLength >= size);
86             OsclPtrC des(iPtr + iLength - size, size, size);
87             return des;
88         }
89         //extract the left-most data
Left(int32 size)90         OsclPtrC Left(int32 size)
91         {
92             OSCL_ASSERT(iLength >= size);
93             OsclPtrC des(iPtr, size, size);
94             return des;
95         }
96     private:
97         const uint8* iPtr;
98         int32 iMaxLength;
99         int32 iLength;
100 };
101 
102 //modifiable buffer pointer container
103 class OsclPtr: public HeapBase
104 {
105     public:
OsclPtr(uint8 * ptr,int32 & len,int32 max)106         OsclPtr(uint8* ptr, int32& len, int32 max): iPtr(ptr), iMaxLength(max), iLength(len)
107         {}
OsclPtr(const OsclPtr & d)108         OsclPtr(const OsclPtr& d): HeapBase(d), iPtr(d.iPtr), iMaxLength(d.iMaxLength), iLength(d.iLength)
109         {}
Ptr()110         uint8* Ptr()
111         {
112             return iPtr;
113         }
SetLength(int32 l)114         void SetLength(int32 l)
115         {
116             OSCL_ASSERT(l <= iMaxLength);
117             iLength = l;
118         }
Length()119         int32 Length()
120         {
121             return iLength;
122         }
Zero()123         void Zero()
124         {
125             iLength = 0;
126         }
Set(OsclPtr & v)127         void Set(OsclPtr &v)
128         {
129             iPtr = v.iPtr;
130             iMaxLength = v.iMaxLength;
131             iLength = v.iLength;
132         }
Set(uint8 * ptr,int32 len,int32 max)133         void Set(uint8* ptr, int32 len, int32 max)
134         {
135             iPtr = ptr;
136             iLength = len;
137             iMaxLength = max;
138         }
Append(OsclPtrC & v)139         void Append(OsclPtrC &v)
140         {
141             OSCL_ASSERT(iLength + v.Length() <= iMaxLength);
142             oscl_memmove(iPtr + iLength, v.Ptr(), v.Length());
143             iLength += v.Length();
144         }
145     private:
146         uint8* iPtr;
147         int32 iMaxLength;
148         int32& iLength;
149 };
150 
151 //buffer container that allocates from the heap
152 class OsclBuf: public HeapBase
153 {
154     public:
NewL(int32 size)155         static OsclBuf* NewL(int32 size)
156         {
157             OsclBuf* self = OSCL_NEW(OsclBuf, (size));
158             self->iBuffer = (uint8*)OSCL_MALLOC(self->iMaxLength);
159             if (!self->iBuffer)
160             {
161                 OSCL_DELETE(self);
162                 OsclError::Leave(OsclErrNoMemory);
163             }
164             return self;
165         }
166 
Delete(OsclBuf * a)167         static void Delete(OsclBuf* a)
168         {
169             if (a)
170             {
171                 if (a->iBuffer)
172                     OSCL_FREE(a->iBuffer);
173                 OSCL_DELETE(a);
174             }
175         }
176 
OsclBuf(int32 size)177         OsclBuf(int32 size): iBuffer(NULL), iMaxLength(size), iLength(0)
178         {}
179 
Length()180         int32 Length()
181         {
182             return iLength;
183         }
184 
Des()185         OsclPtr Des()
186         {
187             OsclPtr des(iBuffer, iLength, iMaxLength);
188             return des;
189         }
DesC()190         OsclPtrC DesC()
191         {
192             OsclPtrC des(iBuffer, iLength, iMaxLength);
193             return des;
194         }
195 
196         uint8* iBuffer;
197         int32 iMaxLength;
198         int32 iLength;
199 };
200 
201 
202 /*!
203 ** Buffer class used with async read.  We keep an array of these, covering
204 ** consecutive areas of the file.  This allows for some seeking without requiring
205 ** a full flush & refill each time.
206 */
207 class OsclAsyncFileBuffer: public HeapBase
208 {
209     public:
210         static OsclAsyncFileBuffer* NewL(int32 aBufferSize, int32 aId);
211         ~OsclAsyncFileBuffer();
212 
213     public:
CleanInUse()214         void CleanInUse()
215         {
216             iInUse = false;
217         }
SetInUse()218         void SetInUse()
219         {
220             iInUse = true;
221         }
IsInUse()222         bool IsInUse()
223         {
224             return iInUse;
225         }
IsValid()226         bool IsValid()
227         {
228             return iValid;
229         }
Offset()230         TOsclFileOffset Offset()
231         {
232             return iOffset;
233         }
SetOffset(TOsclFileOffset aOffset)234         void SetOffset(TOsclFileOffset aOffset)
235         {
236             iOffset = aOffset;
237         }
Length()238         int32 Length()
239         {
240             return iLength;
241         }
242         bool HasThisOffset(TOsclFileOffset aOffset);
Id()243         int32 Id()
244         {
245             return iId;
246         }
247         OsclBuf* Buffer();
248         void UpdateData();
249         void StartAsyncRead(bool aStartAsyncRead);
250 
251     private:
252         OsclAsyncFileBuffer(int32 aBufferSize, int32 aId);
253         void ConstructL();
254 
255     private:
256         OsclBuf* iBuffer;
257         TOsclFileOffset iOffset;
258         bool iInUse;
259         int32 iLength;
260         bool iValid;
261         int32 iBufferSize;
262         int32 iId;
263 };
264 
265 
266 /**
267 * OsclAsyncFile
268 */
269 class OsclAsyncFile : public OsclActiveObject
270 {
271     public:
272         /**
273         * Two-phased constructor.
274         *
275         * @param aAsyncFile: open handle for async file read.
276         *   Note: it is the caller's job to open/close this file handle.
277         *
278         * @param aSyncFile: duplicate open handle for sync file read.
279         *   Note: it is the caller's job to open this file handle, but this
280         *     class will close the handle.
281         *
282         * @param aCacheSize: size of one of the individual cache buffers.  The total
283         *    cached data size will be larger, since multiple buffers are used.
284         *
285         * @param aStartAsyncRead: When true, async file read will start immediately.
286         *     When false, read will not begin until StartAsyncRead is called.
287         *
288         */
289         static OsclAsyncFile* NewL(OsclNativeFile& aAsyncFile, int32 aCacheSize, PVLogger*);
290         static void Delete(OsclAsyncFile*);
291 
292         /**
293         * Destructor.
294         */
295         ~OsclAsyncFile();
296 
297     private:
298         //From OsclActiveObject
299         void Run();
300         void DoCancel();
301 
302     public:
303         ////////////////////////
304         // File IO methods.
305         ////////////////////////
306 
307         int32  Open(const oscl_wchar *filename, uint32 mode
308                     , const OsclNativeFileParams& params
309                     , Oscl_FileServer& fileserv);
310         int32  Open(const char *filename, uint32 mode
311                     , const OsclNativeFileParams& params
312                     , Oscl_FileServer& fileserv);
313 
314         int32 Seek(TOsclFileOffset offset, Oscl_File::seek_type origin);
315         TOsclFileOffset Tell();
316         uint32 Read(OsclAny* aBuffer1, uint32 aDataSize, uint32 aNumElements);
317         int32 EndOfFile();
318         TOsclFileOffset Size();
319         int32 Close();
320 
Write(const OsclAny * aBuffer1,uint32 aDataSize,uint32 aNumElements)321         uint32 Write(const OsclAny* aBuffer1, uint32 aDataSize, uint32 aNumElements)
322         {
323             OSCL_UNUSED_ARG(aBuffer1);
324             OSCL_UNUSED_ARG(aDataSize);
325             OSCL_UNUSED_ARG(aNumElements);
326             return 0;//not supported
327         }
Flush()328         uint32 Flush()
329         {
330             return ((uint32) - 1);//not supported
331         }
332 
333     private:
334         OsclAsyncFile(OsclNativeFile& aAsyncFile, int32 aCacheSize, PVLogger*);
335         /**
336         * Second-phase constructor.
337         */
338         void ConstructL();
339 
340     private:
341         // private utility methods
342         void StartAsyncRead(bool aStartAsyncRead);
343         bool FindDataBuffer(OsclAsyncFileBuffer*& aDataBuffer, int32& aBufferId, TOsclFileOffset aOffset, int32 aSize);
344         void UpdateReading();
345         int32 BytesReadAhead();
346         int32 SortDataBuffers();
347         bool GetNextDataBuffer(OsclAsyncFileBuffer*& aDataBuffer, TOsclFileOffset aFilePointerToReadFrom);
348         void StartNextRead(TOsclFileOffset aPosToReadFrom);
349         void ReOrderBuffersQueue(int32 aFirstBufferId);
350         bool IsLinkedDataBuffer(OsclAsyncFileBuffer* aDataBuffer);
351         bool CanBeLinked(OsclAsyncFileBuffer* aDataBuffer);
352         uint32 doRead(uint8*& aBuffer1, uint32 aDataSize, uint32 aNumElements, TOsclFileOffset aOffset);
353 
354     private:
355         TOsclFileOffset iFileSize;
356 
357         // File object to do async read from
358         OsclNativeFile& iNativeFile;
359 
360         // File position for async reads.
361         TOsclFileOffset iAsyncFilePosition;
362 
363         // For verification
364         OsclNativeFile* iNativeFileVerify;
365         int32 iVerifyCount;
366 
367         // Duplicate file handle for sync read
368         OsclNativeFile* iNativeFileDuplicate;
369 
370         // File position for sync reads.
371         TOsclFileOffset iSyncFilePosition;
372 
373         // Arrays of data buffers
374         Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iDataBufferArray;
375         Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iSortedDataBufferArray;
376         Oscl_Vector<OsclAsyncFileBuffer*, OsclMemAllocator> iLinkedDataBufferArray;
377 
378         // Local data buffer
379         OsclAsyncFileBuffer* iDataBuffer;
380         OsclAsyncFileBuffer* iDataBufferInUse;
381 
382         // Buffer for synchronous read
383         OsclBuf* iSyncBuffer;
384 
385         // Initialized in constructor. Determines the size of each data buffer
386         uint32 iTotalCacheSize;
387 
388         // Logical File Position (as seen by the client of this class)
389         TOsclFileOffset iFilePosition;
390 
391         // Last offset after a user read operation
392         TOsclFileOffset iLastUserFileRead;
393 
394         // Start async read enable flag
395         bool iStartAsyncRead;
396 
397         // Pointer to buffer for asynchronous read
398         int32 iReadPtrDummyLen;
399         OsclPtr iReadPtr;
400 
401         // For profiling
402         PVLogger* iLogger;
403 
404         ////////////////////////
405         // Configuration parameters.
406         ////////////////////////
407 
408         //   Number of buffers in the linked list
409         int32 iKCacheBufferCount ;
410 
411         //   This defines the limit on how much data we will
412         //   read ahead of the current position
413         int32 iKMinBytesReadAhead ;
414 
415         //   This defines the size of the individual async read operations.
416         int32 iKAsyncReadBufferSize ;
417 
418         ////////////////////////
419         // The non-native async read implementation.
420         ////////////////////////
421 
422         // Keeps track of whether we have native async read or not
423         bool iHasNativeAsyncRead;
424 
425         // Thread control sems
426         OsclSemaphore iAsyncReadSem;
427         OsclSemaphore iAsyncReadExitSem;
428 
429         // To keep track of the tread state:
430         // EAsyncReadNotActive - the thread is not created or the thread is stopped
431         // EAsyncReadActive    - the thread is running
432         enum TAsyncReadThreadState {EAsyncReadNotActive, EAsyncReadActive};
433         TAsyncReadThreadState iAsyncReadThreadState;
434 
435         // To signal the thread to exit
436         bool iAsyncReadThreadExitFlag;
437 
438         // Number of bytes read in the last call
439         int32 iAsyncReadNumBytes;
440 
441         // Thread routine
442         void InThread();
443         static TOsclThreadFuncRet OSCL_THREAD_DECL iAsyncReadThreadFunc(TOsclThreadFuncArg);
444 
445         // Thread start/stop.
446         void LaunchAsyncReadThread();
447         void StopAsyncReadThread();
448 
449         // Request an async read.
450         void StartNonNativeAsyncRead();
451 
452     public:
453         // for test&stat
454         uint32 iNumOfRun;
455         uint32 iNumOfRunErr;
456 };
457 
458 #endif
459 
460