|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 #include "FileBuf64.h" |
|
16 |
|
17 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
18 /////////////////////////// PROFILER //////////////////////////////////////////////////////////////////// |
|
19 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
21 #ifdef _SQLPROFILER |
|
22 |
|
23 extern TBool TheOsCallTimeDetailedProfileEnabled;//If true, the OS porting layer call details are enabled and for each call an entry will be added to the log file (epocwind.out). |
|
24 |
|
25 #define PROFILE_READ(pos,amount) \ |
|
26 do \ |
|
27 { \ |
|
28 if(TheOsCallTimeDetailedProfileEnabled) \ |
|
29 { \ |
|
30 ++iFileReadCount; iFileReadAmount += (amount); \ |
|
31 RDebug::Print(_L(" -- FRead this=%X, Cnt=%d, Pos=%ld, Amt=%d, Ttl=%ld\r\n"), (TUint32)this, iFileReadCount, pos, amount, iFileReadAmount); \ |
|
32 } \ |
|
33 } while(0) |
|
34 |
|
35 #define PROFILE_WRITE(pos,amount) \ |
|
36 do \ |
|
37 { \ |
|
38 if(TheOsCallTimeDetailedProfileEnabled) \ |
|
39 { \ |
|
40 ++iFileWriteCount, iFileWriteAmount += (amount); \ |
|
41 RDebug::Print(_L(" -- FWrite this=%X, Cnt=%d, Pos=%ld, Amt=%d, Ttl=%ld\r\n"), (TUint32)this, iFileWriteCount, pos, amount, iFileWriteAmount); \ |
|
42 } \ |
|
43 } while(0) |
|
44 |
|
45 #define PROFILE_SIZE() \ |
|
46 do \ |
|
47 { \ |
|
48 if(TheOsCallTimeDetailedProfileEnabled) \ |
|
49 { \ |
|
50 ++iFileSizeCount; \ |
|
51 RDebug::Print(_L(" -- FSize this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSizeCount); \ |
|
52 } \ |
|
53 } while(0) |
|
54 |
|
55 #define PROFILE_SETSIZE() \ |
|
56 do \ |
|
57 { \ |
|
58 if(TheOsCallTimeDetailedProfileEnabled) \ |
|
59 { \ |
|
60 ++iFileSetSizeCount; \ |
|
61 RDebug::Print(_L(" -- FSetSize this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSetSizeCount); \ |
|
62 } \ |
|
63 } while(0) |
|
64 |
|
65 #define PROFILE_FLUSH() \ |
|
66 do \ |
|
67 { \ |
|
68 if(TheOsCallTimeDetailedProfileEnabled) \ |
|
69 { \ |
|
70 ++iFileFlushCount; \ |
|
71 RDebug::Print(_L(" -- FFlush this=%X, Cnt=%d\r\n"), (TUint32)this, iFileFlushCount); \ |
|
72 } \ |
|
73 } while(0) |
|
74 |
|
75 #else |
|
76 |
|
77 #define PROFILE_READ(pos,amount) void(0) |
|
78 #define PROFILE_WRITE(pos,amount) void(0) |
|
79 |
|
80 #define PROFILE_SIZE() void(0) |
|
81 #define PROFILE_SETSIZE() void(0) |
|
82 #define PROFILE_FLUSH() void(0) |
|
83 |
|
84 #endif//_SQLPROFILER |
|
85 |
|
86 /** |
|
87 This constant is used for initializing the RFileBuf64::iFileSize data member and means that |
|
88 the iFileSize is not yet initialized with the real file size value. |
|
89 (RFileBuf64::iFileSize caches the file size value) |
|
90 @internalComponent |
|
91 */ |
|
92 static const TInt KFileSizeNotSet = -1; |
|
93 |
|
94 /** |
|
95 This constant is used as a default initializer for the RFileBuf64::iNextReadFilePos data member, |
|
96 indicating that the "guessed" file read offset is invalid and should not be used. |
|
97 @internalComponent |
|
98 */ |
|
99 static const TInt KNextReadFilePosNotSet = -1; |
|
100 |
|
101 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
102 /////////////////////////// ASSERTS & INVARIANT ////////////////////////////////////////////////////////// |
|
103 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
104 |
|
105 #ifdef _DEBUG |
|
106 |
|
107 #define __FILEBUF64_INVARIANT() Invariant() |
|
108 |
|
109 /** |
|
110 String literal used in _DEBUG mode for indicating that the reported panic happened inside the RFileBuf64 implementation. |
|
111 |
|
112 @see TFileBufPanic64 |
|
113 @internalComponent |
|
114 */ |
|
115 _LIT(KPanicCategory, "FBuf64"); |
|
116 |
|
117 /** |
|
118 Set of numeric constants used together with the KPanicCategory string literal in _DEBUG mode for providing more detailed |
|
119 information about the reason of the panic. |
|
120 |
|
121 @see KPanicCategory |
|
122 @internalComponent |
|
123 */ |
|
124 enum TFileBufPanic64 |
|
125 { |
|
126 EFBufPanicCapacity = 1, //1 |
|
127 EFBufPanicNullBuf, |
|
128 EFBufPanicBufLen, |
|
129 EFBufPanicFilePos, |
|
130 EFBufPanicFileSize, //5 |
|
131 EFBufPanicFileHandle, |
|
132 EFBufPanicFsHandle, |
|
133 EFBufPanicMsgHandle, |
|
134 EFBufPanicMsgIndex, |
|
135 EFBufPanicFileNameLen, //10 |
|
136 EFBufPanicNullThis, |
|
137 EFBufPanicDirty, |
|
138 EFBufPanicNextReadFilePos, |
|
139 EFBufPanicNextReadFilePosHits, |
|
140 EFBufPanicFileBlockSize, //15 |
|
141 }; |
|
142 |
|
143 /** |
|
144 Helper function used in the implementation of the __FBUF64_ASSERT() macro. |
|
145 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, |
|
146 PanicFileBuf64() will use the supplied aLine and aPanicCode arguments together with the KPanicCategory string literal |
|
147 to prepare and print out a line (including the time of the panic) to the default log. The calling thread will be panic'ed |
|
148 after that. |
|
149 |
|
150 @see TFileBufPanic64 |
|
151 @see KPanicCategory |
|
152 @internalComponent |
|
153 */ |
|
154 static void PanicFileBuf64(TInt aLine, TFileBufPanic64 aPanicCode) |
|
155 { |
|
156 TTime time; |
|
157 time.HomeTime(); |
|
158 TDateTime dt = time.DateTime(); |
|
159 TBuf<16> tbuf; |
|
160 tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond()); |
|
161 |
|
162 TBuf<64> buf; |
|
163 _LIT(KFormat,"**%S:RFileBuf64 panic %d, at line(%d)"); |
|
164 buf.Format(KFormat, &tbuf, aPanicCode, aLine); |
|
165 RDebug::Print(buf); |
|
166 User::Panic(KPanicCategory, aPanicCode); |
|
167 } |
|
168 |
|
169 /** |
|
170 This macro should be used when there is a need to panic the client/server if "expr" condition is not satisfied. |
|
171 Works in only in debug mode. In release mode evaluates to nothing. |
|
172 |
|
173 @see TFileBufPanic64 |
|
174 @see KPanicCategory |
|
175 @see PanicFileBuf64() |
|
176 @internalComponent |
|
177 */ |
|
178 #define __FBUF64_ASSERT(expr, panicCode) (void)(!(expr) ? ::PanicFileBuf64(__LINE__, panicCode) : void(0)) |
|
179 |
|
180 #else //_DEBUG |
|
181 |
|
182 #define __FILEBUF64_INVARIANT() void(0) |
|
183 |
|
184 #define __FBUF64_ASSERT(expr, panicCode) void(0) |
|
185 |
|
186 #endif//_DEBUG |
|
187 |
|
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 ///////////////////////////////////////////////////////////////////// |
|
228 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
229 |
|
230 /** |
|
231 Initializes RFileBuf64 data members with their default values. |
|
232 |
|
233 @param aSize Max file buffer size (capacity) in bytes. |
|
234 |
|
235 @panic FBuf64 1 In _DEBUG mode - aSize is 0 or negative. |
|
236 */ |
|
237 RFileBuf64::RFileBuf64(TInt aSize) : |
|
238 iCapacity(aSize), |
|
239 iReadAheadSize(RFileBuf64::KDefaultReadAheadSize) |
|
240 { |
|
241 __FBUF64_ASSERT(aSize > 0, EFBufPanicCapacity); |
|
242 } |
|
243 |
|
244 /** |
|
245 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface. |
|
246 If the file already exists, an error is returned. |
|
247 If the resulting path does not exist, then the operation cannot proceed and the function returns an error code. |
|
248 |
|
249 @param aFs The file server session. |
|
250 @param aFileName The name of the file. Any path components (i.e. drive letter |
|
251 or directory), which are not specified, are taken from |
|
252 the session path. |
|
253 @param aFileMode The mode in which the file is opened. See TFileMode for details. |
|
254 |
|
255 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
256 |
|
257 @see TFileMode |
|
258 @see RFile64::Create() |
|
259 @see MFileInitializer64 |
|
260 |
|
261 @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). |
|
263 */ |
|
264 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
|
265 { |
|
266 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
|
267 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
|
268 |
|
269 struct TFileCreateInitializer64 : public MFileInitializer64 |
|
270 { |
|
271 inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
|
272 iFs(aFs), |
|
273 iFileName(aFileName), |
|
274 iFileMode(aFileMode) |
|
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 } |
|
288 |
|
289 /** |
|
290 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. |
|
292 |
|
293 @param aFs The file server session. |
|
294 @param aFileName The name of the file. Any path components (i.e. drive letter |
|
295 or directory), which are not specified, are taken from |
|
296 the session path. |
|
297 @param aFileMode The mode in which the file is opened. See TFileMode for details. |
|
298 |
|
299 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
300 |
|
301 @see TFileMode |
|
302 @see RFile64::Open() |
|
303 @see MFileInitializer64 |
|
304 |
|
305 @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). |
|
307 */ |
|
308 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode) |
|
309 { |
|
310 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
|
311 __FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen); |
|
312 |
|
313 struct TFileOpenInitializer64 : public MFileInitializer64 |
|
314 { |
|
315 inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) : |
|
316 iFs(aFs), |
|
317 iFileName(aFileName), |
|
318 iFileMode(aFileMode) |
|
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 } |
|
332 |
|
333 /** |
|
334 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through |
|
335 RFileBuf64 public interface. |
|
336 |
|
337 @param aFs The file server session. |
|
338 @param aPath The directory in which the file is created. |
|
339 @param aFileName On return, contains the full path and file name of the file. |
|
340 The filename is guaranteed to be unique within the directory |
|
341 specified by aPath. |
|
342 @param aFileMode The mode in which the file is opened. The access mode is |
|
343 automatically set to EFileWrite. See TFileMode for details. |
|
344 |
|
345 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
346 |
|
347 @see TFileMode |
|
348 @see RFile64::Temp() |
|
349 @see MFileInitializer64 |
|
350 |
|
351 @panic FBuf64 7 In _DEBUG mode - Invalid aFs object (null file session handle). |
|
352 */ |
|
353 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) |
|
354 { |
|
355 __FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle); |
|
356 |
|
357 struct TFileTempInitializer64 : public MFileInitializer64 |
|
358 { |
|
359 inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) : |
|
360 iFs(aFs), |
|
361 iPath(aPath), |
|
362 iFileName(aFileName), |
|
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 } |
|
378 |
|
379 /** |
|
380 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases |
|
381 the RFileBuf64 resources. |
|
382 RFileBuf64::Flush() should be called before RFileBuf64::Close() to ensure that if there are pending data, they will |
|
383 be written to the file and if the operation fails, the caller will be notified with an appropriate return error. |
|
384 |
|
385 @see RFileBuf64::Flush() |
|
386 */ |
|
387 void RFileBuf64::Close() |
|
388 { |
|
389 if(iFile.SubSessionHandle() != 0 && iBase != 0) |
|
390 { |
|
391 (void)DoFileWrite2(); |
|
392 } |
|
393 iFile.Close(); |
|
394 User::Free(iBase); |
|
395 iBase = 0; |
|
396 } |
|
397 |
|
398 /** |
|
399 Calculates and sets optimal read-ahead buffer size. |
|
400 |
|
401 @param aBlockSize The size of a file block in bytes |
|
402 @param aReadRecBufSize The recommended buffer size for optimised reading performance |
|
403 |
|
404 @return The new read-ahead value |
|
405 |
|
406 @see TVolumeIOParamInfo |
|
407 */ |
|
408 TInt RFileBuf64::SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize) |
|
409 { |
|
410 __FILEBUF64_INVARIANT(); |
|
411 if(aReadRecBufSize > 0 && (aReadRecBufSize & (aReadRecBufSize - 1)) == 0 && aReadRecBufSize > RFileBuf64::KDefaultReadAheadSize) |
|
412 { |
|
413 iReadAheadSize = aReadRecBufSize > iCapacity ? iCapacity : aReadRecBufSize; |
|
414 } |
|
415 else if(aBlockSize > 0 && (aBlockSize & (aBlockSize - 1)) == 0 && aBlockSize > RFileBuf64::KDefaultReadAheadSize) |
|
416 { |
|
417 iReadAheadSize = aBlockSize > iCapacity ? iCapacity : aBlockSize; |
|
418 } |
|
419 __FILEBUF64_INVARIANT(); |
|
420 return iReadAheadSize; |
|
421 } |
|
422 |
|
423 /** |
|
424 Reads from the file at the specified position (aFilePos). |
|
425 If the data to be read is in the buffer, then the data will be taken from the buffer. |
|
426 |
|
427 @param aFilePos Position of first byte to be read. This is an offset from |
|
428 the start of the file. |
|
429 If aPos is beyond the end of the file, the function returns |
|
430 a zero length descriptor. |
|
431 @param aDes Descriptor into which binary data is read. Any existing contents |
|
432 are overwritten. On return, its length is set to the number of |
|
433 bytes read. |
|
434 |
|
435 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
436 |
|
437 @panic FBuf64 4 In _DEBUG mode - negative aFilePos value. |
|
438 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
439 |
|
440 @see RFileBuf64::Invariant() |
|
441 */ |
|
442 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes) |
|
443 { |
|
444 __FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos); |
|
445 __FILEBUF64_INVARIANT(); |
|
446 aDes.SetLength(0); |
|
447 //1. The output buffer max len is 0 |
|
448 if(aDes.MaxLength() == 0) |
|
449 { |
|
450 __FILEBUF64_INVARIANT(); |
|
451 return KErrNone; |
|
452 } |
|
453 //2. Initialize the "iFileSize" if it is not initialized yet |
|
454 TInt err = DoFileSize(); |
|
455 if(err != KErrNone) |
|
456 { |
|
457 __FILEBUF64_INVARIANT(); |
|
458 return err; |
|
459 } |
|
460 //3. Too big "read" request - read directly from the file |
|
461 TInt len = aDes.MaxLength(); |
|
462 if(len > iCapacity) |
|
463 { |
|
464 if((aFilePos + len) > iFilePos && !(aFilePos >= (iFilePos + iLength))) |
|
465 {//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
|
466 err = DoFileWrite1(aFilePos); |
|
467 } |
|
468 if(err == KErrNone) |
|
469 { |
|
470 err = iFile.Read(aFilePos, aDes); |
|
471 PROFILE_READ(aFilePos, aDes.Size()); |
|
472 } |
|
473 __FILEBUF64_INVARIANT(); |
|
474 return err; |
|
475 } |
|
476 //4. The requested data size is smaller than the buffer capacity |
|
477 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr()); |
|
478 while(len > 0 && err == KErrNone && aFilePos < iFileSize) |
|
479 { |
|
480 //1. If part of all of the data is in the buffer - copy the data to the target location |
|
481 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength)) |
|
482 { |
|
483 TInt l = Min(len, (iFilePos + iLength - aFilePos)); |
|
484 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l); |
|
485 len -= l; |
|
486 aFilePos += l; |
|
487 } |
|
488 //2. Perform a read-ahead operation |
|
489 else |
|
490 { |
|
491 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content. |
|
492 err = DoFileWrite1(aFilePos); |
|
493 if(err != KErrNone) |
|
494 { |
|
495 break; |
|
496 } |
|
497 if(iNextReadFilePos != aFilePos) |
|
498 {//Direct "file read" operation |
|
499 iNextReadFilePosHits = 0; |
|
500 TPtr8 ptr2(outptr, len); |
|
501 err = iFile.Read(aFilePos, ptr2); |
|
502 PROFILE_READ(aFilePos, ptr2.Size()); |
|
503 if(err == KErrNone) |
|
504 { |
|
505 iNextReadFilePos = aFilePos + len; |
|
506 len -= ptr2.Length(); |
|
507 } |
|
508 break; |
|
509 } |
|
510 //The guessed from the previous "file read" operation file pos is correct. Start reading-ahead. |
|
511 const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize |
|
512 if(iNextReadFilePosHits < KMaxReadFilePosHits) |
|
513 { |
|
514 ++iNextReadFilePosHits; |
|
515 } |
|
516 TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits); |
|
517 TInt align = (aFilePos + len + maxReadAhead) & (iReadAheadSize - 1); |
|
518 TInt readahead = maxReadAhead - align; |
|
519 if(readahead < 0) |
|
520 { |
|
521 // if read-ahead doesn't cross block boundary do it all |
|
522 readahead = maxReadAhead; |
|
523 } |
|
524 TPtr8 ptr(iBase, Min(iCapacity, (len + readahead))); |
|
525 err = iFile.Read(aFilePos, ptr); |
|
526 PROFILE_READ(aFilePos, ptr.Size()); |
|
527 if(err == KErrNone) |
|
528 { |
|
529 iFilePos = aFilePos; |
|
530 iLength = ptr.Length(); |
|
531 iNextReadFilePos = iFilePos + iLength; |
|
532 if(iLength == 0) |
|
533 { |
|
534 break; |
|
535 } |
|
536 } |
|
537 else |
|
538 { |
|
539 DoDiscard(); |
|
540 } |
|
541 } |
|
542 } |
|
543 aDes.SetLength(aDes.MaxLength() - len); |
|
544 __FILEBUF64_INVARIANT(); |
|
545 return err; |
|
546 } |
|
547 |
|
548 /** |
|
549 Writes to the file at the specified offset (aFilePos) within the file. |
|
550 If certain conditions are met, the data will be stored in the buffer - no call to the file server. |
|
551 |
|
552 @param aFilePos The offset from the start of the file at which the first byte is written. |
|
553 If a position beyond the end of the file is specified, then |
|
554 the write operation begins at the end of the file. |
|
555 If the position has been locked, then the write fails. |
|
556 |
|
557 @param aData The descriptor from which binary data is written. The function writes |
|
558 the entire contents of aData to the file. |
|
559 |
|
560 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
561 |
|
562 @panic FBuf64 4 In _DEBUG mode - negative aFilePos value. |
|
563 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
564 |
|
565 @see RFileBuf64::Invariant() |
|
566 */ |
|
567 TInt RFileBuf64::Write(TInt64 aFilePos, const TDesC8& aData) |
|
568 { |
|
569 __FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos); |
|
570 __FILEBUF64_INVARIANT(); |
|
571 if(aData.Length() == 0) |
|
572 { |
|
573 __FILEBUF64_INVARIANT(); |
|
574 return KErrNone; |
|
575 } |
|
576 TInt err = DoFileSize(); |
|
577 if(err != KErrNone) |
|
578 { |
|
579 __FILEBUF64_INVARIANT(); |
|
580 return err; |
|
581 } |
|
582 DoDiscardBufferedReadData(); |
|
583 const TUint8* data = aData.Ptr(); |
|
584 for(TInt len = aData.Length(); len > 0 && err == KErrNone;) |
|
585 { |
|
586 //1. The new write pos is before the buffered file pos |
|
587 if(aFilePos < iFilePos) |
|
588 { |
|
589 //If the new data sticks to/overlapps the old data and there is room in the buffer to move the old data |
|
590 //toward the end, then the new data can be copied at the beginning of the buffer. |
|
591 if((aFilePos + len) >= iFilePos && (iFilePos - aFilePos) <= (iCapacity - iLength)) |
|
592 { |
|
593 (void)Mem::Copy(iBase + (iFilePos - aFilePos), iBase, iLength); //Make room - move the existing data toward the end |
|
594 (void)Mem::Copy(iBase, data, len); //of the buffer. Stick the new data to the old data |
|
595 iLength += (iFilePos - aFilePos); |
|
596 iFilePos = aFilePos; //The new file pos is associated with the buffer |
|
597 iFileSize = Max(iFileSize, (iFilePos + iLength)); |
|
598 len = 0; //No more new data |
|
599 iDirty = ETrue; |
|
600 } |
|
601 else |
|
602 //The "aFilePos" is too far before the "iFilePos". Write the buffer and associate the new pos with the buffer |
|
603 { |
|
604 err = DoFileWrite2(aFilePos); |
|
605 } |
|
606 } |
|
607 //2. The new write pos is after the associated file pos + the data length. |
|
608 else if(aFilePos > (iFilePos + iLength)) |
|
609 { |
|
610 if(aFilePos > iFileSize) //Beyond the end of the file |
|
611 { |
|
612 if((iFilePos + iLength) == iFileSize && (aFilePos - iFilePos) < iCapacity) |
|
613 { //but within the buffer => extend the file with zeros. |
|
614 Mem::FillZ(iBase + iLength, aFilePos - iFilePos - iLength); |
|
615 iLength = aFilePos - iFilePos; |
|
616 iFileSize = Max(iFileSize, (iFilePos + iLength)); |
|
617 iDirty = ETrue; |
|
618 } |
|
619 else |
|
620 //Beyond the end of the file and not in the buffer - set file size. |
|
621 { |
|
622 err = DoSetFileSize(aFilePos); |
|
623 } |
|
624 } |
|
625 else |
|
626 //Within the file, not in the buffer - write the buffer and associate the new file pos with the buffer |
|
627 { |
|
628 err = DoFileWrite2(aFilePos); |
|
629 } |
|
630 } |
|
631 //3. The new write pos is in the buffer, but the data length is too big |
|
632 // (For SQLite is OK, otherwise the whole block must be written to the file) |
|
633 //4. The new write pos is in the buffer, the data entirely fits in the buffer |
|
634 else |
|
635 { |
|
636 if(iCapacity == iLength) //The buffer is full. Write the buffer and associate the new file pos |
|
637 { |
|
638 err = DoFileWrite2(aFilePos); |
|
639 } |
|
640 if(err == KErrNone) |
|
641 { |
|
642 TInt amount = Min(len, (iCapacity - (aFilePos - iFilePos))); |
|
643 const TUint8* end = Mem::Copy(iBase + (aFilePos - iFilePos), data, amount); |
|
644 iLength = Max(iLength, (end - iBase)); |
|
645 iFileSize = Max(iFileSize, (iFilePos + iLength)); |
|
646 len -= amount; |
|
647 data += amount; |
|
648 aFilePos += amount; |
|
649 iDirty = ETrue; |
|
650 } |
|
651 } |
|
652 } |
|
653 __FILEBUF64_INVARIANT(); |
|
654 return err; |
|
655 } |
|
656 |
|
657 /** |
|
658 Gets the current file size. |
|
659 |
|
660 @param aFileSize On return, the size of the file in bytes. |
|
661 |
|
662 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
663 |
|
664 See RFileBuf64::Invariant() for possible panics that may occur when this method is called. |
|
665 |
|
666 @see RFileBuf64::Invariant() |
|
667 */ |
|
668 TInt RFileBuf64::Size(TInt64& aFileSize) |
|
669 { |
|
670 __FILEBUF64_INVARIANT(); |
|
671 TInt err = DoFileSize(); |
|
672 if(err == KErrNone) |
|
673 { |
|
674 aFileSize = iFileSize; |
|
675 } |
|
676 __FILEBUF64_INVARIANT(); |
|
677 return err; |
|
678 } |
|
679 |
|
680 /** |
|
681 Sets the file size. |
|
682 |
|
683 If the size of the file is reduced, data may be lost from the end of the file. |
|
684 |
|
685 Note: |
|
686 |
|
687 1. The current file position remains unchanged unless SetSize() reduces the size |
|
688 of the file in such a way that the current file position is now beyond |
|
689 the end of the file. In this case, the current file position is set to |
|
690 the end of file. |
|
691 |
|
692 2. If the file was not opened for writing, an error is returned. |
|
693 |
|
694 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic. |
|
695 |
|
696 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
697 |
|
698 @panic FBuf64 5 In _DEBUG mode - negative aFileSize value. |
|
699 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
700 |
|
701 @see RFileBuf64::Invariant() |
|
702 */ |
|
703 TInt RFileBuf64::SetSize(TInt64 aFileSize) |
|
704 { |
|
705 __FBUF64_ASSERT(aFileSize >= 0, EFBufPanicFileSize); |
|
706 __FILEBUF64_INVARIANT(); |
|
707 return DoSetFileSize(aFileSize); |
|
708 } |
|
709 |
|
710 /** |
|
711 Locks a region within the file as defined by a range of bytes. |
|
712 |
|
713 @see RFile64::Lock() |
|
714 |
|
715 @param aFilePos Position in file from which to lock; this is the offset from the beginning of the file. |
|
716 @param aLength Number of bytes to lock. |
|
717 |
|
718 @return KErrNone if successful, otherwise one of the other system-wide error |
|
719 codes. |
|
720 */ |
|
721 TInt RFileBuf64::Lock(TInt64 aFilePos, TInt64 aLength) const |
|
722 { |
|
723 __FILEBUF64_INVARIANT(); |
|
724 return iFile.Lock(aFilePos, aLength); |
|
725 } |
|
726 |
|
727 /** |
|
728 Unlocks a region within the file as defined by a range of bytes. |
|
729 |
|
730 @see RFile64::UnLock() |
|
731 |
|
732 @param aFilePos Position in file from which to unlock; this is the offset from the beginning of the file. |
|
733 @param aLength Number of bytes to unlock. |
|
734 |
|
735 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
736 */ |
|
737 TInt RFileBuf64::UnLock(TInt64 aFilePos, TInt64 aLength) const |
|
738 { |
|
739 __FILEBUF64_INVARIANT(); |
|
740 return iFile.UnLock(aFilePos, aLength); |
|
741 } |
|
742 |
|
743 /** |
|
744 Writes the pending data and then flushes the file. |
|
745 |
|
746 Although RFileBuf64::Close() also flushes internal buffers, it is better |
|
747 to call RFileBuf64::Flush() before the file is closed. This is because Close() returns no |
|
748 error information, so there is no way of telling whether the final data was |
|
749 written to the file successfully or not. |
|
750 |
|
751 @param aFlush The caller should call this function with aResetCachedFileSize parameter set, |
|
752 when the buffer file is shared between threads. |
|
753 |
|
754 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
755 |
|
756 See RFileBuf64::Invariant() for possible panics that may occur when this method is called. |
|
757 |
|
758 @see RFileBuf64::Invariant() |
|
759 */ |
|
760 TInt RFileBuf64::Flush(TBool aResetCachedFileSize /*= EFalse*/) |
|
761 { |
|
762 __FILEBUF64_INVARIANT(); |
|
763 TInt err = DoFileFlush(); |
|
764 if(aResetCachedFileSize && err == KErrNone) |
|
765 {//Unset the iFileSize to force the file buffers used by the other threads to re-read the file size. |
|
766 iFileSize = KFileSizeNotSet; |
|
767 } |
|
768 return err; |
|
769 } |
|
770 |
|
771 /** |
|
772 Gets information about the drive on which this file resides. |
|
773 |
|
774 @param aDriveNumber On return, the drive number. |
|
775 |
|
776 @param aDriveInfo On return, contains information describing the drive |
|
777 and the medium mounted on it. The value of TDriveInfo::iType |
|
778 shows whether the drive contains media. |
|
779 |
|
780 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
781 |
|
782 See RFileBuf64::Invariant() for possible panics that may occur when this method is called. |
|
783 |
|
784 @see RFileBuf64::Invariant() |
|
785 */ |
|
786 TInt RFileBuf64::Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const |
|
787 { |
|
788 __FILEBUF64_INVARIANT(); |
|
789 return iFile.Drive(aDriveNumber, aDriveInfo); |
|
790 } |
|
791 |
|
792 /** |
|
793 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform |
|
794 the variable part of the initialization. |
|
795 |
|
796 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init() |
|
797 |
|
798 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
799 */ |
|
800 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer) |
|
801 { |
|
802 DoDiscard(); |
|
803 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize; |
|
804 TInt err = KErrNoMemory; |
|
805 iBase = static_cast <TUint8*> (User::Alloc(iCapacity)); |
|
806 if(!iBase) |
|
807 { |
|
808 return KErrNoMemory; |
|
809 } |
|
810 err = aFileInitializer.Init(iFile); |
|
811 if(err != KErrNone) |
|
812 { |
|
813 User::Free(iBase); |
|
814 iBase = 0; |
|
815 } |
|
816 return err; |
|
817 } |
|
818 |
|
819 /** |
|
820 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. |
|
821 */ |
|
822 void RFileBuf64::DoDiscard() |
|
823 { |
|
824 iLength = 0; |
|
825 iFilePos = 0; |
|
826 iFileSize = KFileSizeNotSet; |
|
827 iDirty = EFalse; |
|
828 iNextReadFilePos = KNextReadFilePosNotSet; |
|
829 iNextReadFilePosHits = 0; |
|
830 } |
|
831 |
|
832 /** |
|
833 Gets the current file size. |
|
834 If iFileSize value is valid, then no call to the file server will be made. |
|
835 Otherwise the file server will be called and the file size - stored (cached) in iFileSize data member for later use. |
|
836 |
|
837 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
838 |
|
839 See RFileBuf64::Invariant() for possible panics that may occur when this method is called. |
|
840 |
|
841 @see RFileBuf64::Invariant() |
|
842 */ |
|
843 TInt RFileBuf64::DoFileSize() |
|
844 { |
|
845 __FILEBUF64_INVARIANT(); |
|
846 if(iFileSize != KFileSizeNotSet) |
|
847 { |
|
848 __FILEBUF64_INVARIANT(); |
|
849 return KErrNone; |
|
850 } |
|
851 PROFILE_SIZE(); |
|
852 TInt err = iFile.Size(iFileSize); |
|
853 if(err != KErrNone) |
|
854 { |
|
855 DoDiscard(); |
|
856 } |
|
857 __FILEBUF64_INVARIANT(); |
|
858 return err; |
|
859 } |
|
860 |
|
861 /** |
|
862 Sets the file size. |
|
863 If the buffer contains pending data, the data will be written to the file |
|
864 before the "set file size" operation, if certain conditions are met. |
|
865 |
|
866 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic. |
|
867 |
|
868 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
869 |
|
870 @panic FBuf64 5 In _DEBUG mode - negative aFileSize value. |
|
871 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
872 |
|
873 @see RFileBuf64::Invariant() |
|
874 */ |
|
875 TInt RFileBuf64::DoSetFileSize(TInt64 aFileSize) |
|
876 { |
|
877 __FBUF64_ASSERT(aFileSize >= 0, EFBufPanicFileSize); |
|
878 __FILEBUF64_INVARIANT(); |
|
879 if(aFileSize < iFilePos) |
|
880 { |
|
881 iDirty = EFalse; |
|
882 iLength = 0; |
|
883 } |
|
884 //If the new file size is "in" the buffer then change the "iLength" |
|
885 else if(aFileSize < (iFilePos + iLength)) |
|
886 { |
|
887 iLength = aFileSize - iFilePos; |
|
888 } |
|
889 PROFILE_SETSIZE(); |
|
890 TInt err = iFile.SetSize(aFileSize); |
|
891 if(err != KErrNone) |
|
892 { |
|
893 DoDiscard(); |
|
894 } |
|
895 else |
|
896 { |
|
897 iFileSize = aFileSize; |
|
898 } |
|
899 __FILEBUF64_INVARIANT(); |
|
900 return err; |
|
901 } |
|
902 |
|
903 /** |
|
904 Writes the pending data and flushes the file. |
|
905 |
|
906 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
907 |
|
908 See RFileBuf64::Invariant() for possible panics that may occur when this method is called. |
|
909 |
|
910 @see RFileBuf64::Invariant() |
|
911 */ |
|
912 TInt RFileBuf64::DoFileFlush() |
|
913 { |
|
914 __FILEBUF64_INVARIANT(); |
|
915 TInt err = DoFileWrite2();//Write the buffer if the iDirty flag is set. Do not preserve the buffer content and file pos. |
|
916 if(err != KErrNone) |
|
917 { |
|
918 __FILEBUF64_INVARIANT(); |
|
919 return err; |
|
920 } |
|
921 PROFILE_FLUSH(); |
|
922 err = iFile.Flush(); |
|
923 if(err != KErrNone) |
|
924 { |
|
925 DoDiscard(); |
|
926 } |
|
927 iLength = 0; |
|
928 __FILEBUF64_INVARIANT(); |
|
929 return err; |
|
930 } |
|
931 |
|
932 /** |
|
933 Writes the buffered data to the file if the iLength value is > 0. |
|
934 If the file write operation extends the file, the iFileSize data member will be initialized with the new file size. |
|
935 No changes occur in the other data member values. |
|
936 |
|
937 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
938 |
|
939 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
940 |
|
941 @see RFileBuf64::DoFileWrite1() |
|
942 @see RFileBuf64::DoFileWrite2() |
|
943 @see RFileBuf64::Invariant() |
|
944 */ |
|
945 TInt RFileBuf64::DoFileWrite() |
|
946 { |
|
947 __FILEBUF64_INVARIANT(); |
|
948 if(iLength == 0) |
|
949 { |
|
950 __FILEBUF64_INVARIANT(); |
|
951 return KErrNone; |
|
952 } |
|
953 PROFILE_WRITE(iFilePos, iLength); |
|
954 TPtrC8 data(iBase, iLength); |
|
955 TInt err = iFile.Write(iFilePos, data); |
|
956 if(err == KErrNone) |
|
957 { |
|
958 iFileSize = Max(iFileSize, (iFilePos + iLength)); |
|
959 } |
|
960 else |
|
961 { |
|
962 DoDiscard(); |
|
963 } |
|
964 __FILEBUF64_INVARIANT(); |
|
965 return err; |
|
966 } |
|
967 |
|
968 /** |
|
969 Writes the buffered data to the file if the iDirty flag is set. |
|
970 If the iDirty flag is set and the file write operation was successful, the iFilePos will be initialized with |
|
971 the aNewFilePos value, the iLength will be set to 0. |
|
972 This method is called from RFileBuf64::Read(), where: |
|
973 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized |
|
974 with aNewFilePos - the offset in the file where the next file read operation should start from; |
|
975 - if the buffer contains cached reads, then nothing happens, the buffer content will be kept; |
|
976 The function resets the iDirty flag. |
|
977 |
|
978 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with |
|
979 the aNewFilePos value. |
|
980 |
|
981 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
982 |
|
983 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
984 |
|
985 @panic FBuf64 4 In _DEBUG mode - negative aNewFilePos value. |
|
986 |
|
987 @see RFileBuf64::Read() |
|
988 @see RFileBuf64::DoFileWrite() |
|
989 @see RFileBuf64::DoFileWrite2() |
|
990 @see RFileBuf64::Invariant() |
|
991 */ |
|
992 TInt RFileBuf64::DoFileWrite1(TInt64 aNewFilePos) |
|
993 { |
|
994 __FBUF64_ASSERT(aNewFilePos >= 0, EFBufPanicFilePos); |
|
995 __FILEBUF64_INVARIANT(); |
|
996 TInt err = KErrNone; |
|
997 if(iDirty) |
|
998 { |
|
999 err = DoFileWrite(); |
|
1000 if(err == KErrNone) |
|
1001 { |
|
1002 iFilePos = aNewFilePos; |
|
1003 iLength = 0; |
|
1004 } |
|
1005 } |
|
1006 iDirty = EFalse; |
|
1007 __FILEBUF64_INVARIANT(); |
|
1008 return err; |
|
1009 } |
|
1010 |
|
1011 /* |
|
1012 Writes the buffered data to the file if the iDirty flag is set. |
|
1013 If the file write operation was successful or if the iDirty flag was not set, the iFilePos will be initialized with |
|
1014 the aNewFilePos value, the iLength will be set to 0. |
|
1015 This method is called from RFileBuf64::Write() an other RFileBuf64 methods (but not from RFileBuf64::Read()), where: |
|
1016 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized |
|
1017 with aNewFilePos - the offset in the file for which the write data will be cached in the buffer; |
|
1018 - if the buffer contains cached reads, then the buffer content will be destroyed, iFilePos initialized with aNewFilePos |
|
1019 and iLength set to 0; |
|
1020 The function resets the iDirty flag. |
|
1021 The difference between RFileBuf64::DoFileWrite1() and RFileBuf64::DoFileWrite2() is: |
|
1022 - RFileBuf64::DoFileWrite1() perserves the buffer content if iDirty is not set; |
|
1023 - RFileBuf64::DoFileWrite2() always destroys the buffer content and initializes iFilePos; |
|
1024 |
|
1025 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with |
|
1026 the aNewFilePos value. |
|
1027 |
|
1028 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
1029 |
|
1030 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
1031 |
|
1032 @panic FBuf64 4 In _DEBUG mode - negative aNewFilePos value. |
|
1033 |
|
1034 @see RFileBuf64::Write() |
|
1035 @see RFileBuf64::DoFileWrite() |
|
1036 @see RFileBuf64::DoFileWrite1() |
|
1037 @see RFileBuf64::Invariant() |
|
1038 */ |
|
1039 TInt RFileBuf64::DoFileWrite2(TInt64 aNewFilePos) |
|
1040 { |
|
1041 __FBUF64_ASSERT(aNewFilePos >= 0, EFBufPanicFilePos); |
|
1042 __FILEBUF64_INVARIANT(); |
|
1043 TInt err = KErrNone; |
|
1044 if(iDirty) |
|
1045 { |
|
1046 err = DoFileWrite(); |
|
1047 } |
|
1048 if(err == KErrNone) |
|
1049 { |
|
1050 iFilePos = aNewFilePos; |
|
1051 iLength = 0; |
|
1052 } |
|
1053 iDirty = EFalse; |
|
1054 __FILEBUF64_INVARIANT(); |
|
1055 return err; |
|
1056 } |
|
1057 |
|
1058 /** |
|
1059 This function discards the buffer content if the buffer contains cached read data. |
|
1060 The function is called from RFileBuf64::Write(), because if the buffer contains cached read data, |
|
1061 they cannot be mixed with the cached write data. |
|
1062 Reason: for example the buffer contains 8Kb cached read data from file offset 0. |
|
1063 The data write request is 10 bytes at offset 4000. The write data will be cached, |
|
1064 because the buffer contains data from from this file area: [0..8192]. |
|
1065 The iDirty flag will be set. Later when RFileBuf64::Flush() is called, the whole |
|
1066 8Kb buffer will be written. There is nothing wrong with that, the file content will be consistent. |
|
1067 But from performance point of view: 8Kb written vs. 10 bytes written - that may badly impact the performance. |
|
1068 |
|
1069 @see RFileBuf64::Write() |
|
1070 |
|
1071 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called. |
|
1072 */ |
|
1073 void RFileBuf64::DoDiscardBufferedReadData() |
|
1074 { |
|
1075 __FILEBUF64_INVARIANT(); |
|
1076 if(!iDirty && iLength > 0) |
|
1077 { |
|
1078 iLength = 0; |
|
1079 iFilePos = 0; |
|
1080 iNextReadFilePos = KNextReadFilePosNotSet; |
|
1081 iNextReadFilePosHits = 0; |
|
1082 } |
|
1083 __FILEBUF64_INVARIANT(); |
|
1084 } |
|
1085 |
|
1086 #ifdef _DEBUG |
|
1087 |
|
1088 /** |
|
1089 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method |
|
1090 (except the init/destroy methods). |
|
1091 |
|
1092 @panic FBuf64 11 In _DEBUG mode - null "this" pointer. |
|
1093 @panic FBuf64 1 In _DEBUG mode - negative iCapacity value. |
|
1094 @panic FBuf64 2 In _DEBUG mode - the buffer pointer is null (possible the buffer is not allocated or already destroyed). |
|
1095 @panic FBuf64 3 In _DEBUG mode - invalid iLength value (negative or bigger than iCapacity). |
|
1096 @panic FBuf64 4 In _DEBUG mode - negative iFilePos value. |
|
1097 @panic FBuf64 5 In _DEBUG mode - set but negative iFileSize value. |
|
1098 @panic FBuf64 6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed). |
|
1099 @panic FBuf64 13 In _DEBUG mode - set but negative iNextReadFilePos value. |
|
1100 @panic FBuf64 14 In _DEBUG mode - negative iNextReadFilePosHits value. |
|
1101 @panic FBuf64 15 In _DEBUG mode - iReadAheadSize is negative or is not power of two. |
|
1102 */ |
|
1103 void RFileBuf64::Invariant() const |
|
1104 { |
|
1105 __FBUF64_ASSERT(this != 0, EFBufPanicNullThis); |
|
1106 __FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity); |
|
1107 __FBUF64_ASSERT(iBase != 0, EFBufPanicNullBuf); |
|
1108 __FBUF64_ASSERT(iLength >= 0 && iLength <= iCapacity, EFBufPanicBufLen); |
|
1109 __FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos); |
|
1110 __FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize); |
|
1111 __FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle); |
|
1112 __FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos); |
|
1113 __FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits); |
|
1114 __FBUF64_ASSERT(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, EFBufPanicFileBlockSize); |
|
1115 } |
|
1116 |
|
1117 #endif |