Fossil SCM

Reworked ComputeLimits in the last breaker pass. Moved the heavy computation of the max predecessor / min successor data down to the sql in the changeset class.

aku 2007-12-04 04:54 trunk
Commit 711e000206259f355854b886f14b25e6d9601389
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -107,16 +107,21 @@
107107
108108
proc LoadCommitOrder {} {
109109
::variable mycset
110110
::variable myrevisionchangesets
111111
112
+ log write 2 breakacycle {Loading revision commit order}
113
+
114
+ set n 0
112115
state transaction {
113116
foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
117
+ log progress 2 breakacycle $n
114118
set cset [project::rev of $cid]
115119
$cset setpos $pos
116120
set mycset($pos) $cset
117121
lappend myrevisionchangesets $cset
122
+ incr n
118123
}
119124
}
120125
return
121126
}
122127
@@ -149,35 +154,33 @@
149154
# overlap. This allows us to split them into two sets, one
150155
# of non-overlapping branches, and of overlapping
151156
# ones. Each set induces a new changeset, and the second
152157
# one may still be backward and in need of further
153158
# splitting. Hence the looping.
154
- #
159
+
155160
# The border used for the split is the minimal commit
156161
# position among the minimal sucessor commit positions for
157
- # the branches in the changeset.
158
-
159
- # Note that individual branches may not have changesets
160
- # which are their predecessors and/or successors, leaving
161
- # the limits partially or completely undefined.
162
+ # the branches in the changeset. We sort the file level
163
+ # items based on there they sit relative to the border
164
+ # into before and after the border. As the branches cannot
165
+ # be backward at file level thos before the border cannot
166
+ # generate a backward symbol changeset, however the
167
+ # branches after may constitute another backward branch
168
+ # with a new border.
162169
163170
# limits : dict (revision -> list (max predecessor commit, min sucessor commit))
164171
165172
ComputeLimits $cset limits border
166173
167
- log write 5 breakacycle "Breaking backward changeset [$cset str] with commit position $border as border"
168
-
169
- # Secondly we sort the file level items based on there
170
- # they sit relative to the border into before and after
171
- # the border.
174
+ log write 5 breakacycle "Breaking backward changeset [$cset str] using commit position $border as border"
172175
173176
SplitItems $limits $border normalitems backwarditems
174177
175178
set replacements [project::rev split $cset $normalitems $backwarditems]
176179
cyclebreaker replace $graph $cset $replacements
177180
178
- # At last check that the normal frament is indeed not
181
+ # At last we check that the normal frament is indeed not
179182
# backward, and iterate over the possibly still backward
180183
# second fragment.
181184
182185
struct::list assign $replacements normal backward
183186
integrity assert {
@@ -233,84 +236,85 @@
233236
proc ValidPosition {pos} { expr {$pos ne ""} }
234237
235238
proc ComputeLimits {cset lv bv} {
236239
upvar 1 $lv thelimits $bv border
237240
238
- # Initialize the boundaries for all items.
239
-
240
- array set limits {}
241
- foreach revision [$cset items] {
242
- set limits($revision) {0 {}}
243
- }
244
-
245
- # Compute and store the maximal predecessors per item (branch)
246
-
247
- foreach {item csets} [$cset predecessormap] {
248
- set s [Positions $csets]
249
- if {![llength $s]} continue
250
- set limits($item) [lreplace $limits($item) 0 0 [max $s]]
251
- }
252
-
253
- # Compute and store the minimal successors per item (branch)
254
-
255
- foreach {item csets} [$cset successormap] {
256
- set s [Positions $csets]
257
- if {![llength $s]} continue
258
- set limits($item) [lreplace $limits($item) 1 1 [min $s]]
259
- }
241
+ # Individual branches may not have revision changesets which
242
+ # are their predecessors and/or successors, leaving the limits
243
+ # partially or completely undefined. To overcome this
244
+ # initialize boundaries for all items with proper defaults (-1
245
+ # for max, {} for min, representing +infinity).
246
+
247
+ array set maxpa {}
248
+ array set minsa {}
249
+ foreach item [$cset items] {
250
+ set maxpa($item) -1
251
+ set minsa($item) {}
252
+ }
253
+
254
+ # Get the limits from the database, for the items which
255
+ # actually have such, and merge the information with the
256
+ # defaults.
257
+
258
+ struct::list assign [$cset limits] maxpdict minsdict
259
+
260
+ array set maxpa $maxpdict
261
+ array set minsa $minsdict
260262
261263
# Check that the ordering at the file level is correct. We
262264
# cannot have backward ordering per branch, or something is
263265
# wrong.
264266
265267
foreach item [array names limits] {
266
- struct::list assign $limits($item) maxp mins
267
- # Handle min successor position "" as representing infinity
268
+ set mins $minsa($item)
269
+ set maxp $maxp($item)
270
+ # Note that for the min successor position "" represents
271
+ # +infinity
268272
integrity assert {
269273
($mins eq "") || ($maxp < $mins)
270274
} {Item <$item> is backward at file level ($maxp >= $mins)}
271275
}
272276
273277
# Save the limits for the splitter, and compute the border at
274278
# which to split as the minimum of all minimal successor
275279
# positions.
276280
277
- set thelimits [array get limits]
278
- set border [min [struct::list filter [struct::list map [Values $thelimits] \
279
- [myproc MinSuccessorPosition]] \
280
- [myproc ValidPosition]]]
281
+ # Compute the border at which to split as the minimum of all
282
+ # minimal successor positions. By using the database info we
283
+ # automatically/implicitly filter out anything without a min
284
+ # successor. Further the data going into the comparison with
285
+ # the border is put together.
286
+
287
+ set border [min [Values $minsdict]]
288
+ set thelimits [array get maxpa]
281289
return
282290
}
283291
284292
proc Values {dict} {
285293
set res {}
286294
foreach {k v} $dict { lappend res $v }
287295
return $res
288296
}
289297
290
- proc MinSuccessorPosition {item} { lindex $item 1 }
291
-
292298
proc SplitItems {limits border nv bv} {
293299
upvar 1 $nv normalitems $bv backwarditems
294300
295301
set normalitems {}
296302
set backwarditems {}
297303
298
- foreach {rev v} $limits {
299
- struct::list assign $v maxp mins
304
+ foreach {item maxp} $limits {
300305
if {$maxp >= $border} {
301
- lappend backwarditems $rev
306
+ lappend backwarditems $item
302307
} else {
303
- lappend normalitems $rev
308
+ lappend normalitems $item
304309
}
305310
}
306311
307312
integrity assert {[llength $normalitems]} {Set of normal items is empty}
308313
integrity assert {[llength $backwarditems]} {Set of backward items is empty}
309314
return
310315
}
311
-
312316
313317
# # ## ### ##### ######## #############
314318
315319
proc KeepOrder {graph at cset} {
316320
::variable myatfmt
317321
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -107,16 +107,21 @@
107
108 proc LoadCommitOrder {} {
109 ::variable mycset
110 ::variable myrevisionchangesets
111
 
 
 
112 state transaction {
113 foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
 
114 set cset [project::rev of $cid]
115 $cset setpos $pos
116 set mycset($pos) $cset
117 lappend myrevisionchangesets $cset
 
118 }
119 }
120 return
121 }
122
@@ -149,35 +154,33 @@
149 # overlap. This allows us to split them into two sets, one
150 # of non-overlapping branches, and of overlapping
151 # ones. Each set induces a new changeset, and the second
152 # one may still be backward and in need of further
153 # splitting. Hence the looping.
154 #
155 # The border used for the split is the minimal commit
156 # position among the minimal sucessor commit positions for
157 # the branches in the changeset.
158
159 # Note that individual branches may not have changesets
160 # which are their predecessors and/or successors, leaving
161 # the limits partially or completely undefined.
 
 
162
163 # limits : dict (revision -> list (max predecessor commit, min sucessor commit))
164
165 ComputeLimits $cset limits border
166
167 log write 5 breakacycle "Breaking backward changeset [$cset str] with commit position $border as border"
168
169 # Secondly we sort the file level items based on there
170 # they sit relative to the border into before and after
171 # the border.
172
173 SplitItems $limits $border normalitems backwarditems
174
175 set replacements [project::rev split $cset $normalitems $backwarditems]
176 cyclebreaker replace $graph $cset $replacements
177
178 # At last check that the normal frament is indeed not
179 # backward, and iterate over the possibly still backward
180 # second fragment.
181
182 struct::list assign $replacements normal backward
183 integrity assert {
@@ -233,84 +236,85 @@
233 proc ValidPosition {pos} { expr {$pos ne ""} }
234
235 proc ComputeLimits {cset lv bv} {
236 upvar 1 $lv thelimits $bv border
237
238 # Initialize the boundaries for all items.
239
240 array set limits {}
241 foreach revision [$cset items] {
242 set limits($revision) {0 {}}
243 }
244
245 # Compute and store the maximal predecessors per item (branch)
246
247 foreach {item csets} [$cset predecessormap] {
248 set s [Positions $csets]
249 if {![llength $s]} continue
250 set limits($item) [lreplace $limits($item) 0 0 [max $s]]
251 }
252
253 # Compute and store the minimal successors per item (branch)
254
255 foreach {item csets} [$cset successormap] {
256 set s [Positions $csets]
257 if {![llength $s]} continue
258 set limits($item) [lreplace $limits($item) 1 1 [min $s]]
259 }
260
261 # Check that the ordering at the file level is correct. We
262 # cannot have backward ordering per branch, or something is
263 # wrong.
264
265 foreach item [array names limits] {
266 struct::list assign $limits($item) maxp mins
267 # Handle min successor position "" as representing infinity
 
 
268 integrity assert {
269 ($mins eq "") || ($maxp < $mins)
270 } {Item <$item> is backward at file level ($maxp >= $mins)}
271 }
272
273 # Save the limits for the splitter, and compute the border at
274 # which to split as the minimum of all minimal successor
275 # positions.
276
277 set thelimits [array get limits]
278 set border [min [struct::list filter [struct::list map [Values $thelimits] \
279 [myproc MinSuccessorPosition]] \
280 [myproc ValidPosition]]]
 
 
 
 
281 return
282 }
283
284 proc Values {dict} {
285 set res {}
286 foreach {k v} $dict { lappend res $v }
287 return $res
288 }
289
290 proc MinSuccessorPosition {item} { lindex $item 1 }
291
292 proc SplitItems {limits border nv bv} {
293 upvar 1 $nv normalitems $bv backwarditems
294
295 set normalitems {}
296 set backwarditems {}
297
298 foreach {rev v} $limits {
299 struct::list assign $v maxp mins
300 if {$maxp >= $border} {
301 lappend backwarditems $rev
302 } else {
303 lappend normalitems $rev
304 }
305 }
306
307 integrity assert {[llength $normalitems]} {Set of normal items is empty}
308 integrity assert {[llength $backwarditems]} {Set of backward items is empty}
309 return
310 }
311
312
313 # # ## ### ##### ######## #############
314
315 proc KeepOrder {graph at cset} {
316 ::variable myatfmt
317
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -107,16 +107,21 @@
107
108 proc LoadCommitOrder {} {
109 ::variable mycset
110 ::variable myrevisionchangesets
111
112 log write 2 breakacycle {Loading revision commit order}
113
114 set n 0
115 state transaction {
116 foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
117 log progress 2 breakacycle $n
118 set cset [project::rev of $cid]
119 $cset setpos $pos
120 set mycset($pos) $cset
121 lappend myrevisionchangesets $cset
122 incr n
123 }
124 }
125 return
126 }
127
@@ -149,35 +154,33 @@
154 # overlap. This allows us to split them into two sets, one
155 # of non-overlapping branches, and of overlapping
156 # ones. Each set induces a new changeset, and the second
157 # one may still be backward and in need of further
158 # splitting. Hence the looping.
159
160 # The border used for the split is the minimal commit
161 # position among the minimal sucessor commit positions for
162 # the branches in the changeset. We sort the file level
163 # items based on there they sit relative to the border
164 # into before and after the border. As the branches cannot
165 # be backward at file level thos before the border cannot
166 # generate a backward symbol changeset, however the
167 # branches after may constitute another backward branch
168 # with a new border.
169
170 # limits : dict (revision -> list (max predecessor commit, min sucessor commit))
171
172 ComputeLimits $cset limits border
173
174 log write 5 breakacycle "Breaking backward changeset [$cset str] using commit position $border as border"
 
 
 
 
175
176 SplitItems $limits $border normalitems backwarditems
177
178 set replacements [project::rev split $cset $normalitems $backwarditems]
179 cyclebreaker replace $graph $cset $replacements
180
181 # At last we check that the normal frament is indeed not
182 # backward, and iterate over the possibly still backward
183 # second fragment.
184
185 struct::list assign $replacements normal backward
186 integrity assert {
@@ -233,84 +236,85 @@
236 proc ValidPosition {pos} { expr {$pos ne ""} }
237
238 proc ComputeLimits {cset lv bv} {
239 upvar 1 $lv thelimits $bv border
240
241 # Individual branches may not have revision changesets which
242 # are their predecessors and/or successors, leaving the limits
243 # partially or completely undefined. To overcome this
244 # initialize boundaries for all items with proper defaults (-1
245 # for max, {} for min, representing +infinity).
246
247 array set maxpa {}
248 array set minsa {}
249 foreach item [$cset items] {
250 set maxpa($item) -1
251 set minsa($item) {}
252 }
253
254 # Get the limits from the database, for the items which
255 # actually have such, and merge the information with the
256 # defaults.
257
258 struct::list assign [$cset limits] maxpdict minsdict
259
260 array set maxpa $maxpdict
261 array set minsa $minsdict
 
262
263 # Check that the ordering at the file level is correct. We
264 # cannot have backward ordering per branch, or something is
265 # wrong.
266
267 foreach item [array names limits] {
268 set mins $minsa($item)
269 set maxp $maxp($item)
270 # Note that for the min successor position "" represents
271 # +infinity
272 integrity assert {
273 ($mins eq "") || ($maxp < $mins)
274 } {Item <$item> is backward at file level ($maxp >= $mins)}
275 }
276
277 # Save the limits for the splitter, and compute the border at
278 # which to split as the minimum of all minimal successor
279 # positions.
280
281 # Compute the border at which to split as the minimum of all
282 # minimal successor positions. By using the database info we
283 # automatically/implicitly filter out anything without a min
284 # successor. Further the data going into the comparison with
285 # the border is put together.
286
287 set border [min [Values $minsdict]]
288 set thelimits [array get maxpa]
289 return
290 }
291
292 proc Values {dict} {
293 set res {}
294 foreach {k v} $dict { lappend res $v }
295 return $res
296 }
297
 
 
298 proc SplitItems {limits border nv bv} {
299 upvar 1 $nv normalitems $bv backwarditems
300
301 set normalitems {}
302 set backwarditems {}
303
304 foreach {item maxp} $limits {
 
305 if {$maxp >= $border} {
306 lappend backwarditems $item
307 } else {
308 lappend normalitems $item
309 }
310 }
311
312 integrity assert {[llength $normalitems]} {Set of normal items is empty}
313 integrity assert {[llength $backwarditems]} {Set of backward items is empty}
314 return
315 }
 
316
317 # # ## ### ##### ######## #############
318
319 proc KeepOrder {graph at cset} {
320 ::variable myatfmt
321
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -378,10 +378,15 @@
378378
}
379379
return
380380
}
381381
382382
method timerange {} { return [$mytypeobj timerange $myitems] }
383
+
384
+ method limits {} {
385
+ struct::list assign [$mytypeobj limits $myitems] maxp mins
386
+ return [list [TagItemDict $maxp $mytype] [TagItemDict $mins $mytype]]
387
+ }
383388
384389
method drop {} {
385390
log write 8 csets {Dropping $self = [$self str]}
386391
387392
state transaction {
@@ -494,10 +499,16 @@
494499
proc Untag1 {cstype theitem} {
495500
struct::list assign $theitem t i
496501
integrity assert {$cstype eq $t} {Item $i's type is '$t', expected '$cstype'}
497502
return $i
498503
}
504
+
505
+ proc TagItemDict {itemdict cstype} {
506
+ set res {}
507
+ foreach {i v} $itemdict { lappend res [list $cstype $i] $v }
508
+ return $res
509
+ }
499510
500511
proc ValidateFragments {cset fragments} {
501512
# Check the various integrity constraints for the fragments
502513
# specifying how to split the changeset:
503514
#
@@ -1461,10 +1472,49 @@
14611472
AND C.cid = CI.cid
14621473
AND C.type = 1
14631474
"]
14641475
return
14651476
}
1477
+
1478
+ typemethod limits {branches} {
1479
+ # Notes. This method exists only for branches. It is needed to
1480
+ # get detailed information about a backward branch. It does
1481
+ # not apply to tags, nor revisions. The queries can also
1482
+ # restrict themselves to the revision sucessors/predecessors
1483
+ # of branches, as only they have ordering data and thus can
1484
+ # cause the backwardness.
1485
+
1486
+ set theset ('[join $branches {','}]')
1487
+
1488
+ set maxp [state run [subst -nocommands -nobackslashes {
1489
+ -- maximal predecessor position per branch
1490
+ SELECT B.bid, MAX (CO.pos)
1491
+ FROM branch B, revision R, csitem CI, changeset C, csorder CO
1492
+ WHERE B.bid IN $theset
1493
+ AND B.root = R.rid
1494
+ AND CI.iid = R.rid
1495
+ AND C.cid = CI.cid
1496
+ AND C.type = 0
1497
+ AND CO.cid = C.cid
1498
+ GROUP BY B.bid
1499
+ }]]
1500
+
1501
+ set mins [state run [subst -nocommands -nobackslashes {
1502
+ -- minimal successor position per branch
1503
+ SELECT B.bid, MIN (CO.pos)
1504
+ FROM branch B, revision R, csitem CI, changeset C, csorder CO
1505
+ WHERE B.bid IN $theset
1506
+ AND B.first = R.rid
1507
+ AND CI.iid = R.rid
1508
+ AND C.cid = CI.cid
1509
+ AND C.type = 0
1510
+ AND CO.cid = C.cid
1511
+ GROUP BY B.bid
1512
+ }]]
1513
+
1514
+ return [list $maxp $mins]
1515
+ }
14661516
14671517
# # ## ### ##### ######## #############
14681518
## Configuration
14691519
14701520
pragma -hasinstances no ; # singleton
14711521
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -378,10 +378,15 @@
378 }
379 return
380 }
381
382 method timerange {} { return [$mytypeobj timerange $myitems] }
 
 
 
 
 
383
384 method drop {} {
385 log write 8 csets {Dropping $self = [$self str]}
386
387 state transaction {
@@ -494,10 +499,16 @@
494 proc Untag1 {cstype theitem} {
495 struct::list assign $theitem t i
496 integrity assert {$cstype eq $t} {Item $i's type is '$t', expected '$cstype'}
497 return $i
498 }
 
 
 
 
 
 
499
500 proc ValidateFragments {cset fragments} {
501 # Check the various integrity constraints for the fragments
502 # specifying how to split the changeset:
503 #
@@ -1461,10 +1472,49 @@
1461 AND C.cid = CI.cid
1462 AND C.type = 1
1463 "]
1464 return
1465 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1466
1467 # # ## ### ##### ######## #############
1468 ## Configuration
1469
1470 pragma -hasinstances no ; # singleton
1471
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -378,10 +378,15 @@
378 }
379 return
380 }
381
382 method timerange {} { return [$mytypeobj timerange $myitems] }
383
384 method limits {} {
385 struct::list assign [$mytypeobj limits $myitems] maxp mins
386 return [list [TagItemDict $maxp $mytype] [TagItemDict $mins $mytype]]
387 }
388
389 method drop {} {
390 log write 8 csets {Dropping $self = [$self str]}
391
392 state transaction {
@@ -494,10 +499,16 @@
499 proc Untag1 {cstype theitem} {
500 struct::list assign $theitem t i
501 integrity assert {$cstype eq $t} {Item $i's type is '$t', expected '$cstype'}
502 return $i
503 }
504
505 proc TagItemDict {itemdict cstype} {
506 set res {}
507 foreach {i v} $itemdict { lappend res [list $cstype $i] $v }
508 return $res
509 }
510
511 proc ValidateFragments {cset fragments} {
512 # Check the various integrity constraints for the fragments
513 # specifying how to split the changeset:
514 #
@@ -1461,10 +1472,49 @@
1472 AND C.cid = CI.cid
1473 AND C.type = 1
1474 "]
1475 return
1476 }
1477
1478 typemethod limits {branches} {
1479 # Notes. This method exists only for branches. It is needed to
1480 # get detailed information about a backward branch. It does
1481 # not apply to tags, nor revisions. The queries can also
1482 # restrict themselves to the revision sucessors/predecessors
1483 # of branches, as only they have ordering data and thus can
1484 # cause the backwardness.
1485
1486 set theset ('[join $branches {','}]')
1487
1488 set maxp [state run [subst -nocommands -nobackslashes {
1489 -- maximal predecessor position per branch
1490 SELECT B.bid, MAX (CO.pos)
1491 FROM branch B, revision R, csitem CI, changeset C, csorder CO
1492 WHERE B.bid IN $theset
1493 AND B.root = R.rid
1494 AND CI.iid = R.rid
1495 AND C.cid = CI.cid
1496 AND C.type = 0
1497 AND CO.cid = C.cid
1498 GROUP BY B.bid
1499 }]]
1500
1501 set mins [state run [subst -nocommands -nobackslashes {
1502 -- minimal successor position per branch
1503 SELECT B.bid, MIN (CO.pos)
1504 FROM branch B, revision R, csitem CI, changeset C, csorder CO
1505 WHERE B.bid IN $theset
1506 AND B.first = R.rid
1507 AND CI.iid = R.rid
1508 AND C.cid = CI.cid
1509 AND C.type = 0
1510 AND CO.cid = C.cid
1511 GROUP BY B.bid
1512 }]]
1513
1514 return [list $maxp $mins]
1515 }
1516
1517 # # ## ### ##### ######## #############
1518 ## Configuration
1519
1520 pragma -hasinstances no ; # singleton
1521

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button