~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/recordcounter.py

  • Committer: Jelmer Vernooij
  • Date: 2011-01-19 06:13:58 UTC
  • mfrom: (5619 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5620.
  • Revision ID: jelmer@samba.org-20110119061358-qm58pzvcp2l9cdx4
merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
"""Record counting support for showing progress of revision fetch."""
 
17
 
 
18
 
 
19
class RecordCounter(object):
 
20
    """Container for maintains estimates of work requires for fetch.
 
21
 
 
22
    Instance of this class is used along with a progress bar to provide
 
23
    the user an estimate of the amount of work pending for a fetch (push,
 
24
    pull, branch, checkout) operation.
 
25
    """
 
26
    def __init__(self):
 
27
        self.initialized = False
 
28
        self.current = 0
 
29
        self.key_count = 0
 
30
        self.max = 0
 
31
 
 
32
        # Users of RecordCounter instance update progress bar every
 
33
        # _STEP_ records. We choose are reasonably high number to keep
 
34
        # display updates from being too frequent. This is an odd number
 
35
        # to ensure that the last digit of the records fetched in
 
36
        # fetches vs estimate ratio changes periodically.
 
37
        self.STEP = 7
 
38
 
 
39
    def is_initialized(self):
 
40
        return self.initialized
 
41
 
 
42
    def _estimate_max(self, key_count):
 
43
        """Estimate the maximum amount of 'inserting stream' work.
 
44
 
 
45
        This is just an estimate.
 
46
        """
 
47
        # Note: The magic number below is based of empirical data
 
48
        # based on 3 seperate projects. Estimatation can probably
 
49
        # be improved but this should work well for most cases.
 
50
        # The project used for the estimate (with approx. numbers) were:
 
51
        # lp:bzr with records_fetched = 7 * revs_required
 
52
        # lp:emacs with records_fetched = 8 * revs_required
 
53
        # bzr-svn checkout of lp:parrot = 10.63 * revs_required
 
54
        # Hence, 10.3 was chosen as for a realistic progress bar as:
 
55
        # 1. If records fetched is is lower than 10.3x then we simply complete
 
56
        #    with 10.3x. Under promise, over deliver.
 
57
        # 2. In case of remote fetch, when we start the count fetch vs estimate
 
58
        #    display with revs_required/estimate, having a multiplier with a
 
59
        #    decimal point produces a realistic looking _estimate_ number rather
 
60
        #    than using something like 3125/31250 (for 10x)
 
61
        # 3. Based on the above data, the possibility of overshooting this
 
62
        #    factor is minimal, and in case of an overshoot the estimate value
 
63
        #    should not need to be corrected too many times.
 
64
        return int(key_count * 10.3)
 
65
 
 
66
    def setup(self, key_count, current=0):
 
67
        """Setup RecordCounter with basic estimate of work pending.
 
68
 
 
69
        Setup self.max and self.current to reflect the amount of work
 
70
        pending for a fetch.
 
71
        """
 
72
        self.current = current
 
73
        self.key_count = key_count
 
74
        self.max = self._estimate_max(key_count)
 
75
        self.initialized = True
 
76
 
 
77
    def increment(self, count):
 
78
        """Increment self.current by count.
 
79
 
 
80
        Apart from incrementing self.current by count, also ensure
 
81
        that self.max > self.current.
 
82
        """
 
83
        self.current += count
 
84
        if self.current > self.max:
 
85
            self.max += self.key_count
 
86