190 #define __FBUF64_ASSERT(expr, panicCode) void(0) |
190 #define __FBUF64_ASSERT(expr, panicCode) void(0) |
191 |
191 |
192 #endif//_DEBUG |
192 #endif//_DEBUG |
193 |
193 |
194 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
194 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
195 /////////////////////////// MFileInitializer64 ///////////////////////////////////////////////////////////// |
|
196 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
197 |
|
198 /** |
|
199 MFileInitializer64 interface provides only one abstract method - Init() that is used during the initialization of |
|
200 the RFileBuf64 objects. |
|
201 Here is what is the problem MFileInitializer64 tries to solve. |
|
202 RFileBuf64 has 4 different "resource acquisition" methods - Create(), Open(), Temp() and AdoptFromClient(). |
|
203 They perform different actions and have different input arguments. |
|
204 This is the variable part of the RFileBuf64 initialization. |
|
205 Apart from that, RFileBuf64 has a "fixed" initialization part that does not change whatever the variable part is. |
|
206 If MFileInitializer64 interface is not used then the following chunk of code has to be duplicated 4 times: |
|
207 @code |
|
208 TInt err = do_fixed_init(); |
|
209 if(err == KErrNone) |
|
210 { |
|
211 err = do_variable_init(); |
|
212 if(err != KErrNone) |
|
213 { |
|
214 revert_fixed_init(); |
|
215 } |
|
216 } |
|
217 return err; |
|
218 @endcode |
|
219 In order to avoid the code duplication, the fixed part of the initialization is moved to RFileBuf64::DoInit(), which |
|
220 is given a reference to a MFileInitializer64 derived class that performas the variable part of the initialization. |
|
221 4 different MFileInitializer64 derived classes are provided for the 4 different "resource acquisition" methods. |
|
222 All they store the variable part of the RFileBuf64 initialization parameters and implement MFileInitializer64::Init(). |
|
223 |
|
224 @see RFileBuf64::DoInit() |
|
225 @internalComponent |
|
226 */ |
|
227 struct MFileInitializer64 |
|
228 { |
|
229 virtual TInt Init(RFile64& aFile) = 0; |
|
230 }; |
|
231 |
|
232 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
233 /////////////////////////// RFileBuf64 ///////////////////////////////////////////////////////////////////// |
195 /////////////////////////// RFileBuf64 ///////////////////////////////////////////////////////////////////// |
234 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
196 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
235 |
197 |
236 /** |
198 /** |
237 Initializes RFileBuf64 data members with their default values. |
199 Initializes RFileBuf64 data members with their default values. |
260 |
222 |
261 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
223 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
262 |
224 |
263 @see TFileMode |
225 @see TFileMode |
264 @see RFile64::Create() |
226 @see RFile64::Create() |
265 @see MFileInitializer64 |
|
266 |
227 |
267 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
228 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
268 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
229 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
269 */ |
230 */ |
270 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
231 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
271 { |
232 { |
272 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
233 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
273 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
234 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
274 |
235 |
275 struct TFileCreateInitializer64 : public MFileInitializer64 |
236 TInt err = DoPreInit(); |
276 { |
237 if(err == KErrNone) |
277 inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
238 { |
278 iFs(aFs), |
239 err = iFile.Create(aFs, aFileName, aFileMode); |
279 iFileName(aFileName), |
240 } |
280 iFileMode(aFileMode) |
241 return DoPostInit(err); |
281 { |
|
282 } |
|
283 virtual TInt Init(RFile64& aFile) |
|
284 { |
|
285 return aFile.Create(iFs, iFileName, iFileMode); |
|
286 } |
|
287 RFs& iFs; |
|
288 const TDesC& iFileName; |
|
289 TUint iFileMode; |
|
290 } initializer(aFs, aFileName, aFileMode); |
|
291 |
|
292 return DoInit(initializer); |
|
293 } |
242 } |
294 |
243 |
295 /** |
244 /** |
296 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface. |
245 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface. |
297 If the file does not already exist, an error is returned. |
246 If the file does not already exist, an error is returned. |
304 |
253 |
305 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
254 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
306 |
255 |
307 @see TFileMode |
256 @see TFileMode |
308 @see RFile64::Open() |
257 @see RFile64::Open() |
309 @see MFileInitializer64 |
|
310 |
258 |
311 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
259 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
312 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
260 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
313 */ |
261 */ |
314 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
262 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
315 { |
263 { |
316 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
264 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
317 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
265 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
318 |
266 |
319 struct TFileOpenInitializer64 : public MFileInitializer64 |
267 TInt err = DoPreInit(); |
320 { |
268 if(err == KErrNone) |
321 inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
269 { |
322 iFs(aFs), |
270 err = iFile.Open(aFs, aFileName, aFileMode); |
323 iFileName(aFileName), |
271 } |
324 iFileMode(aFileMode) |
272 return DoPostInit(err); |
325 { |
|
326 } |
|
327 virtual TInt Init(RFile64& aFile) |
|
328 { |
|
329 return aFile.Open(iFs, iFileName, iFileMode); |
|
330 } |
|
331 RFs& iFs; |
|
332 const TDesC& iFileName; |
|
333 TUint iFileMode; |
|
334 } initializer(aFs, aFileName, aFileMode); |
|
335 |
|
336 return DoInit(initializer); |
|
337 } |
273 } |
338 |
274 |
339 /** |
275 /** |
340 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through |
276 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through |
341 RFileBuf64 public interface. |
277 RFileBuf64 public interface. |
350 |
286 |
351 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
287 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
352 |
288 |
353 @see TFileMode |
289 @see TFileMode |
354 @see RFile64::Temp() |
290 @see RFile64::Temp() |
355 @see MFileInitializer64 |
|
356 |
291 |
357 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
292 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
358 */ |
293 */ |
359 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) |
294 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) |
360 { |
295 { |
361 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
296 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
362 |
297 |
363 struct TFileTempInitializer64 : public MFileInitializer64 |
298 TInt err = DoPreInit(); |
364 { |
299 if(err == KErrNone) |
365 inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) : |
300 { |
366 iFs(aFs), |
301 err = iFile.Temp(aFs, aPath, aFileName, aFileMode); |
367 iPath(aPath), |
302 } |
368 iFileName(aFileName), |
303 return DoPostInit(err); |
369 iFileMode(aFileMode) |
|
370 { |
|
371 } |
|
372 virtual TInt Init(RFile64& aFile) |
|
373 { |
|
374 return aFile.Temp(iFs, iPath, iFileName, iFileMode); |
|
375 } |
|
376 RFs& iFs; |
|
377 const TDesC& iPath; |
|
378 TFileName& iFileName; |
|
379 TUint iFileMode; |
|
380 } initializer(aFs, aPath, aFileName, aFileMode); |
|
381 |
|
382 return DoInit(initializer); |
|
383 } |
304 } |
384 |
305 |
385 /** |
306 /** |
386 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through |
307 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through |
387 RFileBuf64 public interface. |
308 RFileBuf64 public interface. |
396 |
317 |
397 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
318 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
398 |
319 |
399 @see TFileMode |
320 @see TFileMode |
400 @see RFile64::AdoptFromClient() |
321 @see RFile64::AdoptFromClient() |
401 @see MFileInitializer64 |
|
402 @see KMaxMessageArguments |
322 @see KMaxMessageArguments |
403 |
323 |
404 @panic FBuf64 8 In _DEBUG mode - Invalid aMsg object (null message handle). |
324 @panic FBuf64 8 In _DEBUG mode - Invalid aMsg object (null message handle). |
405 @panic FBuf64 9 In _DEBUG mode - Invalid file session handle message slot index or invalid file handle message slot index. |
325 @panic FBuf64 9 In _DEBUG mode - Invalid file session handle message slot index or invalid file handle message slot index. |
406 (Probably negative index or index bigger or equal to KMaxMessageArguments) |
326 (Probably negative index or index bigger or equal to KMaxMessageArguments) |
409 { |
329 { |
410 __FBUF64_ASSERT(aMsg.Handle() != 0, EFBufPanicMsgHandle); |
330 __FBUF64_ASSERT(aMsg.Handle() != 0, EFBufPanicMsgHandle); |
411 __FBUF64_ASSERT(aFsIndex >= 0 && aFsIndex < KMaxMessageArguments, EFBufPanicMsgIndex); |
331 __FBUF64_ASSERT(aFsIndex >= 0 && aFsIndex < KMaxMessageArguments, EFBufPanicMsgIndex); |
412 __FBUF64_ASSERT(aFileIndex >= 0 && aFileIndex < KMaxMessageArguments, EFBufPanicMsgIndex); |
332 __FBUF64_ASSERT(aFileIndex >= 0 && aFileIndex < KMaxMessageArguments, EFBufPanicMsgIndex); |
413 |
333 |
414 struct TFileAdoptInitializer64 : public MFileInitializer64 |
334 TInt err = DoPreInit(); |
415 { |
335 if(err == KErrNone) |
416 inline TFileAdoptInitializer64(const RMessage2& aMsg, TInt aFsIndex, TInt aFileIndex) : |
336 { |
417 iMsg(aMsg), |
337 err = iFile.AdoptFromClient(aMsg, aFsIndex, aFileIndex); |
418 iFsIndex(aFsIndex), |
338 } |
419 iFileIndex(aFileIndex) |
339 return DoPostInit(err); |
420 { |
|
421 } |
|
422 virtual TInt Init(RFile64& aFile) |
|
423 { |
|
424 return aFile.AdoptFromClient(iMsg, iFsIndex, iFileIndex); |
|
425 } |
|
426 const RMessage2& iMsg; |
|
427 TInt iFsIndex; |
|
428 TInt iFileIndex; |
|
429 } initializer(aMsg, aFsIndex, aFileIndex); |
|
430 |
|
431 return DoInit(initializer); |
|
432 } |
340 } |
433 |
341 |
434 /** |
342 /** |
435 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases |
343 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases |
436 the RFileBuf64 resources. |
344 the RFileBuf64 resources. |
450 iBase = 0; |
358 iBase = 0; |
451 } |
359 } |
452 |
360 |
453 /** |
361 /** |
454 Calculates and sets optimal read-ahead buffer size. |
362 Calculates and sets optimal read-ahead buffer size. |
|
363 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system. |
|
364 |
|
365 Initialization rules: |
|
366 Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and |
|
367 a power of two then the read-ahead value will be |
|
368 initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise |
|
369 the buffer capacity will be used as a read-ahead value). |
|
370 Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize. |
|
371 If aBlockSize passes the checks then it will be used as a read-ahead value. |
|
372 |
455 |
373 |
456 @param aBlockSize The size of a file block in bytes |
374 @param aBlockSize The size of a file block in bytes |
457 @param aReadRecBufSize The recommended buffer size for optimised reading performance |
375 @param aReadRecBufSize The recommended buffer size for optimised reading performance |
458 |
376 |
459 @return The new read-ahead value |
377 @return The new read-ahead value |
514 } |
432 } |
515 //3. Too big "read" request - read directly from the file |
433 //3. Too big "read" request - read directly from the file |
516 TInt len = aDes.MaxLength(); |
434 TInt len = aDes.MaxLength(); |
517 if(len > iCapacity) |
435 if(len > iCapacity) |
518 { |
436 { |
519 if((aFilePos + len) > iFilePos && !(aFilePos >= (iFilePos + iLength))) |
437 if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength)) |
520 {//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
438 {//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
521 err = DoFileWrite1(aFilePos); |
439 err = DoFileWrite1(aFilePos); |
522 } |
440 } |
523 if(err == KErrNone) |
441 if(err == KErrNone) |
524 { |
442 { |
530 } |
448 } |
531 //4. The requested data size is smaller than the buffer capacity |
449 //4. The requested data size is smaller than the buffer capacity |
532 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr()); |
450 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr()); |
533 while(len > 0 && err == KErrNone && aFilePos < iFileSize) |
451 while(len > 0 && err == KErrNone && aFilePos < iFileSize) |
534 { |
452 { |
535 //1. If part of all of the data is in the buffer - copy the data to the target location |
453 //1. If part or all of the data is in the buffer - copy the data to the target location |
536 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength)) |
454 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength)) |
537 { |
455 { |
538 TInt l = Min(len, (iFilePos + iLength - aFilePos)); |
456 TInt blocklen = Min(len, (iFilePos + iLength - aFilePos)); |
539 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l); |
457 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen); |
540 len -= l; |
458 len -= blocklen; |
541 aFilePos += l; |
459 aFilePos += blocklen; |
542 } |
460 } |
543 //2. Perform a read-ahead operation |
461 //2. Perform a read-ahead operation |
544 else |
462 else |
545 { |
463 { |
546 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
464 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
548 if(err != KErrNone) |
466 if(err != KErrNone) |
549 { |
467 { |
550 break; |
468 break; |
551 } |
469 } |
552 if(iNextReadFilePos != aFilePos) |
470 if(iNextReadFilePos != aFilePos) |
553 {//Direct "file read" operation |
471 {//Guessed read ahead was wrong. Direct "file read" operation |
554 iNextReadFilePosHits = 0; |
472 iNextReadFilePosHits = 0; |
555 TPtr8 ptr2(outptr, len); |
473 TPtr8 ptr2(outptr, len); |
556 err = iFile.Read(aFilePos, ptr2); |
474 err = iFile.Read(aFilePos, ptr2); |
557 PROFILE_READ(aFilePos, ptr2.Size()); |
475 PROFILE_READ(aFilePos, ptr2.Size()); |
558 if(err == KErrNone) |
476 if(err == KErrNone) |
802 __FILEBUF64_INVARIANT(); |
720 __FILEBUF64_INVARIANT(); |
803 return iFile.Drive(aDriveNumber, aDriveInfo); |
721 return iFile.Drive(aDriveNumber, aDriveInfo); |
804 } |
722 } |
805 |
723 |
806 /** |
724 /** |
807 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform |
725 Initializes RFileBuf64 data members with their initial values. |
808 the variable part of the initialization. |
726 Allocates memory for the file buffer. |
809 |
727 |
810 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init() |
728 @return KErrNone if successful, |
811 |
729 KErrNoMemory out of memory; |
812 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
730 */ |
813 */ |
731 TInt RFileBuf64::DoPreInit() |
814 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer) |
732 { |
815 { |
733 DoDiscard(); |
816 DoDiscard(); |
734 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize; |
817 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize; |
735 iBase = static_cast <TUint8*> (User::Alloc(iCapacity)); |
818 TInt err = KErrNoMemory; |
736 return iBase ? KErrNone : KErrNoMemory; |
819 iBase = static_cast <TUint8*> (User::Alloc(iCapacity)); |
737 } |
820 if(!iBase) |
738 |
821 { |
739 /** |
822 return KErrNoMemory; |
740 Performs post-initialization of the RFileBuf64 object. |
823 } |
741 If aInitErr is not KErrNone, then the buffer memory will be released. |
824 err = aFileInitializer.Init(iFile); |
742 The function returns the aInitErr value to the caller. |
825 if(err != KErrNone) |
743 |
826 { |
744 @param aInitErr The result of the performed before the call RFileBuf64 initialization. |
827 User::Free(iBase); |
745 |
828 iBase = 0; |
746 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
829 } |
747 */ |
830 return err; |
748 TInt RFileBuf64::DoPostInit(TInt aInitErr) |
831 } |
749 { |
|
750 if(aInitErr != KErrNone) |
|
751 { |
|
752 User::Free(iBase); |
|
753 iBase = 0; |
|
754 } |
|
755 return aInitErr; |
|
756 } |
832 |
757 |
833 /** |
758 /** |
834 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. |
759 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. |
835 */ |
760 */ |
836 void RFileBuf64::DoDiscard() |
761 void RFileBuf64::DoDiscard() |