Check-in [711e000206]
Not logged in
Overview

SHA1 Hash:711e000206259f355854b886f14b25e6d9601389
Date: 2007-12-04 04:54:10
User: aku
Comment: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.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified tools/cvs2fossil/lib/c2f_pbreakacycle.tcl from [7e073778fc] to [4af9517982].

@@ -107,16 +107,21 @@
 
     proc LoadCommitOrder {} {
 	::variable mycset
 	::variable myrevisionchangesets
 
+	log write 2 breakacycle {Loading revision commit order}
+
+	set n 0
 	state transaction {
 	    foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
+		log progress 2 breakacycle $n
 		set cset [project::rev of $cid]
 		$cset setpos $pos
 		set mycset($pos) $cset
 		lappend myrevisionchangesets $cset
+		incr n
 	    }
 	}
 	return
     }
 
@@ -149,35 +154,33 @@
 	    # overlap. This allows us to split them into two sets, one
 	    # of non-overlapping branches, and of overlapping
 	    # ones. Each set induces a new changeset, and the second
 	    # one may still be backward and in need of further
 	    # splitting. Hence the looping.
-	    #
+
 	    # The border used for the split is the minimal commit
 	    # position among the minimal sucessor commit positions for
-	    # the branches in the changeset.
-
-	    # Note that individual branches may not have changesets
-	    # which are their predecessors and/or successors, leaving
-	    # the limits partially or completely undefined.
+	    # the branches in the changeset.  We sort the file level
+	    # items based on there they sit relative to the border
+	    # into before and after the border. As the branches cannot
+	    # be backward at file level thos before the border cannot
+	    # generate a backward symbol changeset, however the
+	    # branches after may constitute another backward branch
+	    # with a new border.
 
 	    # limits : dict (revision -> list (max predecessor commit, min sucessor commit))
 
 	    ComputeLimits $cset limits border
 
-	    log write 5 breakacycle "Breaking backward changeset [$cset str] with commit position $border as border"
-
-	    # Secondly we sort the file level items based on there
-	    # they sit relative to the border into before and after
-	    # the border.
+	    log write 5 breakacycle "Breaking backward changeset [$cset str] using commit position $border as border"
 
 	    SplitItems $limits $border normalitems backwarditems
 
 	    set replacements [project::rev split $cset $normalitems $backwarditems]
 	    cyclebreaker replace $graph $cset $replacements
 
-	    # At last check that the normal frament is indeed not
+	    # At last we check that the normal frament is indeed not
 	    # backward, and iterate over the possibly still backward
 	    # second fragment.
 
 	    struct::list assign $replacements normal backward
 	    integrity assert {
@@ -233,84 +236,85 @@
     proc ValidPosition {pos}  { expr {$pos ne ""} }
 
     proc ComputeLimits {cset lv bv} {
 	upvar 1 $lv thelimits $bv border
 
-	# Initialize the boundaries for all items.
-
-	array set limits {}
-	foreach revision [$cset items] {
-	    set limits($revision) {0 {}}
-	}
-
-	# Compute and store the maximal predecessors per item (branch)
-
-	foreach {item csets} [$cset predecessormap] {
-	    set s [Positions $csets]
-	    if {![llength $s]} continue
-	    set limits($item) [lreplace $limits($item) 0 0 [max $s]]
+	# Individual branches may not have revision changesets which
+	# are their predecessors and/or successors, leaving the limits
+	# partially or completely undefined. To overcome this
+	# initialize boundaries for all items with proper defaults (-1
+	# for max, {} for min, representing +infinity).
+
+	array set maxpa {}
+	array set minsa {}
+	foreach item [$cset items] {
+	    set maxpa($item) -1
+	    set minsa($item) {}
 	}
 
-	# Compute and store the minimal successors per item (branch)
-
-	foreach {item csets} [$cset successormap] {
-	    set s [Positions $csets]
-	    if {![llength $s]} continue
-	    set limits($item) [lreplace $limits($item) 1 1 [min $s]]
-	}
+	# Get the limits from the database, for the items which
+	# actually have such, and merge the information with the
+	# defaults.
+
+	struct::list assign [$cset limits] maxpdict minsdict
+
+	array set maxpa $maxpdict
+	array set minsa $minsdict
 
 	# Check that the ordering at the file level is correct. We
 	# cannot have backward ordering per branch, or something is
 	# wrong.
 
 	foreach item [array names limits] {
-	    struct::list assign $limits($item) maxp mins
-	    # Handle min successor position "" as representing infinity
+	    set mins $minsa($item)
+	    set maxp $maxp($item)
+	    # Note that for the min successor position "" represents
+	    # +infinity
 	    integrity assert {
 		($mins eq "") || ($maxp < $mins)
 	    } {Item <$item> is backward at file level ($maxp >= $mins)}
 	}
 
 	# Save the limits for the splitter, and compute the border at
 	# which to split as the minimum of all minimal successor
 	# positions.
 
-	set thelimits [array get limits]
-	set border [min [struct::list filter [struct::list map [Values $thelimits] \
-						  [myproc MinSuccessorPosition]] \
-			     [myproc ValidPosition]]]
+	# Compute the border at which to split as the minimum of all
+	# minimal successor positions. By using the database info we
+	# automatically/implicitly filter out anything without a min
+	# successor. Further the data going into the comparison with
+	# the border is put together.
+
+	set border    [min [Values $minsdict]]
+	set thelimits [array get maxpa]
 	return
     }
 
     proc Values {dict} {
 	set res {}
 	foreach {k v} $dict { lappend res $v }
 	return $res
     }
 
-    proc MinSuccessorPosition {item} { lindex $item 1 }
-
     proc SplitItems {limits border nv bv} {
 	upvar 1 $nv normalitems $bv backwarditems
 
 	set normalitems   {}
 	set backwarditems {}
 
-	foreach {rev v} $limits {
-	    struct::list assign $v maxp mins
+	foreach {item maxp} $limits {
 	    if {$maxp >= $border} {
-		lappend backwarditems  $rev
+		lappend backwarditems $item
 	    } else {
-		lappend normalitems $rev
+		lappend normalitems   $item
 	    }
 	}
 
 	integrity assert {[llength $normalitems]}   {Set of normal items is empty}
 	integrity assert {[llength $backwarditems]} {Set of backward items is empty}
 	return
     }
-
 
     # # ## ### ##### ######## #############
 
     proc KeepOrder {graph at cset} {
 	::variable myatfmt

Modified tools/cvs2fossil/lib/c2f_prev.tcl from [bf483d028a] to [f2b05566df].

@@ -379,10 +379,15 @@
 	return
     }
 
     method timerange {} { return [$mytypeobj timerange $myitems] }
 
+    method limits {} {
+	struct::list assign [$mytypeobj limits $myitems] maxp mins
+	return [list [TagItemDict $maxp $mytype] [TagItemDict $mins $mytype]]
+    }
+
     method drop {} {
 	log write 8 csets {Dropping $self = [$self str]}
 
 	state transaction {
 	    state run {
@@ -493,10 +498,16 @@
 
     proc Untag1 {cstype theitem} {
 	struct::list assign $theitem t i
 	integrity assert {$cstype eq $t} {Item $i's type is '$t', expected '$cstype'}
 	return $i
+    }
+
+    proc TagItemDict {itemdict cstype} {
+	set res {}
+	foreach {i v} $itemdict { lappend res [list $cstype $i] $v }
+	return $res
     }
 
     proc ValidateFragments {cset fragments} {
 	# Check the various integrity constraints for the fragments
 	# specifying how to split the changeset:
@@ -1460,10 +1471,49 @@
             AND    CI.iid = T.tid
             AND    C.cid = CI.cid
             AND    C.type = 1
 	"]
 	return
+    }
+
+    typemethod limits {branches} {
+	# Notes. This method exists only for branches. It is needed to
+	# get detailed information about a backward branch. It does
+	# not apply to tags, nor revisions. The queries can also
+	# restrict themselves to the revision sucessors/predecessors
+	# of branches, as only they have ordering data and thus can
+	# cause the backwardness.
+
+	set theset ('[join $branches {','}]')
+
+	set maxp [state run [subst -nocommands -nobackslashes {
+	    -- maximal predecessor position per branch
+	    SELECT B.bid, MAX (CO.pos)
+	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
+	    WHERE  B.bid IN $theset
+	    AND    B.root = R.rid
+	    AND    CI.iid = R.rid
+	    AND    C.cid = CI.cid
+	    AND    C.type = 0
+	    AND    CO.cid = C.cid
+	    GROUP BY B.bid
+	}]]
+
+	set mins [state run [subst -nocommands -nobackslashes {
+	    -- minimal successor position per branch
+	    SELECT B.bid, MIN (CO.pos)
+	    FROM   branch B, revision R, csitem CI, changeset C, csorder CO
+	    WHERE  B.bid IN $theset
+	    AND    B.first = R.rid
+	    AND    CI.iid = R.rid
+	    AND    C.cid = CI.cid
+	    AND    C.type = 0
+	    AND    CO.cid = C.cid
+	    GROUP BY B.bid
+	}]]
+
+        return [list $maxp $mins]
     }
 
     # # ## ### ##### ######## #############
     ## Configuration