Merge lp:~zorba-coders/zorba/bug-1042840 into lp:zorba
- bug-1042840
- Merge into trunk
Proposed by
Markos Zaharioudakis
Status: | Merged |
---|---|
Approved by: | Markos Zaharioudakis |
Approved revision: | 11005 |
Merged at revision: | 11005 |
Proposed branch: | lp:~zorba-coders/zorba/bug-1042840 |
Merge into: | lp:zorba |
Diff against target: |
427 lines (+181/-98) 3 files modified
ChangeLog (+1/-1) src/store/naive/qname_pool.cpp (+143/-67) src/store/naive/qname_pool.h (+37/-30) |
To merge this branch: | bzr merge lp:~zorba-coders/zorba/bug-1042840 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Markos Zaharioudakis | Approve | ||
Review via email: mp+121682@code.launchpad.net |
Commit message
Fixed bug #1042840 (qname pool free-list corruption)
Description of the change
Fixed bug #1042840 (qname pool free-list corruption)
To post a comment you must log in.
- 11005. By Markos Zaharioudakis
-
fixed bug #1042840$
Revision history for this message
Markos Zaharioudakis (markos-za) : | # |
review:
Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job bug-1042840-2012-08-
All tests succeeded!
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2012-08-28 07:15:46 +0000 |
3 | +++ ChangeLog 2012-08-28 19:26:23 +0000 |
4 | @@ -13,7 +13,7 @@ |
5 | * Fixed bug #1024892 (index declaration references udf declared after the index) |
6 | * Fixed bug #1038410 (Memory leaks in parser, trace iterator, and general index) |
7 | * Fixed bug #1039488 (inserting more than one pair at once in a JSON object) |
8 | - |
9 | + * Fixed bug #1042840 (qname pool free-list corruption) |
10 | |
11 | version 2.6 |
12 | |
13 | |
14 | === modified file 'src/store/naive/qname_pool.cpp' |
15 | --- src/store/naive/qname_pool.cpp 2012-08-28 07:03:17 +0000 |
16 | +++ src/store/naive/qname_pool.cpp 2012-08-28 19:26:23 +0000 |
17 | @@ -48,7 +48,7 @@ |
18 | QNameItem* qn = &theCache[1]; |
19 | QNameItem* last = qn + size - 1; |
20 | |
21 | - for (uint16_t i = 1; qn < last; qn++, i++) |
22 | + for (csize i = 1; qn < last; qn++, i++) |
23 | { |
24 | qn->theNextFree = i + 1; |
25 | qn->thePrevFree = i - 1; |
26 | @@ -82,23 +82,121 @@ |
27 | /******************************************************************************* |
28 | |
29 | ********************************************************************************/ |
30 | +void QNamePool::addInFreeList(QNameItem* qn) |
31 | +{ |
32 | + assert(qn->thePrevFree == 0); |
33 | + assert(qn->theNextFree == 0); |
34 | + assert(qn->getRefCount() == 0); |
35 | + assert(theCache[theFirstFree].thePrevFree == 0); |
36 | + |
37 | + qn->theNextFree = (uint16_t)theFirstFree; |
38 | + |
39 | + if (theFirstFree != 0) |
40 | + theCache[theFirstFree].thePrevFree = qn->thePosition; |
41 | + |
42 | + theFirstFree = qn->thePosition; |
43 | + |
44 | + theNumFree++; |
45 | +} |
46 | + |
47 | + |
48 | +/******************************************************************************* |
49 | + |
50 | +********************************************************************************/ |
51 | +void QNamePool::removeFromFreeList(QNameItem* qn) |
52 | +{ |
53 | + assert(qn->isInCache()); |
54 | + |
55 | + if (qn->theNextFree == 0 && qn->thePrevFree == 0) |
56 | + { |
57 | + // Either qn does not belong to the free list, or is the only one in the |
58 | + // free list |
59 | + |
60 | + if (theFirstFree != qn->thePosition) |
61 | + return; |
62 | + } |
63 | + |
64 | + assert(qn->getRefCount() == 0); |
65 | + |
66 | + if (qn->theNextFree != 0) |
67 | + { |
68 | + assert(theCache[qn->theNextFree].thePrevFree = qn->thePosition); |
69 | + |
70 | + theCache[qn->theNextFree].thePrevFree = qn->thePrevFree; |
71 | + } |
72 | + |
73 | + if (qn->thePrevFree != 0) |
74 | + { |
75 | + assert(theCache[qn->thePrevFree].theNextFree = qn->thePosition); |
76 | + |
77 | + theCache[qn->thePrevFree].theNextFree = qn->theNextFree; |
78 | + } |
79 | + else |
80 | + { |
81 | + assert(theFirstFree == qn->thePosition); |
82 | + |
83 | + theFirstFree = qn->theNextFree; |
84 | + } |
85 | + |
86 | + qn->theNextFree = qn->thePrevFree = 0; |
87 | + |
88 | + theNumFree--; |
89 | +} |
90 | + |
91 | + |
92 | +/******************************************************************************* |
93 | + |
94 | +********************************************************************************/ |
95 | +QNameItem* QNamePool::popFreeList() |
96 | +{ |
97 | + if (theFirstFree != 0) |
98 | + { |
99 | + assert(theNumFree > 0); |
100 | + |
101 | + QNameItem* qn = &theCache[theFirstFree]; |
102 | + |
103 | + assert(qn->getRefCount() == 0); |
104 | + |
105 | + theFirstFree = qn->theNextFree; |
106 | + |
107 | + if (theFirstFree != 0) |
108 | + { |
109 | + assert(theCache[theFirstFree].thePrevFree == qn->thePosition); |
110 | + theCache[theFirstFree].thePrevFree = 0; |
111 | + } |
112 | + |
113 | + qn->theNextFree = qn->thePrevFree = 0; |
114 | + |
115 | + theNumFree--; |
116 | + |
117 | + return qn; |
118 | + } |
119 | + else |
120 | + { |
121 | + assert(theNumFree == 0); |
122 | + return NULL; |
123 | + } |
124 | +} |
125 | + |
126 | + |
127 | +/******************************************************************************* |
128 | + |
129 | +********************************************************************************/ |
130 | void QNamePool::remove(QNameItem* qn) |
131 | { |
132 | QNameItem* normVictim = NULL; |
133 | |
134 | SYNC_CODE(theHashSet.theMutex.lock(); \ |
135 | - bool haveLock = true;) |
136 | + bool haveLock = true;) |
137 | |
138 | - try { |
139 | + try |
140 | + { |
141 | if (qn->getRefCount() > 0) |
142 | return; |
143 | |
144 | if (qn->isInCache()) |
145 | { |
146 | - qn->theNextFree = (uint16_t)theFirstFree; |
147 | - theCache[theFirstFree].thePrevFree = qn->thePosition; |
148 | - theFirstFree = qn->thePosition; |
149 | - theNumFree++; |
150 | + addInFreeList(qn); |
151 | } |
152 | else |
153 | { |
154 | @@ -114,13 +212,16 @@ |
155 | // Releasing the lock here to avoid deadlock, because decrementing the |
156 | // normVictim counter might reenter QNamePool::remove. |
157 | SYNC_CODE(theHashSet.theMutex.unlock(); \ |
158 | - haveLock = false;) |
159 | + haveLock = false;) |
160 | + |
161 | if (normVictim) |
162 | { |
163 | normVictim->removeReference(); |
164 | } |
165 | |
166 | - } catch(...) { |
167 | + } |
168 | + catch(...) |
169 | + { |
170 | SYNC_CODE(if (haveLock) \ |
171 | theHashSet.theMutex.unlock();) |
172 | |
173 | @@ -142,8 +243,7 @@ |
174 | store::Item_t QNamePool::insert( |
175 | const char* ns, |
176 | const char* pre, |
177 | - const char* ln, |
178 | - bool sync) |
179 | + const char* ln) |
180 | { |
181 | QNameItem* qn; |
182 | QNameItem* normVictim = NULL; |
183 | @@ -168,18 +268,16 @@ |
184 | SYNC_CODE(theHashSet.theMutex.lock();\ |
185 | haveLock = true;) |
186 | |
187 | - QNHashEntry* entry = hashFind(ns, pre, ln, |
188 | - (ulong)pooledNs.size(), |
189 | - (ulong)strlen(pre), |
190 | - (ulong)strlen(ln), |
191 | - hval); |
192 | + QNHashEntry* entry = |
193 | + hashFind(ns, pre, ln, pooledNs.size(), strlen(pre), strlen(ln), hval); |
194 | + |
195 | if (entry == 0) |
196 | { |
197 | if (normalized) |
198 | { |
199 | // Build a new QName (either new object or in cache). |
200 | qn = cacheInsert(normVictim); |
201 | - qn->initializeAsNormalizedQName(pooledNs, zstring(ln)); |
202 | + qn->initializeAsNormalizedQName(pooledNs, ln); |
203 | } |
204 | else |
205 | { |
206 | @@ -188,7 +286,7 @@ |
207 | SYNC_CODE(theHashSet.theMutex.unlock();\ |
208 | haveLock = false;) |
209 | |
210 | - normItem = insert(ns, NULL, ln, false); |
211 | + normItem = insert(ns, NULL, ln); |
212 | normQName = static_cast<QNameItem*>(normItem.getp()); |
213 | goto retry; |
214 | } |
215 | @@ -236,8 +334,7 @@ |
216 | store::Item_t QNamePool::insert( |
217 | const zstring& ns, |
218 | const zstring& pre, |
219 | - const zstring& ln, |
220 | - bool sync) |
221 | + const zstring& ln) |
222 | { |
223 | QNameItem* qn = NULL; |
224 | QNameItem* normVictim = NULL; |
225 | @@ -259,11 +356,11 @@ |
226 | SYNC_CODE(theHashSet.theMutex.lock();\ |
227 | haveLock = true;) |
228 | |
229 | - QNHashEntry* entry = hashFind(ns.c_str(), pre.c_str(), ln.c_str(), |
230 | - (ulong)ns.size(), |
231 | - (ulong)pre.size(), |
232 | - (ulong)ln.size(), |
233 | - hval); |
234 | + QNHashEntry* entry = |
235 | + hashFind(ns.c_str(), pre.c_str(), ln.c_str(), |
236 | + ns.size(), pre.size(), ln.size(), |
237 | + hval); |
238 | + |
239 | if (entry == 0) |
240 | { |
241 | if (normalized) |
242 | @@ -280,7 +377,7 @@ |
243 | haveLock = false;) |
244 | |
245 | // This call will need the lock. |
246 | - normItem = insert(pooledNs, zstring(), ln, false); |
247 | + normItem = insert(pooledNs, zstring(), ln); |
248 | normQName = static_cast<QNameItem*>(normItem.getp()); |
249 | |
250 | goto retry; |
251 | @@ -329,30 +426,23 @@ |
252 | ********************************************************************************/ |
253 | QNameItem* QNamePool::cacheInsert(QNameItem*& normVictim) |
254 | { |
255 | - assert (normVictim == NULL); |
256 | - if (theFirstFree != 0) |
257 | - { |
258 | - QNameItem* qn = &theCache[theFirstFree]; |
259 | - |
260 | - theFirstFree = qn->theNextFree; |
261 | - theCache[theFirstFree].thePrevFree = 0; |
262 | - |
263 | - if (qn->isValid()) |
264 | - { |
265 | - ulong hval = CompareFunction::hash(qn); |
266 | - theHashSet.eraseNoSync(qn, hval); |
267 | - qn->invalidate(true, &normVictim); |
268 | - } |
269 | - |
270 | - qn->theNextFree = qn->thePrevFree = 0; |
271 | - |
272 | - theNumFree--; |
273 | - return qn; |
274 | - } |
275 | - else |
276 | + assert(normVictim == NULL); |
277 | + |
278 | + QNameItem* qn = popFreeList(); |
279 | + |
280 | + if (qn == NULL) |
281 | { |
282 | return new QNameItem(); |
283 | } |
284 | + |
285 | + if (qn->isValid()) |
286 | + { |
287 | + ulong hval = CompareFunction::hash(qn); |
288 | + theHashSet.eraseNoSync(qn, hval); |
289 | + qn->invalidate(true, &normVictim); |
290 | + } |
291 | + |
292 | + return qn; |
293 | } |
294 | |
295 | |
296 | @@ -362,23 +452,9 @@ |
297 | ********************************************************************************/ |
298 | void QNamePool::cachePin(QNameItem* qn) |
299 | { |
300 | - if (qn->isInCache() && (qn->theNextFree != 0 || qn->thePrevFree != 0)) |
301 | + if (qn->isInCache()) |
302 | { |
303 | - if (qn->theNextFree != 0) |
304 | - theCache[qn->theNextFree].thePrevFree = qn->thePrevFree; |
305 | - |
306 | - if (qn->thePrevFree != 0) |
307 | - { |
308 | - theCache[qn->thePrevFree].theNextFree = qn->theNextFree; |
309 | - } |
310 | - else |
311 | - { |
312 | - assert(theFirstFree == qn->thePosition); |
313 | - theFirstFree = qn->theNextFree; |
314 | - } |
315 | - |
316 | - qn->theNextFree = qn->thePrevFree = 0; |
317 | - theNumFree--; |
318 | + removeFromFreeList(qn); |
319 | } |
320 | } |
321 | |
322 | @@ -390,10 +466,10 @@ |
323 | const char* ns, |
324 | const char* pre, |
325 | const char* ln, |
326 | - ulong nslen, |
327 | - ulong prelen, |
328 | - ulong lnlen, |
329 | - ulong hval) |
330 | + csize nslen, |
331 | + csize prelen, |
332 | + csize lnlen, |
333 | + csize hval) |
334 | { |
335 | QNHashEntry* entry = theHashSet.bucket(hval); |
336 | |
337 | |
338 | === modified file 'src/store/naive/qname_pool.h' |
339 | --- src/store/naive/qname_pool.h 2012-08-16 18:31:02 +0000 |
340 | +++ src/store/naive/qname_pool.h 2012-08-28 19:26:23 +0000 |
341 | @@ -32,22 +32,31 @@ |
342 | |
343 | /******************************************************************************* |
344 | |
345 | - theCache : An array of QName slots that is managed as a cache. This |
346 | - means that slots that are not used are placed in a free list. |
347 | - When a new qname is inserted in the cache, a slot is taken |
348 | - from the free list and the qname currently in that slot is |
349 | - replaced with the new slot. |
350 | - theCacheSize : The size of theCache (number of slots). This size is given |
351 | - as a param to the QNamePool constructor, and it never changes |
352 | - afterwards. |
353 | - theFirstFree : The position in theCache of the 1st free slot. NOTE: the 1st |
354 | - slot of theCache (at position 0) is reserved (i.e., never |
355 | - used) so that position 0 can be used to indicate the end of |
356 | - the free list. |
357 | - theNumFree : Number of free slots in theCache. |
358 | - |
359 | - theHashSet : A hash set mapping qnames (i.e. triplets of strings) to |
360 | - QName slots. |
361 | + theCache : |
362 | + ---------- |
363 | + An array of QName slots that is managed as a cache. This means that slots that |
364 | + are not used are placed in a free list. When a new qname is inserted in the |
365 | + cache, a slot is taken from the free list and the qname currently in that slot |
366 | + is replaced with the new slot. |
367 | + |
368 | + theCacheSize : |
369 | + -------------- |
370 | + The size of theCache (number of slots). This size is given as a param to the |
371 | + QNamePool constructor, and it never changes afterwards. |
372 | + |
373 | + theFirstFree : |
374 | + -------------- |
375 | + The position in theCache of the 1st free slot. NOTE: the 1st slot of theCache |
376 | + (at position 0) is reserved (i.e., never used) so that position 0 can be used |
377 | + to indicate the end of the free list. |
378 | + |
379 | + theNumFree : |
380 | + ------------ |
381 | + Number of free slots in theCache. |
382 | + |
383 | + theHashSet : |
384 | + ------------ |
385 | + A hash set mapping qnames (i.e. triplets of strings) to QName slots. |
386 | |
387 | ********************************************************************************/ |
388 | class QNamePool |
389 | @@ -106,17 +115,9 @@ |
390 | |
391 | ~QNamePool(); |
392 | |
393 | - store::Item_t insert( |
394 | - const char* ns, |
395 | - const char* pre, |
396 | - const char* ln, |
397 | - bool sync = true); |
398 | + store::Item_t insert(const char* ns, const char* pre, const char* ln); |
399 | |
400 | - store::Item_t insert( |
401 | - const zstring& ns, |
402 | - const zstring& pre, |
403 | - const zstring& ln, |
404 | - bool sync = true); |
405 | + store::Item_t insert(const zstring& ns, const zstring& pre, const zstring& ln); |
406 | |
407 | void remove(QNameItem* qn); |
408 | |
409 | @@ -129,10 +130,16 @@ |
410 | const char* ns, |
411 | const char* pre, |
412 | const char* ln, |
413 | - ulong nslen, |
414 | - ulong prelen, |
415 | - ulong lnlen, |
416 | - ulong hval); |
417 | + csize nslen, |
418 | + csize prelen, |
419 | + csize lnlen, |
420 | + csize hval); |
421 | + |
422 | + void addInFreeList(QNameItem* qn); |
423 | + |
424 | + void removeFromFreeList(QNameItem* qn); |
425 | + |
426 | + QNameItem* popFreeList(); |
427 | }; |
428 | |
429 |
Validation queue starting for merge proposal. zorbatest. lambda. nu:8080/ remotequeue/ bug-1042840- 2012-08- 28T19-42- 04.317Z/ log.html
Log at: http://