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