Fossil

Check-in [4b0f43fb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Plugged memory leak in changeset destructor. Updated commentary. Reformatting of a few integrity checks for readability.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4b0f43fb2f97fe23378ac43ee71fe8b56daa152c
User & Date: aku 2008-02-24 02:16:25
Context
2008-02-24
04:43
New command 'state foreachrow' for incremental result processing, using less memory. Converted a number of places in pass InitCSet to this command, and marked a number of othre places for possible future use. check-in: 6559f323 user: aku tags: trunk
02:16
Plugged memory leak in changeset destructor. Updated commentary. Reformatting of a few integrity checks for readability. check-in: 4b0f43fb user: aku tags: trunk
00:14
Changed the encoding of the values stored in DEPC. Keep only start/end of the range, not the list of all positions in it. That caused the memory-blowup. check-in: 59b54efa user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to tools/cvs2fossil/lib/c2f_prev.tcl.

46
47
48
49
50
51
52


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71






72
73
74
75
76
77
78
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
217
218
219
220
221
222
223

224
225
226
227
228
229
230
...
651
652
653
654
655
656
657


658
659
660
661
662


663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
689
690
691
692
693
694
695



696

697
698
699
700
701
702
703
	set myproject   $project
	set mytype      $cstype
	set mytypeobj   ::vc::fossil::import::cvs::project::rev::${cstype}
	set mysrcid	$srcid
	set myitems     $items
	set mypos       {} ; # Commit location is not known yet.



	# Keep track of the generated changesets and of the inverse
	# mapping from items to them.
	lappend mychangesets   $self
	lappend mytchangesets($cstype) $self
	set     myidmap($myid) $self
	foreach iid $items { lappend mytitems [list $cstype $iid] }

	MapItems $cstype $items
	return
    }

    destructor {
	# The main thing is to keep track of the itemmap and remove
	# the object from it. The lists of changesets (mychangesets,
	# mytchangesets) are not maintained (= reduced), for the
	# moment. We may be able to get rid of this entirely, at least
	# for (de)construction and pass InitCSets.

	UnmapItems $mytype $myitems






	return
    }

    method str {} {
	set str    "<"
	set detail ""
	if {[$mytypeobj bysymbol]} {
................................................................................
	return [array get tmp]
    }

    method breakinternaldependencies {cv} {
	upvar 1 $cv counter
	log write 14 csets {[$self str] BID}
	vc::tools::mem::mark
	##
	## NOTE: This method, maybe in conjunction with its caller
	##       seems to be a memory hog, especially for large
	##       changesets, with 'large' meaning to have a 'long list
	##       of items, several thousand'. Investigate where the
	##       memory is spent and then look for ways of rectifying
	##       the problem.
	##

	# This method inspects the changesets for internal
	# dependencies. Nothing is done if there are no

	# such. Otherwise the changeset is split into a set of
	# fragments without internal dependencies, transforming the
	# internal dependencies into external ones. The new changesets
	# generated from the fragment information are added to the
	# list of all changesets.

	# The code checks only successor dependencies, as this
	# automatically covers the predecessor dependencies as well (A
	# successor dependency a -> b is also a predecessor dependency
	# b -> a).

	# Array of dependencies (parent -> child). This is pulled from
	# the state, and limited to successors within the changeset.

	array set breaks {}

	set fragments [BreakDirectDependencies $myitems breaks]

	if {![llength $fragments]} { return {} }

	return [$self CreateFromFragments $fragments counter breaks]
................................................................................
		DELETE FROM changeset   WHERE cid = $myid;
		DELETE FROM csitem      WHERE cid = $myid;
		DELETE FROM cssuccessor WHERE cid = $myid;
	    }
	}

	UnmapItems $mytype $myitems


	set pos                    [lsearch -exact $mychangesets $self]
	set mychangesets           [lreplace       $mychangesets $pos $pos]
	set pos                    [lsearch -exact $mytchangesets($mytype) $self]
	set mytchangesets($mytype) [lreplace       $mytchangesets($mytype) $pos $pos]

	# Return the list of predecessors so that they can be adjusted.
................................................................................
	set newcsets  {}
	set fragments [lsort -index 0 -integer $fragments]

	#puts \t.[join [PRs $fragments] .\n\t.].

	Border [lindex $fragments 0] firsts firste



	integrity assert {$firsts == 0} {Bad fragment start @ $firsts, gap, or before beginning of the range}

	set laste $firste
	foreach fragment [lrange $fragments 1 end] {
	    Border $fragment s e


	    integrity assert {$laste == ($s - 1)} {Bad fragment border <$laste | $s>, gap or overlap}

	    set new [$type %AUTO% $myproject $mytype $mysrcid [lrange $myitems $s $e]]
	    lappend newcsets $new
	    incr counter

            log write 4 csets "Breaking [$self str ] @ $laste, new [$new str], cutting $breaks($laste)"

	    set laste $e
	}

	integrity assert {
	    $laste == ([llength $myitems]-1)
	} {Bad fragment end @ $laste, gap, or beyond end of the range}
................................................................................
    }

    # # ## ### ##### ######## #############

    proc BreakDirectDependencies {theitems bv} {
	upvar 1 mytypeobj mytypeobj self self $bv breaks




	array set dependencies {}

	$mytypeobj internalsuccessors dependencies $theitems
	if {![array size dependencies]} {
	    return {}
	} ; # Nothing to break.

	log write 5 csets ...[$self str].......................................................
	vc::tools::mem::mark







>
>





<






<
<
<
|
|


>
>
>
>
>
>







 







<
<
<
<
<
<
<
<

|
|
>
|
|


|

|
|



<
<
<







 







>







 







>
>
|




>
>
|





|







 







>
>
>

>







46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
146
147
148
149
150
151
152








153
154
155
156
157
158
159
160
161
162
163
164
165
166
167



168
169
170
171
172
173
174
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
	set myproject   $project
	set mytype      $cstype
	set mytypeobj   ::vc::fossil::import::cvs::project::rev::${cstype}
	set mysrcid	$srcid
	set myitems     $items
	set mypos       {} ; # Commit location is not known yet.

	foreach iid $items { lappend mytitems [list $cstype $iid] }

	# Keep track of the generated changesets and of the inverse
	# mapping from items to them.
	lappend mychangesets   $self
	lappend mytchangesets($cstype) $self
	set     myidmap($myid) $self


	MapItems $cstype $items
	return
    }

    destructor {



	# We may be able to get rid of this entirely, at least for
	# (de)construction and pass InitCSets.

	UnmapItems $mytype $myitems
	unset myidmap($myid)

	set pos                    [lsearch -exact $mychangesets $self]
	set mychangesets           [lreplace       $mychangesets $pos $pos]
	set pos                    [lsearch -exact $mytchangesets($mytype) $self]
	set mytchangesets($mytype) [lreplace       $mytchangesets($mytype) $pos $pos]
	return
    }

    method str {} {
	set str    "<"
	set detail ""
	if {[$mytypeobj bysymbol]} {
................................................................................
	return [array get tmp]
    }

    method breakinternaldependencies {cv} {
	upvar 1 $cv counter
	log write 14 csets {[$self str] BID}
	vc::tools::mem::mark









	# This method inspects the changeset, looking for internal
	# dependencies. Nothing is done if there are no such.

	# Otherwise the changeset is split into a set of fragments
	# which have no internal dependencies, transforming the
	# internal dependencies into external ones. The new changesets
	# generated from the fragment information are added to the
	# list of all changesets (by the caller).

	# The code checks only successor dependencies, as this auto-
	# matically covers the predecessor dependencies as well (Any
	# successor dependency a -> b is also a predecessor dependency
	# b -> a).




	array set breaks {}

	set fragments [BreakDirectDependencies $myitems breaks]

	if {![llength $fragments]} { return {} }

	return [$self CreateFromFragments $fragments counter breaks]
................................................................................
		DELETE FROM changeset   WHERE cid = $myid;
		DELETE FROM csitem      WHERE cid = $myid;
		DELETE FROM cssuccessor WHERE cid = $myid;
	    }
	}

	UnmapItems $mytype $myitems
	unset myidmap($myid)

	set pos                    [lsearch -exact $mychangesets $self]
	set mychangesets           [lreplace       $mychangesets $pos $pos]
	set pos                    [lsearch -exact $mytchangesets($mytype) $self]
	set mytchangesets($mytype) [lreplace       $mytchangesets($mytype) $pos $pos]

	# Return the list of predecessors so that they can be adjusted.
................................................................................
	set newcsets  {}
	set fragments [lsort -index 0 -integer $fragments]

	#puts \t.[join [PRs $fragments] .\n\t.].

	Border [lindex $fragments 0] firsts firste

	integrity assert {
	    $firsts == 0
	} {Bad fragment start @ $firsts, gap, or before beginning of the range}

	set laste $firste
	foreach fragment [lrange $fragments 1 end] {
	    Border $fragment s e
	    integrity assert {
		$laste == ($s - 1)
	    } {Bad fragment border <$laste | $s>, gap or overlap}

	    set new [$type %AUTO% $myproject $mytype $mysrcid [lrange $myitems $s $e]]
	    lappend newcsets $new
	    incr counter

            log write 4 csets {Breaking [$self str ] @ $laste, new [$new str], cutting $breaks($laste)}

	    set laste $e
	}

	integrity assert {
	    $laste == ([llength $myitems]-1)
	} {Bad fragment end @ $laste, gap, or beyond end of the range}
................................................................................
    }

    # # ## ### ##### ######## #############

    proc BreakDirectDependencies {theitems bv} {
	upvar 1 mytypeobj mytypeobj self self $bv breaks

	# Array of dependencies (parent -> child). This is pulled from
	# the state, and limited to successors within the changeset.

	array set dependencies {}

	$mytypeobj internalsuccessors dependencies $theitems
	if {![array size dependencies]} {
	    return {}
	} ; # Nothing to break.

	log write 5 csets ...[$self str].......................................................
	vc::tools::mem::mark