|
1 // Copyright (c) 2004-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 // This file holds the class methods for the CFbTopMBMCache |
|
15 // |
|
16 // |
|
17 |
|
18 #include "FBSMBMC.H" |
|
19 |
|
20 |
|
21 // |
|
22 //Constructor for CFbTopMBMCache objects with both forward and backward cache size |
|
23 //The forward(backward) cache size determines the number of stream ids after(before) |
|
24 //the current loaded bitmap ids to be stored in the cache |
|
25 //e.g Loading a bitmap with id=20 from a 40 bitmaps mbm file will load the cache(10,10) |
|
26 //with stream ids from 30-39(10 backward) and 40-49(10 forward) |
|
27 CFbTopStreamIdCache::CFbTopStreamIdCache(TInt aForwardSize, TInt aBackwardSize, TInt aMaxFilestores) |
|
28 :CBase(), |
|
29 iEntries(aMaxFilestores), |
|
30 iForwardCacheSize(aForwardSize), |
|
31 iBackwardCacheSize(aBackwardSize), |
|
32 iMaxCacheFilestores(aMaxFilestores) |
|
33 { |
|
34 } |
|
35 |
|
36 // |
|
37 //Destructor of CFbTopMBMCache objects |
|
38 CFbTopStreamIdCache::~CFbTopStreamIdCache() |
|
39 { |
|
40 FlushCache(); |
|
41 } |
|
42 |
|
43 //Function to reset all the internal state of the class |
|
44 void CFbTopStreamIdCache::FlushCache() |
|
45 { |
|
46 CloseFileStores(); |
|
47 iEntries.Reset(); |
|
48 User::Free(iBuffer); |
|
49 iBuffer = NULL; |
|
50 } |
|
51 |
|
52 |
|
53 //Function to get the most recently used filestore stored in the cache |
|
54 CShiftedFileStore* CFbTopStreamIdCache::MruFileStore() |
|
55 { |
|
56 return iEntries[0]->FileStore(); |
|
57 } |
|
58 |
|
59 //Function to get the stream id for a bitmap id from a mbm file with certain offset. |
|
60 //It also fills up the cache with the stream ids for different bitmap from the same |
|
61 //mbm file and the number of stream ids stored depend on the initial setting of the |
|
62 //cache size. Also associates each resource with a client handle to improve the |
|
63 //performance of cleaning up. |
|
64 TStreamId CFbTopStreamIdCache::GetStreamIdL(RFile& aFile,const TDesC& aFilename,TInt32 aId,TUint aFileOffset, TInt aSessionHandle) |
|
65 { |
|
66 if (aId < 0) |
|
67 { |
|
68 User::Leave(KErrEof); |
|
69 } |
|
70 RCacheEntry *entry = FindCacheEntry(aFilename, aFileOffset); |
|
71 if (entry == NULL) |
|
72 { |
|
73 entry = AddCacheEntryL(aFilename, aFileOffset); |
|
74 } |
|
75 entry->CreateFileStoreL(aFile, aSessionHandle); |
|
76 return entry->GetStreamIdL(aId, iForwardCacheSize, iBackwardCacheSize); |
|
77 } |
|
78 |
|
79 /** |
|
80 The overloaded version of GetStreamIdL which works with file session instead of file handle. |
|
81 */ |
|
82 TStreamId CFbTopStreamIdCache::GetStreamIdL(RFs& aFs, const TDesC& aFileName,TInt32 aId,TUint aFileOffset, TInt aSessionHandle) |
|
83 { |
|
84 if (aId < 0) |
|
85 { |
|
86 User::Leave(KErrEof); |
|
87 } |
|
88 RCacheEntry *entry = FindCacheEntry(aFileName, aFileOffset); |
|
89 if (entry == NULL) |
|
90 { |
|
91 entry = AddCacheEntryL(aFileName, aFileOffset); |
|
92 } |
|
93 entry->CreateFileStoreL(aFs, aFileName, aSessionHandle); |
|
94 return entry->GetStreamIdL(aId, iForwardCacheSize, iBackwardCacheSize); |
|
95 } |
|
96 |
|
97 void CFbTopStreamIdCache::CloseFileStores(TInt aSessionHandle) |
|
98 { |
|
99 TInt n = iEntries.Count(); |
|
100 for (TInt i = 0; i < n; ++i) |
|
101 { |
|
102 if (!aSessionHandle || aSessionHandle == iEntries[i]->SessionHandle()) |
|
103 iEntries[i]->CloseFileStore(); |
|
104 } |
|
105 } |
|
106 |
|
107 CFbTopStreamIdCache::RCacheEntry* CFbTopStreamIdCache::AddCacheEntryL(const TDesC& aFilename, TUint aFileOffset) |
|
108 { |
|
109 RCacheEntry *entry; |
|
110 TInt n = iEntries.Count(); |
|
111 if (n < iMaxCacheFilestores) |
|
112 { |
|
113 TInt size = RCacheEntry::KBaseSize + (iForwardCacheSize + iBackwardCacheSize) * sizeof(TStreamId); |
|
114 if (iBuffer == NULL) |
|
115 iBuffer = static_cast<TUint8*>(User::AllocL(iMaxCacheFilestores * size)); |
|
116 entry = reinterpret_cast<RCacheEntry*>(iBuffer + n * size); |
|
117 } |
|
118 else |
|
119 { |
|
120 entry = iEntries[--n]; |
|
121 entry->CloseFileStore(); |
|
122 iEntries.Remove(n); |
|
123 } |
|
124 iEntries.InsertL(entry, 0); |
|
125 return new(entry) RCacheEntry(aFilename, aFileOffset); |
|
126 } |
|
127 |
|
128 CFbTopStreamIdCache::RCacheEntry* CFbTopStreamIdCache::FindCacheEntry(const TDesC& aFilename, TUint aFileOffset) |
|
129 { |
|
130 TInt n = iEntries.Count(); |
|
131 for (TInt i = 0; i < n; ++i) |
|
132 { |
|
133 RCacheEntry *entry = iEntries[i]; |
|
134 if (entry->SameFile(aFilename, aFileOffset)) |
|
135 { |
|
136 if (i > 0) |
|
137 { |
|
138 iEntries.Remove(i); // Keep least-recently-used order |
|
139 iEntries.Insert(entry, 0); // Cannot fail |
|
140 } |
|
141 return entry; |
|
142 } |
|
143 } |
|
144 return NULL; |
|
145 } |
|
146 |
|
147 |
|
148 const TInt CFbTopStreamIdCache::RCacheEntry::KBaseSize = _FOFF(CFbTopStreamIdCache::RCacheEntry, iStreamIdCache); |
|
149 |
|
150 |
|
151 CFbTopStreamIdCache::RCacheEntry::RCacheEntry(const TDesC& aFilename, TUint aFileOffset) |
|
152 : iFilename(aFilename), |
|
153 iFileOffset(aFileOffset), |
|
154 iFilestore(NULL), |
|
155 iLastId(KErrNotFound), |
|
156 iStreamIdCount(0), |
|
157 iSessionHandle(0) |
|
158 { |
|
159 } |
|
160 |
|
161 TBool CFbTopStreamIdCache::RCacheEntry::SameFile(const TDesC& aFilename, TUint aFileOffset) |
|
162 { |
|
163 return !aFilename.Compare(iFilename) && aFileOffset == iFileOffset; |
|
164 } |
|
165 |
|
166 TStreamId CFbTopStreamIdCache::RCacheEntry::GetStreamIdL(TInt32 aId, TInt aForwardSize, TInt aBackwardSize) |
|
167 { |
|
168 if (iLastId >= 0 && aId >= iLastId - aBackwardSize && aId < iLastId + aForwardSize) |
|
169 { |
|
170 TInt startindex = iLastId < aBackwardSize ? 0 : iLastId - aBackwardSize; |
|
171 // ensure aId exists in the MBM file |
|
172 // cache size previously set using the number of bitmaps |
|
173 if (aId - startindex >= iStreamIdCount) |
|
174 User::Leave(KErrEof); |
|
175 return iStreamIdCache[aId - startindex]; |
|
176 } |
|
177 //Flush the cache array |
|
178 iLastId = KErrNotFound; |
|
179 iStreamIdCount = 0; |
|
180 |
|
181 //Extracting the header stream parameters numbitmaps and the stream ids |
|
182 TStreamId bmpstreamid(iFilestore->Root().Value() + iFileOffset); |
|
183 RStoreReadStream readstream; |
|
184 readstream.OpenLC(*iFilestore, bmpstreamid); |
|
185 TInt numbitmaps = readstream.ReadInt32L(); |
|
186 if (aId >= numbitmaps) |
|
187 User::Leave(KErrEof); |
|
188 TInt endcount = aId + aForwardSize; |
|
189 //if endcount is greater than the numbitmaps we need to truncate it so we |
|
190 //never overread and cause panic. |
|
191 if (endcount > numbitmaps) |
|
192 endcount = numbitmaps; |
|
193 for (TInt count = 0; count < endcount; ++count) |
|
194 { |
|
195 bmpstreamid.InternalizeL(readstream); |
|
196 bmpstreamid=TStreamId(bmpstreamid.Value() + iFileOffset); |
|
197 if (count >= aId - aBackwardSize) |
|
198 iStreamIdCache[iStreamIdCount++] = bmpstreamid; |
|
199 } |
|
200 //get the stream id of the requested bitmap id |
|
201 TInt startindex = aId < aBackwardSize ? 0 : aId - aBackwardSize; |
|
202 bmpstreamid = iStreamIdCache[aId - startindex]; |
|
203 CleanupStack::PopAndDestroy(); |
|
204 // iLastId is updated just before returning to ensure that for error cases |
|
205 // the cache is not used in subsequent calls to this method. |
|
206 iLastId = aId; |
|
207 return bmpstreamid; |
|
208 } |
|
209 |
|
210 CShiftedFileStore* CFbTopStreamIdCache::RCacheEntry::FileStore() |
|
211 { |
|
212 return iFilestore; |
|
213 } |
|
214 |
|
215 TInt CFbTopStreamIdCache::RCacheEntry::SessionHandle() const |
|
216 { |
|
217 return iSessionHandle; |
|
218 } |
|
219 |
|
220 void CFbTopStreamIdCache::RCacheEntry::CloseFileStore() |
|
221 { |
|
222 delete iFilestore; |
|
223 iFilestore = NULL; |
|
224 iSessionHandle = 0; |
|
225 } |
|
226 |
|
227 /** |
|
228 It creates a file store if is not there i.e. if iFileStore is NULL. |
|
229 |
|
230 @param aFile the mbm or rsc file handle |
|
231 @param aSessionHandle the associated client session handle |
|
232 */ |
|
233 void CFbTopStreamIdCache::RCacheEntry::CreateFileStoreL(RFile& aFile, TInt aSessionHandle) |
|
234 { |
|
235 if (iFilestore == NULL) |
|
236 { |
|
237 iFilestore = CShiftedFileStore::FromL(aFile, iFileOffset); |
|
238 iSessionHandle = aSessionHandle; |
|
239 } |
|
240 } |
|
241 |
|
242 /** |
|
243 It creates a file store if is not there i.e. if iFileStore is NULL. |
|
244 |
|
245 @param aFs the associated file session handle |
|
246 @param aFileName the mbm or rsc file name |
|
247 @param aSessionHandle the associated client session handle |
|
248 */ |
|
249 void CFbTopStreamIdCache::RCacheEntry::CreateFileStoreL(RFs& aFs, const TDesC& aFileName, TInt aSessionHandle) |
|
250 { |
|
251 if (iFilestore == NULL) |
|
252 { |
|
253 RFile file; |
|
254 User::LeaveIfError(file.Open(aFs,aFileName,EFileShareReadersOnly)); |
|
255 iFilestore = CShiftedFileStore::FromL(file, iFileOffset); |
|
256 iSessionHandle = aSessionHandle; |
|
257 } |
|
258 } |