~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/recordcounter.py

  • Committer: Jelmer Vernooij
  • Date: 2012-02-07 00:49:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6465.
  • Revision ID: jelmer@samba.org-20120207004958-rdtzmipi10p1oq97
Migrate 'bugtracker' setting to config stacks.

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
 
 
17
"""Record counting support for showing progress of revision fetch."""
 
18
 
 
19
from __future__ import absolute_import
 
20
 
 
21
 
 
22
class RecordCounter(object):
 
23
    """Container for maintains estimates of work requires for fetch.
 
24
 
 
25
    Instance of this class is used along with a progress bar to provide
 
26
    the user an estimate of the amount of work pending for a fetch (push,
 
27
    pull, branch, checkout) operation.
 
28
    """
 
29
    def __init__(self):
 
30
        self.initialized = False
 
31
        self.current = 0
 
32
        self.key_count = 0
 
33
        self.max = 0
 
34
 
 
35
        # Users of RecordCounter instance update progress bar every
 
36
        # _STEP_ records. We choose are reasonably high number to keep
 
37
        # display updates from being too frequent. This is an odd number
 
38
        # to ensure that the last digit of the records fetched in
 
39
        # fetches vs estimate ratio changes periodically.
 
40
        self.STEP = 7
 
41
 
 
42
    def is_initialized(self):
 
43
        return self.initialized
 
44
 
 
45
    def _estimate_max(self, key_count):
 
46
        """Estimate the maximum amount of 'inserting stream' work.
 
47
 
 
48
        This is just an estimate.
 
49
        """
 
50
        # Note: The magic number below is based of empirical data
 
51
        # based on 3 seperate projects. Estimatation can probably
 
52
        # be improved but this should work well for most cases.
 
53
        # The project used for the estimate (with approx. numbers) were:
 
54
        # lp:bzr with records_fetched = 7 * revs_required
 
55
        # lp:emacs with records_fetched = 8 * revs_required
 
56
        # bzr-svn checkout of lp:parrot = 10.63 * revs_required
 
57
        # Hence, 10.3 was chosen as for a realistic progress bar as:
 
58
        # 1. If records fetched is is lower than 10.3x then we simply complete
 
59
        #    with 10.3x. Under promise, over deliver.
 
60
        # 2. In case of remote fetch, when we start the count fetch vs estimate
 
61
        #    display with revs_required/estimate, having a multiplier with a
 
62
        #    decimal point produces a realistic looking _estimate_ number rather
 
63
        #    than using something like 3125/31250 (for 10x)
 
64
        # 3. Based on the above data, the possibility of overshooting this
 
65
        #    factor is minimal, and in case of an overshoot the estimate value
 
66
        #    should not need to be corrected too many times.
 
67
        return int(key_count * 10.3)
 
68
 
 
69
    def setup(self, key_count, current=0):
 
70
        """Setup RecordCounter with basic estimate of work pending.
 
71
 
 
72
        Setup self.max and self.current to reflect the amount of work
 
73
        pending for a fetch.
 
74
        """
 
75
        self.current = current
 
76
        self.key_count = key_count
 
77
        self.max = self._estimate_max(key_count)
 
78
        self.initialized = True
 
79
 
 
80
    def increment(self, count):
 
81
        """Increment self.current by count.
 
82
 
 
83
        Apart from incrementing self.current by count, also ensure
 
84
        that self.max > self.current.
 
85
        """
 
86
        self.current += count
 
87
        if self.current > self.max:
 
88
            self.max += self.key_count
 
89