File: | src/BTrees/MergeTemplate.c |
Function: | bucket_merge |
Error: | ob_refcnt of new ref from (unknown) merge_error is 1 too high |
88 static PyObject *
89 bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
90 {
91 Bucket *r=0;
92 PyObject *s;
93 SetIteration i1 = {0,0,0}, i2 = {0,0,0}, i3 = {0,0,0};
94 int cmp12, cmp13, cmp23, mapping, set;
95
96 /* If either "after" bucket is empty, punt. */
97 if (s2->len == 0 || s3->len == 0)
when considering range: -0x80000000 <= value <= -1
taking False path
when considering range: -0x80000000 <= value <= -1
taking False path
98 {
99 merge_error(-1, -1, -1, 12);
100 goto err;
101 }
102
103 if (initSetIteration(&i1, OBJECT(s1), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
104 goto err;
105 if (initSetIteration(&i2, OBJECT(s2), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
106 goto err;
107 if (initSetIteration(&i3, OBJECT(s3), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
108 goto err;
109
110 mapping = i1.usesValue | i2.usesValue | i3.usesValue;
111 set = !mapping;
when considering range: -0x80000000 <= value <= -1
112
113 if (mapping)
taking True path
114 r = (Bucket *)PyObject_CallObject((PyObject *)&BucketType, NULL);
when PyObject_CallObject() succeeds
115 else
116 r = (Bucket *)PyObject_CallObject((PyObject *)&SetType, NULL);
117 if (r == NULL)
taking False path
118 goto err;
119
120 if (i1.next(&i1) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:120
when considering range: 0 <= value <= 0x7fffffff
taking False path
121 goto err;
122 if (i2.next(&i2) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:122
when considering range: 0 <= value <= 0x7fffffff
taking False path
123 goto err;
124 if (i3.next(&i3) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:124
when considering range: 0 <= value <= 0x7fffffff
taking False path
125 goto err;
126
127 /* Consult zodb/btrees/interfaces.py for the meaning of the last
128 * argument passed to merge_error().
129 */
130 /* TODO: This isn't passing on errors raised by value comparisons. */
131 while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
132 {
133 TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
134 TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
135 if (cmp12==0)
136 {
137 if (cmp13==0)
138 {
139 if (set || (TEST_VALUE(i1.value, i2.value) == 0))
140 { /* change in i3 value or all same */
141 if (merge_output(r, &i3, mapping) < 0) goto err;
142 }
143 else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
144 { /* change in i2 value */
145 if (merge_output(r, &i2, mapping) < 0) goto err;
146 }
147 else
148 { /* conflicting value changes in i2 and i3 */
149 merge_error(i1.position, i2.position, i3.position, 1);
150 goto err;
151 }
152 if (i1.next(&i1) < 0) goto err;
153 if (i2.next(&i2) < 0) goto err;
154 if (i3.next(&i3) < 0) goto err;
155 }
156 else if (cmp13 > 0)
157 { /* insert i3 */
158 if (merge_output(r, &i3, mapping) < 0) goto err;
159 if (i3.next(&i3) < 0) goto err;
160 }
161 else if (set || (TEST_VALUE(i1.value, i2.value) == 0))
162 { /* deleted in i3 */
163 if (i3.position == 1)
164 {
165 /* Deleted the first item. This will modify the
166 parent node, so we don't know if merging will be
167 safe
168 */
169 merge_error(i1.position, i2.position, i3.position, 13);
170 goto err;
171 }
172 if (i1.next(&i1) < 0) goto err;
173 if (i2.next(&i2) < 0) goto err;
174 }
175 else
176 { /* conflicting del in i3 and change in i2 */
177 merge_error(i1.position, i2.position, i3.position, 2);
178 goto err;
179 }
180 }
181 else if (cmp13 == 0)
182 {
183 if (cmp12 > 0)
184 { /* insert i2 */
185 if (merge_output(r, &i2, mapping) < 0) goto err;
186 if (i2.next(&i2) < 0) goto err;
187 }
188 else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
189 { /* deleted in i2 */
190 if (i2.position == 1)
191 {
192 /* Deleted the first item. This will modify the
193 parent node, so we don't know if merging will be
194 safe
195 */
196 merge_error(i1.position, i2.position, i3.position, 13);
197 goto err;
198 }
199 if (i1.next(&i1) < 0) goto err;
200 if (i3.next(&i3) < 0) goto err;
201 }
202 else
203 { /* conflicting del in i2 and change in i3 */
204 merge_error(i1.position, i2.position, i3.position, 3);
205 goto err;
206 }
207 }
208 else
209 { /* Both keys changed */
210 TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
211 if (cmp23==0)
212 { /* dueling inserts or deletes */
213 merge_error(i1.position, i2.position, i3.position, 4);
214 goto err;
215 }
216 if (cmp12 > 0)
217 { /* insert i2 */
218 if (cmp23 > 0)
219 { /* insert i3 first */
220 if (merge_output(r, &i3, mapping) < 0) goto err;
221 if (i3.next(&i3) < 0) goto err;
222 }
223 else
224 { /* insert i2 first */
225 if (merge_output(r, &i2, mapping) < 0) goto err;
226 if (i2.next(&i2) < 0) goto err;
227 }
228 }
229 else if (cmp13 > 0)
230 { /* Insert i3 */
231 if (merge_output(r, &i3, mapping) < 0) goto err;
232 if (i3.next(&i3) < 0) goto err;
233 }
234 else
235 { /* 1<2 and 1<3: both deleted 1.key */
236 merge_error(i1.position, i2.position, i3.position, 5);
237 goto err;
238 }
239 }
240 }
241
242 while (i2.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
243 { /* New inserts */
244 TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
245 if (cmp23==0)
246 { /* dueling inserts */
247 merge_error(i1.position, i2.position, i3.position, 6);
248 goto err;
249 }
250 if (cmp23 > 0)
251 { /* insert i3 */
252 if (merge_output(r, &i3, mapping) < 0) goto err;
253 if (i3.next(&i3) < 0) goto err;
254 }
255 else
256 { /* insert i2 */
257 if (merge_output(r, &i2, mapping) < 0) goto err;
258 if (i2.next(&i2) < 0) goto err;
259 }
260 }
261
262 while (i1.position >= 0 && i2.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
263 { /* remainder of i1 deleted in i3 */
264 TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
265 if (cmp12 > 0)
266 { /* insert i2 */
267 if (merge_output(r, &i2, mapping) < 0) goto err;
268 if (i2.next(&i2) < 0) goto err;
269 }
270 else if (cmp12==0 && (set || (TEST_VALUE(i1.value, i2.value) == 0)))
271 { /* delete i3 */
272 if (i1.next(&i1) < 0) goto err;
273 if (i2.next(&i2) < 0) goto err;
274 }
275 else
276 { /* Dueling deletes or delete and change */
277 merge_error(i1.position, i2.position, i3.position, 7);
278 goto err;
279 }
280 }
281
282 while (i1.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
283 { /* remainder of i1 deleted in i2 */
284 TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
285 if (cmp13 > 0)
286 { /* insert i3 */
287 if (merge_output(r, &i3, mapping) < 0) goto err;
288 if (i3.next(&i3) < 0) goto err;
289 }
290 else if (cmp13==0 && (set || (TEST_VALUE(i1.value, i3.value) == 0)))
291 { /* delete i2 */
292 if (i1.next(&i1) < 0) goto err;
293 if (i3.next(&i3) < 0) goto err;
294 }
295 else
296 { /* Dueling deletes or delete and change */
297 merge_error(i1.position, i2.position, i3.position, 8);
298 goto err;
299 }
300 }
301
302 if (i1.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
303 { /* Dueling deletes */
304 merge_error(i1.position, i2.position, i3.position, 9);
305 goto err;
306 }
307
308 while (i2.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
309 { /* Inserting i2 at end */
310 if (merge_output(r, &i2, mapping) < 0) goto err;
311 if (i2.next(&i2) < 0) goto err;
312 }
313
314 while (i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
315 { /* Inserting i3 at end */
316 if (merge_output(r, &i3, mapping) < 0) goto err;
317 if (i3.next(&i3) < 0) goto err;
318 }
319
320 /* If the output bucket is empty, conflict resolution doesn't have
321 * enough info to unlink it from its containing BTree correctly.
322 */
323 if (r->len == 0)
when considering value == (int)0 from src/BTrees/MergeTemplate.c:323
taking True path
324 {
325 merge_error(-1, -1, -1, 10);
when merge_error() succeeds
new ref from (unknown) merge_error allocated at: merge_error(-1, -1, -1, 10);
ob_refcnt is now refs: 1 + N where N >= 0
326 goto err;
327 }
328
329 finiSetIteration(&i1);
330 finiSetIteration(&i2);
331 finiSetIteration(&i3);
332
333 if (s1->next)
334 {
335 Py_INCREF(s1->next);
336 r->next = s1->next;
337 }
338 s = bucket_getstate(r);
339 Py_DECREF(r);
340
341 return s;
342
343 err:
344 finiSetIteration(&i1);
345 finiSetIteration(&i2);
346 finiSetIteration(&i3);
347 Py_XDECREF(r);
taking False path
when taking True path
348 return NULL;
349 }
ob_refcnt of new ref from (unknown) merge_error is 1 too high
was expecting final ob_refcnt to be N + 0 (for some unknown N)
but final ob_refcnt is N + 1
File: | src/BTrees/MergeTemplate.c |
Function: | bucket_merge |
Error: | returning (PyObject*)NULL without setting an exception |
88 static PyObject *
89 bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
90 {
91 Bucket *r=0;
92 PyObject *s;
93 SetIteration i1 = {0,0,0}, i2 = {0,0,0}, i3 = {0,0,0};
94 int cmp12, cmp13, cmp23, mapping, set;
95
96 /* If either "after" bucket is empty, punt. */
97 if (s2->len == 0 || s3->len == 0)
when considering range: -0x80000000 <= value <= -1
taking False path
when considering range: -0x80000000 <= value <= -1
taking False path
98 {
99 merge_error(-1, -1, -1, 12);
100 goto err;
101 }
102
103 if (initSetIteration(&i1, OBJECT(s1), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
104 goto err;
105 if (initSetIteration(&i2, OBJECT(s2), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
106 goto err;
107 if (initSetIteration(&i3, OBJECT(s3), 1) < 0)
when considering range: 0 <= value <= 0x7fffffff
taking False path
108 goto err;
109
110 mapping = i1.usesValue | i2.usesValue | i3.usesValue;
111 set = !mapping;
when considering range: -0x80000000 <= value <= -1
112
113 if (mapping)
taking True path
114 r = (Bucket *)PyObject_CallObject((PyObject *)&BucketType, NULL);
when PyObject_CallObject() succeeds
115 else
116 r = (Bucket *)PyObject_CallObject((PyObject *)&SetType, NULL);
117 if (r == NULL)
taking False path
118 goto err;
119
120 if (i1.next(&i1) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:120
when considering range: 0 <= value <= 0x7fffffff
taking False path
121 goto err;
122 if (i2.next(&i2) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:122
when considering range: 0 <= value <= 0x7fffffff
taking False path
123 goto err;
124 if (i3.next(&i3) < 0)
calling unknown int (*) (struct SetIteration_s *) from src/BTrees/MergeTemplate.c:124
when considering range: 0 <= value <= 0x7fffffff
taking False path
125 goto err;
126
127 /* Consult zodb/btrees/interfaces.py for the meaning of the last
128 * argument passed to merge_error().
129 */
130 /* TODO: This isn't passing on errors raised by value comparisons. */
131 while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
132 {
133 TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
134 TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
135 if (cmp12==0)
136 {
137 if (cmp13==0)
138 {
139 if (set || (TEST_VALUE(i1.value, i2.value) == 0))
140 { /* change in i3 value or all same */
141 if (merge_output(r, &i3, mapping) < 0) goto err;
142 }
143 else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
144 { /* change in i2 value */
145 if (merge_output(r, &i2, mapping) < 0) goto err;
146 }
147 else
148 { /* conflicting value changes in i2 and i3 */
149 merge_error(i1.position, i2.position, i3.position, 1);
150 goto err;
151 }
152 if (i1.next(&i1) < 0) goto err;
153 if (i2.next(&i2) < 0) goto err;
154 if (i3.next(&i3) < 0) goto err;
155 }
156 else if (cmp13 > 0)
157 { /* insert i3 */
158 if (merge_output(r, &i3, mapping) < 0) goto err;
159 if (i3.next(&i3) < 0) goto err;
160 }
161 else if (set || (TEST_VALUE(i1.value, i2.value) == 0))
162 { /* deleted in i3 */
163 if (i3.position == 1)
164 {
165 /* Deleted the first item. This will modify the
166 parent node, so we don't know if merging will be
167 safe
168 */
169 merge_error(i1.position, i2.position, i3.position, 13);
170 goto err;
171 }
172 if (i1.next(&i1) < 0) goto err;
173 if (i2.next(&i2) < 0) goto err;
174 }
175 else
176 { /* conflicting del in i3 and change in i2 */
177 merge_error(i1.position, i2.position, i3.position, 2);
178 goto err;
179 }
180 }
181 else if (cmp13 == 0)
182 {
183 if (cmp12 > 0)
184 { /* insert i2 */
185 if (merge_output(r, &i2, mapping) < 0) goto err;
186 if (i2.next(&i2) < 0) goto err;
187 }
188 else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
189 { /* deleted in i2 */
190 if (i2.position == 1)
191 {
192 /* Deleted the first item. This will modify the
193 parent node, so we don't know if merging will be
194 safe
195 */
196 merge_error(i1.position, i2.position, i3.position, 13);
197 goto err;
198 }
199 if (i1.next(&i1) < 0) goto err;
200 if (i3.next(&i3) < 0) goto err;
201 }
202 else
203 { /* conflicting del in i2 and change in i3 */
204 merge_error(i1.position, i2.position, i3.position, 3);
205 goto err;
206 }
207 }
208 else
209 { /* Both keys changed */
210 TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
211 if (cmp23==0)
212 { /* dueling inserts or deletes */
213 merge_error(i1.position, i2.position, i3.position, 4);
214 goto err;
215 }
216 if (cmp12 > 0)
217 { /* insert i2 */
218 if (cmp23 > 0)
219 { /* insert i3 first */
220 if (merge_output(r, &i3, mapping) < 0) goto err;
221 if (i3.next(&i3) < 0) goto err;
222 }
223 else
224 { /* insert i2 first */
225 if (merge_output(r, &i2, mapping) < 0) goto err;
226 if (i2.next(&i2) < 0) goto err;
227 }
228 }
229 else if (cmp13 > 0)
230 { /* Insert i3 */
231 if (merge_output(r, &i3, mapping) < 0) goto err;
232 if (i3.next(&i3) < 0) goto err;
233 }
234 else
235 { /* 1<2 and 1<3: both deleted 1.key */
236 merge_error(i1.position, i2.position, i3.position, 5);
237 goto err;
238 }
239 }
240 }
241
242 while (i2.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
243 { /* New inserts */
244 TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
245 if (cmp23==0)
246 { /* dueling inserts */
247 merge_error(i1.position, i2.position, i3.position, 6);
248 goto err;
249 }
250 if (cmp23 > 0)
251 { /* insert i3 */
252 if (merge_output(r, &i3, mapping) < 0) goto err;
253 if (i3.next(&i3) < 0) goto err;
254 }
255 else
256 { /* insert i2 */
257 if (merge_output(r, &i2, mapping) < 0) goto err;
258 if (i2.next(&i2) < 0) goto err;
259 }
260 }
261
262 while (i1.position >= 0 && i2.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
263 { /* remainder of i1 deleted in i3 */
264 TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
265 if (cmp12 > 0)
266 { /* insert i2 */
267 if (merge_output(r, &i2, mapping) < 0) goto err;
268 if (i2.next(&i2) < 0) goto err;
269 }
270 else if (cmp12==0 && (set || (TEST_VALUE(i1.value, i2.value) == 0)))
271 { /* delete i3 */
272 if (i1.next(&i1) < 0) goto err;
273 if (i2.next(&i2) < 0) goto err;
274 }
275 else
276 { /* Dueling deletes or delete and change */
277 merge_error(i1.position, i2.position, i3.position, 7);
278 goto err;
279 }
280 }
281
282 while (i1.position >= 0 && i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
283 { /* remainder of i1 deleted in i2 */
284 TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
285 if (cmp13 > 0)
286 { /* insert i3 */
287 if (merge_output(r, &i3, mapping) < 0) goto err;
288 if (i3.next(&i3) < 0) goto err;
289 }
290 else if (cmp13==0 && (set || (TEST_VALUE(i1.value, i3.value) == 0)))
291 { /* delete i2 */
292 if (i1.next(&i1) < 0) goto err;
293 if (i3.next(&i3) < 0) goto err;
294 }
295 else
296 { /* Dueling deletes or delete and change */
297 merge_error(i1.position, i2.position, i3.position, 8);
298 goto err;
299 }
300 }
301
302 if (i1.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
303 { /* Dueling deletes */
304 merge_error(i1.position, i2.position, i3.position, 9);
305 goto err;
306 }
307
308 while (i2.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
309 { /* Inserting i2 at end */
310 if (merge_output(r, &i2, mapping) < 0) goto err;
311 if (i2.next(&i2) < 0) goto err;
312 }
313
314 while (i3.position >= 0)
when considering range: -0x80000000 <= value <= -1
taking False path
315 { /* Inserting i3 at end */
316 if (merge_output(r, &i3, mapping) < 0) goto err;
317 if (i3.next(&i3) < 0) goto err;
318 }
319
320 /* If the output bucket is empty, conflict resolution doesn't have
321 * enough info to unlink it from its containing BTree correctly.
322 */
323 if (r->len == 0)
when considering value == (int)0 from src/BTrees/MergeTemplate.c:323
taking True path
324 {
325 merge_error(-1, -1, -1, 10);
when merge_error() succeeds
326 goto err;
327 }
328
329 finiSetIteration(&i1);
330 finiSetIteration(&i2);
331 finiSetIteration(&i3);
332
333 if (s1->next)
334 {
335 Py_INCREF(s1->next);
336 r->next = s1->next;
337 }
338 s = bucket_getstate(r);
339 Py_DECREF(r);
340
341 return s;
342
343 err:
344 finiSetIteration(&i1);
345 finiSetIteration(&i2);
346 finiSetIteration(&i3);
347 Py_XDECREF(r);
taking False path
when taking True path
348 return NULL;
349 }
returning (PyObject*)NULL without setting an exception
found 9 similar trace(s) to this