|
1 // Copyright (c) 2002-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 |
|
16 #include "LogServCacheStrings.h" |
|
17 #include "LogServDatabaseTransactionInterface.h" |
|
18 #include "logservpanic.h" |
|
19 #include "LogServSqlStrings.h" |
|
20 |
|
21 /** |
|
22 Strings array granularity. |
|
23 @internalComponent |
|
24 */ |
|
25 const TInt KLogNumberOfInitialStrings = 16; |
|
26 |
|
27 ///////////////////////////////////////////////////////////////////////////////////////// |
|
28 // -----> CLogServCacheStrings (source) |
|
29 ///////////////////////////////////////////////////////////////////////////////////////// |
|
30 |
|
31 CLogServCacheStrings::CLogServCacheStrings(MLogServDatabaseTransactionInterface& aDatabase) : |
|
32 iDatabase(aDatabase), |
|
33 iStrings(KLogNumberOfInitialStrings) |
|
34 { |
|
35 } |
|
36 |
|
37 CLogServCacheStrings::~CLogServCacheStrings() |
|
38 { |
|
39 DestroyCache(); |
|
40 } |
|
41 |
|
42 void CLogServCacheStrings::DestroyCache() |
|
43 { |
|
44 for(TInt i=iStrings.Count()-1;i>=0;--i) |
|
45 { |
|
46 TLogServCacheStringEntry::DeleteEntry(iStrings[i]); |
|
47 } |
|
48 iStrings.Close(); |
|
49 } |
|
50 |
|
51 void CLogServCacheStrings::ConstructL() |
|
52 { |
|
53 ReadStringsFromDatabaseL(); |
|
54 } |
|
55 |
|
56 CLogServCacheStrings* CLogServCacheStrings::NewL(MLogServDatabaseTransactionInterface& aDatabase) |
|
57 { |
|
58 CLogServCacheStrings* self = new(ELeave) CLogServCacheStrings(aDatabase); |
|
59 CleanupStack::PushL(self); |
|
60 self->ConstructL(); |
|
61 CleanupStack::Pop(self); |
|
62 return self; |
|
63 } |
|
64 |
|
65 ///////////////////////////////////////////////////////////////////////////////////////// |
|
66 ///////////////////////////////////////////////////////////////////////////////////////// |
|
67 ///////////////////////////////////////////////////////////////////////////////////////// |
|
68 |
|
69 /** |
|
70 Find the descriptor corresponding to a given string id. KNullDesC if the id is not found. |
|
71 */ |
|
72 const TPtrC CLogServCacheStrings::FindString(TLogStringId aId) const |
|
73 { |
|
74 if(aId != KLogNullStringId) |
|
75 { |
|
76 for(TInt i=iStrings.Count()-1;i>=0;--i) |
|
77 { |
|
78 if(iStrings[i]->iId == aId) |
|
79 { |
|
80 return iStrings[i]->String(); |
|
81 } |
|
82 } |
|
83 } |
|
84 return KNullDesC(); |
|
85 } |
|
86 |
|
87 |
|
88 /** |
|
89 Find the id of a given string. KLogNullStringId if no string is found. |
|
90 */ |
|
91 TLogStringId CLogServCacheStrings::FindId(const TDesC& aString) |
|
92 { |
|
93 if(aString.Length() == 0) |
|
94 { |
|
95 return KLogNullStringId; |
|
96 } |
|
97 TInt position = iStrings.FindInOrder(aString, &CLogServCacheStrings::Compare1); |
|
98 return position >= 0 ? iStrings[position]->iId : KLogNullStringId; |
|
99 } |
|
100 |
|
101 /** |
|
102 Find the id of a given string. Add the string to the cache if the string is not there. |
|
103 If the aString length is 0, then do not search the cache, do not add the string, just return KLogNullStringId. |
|
104 If the string has to be added - the string will be added to the cache and |
|
105 a new record will be inserted into the database. |
|
106 If the database is in transaction, the string in the cache will have its "dirty" flag set. During the rollback |
|
107 (if a rollback occurs) all strings with "dirty" flag set will be removed from the cache. |
|
108 The idea is to keep the cache content consistent with the database content. |
|
109 */ |
|
110 TLogStringId CLogServCacheStrings::GetIdL(const TDesC& aString) |
|
111 { |
|
112 if(aString.Length() == 0) |
|
113 { |
|
114 return KLogNullStringId; |
|
115 } |
|
116 TLogStringId id = FindId(aString); |
|
117 if(id == KLogNullStringId) |
|
118 { |
|
119 id = DoAddStringL(aString); |
|
120 } |
|
121 return id; |
|
122 } |
|
123 |
|
124 /** |
|
125 Clears the dirty flag of the cache entries that have been added during the last transaction. |
|
126 */ |
|
127 void CLogServCacheStrings::Commit() |
|
128 { |
|
129 if(iDirty) |
|
130 { |
|
131 for(TInt i=iStrings.Count()-1;i>=0;--i) |
|
132 { |
|
133 iStrings[i]->iDirty = EFalse; |
|
134 } |
|
135 iDirty = EFalse; |
|
136 } |
|
137 } |
|
138 |
|
139 |
|
140 /** |
|
141 Removes any strings added to the cache of strings since the beginning of last transaction (with iDirty flag set). |
|
142 */ |
|
143 void CLogServCacheStrings::Rollback() |
|
144 { |
|
145 if(iDirty) |
|
146 { |
|
147 for(TInt i=iStrings.Count()-1;i>=0;--i) |
|
148 { |
|
149 if(iStrings[i]->iDirty) |
|
150 { |
|
151 TLogServCacheStringEntry::DeleteEntry(iStrings[i]); |
|
152 iStrings.Remove(i); |
|
153 } |
|
154 } |
|
155 iDirty = EFalse; |
|
156 } |
|
157 } |
|
158 |
|
159 ///////////////////////////////////////////////////////////////////////////////////////// |
|
160 ///////////////////////////////////////////////////////////////////////////////////////// |
|
161 ///////////////////////////////////////////////////////////////////////////////////////// |
|
162 |
|
163 void CLogServCacheStrings::ReadStringsFromDatabaseL() |
|
164 { |
|
165 DestroyCache(); |
|
166 RDbTable tbl; |
|
167 CleanupClosePushL(tbl); |
|
168 User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString, RDbRowSet::EReadOnly)); |
|
169 if(tbl.FirstL()) |
|
170 { |
|
171 InitializeColNumsL(tbl); |
|
172 iStrings.ReserveL(tbl.CountL()); |
|
173 do |
|
174 { |
|
175 tbl.GetL(); |
|
176 const TLogStringId id = tbl.ColInt16(iIdColNo); |
|
177 const TPtrC pString(tbl.ColDes(iStringColNo)); |
|
178 TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2); |
|
179 TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryL(id, pString); |
|
180 TInt err = iStrings.InsertInOrder(entry, orderer); |
|
181 __ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved)); |
|
182 } |
|
183 while(tbl.NextL()); |
|
184 } |
|
185 CleanupStack::PopAndDestroy(&tbl); |
|
186 } |
|
187 |
|
188 //Atomic "add string to cache" operation. |
|
189 TLogStringId CLogServCacheStrings::DoAddStringL(const TDesC& aString) |
|
190 { |
|
191 //Reserve space for the new string in the cache |
|
192 iStrings.ReserveL(iStrings.Count() + 1); |
|
193 //Open the database table and push it on the cleanup stack. |
|
194 //If the InitializeColNumsL() operation leaves then the table will be closed automatically. |
|
195 RDbTable tbl; |
|
196 CleanupClosePushL(tbl); |
|
197 User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString)); |
|
198 InitializeColNumsL(tbl); |
|
199 //Allocate space for the new record in the table. Push the Cancel() function on the cleanup stack. |
|
200 //If some of the next calls leaves, the insert operation will be automatically cancelled. |
|
201 tbl.InsertL(); |
|
202 const TLogStringId id = tbl.ColInt16(iIdColNo); |
|
203 tbl.SetColL(iStringColNo, aString); |
|
204 //Create new cache entry and push it on the cleanup stack. |
|
205 TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryLC(id, aString, iDatabase.DTIInTransaction()); |
|
206 //Finish the "insert record" operation. If PutL() leaves, then: |
|
207 // - the new cache entry is deleted |
|
208 // - the insert operation is cancelled |
|
209 // - the table is closed |
|
210 tbl.PutL(); |
|
211 //Pop the entry and the Cancel() from the cleanup stack. Close the table. |
|
212 CleanupStack::Pop();//TLogServCacheStringEntry |
|
213 CleanupStack::PopAndDestroy(&tbl); |
|
214 //The next operation is guaranteed to be a non-failing "add entry" operation. |
|
215 TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2); |
|
216 TInt err = iStrings.InsertInOrder(entry, orderer); |
|
217 __ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved)); |
|
218 //Mark the cache as dirty. Later if there was an outstanding transaction and that transaction failed, |
|
219 //The database rollback operation will restore the original state of the table. |
|
220 //The CLogServCacheStrings::RollbackAddStringsL() will remove from the cache all "dirty" strings. |
|
221 iDirty = ETrue; |
|
222 return id; |
|
223 } |
|
224 |
|
225 TInt CLogServCacheStrings::Compare1(const TDesC* aString, TLogServCacheStringEntry* const& aRight) |
|
226 { |
|
227 __ASSERT_DEBUG(aString != NULL, Panic(ELogStringsCacheNullArg1)); |
|
228 __ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg1)); |
|
229 return aString->Compare(aRight->String()); |
|
230 } |
|
231 |
|
232 TInt CLogServCacheStrings::Compare2(TLogServCacheStringEntry* const& aLeft, TLogServCacheStringEntry* const& aRight) |
|
233 { |
|
234 __ASSERT_DEBUG(aLeft != NULL, Panic(ELogStringsCacheNullArg2)); |
|
235 __ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg2)); |
|
236 return aLeft->String().Compare(aRight->String()); |
|
237 } |
|
238 |
|
239 void CLogServCacheStrings::InitializeColNumsL(RDbRowSet& aRowSet) |
|
240 { |
|
241 if(iIdColNo == 0) |
|
242 { |
|
243 CDbColSet* colset = aRowSet.ColSetL(); |
|
244 iIdColNo = colset->ColNo(KLogFieldStringIdString); |
|
245 iStringColNo = colset->ColNo(KLogFieldStringTextString); |
|
246 delete colset; |
|
247 } |
|
248 __ASSERT_DEBUG(iIdColNo > 0, Panic(ELogInvalidStringColNo)); |
|
249 __ASSERT_DEBUG(iStringColNo > 0, Panic(ELogInvalidStringColNo)); |
|
250 } |
|
251 |
|
252 void CLogServCacheStrings::TLogServCacheStringEntry::CleanupEntry(TAny* aEntry) |
|
253 { |
|
254 TLogServCacheStringEntry* entry = reinterpret_cast <TLogServCacheStringEntry*> (aEntry); |
|
255 CLogServCacheStrings::TLogServCacheStringEntry::DeleteEntry(entry); |
|
256 } |