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