184 #define __FBUF64_ASSERT(expr, panicCode) void(0) |
184 #define __FBUF64_ASSERT(expr, panicCode) void(0) |
185 |
185 |
186 #endif//_DEBUG |
186 #endif//_DEBUG |
187 |
187 |
188 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
188 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
189 /////////////////////////// MFileInitializer64 ///////////////////////////////////////////////////////////// |
|
190 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
191 |
|
192 /** |
|
193 MFileInitializer64 interface provides only one abstract method - Init() that is used during the initialization of |
|
194 the RFileBuf64 objects. |
|
195 Here is what is the problem MFileInitializer64 tries to solve. |
|
196 RFileBuf64 has 4 different "resource acquisition" methods - Create(), Open() and Temp(). |
|
197 They perform different actions and have different input arguments. |
|
198 This is the variable part of the RFileBuf64 initialization. |
|
199 Apart from that, RFileBuf64 has a "fixed" initialization part that does not change whatever the variable part is. |
|
200 If MFileInitializer64 interface is not used then the following chunk of code has to be duplicated 4 times: |
|
201 @code |
|
202 TInt err = do_fixed_init(); |
|
203 if(err == KErrNone) |
|
204 { |
|
205 err = do_variable_init(); |
|
206 if(err != KErrNone) |
|
207 { |
|
208 revert_fixed_init(); |
|
209 } |
|
210 } |
|
211 return err; |
|
212 @endcode |
|
213 In order to avoid the code duplication, the fixed part of the initialization is moved to RFileBuf64::DoInit(), which |
|
214 is given a reference to a MFileInitializer64 derived class that performas the variable part of the initialization. |
|
215 4 different MFileInitializer64 derived classes are provided for the 4 different "resource acquisition" methods. |
|
216 All they store the variable part of the RFileBuf64 initialization parameters and implement MFileInitializer64::Init(). |
|
217 |
|
218 @see RFileBuf64::DoInit() |
|
219 @internalComponent |
|
220 */ |
|
221 struct MFileInitializer64 |
|
222 { |
|
223 virtual TInt Init(RFile64& aFile) = 0; |
|
224 }; |
|
225 |
|
226 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
227 /////////////////////////// RFileBuf64 ///////////////////////////////////////////////////////////////////// |
189 /////////////////////////// RFileBuf64 ///////////////////////////////////////////////////////////////////// |
228 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
190 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
229 |
191 |
230 /** |
192 /** |
231 Initializes RFileBuf64 data members with their default values. |
193 Initializes RFileBuf64 data members with their default values. |
254 |
216 |
255 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
217 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
256 |
218 |
257 @see TFileMode |
219 @see TFileMode |
258 @see RFile64::Create() |
220 @see RFile64::Create() |
259 @see MFileInitializer64 |
|
260 |
221 |
261 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
222 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
262 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
223 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
263 */ |
224 */ |
264 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
225 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
265 { |
226 { |
266 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
227 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
267 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
228 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
268 |
229 |
269 struct TFileCreateInitializer64 : public MFileInitializer64 |
230 TInt err = DoPreInit(); |
270 { |
231 if(err == KErrNone) |
271 inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
232 { |
272 iFs(aFs), |
233 err = iFile.Create(aFs, aFileName, aFileMode); |
273 iFileName(aFileName), |
234 } |
274 iFileMode(aFileMode) |
235 return DoPostInit(err); |
275 { |
|
276 } |
|
277 virtual TInt Init(RFile64& aFile) |
|
278 { |
|
279 return aFile.Create(iFs, iFileName, iFileMode); |
|
280 } |
|
281 RFs& iFs; |
|
282 const TDesC& iFileName; |
|
283 TUint iFileMode; |
|
284 } initializer(aFs, aFileName, aFileMode); |
|
285 |
|
286 return DoInit(initializer); |
|
287 } |
236 } |
288 |
237 |
289 /** |
238 /** |
290 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface. |
239 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface. |
291 If the file does not already exist, an error is returned. |
240 If the file does not already exist, an error is returned. |
298 |
247 |
299 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
248 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
300 |
249 |
301 @see TFileMode |
250 @see TFileMode |
302 @see RFile64::Open() |
251 @see RFile64::Open() |
303 @see MFileInitializer64 |
|
304 |
252 |
305 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
253 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
306 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
254 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length). |
307 */ |
255 */ |
308 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
256 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
309 { |
257 { |
310 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
258 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
311 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
259 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
312 |
260 |
313 struct TFileOpenInitializer64 : public MFileInitializer64 |
261 TInt err = DoPreInit(); |
314 { |
262 if(err == KErrNone) |
315 inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
263 { |
316 iFs(aFs), |
264 err = iFile.Open(aFs, aFileName, aFileMode); |
317 iFileName(aFileName), |
265 } |
318 iFileMode(aFileMode) |
266 return DoPostInit(err); |
319 { |
|
320 } |
|
321 virtual TInt Init(RFile64& aFile) |
|
322 { |
|
323 return aFile.Open(iFs, iFileName, iFileMode); |
|
324 } |
|
325 RFs& iFs; |
|
326 const TDesC& iFileName; |
|
327 TUint iFileMode; |
|
328 } initializer(aFs, aFileName, aFileMode); |
|
329 |
|
330 return DoInit(initializer); |
|
331 } |
267 } |
332 |
268 |
333 /** |
269 /** |
334 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through |
270 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through |
335 RFileBuf64 public interface. |
271 RFileBuf64 public interface. |
344 |
280 |
345 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
281 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
346 |
282 |
347 @see TFileMode |
283 @see TFileMode |
348 @see RFile64::Temp() |
284 @see RFile64::Temp() |
349 @see MFileInitializer64 |
|
350 |
285 |
351 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
286 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
352 */ |
287 */ |
353 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) |
288 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) |
354 { |
289 { |
355 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
290 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
356 |
291 |
357 struct TFileTempInitializer64 : public MFileInitializer64 |
292 TInt err = DoPreInit(); |
358 { |
293 if(err == KErrNone) |
359 inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) : |
294 { |
360 iFs(aFs), |
295 err = iFile.Temp(aFs, aPath, aFileName, aFileMode); |
361 iPath(aPath), |
296 } |
362 iFileName(aFileName), |
297 return DoPostInit(err); |
363 iFileMode(aFileMode) |
|
364 { |
|
365 } |
|
366 virtual TInt Init(RFile64& aFile) |
|
367 { |
|
368 return aFile.Temp(iFs, iPath, iFileName, iFileMode); |
|
369 } |
|
370 RFs& iFs; |
|
371 const TDesC& iPath; |
|
372 TFileName& iFileName; |
|
373 TUint iFileMode; |
|
374 } initializer(aFs, aPath, aFileName, aFileMode); |
|
375 |
|
376 return DoInit(initializer); |
|
377 } |
298 } |
378 |
299 |
379 /** |
300 /** |
380 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases |
301 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases |
381 the RFileBuf64 resources. |
302 the RFileBuf64 resources. |
395 iBase = 0; |
316 iBase = 0; |
396 } |
317 } |
397 |
318 |
398 /** |
319 /** |
399 Calculates and sets optimal read-ahead buffer size. |
320 Calculates and sets optimal read-ahead buffer size. |
|
321 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system. |
|
322 |
|
323 Initialization rules: |
|
324 Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and |
|
325 a power of two then the read-ahead value will be |
|
326 initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise |
|
327 the buffer capacity will be used as a read-ahead value). |
|
328 Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize. |
|
329 If aBlockSize passes the checks then it will be used as a read-ahead value. |
400 |
330 |
401 @param aBlockSize The size of a file block in bytes |
331 @param aBlockSize The size of a file block in bytes |
402 @param aReadRecBufSize The recommended buffer size for optimised reading performance |
332 @param aReadRecBufSize The recommended buffer size for optimised reading performance |
403 |
333 |
404 @return The new read-ahead value |
334 @return The new read-ahead value |
475 } |
405 } |
476 //4. The requested data size is smaller than the buffer capacity |
406 //4. The requested data size is smaller than the buffer capacity |
477 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr()); |
407 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr()); |
478 while(len > 0 && err == KErrNone && aFilePos < iFileSize) |
408 while(len > 0 && err == KErrNone && aFilePos < iFileSize) |
479 { |
409 { |
480 //1. If part of all of the data is in the buffer - copy the data to the target location |
410 //1. If part or all of the data is in the buffer - copy the data to the target location |
481 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength)) |
411 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength)) |
482 { |
412 { |
483 TInt l = Min(len, (iFilePos + iLength - aFilePos)); |
413 TInt blocklen = Min(len, (iFilePos + iLength - aFilePos)); |
484 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l); |
414 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen); |
485 len -= l; |
415 len -= blocklen; |
486 aFilePos += l; |
416 aFilePos += blocklen; |
487 } |
417 } |
488 //2. Perform a read-ahead operation |
418 //2. Perform a read-ahead operation |
489 else |
419 else |
490 { |
420 { |
491 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
421 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
493 if(err != KErrNone) |
423 if(err != KErrNone) |
494 { |
424 { |
495 break; |
425 break; |
496 } |
426 } |
497 if(iNextReadFilePos != aFilePos) |
427 if(iNextReadFilePos != aFilePos) |
498 {//Direct "file read" operation |
428 {//Guessed read ahead was wrong. Direct "file read" operation |
499 iNextReadFilePosHits = 0; |
429 iNextReadFilePosHits = 0; |
500 TPtr8 ptr2(outptr, len); |
430 TPtr8 ptr2(outptr, len); |
501 err = iFile.Read(aFilePos, ptr2); |
431 err = iFile.Read(aFilePos, ptr2); |
502 PROFILE_READ(aFilePos, ptr2.Size()); |
432 PROFILE_READ(aFilePos, ptr2.Size()); |
503 if(err == KErrNone) |
433 if(err == KErrNone) |
788 __FILEBUF64_INVARIANT(); |
718 __FILEBUF64_INVARIANT(); |
789 return iFile.Drive(aDriveNumber, aDriveInfo); |
719 return iFile.Drive(aDriveNumber, aDriveInfo); |
790 } |
720 } |
791 |
721 |
792 /** |
722 /** |
793 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform |
723 Initializes RFileBuf64 data members with their initial values. |
794 the variable part of the initialization. |
724 Allocates memory for the file buffer. |
795 |
725 |
796 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init() |
726 @return KErrNone if successful, |
797 |
727 KErrNoMemory out of memory; |
798 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
728 */ |
799 */ |
729 TInt RFileBuf64::DoPreInit() |
800 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer) |
730 { |
801 { |
731 DoDiscard(); |
802 DoDiscard(); |
732 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize; |
803 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize; |
733 iBase = static_cast <TUint8*> (User::Alloc(iCapacity)); |
804 TInt err = KErrNoMemory; |
734 return iBase ? KErrNone : KErrNoMemory; |
805 iBase = static_cast <TUint8*> (User::Alloc(iCapacity)); |
735 } |
806 if(!iBase) |
736 |
807 { |
737 /** |
808 return KErrNoMemory; |
738 Performs post-initialization of the RFileBuf64 object. |
809 } |
739 If aInitErr is not KErrNone, then the buffer memory will be released. |
810 err = aFileInitializer.Init(iFile); |
740 The function returns the aInitErr value to the caller. |
811 if(err != KErrNone) |
741 |
812 { |
742 @param aInitErr The result of the performed before the call RFileBuf64 initialization. |
813 User::Free(iBase); |
743 |
814 iBase = 0; |
744 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
815 } |
745 */ |
816 return err; |
746 TInt RFileBuf64::DoPostInit(TInt aInitErr) |
817 } |
747 { |
|
748 if(aInitErr != KErrNone) |
|
749 { |
|
750 User::Free(iBase); |
|
751 iBase = 0; |
|
752 } |
|
753 return aInitErr; |
|
754 } |
818 |
755 |
819 /** |
756 /** |
820 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. |
757 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. |
821 */ |
758 */ |
822 void RFileBuf64::DoDiscard() |
759 void RFileBuf64::DoDiscard() |