mirror of
				https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
				synced 2025-11-04 10:34:05 +00:00 
			
		
		
		
	Merge branch 'master' into p-u
Signed-off-by: Adam D. Barratt <adam@adam-barratt.org.uk>
This commit is contained in:
		
						commit
						6667b8fcf9
					
				
							
								
								
									
										7
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								INSTALL
									
									
									
									
									
								
							@ -8,3 +8,10 @@ Requirements:
 | 
			
		||||
  * Python APT/DPKG bindings    aptitude install python2.5-apt libapt-pkg-dev dpkg-dev
 | 
			
		||||
  * Python dev headers          aptitude install python2.5-dev
 | 
			
		||||
 | 
			
		||||
Compiling:
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
Run "make all" in the lib directory and add a symlink called
 | 
			
		||||
britneymodule.so pointing to the freshly generated britneymodule.so in
 | 
			
		||||
the lib directory.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										107
									
								
								britney.py
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								britney.py
									
									
									
									
									
								
							@ -317,31 +317,31 @@ class Britney:
 | 
			
		||||
        in a suitable form for the other methods of the class.
 | 
			
		||||
        """
 | 
			
		||||
        # initialize the parser
 | 
			
		||||
        self.parser = optparse.OptionParser(version="%prog")
 | 
			
		||||
        self.parser.add_option("-v", "", action="count", dest="verbose", help="enable verbose output")
 | 
			
		||||
        self.parser.add_option("-c", "--config", action="store", dest="config", default="/etc/britney.conf",
 | 
			
		||||
        parser = optparse.OptionParser(version="%prog")
 | 
			
		||||
        parser.add_option("-v", "", action="count", dest="verbose", help="enable verbose output")
 | 
			
		||||
        parser.add_option("-c", "--config", action="store", dest="config", default="/etc/britney.conf",
 | 
			
		||||
                               help="path for the configuration file")
 | 
			
		||||
        self.parser.add_option("", "--architectures", action="store", dest="architectures", default=None,
 | 
			
		||||
        parser.add_option("", "--architectures", action="store", dest="architectures", default=None,
 | 
			
		||||
                               help="override architectures from configuration file")
 | 
			
		||||
        self.parser.add_option("", "--actions", action="store", dest="actions", default=None,
 | 
			
		||||
        parser.add_option("", "--actions", action="store", dest="actions", default=None,
 | 
			
		||||
                               help="override the list of actions to be performed")
 | 
			
		||||
        self.parser.add_option("", "--hints", action="store", dest="hints", default=None,
 | 
			
		||||
        parser.add_option("", "--hints", action="store", dest="hints", default=None,
 | 
			
		||||
                               help="additional hints, separated by semicolons")
 | 
			
		||||
        self.parser.add_option("", "--hint-tester", action="store_true", dest="hint_tester", default=None,
 | 
			
		||||
        parser.add_option("", "--hint-tester", action="store_true", dest="hint_tester", default=None,
 | 
			
		||||
                               help="provide a command line interface to test hints")
 | 
			
		||||
        self.parser.add_option("", "--dry-run", action="store_true", dest="dry_run", default=False,
 | 
			
		||||
        parser.add_option("", "--dry-run", action="store_true", dest="dry_run", default=False,
 | 
			
		||||
                               help="disable all outputs to the testing directory")
 | 
			
		||||
        self.parser.add_option("", "--compatible", action="store_true", dest="compatible", default=False,
 | 
			
		||||
        parser.add_option("", "--compatible", action="store_true", dest="compatible", default=False,
 | 
			
		||||
                               help="enable full compatibility with old britney's output")
 | 
			
		||||
        self.parser.add_option("", "--auto-hinter", action="store_true", dest="autohinter", default=False,
 | 
			
		||||
        parser.add_option("", "--auto-hinter", action="store_true", dest="autohinter", default=False,
 | 
			
		||||
                               help="enable use of auto-hinter")
 | 
			
		||||
        self.parser.add_option("", "--control-files", action="store_true", dest="control_files", default=False,
 | 
			
		||||
        parser.add_option("", "--control-files", action="store_true", dest="control_files", default=False,
 | 
			
		||||
                               help="enable control files generation")
 | 
			
		||||
        self.parser.add_option("", "--nuninst-cache", action="store_true", dest="nuninst_cache", default=False,
 | 
			
		||||
        parser.add_option("", "--nuninst-cache", action="store_true", dest="nuninst_cache", default=False,
 | 
			
		||||
                               help="do not build the non-installability status, use the cache from file")
 | 
			
		||||
        self.parser.add_option("", "--print-uninst", action="store_true", dest="print_uninst", default=False,
 | 
			
		||||
        parser.add_option("", "--print-uninst", action="store_true", dest="print_uninst", default=False,
 | 
			
		||||
                               help="just print a summary of uninstallable packages")
 | 
			
		||||
        (self.options, self.args) = self.parser.parse_args()
 | 
			
		||||
        (self.options, self.args) = parser.parse_args()
 | 
			
		||||
        
 | 
			
		||||
        # integrity checks
 | 
			
		||||
        if self.options.nuninst_cache and self.options.print_uninst:
 | 
			
		||||
@ -415,14 +415,13 @@ class Britney:
 | 
			
		||||
        package as a dictionary.
 | 
			
		||||
        """
 | 
			
		||||
        sources = {}
 | 
			
		||||
        package = None
 | 
			
		||||
        filename = os.path.join(basedir, "Sources")
 | 
			
		||||
        self.__log("Loading source packages from %s" % filename)
 | 
			
		||||
        try:
 | 
			
		||||
            Packages = apt_pkg.TagFile(open(filename))
 | 
			
		||||
            get_field = Packages.section.get
 | 
			
		||||
            step = Packages.step
 | 
			
		||||
        except AttributeError, e:
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            Packages = apt_pkg.ParseTagFile(open(filename))
 | 
			
		||||
            get_field = Packages.Section.get
 | 
			
		||||
            step = Packages.Step
 | 
			
		||||
@ -470,7 +469,6 @@ class Britney:
 | 
			
		||||
        packages = {}
 | 
			
		||||
        provides = {}
 | 
			
		||||
        sources = self.sources
 | 
			
		||||
        package = None
 | 
			
		||||
 | 
			
		||||
        filename = os.path.join(basedir, "Packages_%s" % arch)
 | 
			
		||||
        self.__log("Loading binary packages from %s" % filename)
 | 
			
		||||
@ -478,7 +476,7 @@ class Britney:
 | 
			
		||||
            Packages = apt_pkg.TagFile(open(filename))
 | 
			
		||||
            get_field = Packages.section.get
 | 
			
		||||
            step = Packages.step
 | 
			
		||||
        except AttributeError, e:
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            Packages = apt_pkg.ParseTagFile(open(filename))
 | 
			
		||||
            get_field = Packages.Section.get
 | 
			
		||||
            step = Packages.Step
 | 
			
		||||
@ -940,7 +938,7 @@ class Britney:
 | 
			
		||||
        return nuninst
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # Utility methods for package analisys
 | 
			
		||||
    # Utility methods for package analysis
 | 
			
		||||
    # ------------------------------------
 | 
			
		||||
 | 
			
		||||
    def same_source(self, sv1, sv2):
 | 
			
		||||
@ -1003,7 +1001,7 @@ class Britney:
 | 
			
		||||
 | 
			
		||||
        return (len(packages) > 0, packages)
 | 
			
		||||
 | 
			
		||||
    def excuse_unsat_deps(self, pkg, src, arch, suite, excuse, excluded=[], conflicts=False):
 | 
			
		||||
    def excuse_unsat_deps(self, pkg, src, arch, suite, excuse, excluded=[]):
 | 
			
		||||
        """Find unsatisfied dependencies for a binary package
 | 
			
		||||
 | 
			
		||||
        This method analyzes the dependencies of the binary package specified
 | 
			
		||||
@ -2419,21 +2417,76 @@ class Britney:
 | 
			
		||||
            self.output_write("\nNewly uninstallable packages in testing:\n%s" % \
 | 
			
		||||
                (text))
 | 
			
		||||
 | 
			
		||||
    def generate_package_list(self):
 | 
			
		||||
        # list of local methods and variables (for better performance)
 | 
			
		||||
        sources = self.sources
 | 
			
		||||
        architectures = self.options.architectures
 | 
			
		||||
        should_remove_source = self.should_remove_source
 | 
			
		||||
        should_upgrade_srcarch = self.should_upgrade_srcarch
 | 
			
		||||
        should_upgrade_src = self.should_upgrade_src
 | 
			
		||||
 | 
			
		||||
        # this list will contain the packages which are valid candidates;
 | 
			
		||||
        # if a package is going to be removed, it will have a "-" prefix
 | 
			
		||||
        upgrade_me = []
 | 
			
		||||
 | 
			
		||||
        # for every source package in testing, check if it should be removed
 | 
			
		||||
        for pkg in sources['testing']:
 | 
			
		||||
            if should_remove_source(pkg):
 | 
			
		||||
                upgrade_me.append("-" + pkg)
 | 
			
		||||
 | 
			
		||||
        # for every source package in unstable check if it should be upgraded
 | 
			
		||||
        for pkg in sources['unstable']:
 | 
			
		||||
            if sources['unstable'][pkg][FAKESRC]: continue
 | 
			
		||||
            # if the source package is already present in testing,
 | 
			
		||||
            # check if it should be upgraded for every binary package
 | 
			
		||||
            if pkg in sources['testing'] and not sources['testing'][pkg][FAKESRC]:
 | 
			
		||||
                for arch in architectures:
 | 
			
		||||
                    if should_upgrade_srcarch(pkg, arch, 'unstable'):
 | 
			
		||||
                        upgrade_me.append("%s/%s/%s" % (pkg, arch, sources['unstable'][pkg][VERSION]))
 | 
			
		||||
 | 
			
		||||
            # check if the source package should be upgraded
 | 
			
		||||
            if should_upgrade_src(pkg, 'unstable'):
 | 
			
		||||
                upgrade_me.append("%s/%s" % (pkg, sources['unstable'][pkg][VERSION]))
 | 
			
		||||
 | 
			
		||||
        # for every source package in *-proposed-updates, check if it should be upgraded
 | 
			
		||||
        for suite in ['pu', 'tpu']:
 | 
			
		||||
            for pkg in sources[suite]:
 | 
			
		||||
                # if the source package is already present in testing,
 | 
			
		||||
                # check if it should be upgraded for every binary package
 | 
			
		||||
                if pkg in sources['testing']:
 | 
			
		||||
                    for arch in architectures:
 | 
			
		||||
                        if should_upgrade_srcarch(pkg, arch, suite):
 | 
			
		||||
                            upgrade_me.append("%s/%s_%s" % (pkg, arch, suite))
 | 
			
		||||
 | 
			
		||||
                # check if the source package should be upgraded
 | 
			
		||||
                if should_upgrade_src(pkg, suite):
 | 
			
		||||
                    upgrade_me.append("%s_%s" % (pkg, suite))
 | 
			
		||||
 | 
			
		||||
        return upgrade_me
 | 
			
		||||
 | 
			
		||||
    def hint_tester(self):
 | 
			
		||||
        """Run a command line interface to test hints
 | 
			
		||||
 | 
			
		||||
        This method provides a command line interface for the release team to
 | 
			
		||||
        try hints and evaulate the results.
 | 
			
		||||
        try hints and evaluate the results.
 | 
			
		||||
        """
 | 
			
		||||
        self.__log("> Calculating current uninstallability counters", type="I")
 | 
			
		||||
        self.nuninst_orig = self.get_nuninst()
 | 
			
		||||
        self.nuninst_orig_save = self.get_nuninst()
 | 
			
		||||
 | 
			
		||||
        import readline
 | 
			
		||||
        from completer import Completer
 | 
			
		||||
 | 
			
		||||
        histfile = os.path.expanduser('~/.britney2_history')
 | 
			
		||||
        if os.path.exists(histfile):
 | 
			
		||||
            readline.read_history_file(histfile)
 | 
			
		||||
 | 
			
		||||
        readline.parse_and_bind('tab: complete')
 | 
			
		||||
        readline.set_completer(Completer(self).completer)
 | 
			
		||||
        # Package names can contain "-" and we use "/" in our presentation of them as well,
 | 
			
		||||
        # so ensure readline does not split on these characters.
 | 
			
		||||
        readline.set_completer_delims(readline.get_completer_delims().replace('-', '').replace('/', ''))
 | 
			
		||||
 | 
			
		||||
        while True:
 | 
			
		||||
            # read the command from the command line
 | 
			
		||||
            try:
 | 
			
		||||
@ -2455,8 +2508,10 @@ class Britney:
 | 
			
		||||
                    self.printuninstchange()
 | 
			
		||||
                except KeyboardInterrupt:
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
        readline.write_history_file(histfile)
 | 
			
		||||
        try:
 | 
			
		||||
            readline.write_history_file(histfile)
 | 
			
		||||
        except IOError, e:
 | 
			
		||||
            self.__log("Could not write %s: %s" % (histfile, e), type="W")
 | 
			
		||||
 | 
			
		||||
    def do_hint(self, type, who, pkgvers):
 | 
			
		||||
        """Process hints
 | 
			
		||||
@ -2577,7 +2632,7 @@ class Britney:
 | 
			
		||||
        for e in excuses:
 | 
			
		||||
            excuse = excuses[e]
 | 
			
		||||
            if e in self.sources['testing'] and self.sources['testing'][e][VERSION] == excuse.ver[1]:
 | 
			
		||||
               continue
 | 
			
		||||
                continue
 | 
			
		||||
            if len(excuse.deps) > 0:
 | 
			
		||||
                hint = find_related(e, {}, True)
 | 
			
		||||
                if isinstance(hint, dict) and e in hint and hint not in candidates:
 | 
			
		||||
@ -2640,9 +2695,9 @@ class Britney:
 | 
			
		||||
            pkg, arch = i.split("/")
 | 
			
		||||
            pkg = pkg[1:]
 | 
			
		||||
            if pkg in libraries:
 | 
			
		||||
                    libraries[pkg].append(arch)
 | 
			
		||||
                libraries[pkg].append(arch)
 | 
			
		||||
            else:
 | 
			
		||||
                    libraries[pkg] = [arch]
 | 
			
		||||
                libraries[pkg] = [arch]
 | 
			
		||||
        return "\n".join(["  " + k + ": " + " ".join(libraries[k]) for k in libraries]) + "\n"
 | 
			
		||||
 | 
			
		||||
    def nuninst_arch_report(self, nuninst, arch):
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								completer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								completer.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
# Copyright (C) 2011 Niels Thykier <niels@thykier.net>
 | 
			
		||||
 | 
			
		||||
# This program is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
import readline
 | 
			
		||||
import bisect
 | 
			
		||||
 | 
			
		||||
class Completer:
 | 
			
		||||
    """Completer class
 | 
			
		||||
 | 
			
		||||
    This class provides a readline completer for the britney hint-tester
 | 
			
		||||
    command-line interface.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, britney):
 | 
			
		||||
        """Constructor
 | 
			
		||||
 | 
			
		||||
        Creates a completer for a given britney.
 | 
			
		||||
        """
 | 
			
		||||
        self.matches = []
 | 
			
		||||
        self.cmds = ['easy', 'hint', 'force-hint', 'exit', 'quit']
 | 
			
		||||
        self.britney = britney
 | 
			
		||||
        self.packages = sorted(britney.generate_package_list())
 | 
			
		||||
 | 
			
		||||
    def completer(self, text, state):
 | 
			
		||||
        """readline completer (see the readline API)"""
 | 
			
		||||
 | 
			
		||||
        origline = readline.get_line_buffer()
 | 
			
		||||
        words = origline.split()
 | 
			
		||||
 | 
			
		||||
        if state < 1:
 | 
			
		||||
            self.matches = []
 | 
			
		||||
            if len(words) < 1 or words[0] == text:
 | 
			
		||||
                # complete a command
 | 
			
		||||
                self.matches = [x for x in self.cmds if x.startswith(text)]
 | 
			
		||||
            else:
 | 
			
		||||
                # complete pkg/[arch/]version
 | 
			
		||||
                prefix = ''
 | 
			
		||||
                if len(text) > 0 and text[0] == '-':
 | 
			
		||||
                    text = text[1:]
 | 
			
		||||
                    prefix = '-'
 | 
			
		||||
                start = bisect.bisect_left(self.packages, text)
 | 
			
		||||
                while start < len(self.packages):
 | 
			
		||||
                    if not self.packages[start].startswith(text):
 | 
			
		||||
                        break
 | 
			
		||||
                    self.matches.append(prefix + self.packages[start])
 | 
			
		||||
                    start += 1
 | 
			
		||||
 | 
			
		||||
        if len(self.matches) > state:
 | 
			
		||||
            return self.matches[state]
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
@ -867,7 +867,7 @@
 | 
			
		||||
<a name="l00853"></a>00853         <span class="keywordflow">return</span> nuninst
 | 
			
		||||
<a name="l00854"></a>00854 
 | 
			
		||||
<a name="l00855"></a>00855 
 | 
			
		||||
<a name="l00856"></a>00856     <span class="comment"># Utility methods for package analisys</span>
 | 
			
		||||
<a name="l00856"></a>00856     <span class="comment"># Utility methods for package analysis</span>
 | 
			
		||||
<a name="l00857"></a>00857     <span class="comment"># ------------------------------------</span>
 | 
			
		||||
<a name="l00858"></a>00858 
 | 
			
		||||
<a name="l00859"></a>00859     <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(self, sv1, sv2):
 | 
			
		||||
@ -1007,7 +1007,7 @@
 | 
			
		||||
<a name="l00993"></a>00993 
 | 
			
		||||
<a name="l00994"></a>00994         <span class="keywordflow">return</span> <span class="keyword">True</span>
 | 
			
		||||
<a name="l00995"></a>00995 
 | 
			
		||||
<a name="l00996"></a>00996     <span class="comment"># Package analisys methods</span>
 | 
			
		||||
<a name="l00996"></a>00996     <span class="comment"># Package analysis methods</span>
 | 
			
		||||
<a name="l00997"></a>00997     <span class="comment"># ------------------------</span>
 | 
			
		||||
<a name="l00998"></a>00998 
 | 
			
		||||
<a name="l00999"></a>00999     <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#f8a6c9adbdec7a5a982dd2b74febcc08">should_remove_source</a>(self, pkg):
 | 
			
		||||
@ -1045,7 +1045,7 @@
 | 
			
		||||
<a name="l01031"></a>01031 <span class="stringliteral"></span>
 | 
			
		||||
<a name="l01032"></a>01032 <span class="stringliteral">        This method checks if a binary package should be upgraded; this can</span>
 | 
			
		||||
<a name="l01033"></a>01033 <span class="stringliteral">        happen also if the binary package is a binary-NMU for the given arch.</span>
 | 
			
		||||
<a name="l01034"></a>01034 <span class="stringliteral">        The analisys is performed for the source package specified by the</span>
 | 
			
		||||
<a name="l01034"></a>01034 <span class="stringliteral">        The analysis is performed for the source package specified by the</span>
 | 
			
		||||
<a name="l01035"></a>01035 <span class="stringliteral">        `src' parameter, checking the architecture `arch' for the distribution</span>
 | 
			
		||||
<a name="l01036"></a>01036 <span class="stringliteral">        `suite'.</span>
 | 
			
		||||
<a name="l01037"></a>01037 <span class="stringliteral">       </span>
 | 
			
		||||
@ -1157,7 +1157,7 @@
 | 
			
		||||
<a name="l01143"></a>01143     <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#94785175a85f44b1afaf3add167a211f">should_upgrade_src</a>(self, src, suite):
 | 
			
		||||
<a name="l01144"></a>01144         <span class="stringliteral">"""Check if source package should be upgraded</span>
 | 
			
		||||
<a name="l01145"></a>01145 <span class="stringliteral"></span>
 | 
			
		||||
<a name="l01146"></a>01146 <span class="stringliteral">        This method checks if a source package should be upgraded. The analisys</span>
 | 
			
		||||
<a name="l01146"></a>01146 <span class="stringliteral">        This method checks if a source package should be upgraded. The analysis</span>
 | 
			
		||||
<a name="l01147"></a>01147 <span class="stringliteral">        is performed for the source package specified by the `src' parameter, </span>
 | 
			
		||||
<a name="l01148"></a>01148 <span class="stringliteral">        checking the architecture `arch' for the distribution `suite'.</span>
 | 
			
		||||
<a name="l01149"></a>01149 <span class="stringliteral">       </span>
 | 
			
		||||
 | 
			
		||||
@ -1603,7 +1603,7 @@ Definition at line <a class="el" href="britney_8py-source.html#l00990">990</a> o
 | 
			
		||||
<p>
 | 
			
		||||
<div class="fragment"><pre class="fragment">Check if source package should be upgraded
 | 
			
		||||
 | 
			
		||||
This method checks if a source package should be upgraded. The analisys
 | 
			
		||||
This method checks if a source package should be upgraded. The analysis
 | 
			
		||||
is performed for the source package specified by the `src' parameter, 
 | 
			
		||||
checking the architecture `arch' for the distribution `suite'.
 | 
			
		||||
       
 | 
			
		||||
@ -1657,7 +1657,7 @@ Definition at line <a class="el" href="britney_8py-source.html#l01134">1134</a>
 | 
			
		||||
 | 
			
		||||
This method checks if a binary package should be upgraded; this can
 | 
			
		||||
happen also if the binary package is a binary-NMU for the given arch.
 | 
			
		||||
The analisys is performed for the source package specified by the
 | 
			
		||||
The analysis is performed for the source package specified by the
 | 
			
		||||
`src' parameter, checking the architecture `arch' for the distribution
 | 
			
		||||
`suite'.
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
@ -743,7 +743,7 @@ Definition at line 990 of file britney.py.\index{britney::Britney@{britney::Brit
 | 
			
		||||
 | 
			
		||||
\footnotesize\begin{verbatim}Check if source package should be upgraded
 | 
			
		||||
 | 
			
		||||
This method checks if a source package should be upgraded. The analisys
 | 
			
		||||
This method checks if a source package should be upgraded. The analysis
 | 
			
		||||
is performed for the source package specified by the `src' parameter, 
 | 
			
		||||
checking the architecture `arch' for the distribution `suite'.
 | 
			
		||||
       
 | 
			
		||||
@ -765,7 +765,7 @@ Definition at line 1134 of file britney.py.\index{britney::Britney@{britney::Bri
 | 
			
		||||
 | 
			
		||||
This method checks if a binary package should be upgraded; this can
 | 
			
		||||
happen also if the binary package is a binary-NMU for the given arch.
 | 
			
		||||
The analisys is performed for the source package specified by the
 | 
			
		||||
The analysis is performed for the source package specified by the
 | 
			
		||||
`src' parameter, checking the architecture `arch' for the distribution
 | 
			
		||||
`suite'.
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										389
									
								
								lib/memory.c
									
									
									
									
									
								
							
							
						
						
									
										389
									
								
								lib/memory.c
									
									
									
									
									
								
							@ -1,389 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
#include "templates.h"
 | 
			
		||||
#include "freelist.h"
 | 
			
		||||
 | 
			
		||||
/**** THEORY
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
So, we have blocks with a freelist
 | 
			
		||||
 | 
			
		||||
        XXX............XXXXXXX..XXXXX.....XXXXXX......
 | 
			
		||||
        
 | 
			
		||||
Within a block, we work with segments. A segment is...
 | 
			
		||||
 | 
			
		||||
	   ^..........|
 | 
			
		||||
 | 
			
		||||
Every now and then we make sure we've got a decent sized segment.
 | 
			
		||||
 | 
			
		||||
We have multiple blocks. They're kept ordered by the size of their
 | 
			
		||||
current segment.
 | 
			
		||||
 | 
			
		||||
 **********************************************/
 | 
			
		||||
 | 
			
		||||
#define ALIGN 4
 | 
			
		||||
 | 
			
		||||
#define FLBT_BITS (sizeof(flb_t)*8)
 | 
			
		||||
#define MEMBLOCKSIZE (1 << 22)
 | 
			
		||||
#define ALIGNEDSIZE(s) (((s) + ALIGN - 1) / ALIGN * ALIGN)
 | 
			
		||||
 | 
			
		||||
struct memblock {
 | 
			
		||||
    struct memblock *next;
 | 
			
		||||
 | 
			
		||||
    size_t          n_bytes;          /* index of free char */
 | 
			
		||||
    size_t          size;             /* size of block after char */
 | 
			
		||||
 | 
			
		||||
    unsigned        n_used_chunks;    /* number of unfreed blocks */
 | 
			
		||||
    size_t          n_used_bytes;     /* number of bytes actually used */
 | 
			
		||||
    size_t          n_productive_bytes; /* number of bytes used usefully */
 | 
			
		||||
 | 
			
		||||
    flb_t           free[MEMBLOCKSIZE/ALIGN/FLBT_BITS + 1];
 | 
			
		||||
    unsigned char   mem[MEMBLOCKSIZE];
 | 
			
		||||
};
 | 
			
		||||
typedef struct memblock memblock;
 | 
			
		||||
 | 
			
		||||
static memblock *base = NULL;
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
static int valid_memblock_mdebug1(struct memblock *mb) {
 | 
			
		||||
    size_t cnt, i;
 | 
			
		||||
    static int rarity = 0;
 | 
			
		||||
 | 
			
		||||
    assert(mb->n_bytes + mb->size <= sizeof(mb->mem));
 | 
			
		||||
 | 
			
		||||
    if (mb->n_used_chunks == 0) assert(mb->n_bytes == 0);
 | 
			
		||||
    assert(((unsigned long)mb->mem + mb->n_bytes) % ALIGN == 0);
 | 
			
		||||
 | 
			
		||||
    assert(mb->n_productive_bytes <= mb->n_used_bytes);
 | 
			
		||||
    assert(mb->n_used_bytes + mb->size <= sizeof(mb->mem));
 | 
			
		||||
 | 
			
		||||
#define TWO(k)    (1ul << (k))
 | 
			
		||||
#define CYCL(k)   (~0ul / (1 + TWO(TWO(k))))
 | 
			
		||||
 | 
			
		||||
    rarity++; rarity %= 25000;
 | 
			
		||||
    if (rarity != 0) {
 | 
			
		||||
	cnt = mb->n_used_bytes;
 | 
			
		||||
    } else {
 | 
			
		||||
        cnt = 0;
 | 
			
		||||
        for (i = 0; i < sizeof(mb->mem)/ALIGN/FLBT_BITS+1; i++) {
 | 
			
		||||
    	unsigned long x = mb->free[i];
 | 
			
		||||
            size_t s;
 | 
			
		||||
    	    x = (x & CYCL(0)) + ((x >> TWO(0)) & CYCL(0));
 | 
			
		||||
    	    x = (x & CYCL(1)) + ((x >> TWO(1)) & CYCL(1));
 | 
			
		||||
            for (s = 2; (2u << s) <= FLBT_BITS; s++) {
 | 
			
		||||
    		x += x >> TWO(s);
 | 
			
		||||
    		x &= CYCL(s);
 | 
			
		||||
    	    }
 | 
			
		||||
	    cnt += x * ALIGN;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#undef TWO
 | 
			
		||||
#undef CYCL
 | 
			
		||||
 | 
			
		||||
    assert(cnt == mb->n_used_bytes);
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if MDEBUG3
 | 
			
		||||
static int valid_memblock_mdebug3(struct memblock *mb) {
 | 
			
		||||
    size_t offset, step, used;
 | 
			
		||||
    unsigned chunk = 0;
 | 
			
		||||
 | 
			
		||||
    offset = 0;
 | 
			
		||||
    used = 0;
 | 
			
		||||
    if ((unsigned long)mb->mem % ALIGN != 0)
 | 
			
		||||
        offset = ALIGN - ((unsigned long)mb->mem % ALIGN);
 | 
			
		||||
 | 
			
		||||
    while(offset < mb->n_bytes) {
 | 
			
		||||
        step = *(size_t*)(mb->mem + offset);
 | 
			
		||||
        assert(step % ALIGN == 0 || step % ALIGN == 1);
 | 
			
		||||
        if (step % ALIGN == 1) step--; /* freed */
 | 
			
		||||
        else used += step;
 | 
			
		||||
        assert(step > 0);
 | 
			
		||||
        offset += step;
 | 
			
		||||
        chunk++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(used == mb->n_used_bytes);
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline static int valid_memblock(struct memblock *mb) {
 | 
			
		||||
    (void)mb;
 | 
			
		||||
 | 
			
		||||
    MDEBUG1_ONLY( if (!valid_memblock_mdebug1(mb)) return 0; )
 | 
			
		||||
    MDEBUG3_ONLY( if (!valid_memblock_mdebug3(mb)) return 0; )
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_memblock_summary(void) {
 | 
			
		||||
    struct memblock *mb;
 | 
			
		||||
    unsigned long tused = 0, talloc = 0, tprod = 0, tavail = 0, nb = 0;
 | 
			
		||||
 | 
			
		||||
    for (mb = base; mb != NULL; mb = mb->next) {
 | 
			
		||||
        assert(valid_memblock(mb));
 | 
			
		||||
 | 
			
		||||
	MDEBUG3_ONLY(
 | 
			
		||||
            fprintf(stderr, "%p: [%d,%lu/%lu,%p,%p]\n", mb,
 | 
			
		||||
               mb->n_used_chunks, (unsigned long)mb->n_used_bytes, 
 | 
			
		||||
               (unsigned long)mb->n_bytes, mb->next, mb->mem);
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if (mb != base && mb->size * 50 < sizeof(mb->mem) - mb->n_used_bytes) {
 | 
			
		||||
		flb_t k; size_t s;
 | 
			
		||||
		k = mb->n_bytes / ALIGN;
 | 
			
		||||
		s = mb->size / ALIGN;
 | 
			
		||||
		find_long_freebits(mb->free,MEMBLOCKSIZE/ALIGN/FLBT_BITS+1,&k,&s);
 | 
			
		||||
		k *= ALIGN; s *= ALIGN;
 | 
			
		||||
		fprintf(stderr, "%p %lu: Wasted block "
 | 
			
		||||
                                "[%d chunks, %lu free bytes, %lu avail bytes, %2.2f%%], suggested [%ld,%ld] -> [%ld,%ld]\n",
 | 
			
		||||
			mb->mem, nb, mb->n_used_chunks, 
 | 
			
		||||
			(unsigned long) sizeof(mb->mem) - mb->n_used_bytes,
 | 
			
		||||
			(unsigned long) mb->size,
 | 
			
		||||
			(float) 100.0 * mb->size / (sizeof(mb->mem) - mb->n_used_bytes),
 | 
			
		||||
			(unsigned long) mb->n_bytes, (unsigned long) mb->size, 
 | 
			
		||||
			(unsigned long) k, (unsigned long) s);
 | 
			
		||||
		if (s > mb->size * 4 || s * 25 > sizeof(mb->mem) - mb->n_used_bytes) {
 | 
			
		||||
			mb->n_bytes = k;
 | 
			
		||||
			mb->size = s;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	nb++;
 | 
			
		||||
	tprod += mb->n_productive_bytes; 
 | 
			
		||||
	tused += mb->n_used_bytes; 
 | 
			
		||||
	tavail += mb->size;
 | 
			
		||||
	talloc += sizeof(memblock);
 | 
			
		||||
    }
 | 
			
		||||
    fprintf(stderr, "TOTAL: %lu %lu KiB alloc"
 | 
			
		||||
		 "(%lu/%lu available, %2.2f%%) (%lu KiB used, %2.2f%%) (%lu KiB useful, %2.2f%%)\n", 
 | 
			
		||||
	nb, talloc / 1024, 
 | 
			
		||||
	(unsigned long) (base ? base->size / 1024 : 0), 
 | 
			
		||||
	  tavail / 1024, (talloc > 0 ? 100.0*tavail/talloc : 0.0),
 | 
			
		||||
	tused / 1024, (talloc > 0 ? 100.0*tused/talloc : 0.0), 
 | 
			
		||||
	tprod / 1024, (talloc > 0 ? 100.0*tprod/talloc : 0.0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MDEBUG1_ONLY(static int first_malloc = 0;)
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG3
 | 
			
		||||
static void print_memblock_stats(void) {
 | 
			
		||||
    struct memblock *mb;
 | 
			
		||||
    size_t offset;
 | 
			
		||||
   
 | 
			
		||||
    for (mb = base; mb != NULL; mb = mb->next) {
 | 
			
		||||
        assert(valid_memblock(mb));
 | 
			
		||||
 | 
			
		||||
        printf("%p: [%d,%lu/%lu/%lu,%p,%p:\n", mb,
 | 
			
		||||
               mb->n_used_chunks, (unsigned long)mb->n_productive_bytes, 
 | 
			
		||||
	       (unsigned long)mb->n_used_bytes, (unsigned long)mb->n_bytes,
 | 
			
		||||
               mb->next, mb->mem);
 | 
			
		||||
 | 
			
		||||
        offset = 0;
 | 
			
		||||
        if ((unsigned long)mb->mem % ALIGN != 0)
 | 
			
		||||
             offset = ALIGN - ((unsigned long)mb->mem % ALIGN);
 | 
			
		||||
        while(offset < mb->n_bytes) {
 | 
			
		||||
             size_t step = *(size_t*)(mb->mem + offset);
 | 
			
		||||
             if (step % ALIGN == 1) {
 | 
			
		||||
                 step--;
 | 
			
		||||
                 printf(" (%d)", (int) step);
 | 
			
		||||
             } else {
 | 
			
		||||
                 printf(" %d", (int) step);
 | 
			
		||||
             }
 | 
			
		||||
             offset += step;
 | 
			
		||||
        }
 | 
			
		||||
        printf("\n");
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void *block_malloc(size_t size) {
 | 
			
		||||
    memblock *where = base;
 | 
			
		||||
    void *result;
 | 
			
		||||
    size_t realsize = size;
 | 
			
		||||
 | 
			
		||||
    MDEBUG3_ONLY( if (first_malloc) print_memblock_stats(); )
 | 
			
		||||
    MDEBUG3_ONLY( first_malloc = 0; )
 | 
			
		||||
 | 
			
		||||
    (void)assert(ALIGN >= sizeof(size_t)); /* ALIGN is set too small! */
 | 
			
		||||
 | 
			
		||||
    MDEBUG2_ONLY(size += ALIGN;) 
 | 
			
		||||
	/* for the size, so the caller can be checked */
 | 
			
		||||
 | 
			
		||||
    size = ALIGNEDSIZE(size);
 | 
			
		||||
 
 | 
			
		||||
    assert(size > 0 && size < sizeof(where->mem)); 
 | 
			
		||||
    assert(!where || ((unsigned long)where->mem + where->n_bytes) % ALIGN == 0);
 | 
			
		||||
     
 | 
			
		||||
    if ( !where || where->size < size ) {
 | 
			
		||||
        MDEBUG1_ONLY(print_memblock_summary();)
 | 
			
		||||
        where = malloc(sizeof(memblock));
 | 
			
		||||
        if (where == NULL) {
 | 
			
		||||
	    int i;
 | 
			
		||||
            fprintf(stderr, "block_malloc: failed trying to allocate memblock\n");
 | 
			
		||||
            i = 0; where = base; while(where) {i++; where = where->next;}
 | 
			
		||||
	    fprintf(stderr, "(had allocated %d blocks, each %lu bytes)\n", i, 
 | 
			
		||||
		(unsigned long)sizeof(memblock));
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        where->n_used_chunks = 0;
 | 
			
		||||
	memset(where->free, 0, sizeof(where->free));
 | 
			
		||||
        where->n_bytes = 0;
 | 
			
		||||
	where->size = sizeof(where->mem);
 | 
			
		||||
 | 
			
		||||
	assert( (unsigned long)where->mem % ALIGN == 0);
 | 
			
		||||
		/* XXX: should be able to cope with this :( */
 | 
			
		||||
 | 
			
		||||
        where->n_used_bytes = where->n_bytes;
 | 
			
		||||
        where->n_productive_bytes = 0;
 | 
			
		||||
        (where)->next = base;
 | 
			
		||||
	base = where;
 | 
			
		||||
	
 | 
			
		||||
        MDEBUG2_ONLY(memset(where->mem, 0xDD, sizeof(where->mem));)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = where->mem + where->n_bytes;
 | 
			
		||||
 | 
			
		||||
    assert( (unsigned long)where->mem % ALIGN == where->n_bytes % ALIGN );
 | 
			
		||||
    assert( size % ALIGN == 0 );
 | 
			
		||||
    mark_bits(where->free, 
 | 
			
		||||
	(unsigned long)((unsigned char*)result - where->mem) / ALIGN,
 | 
			
		||||
	size / ALIGN, 1);
 | 
			
		||||
 | 
			
		||||
    where->n_bytes += size;
 | 
			
		||||
    where->size -= size;
 | 
			
		||||
    where->n_used_bytes += size;
 | 
			
		||||
    where->n_productive_bytes += realsize;
 | 
			
		||||
    where->n_used_chunks++;
 | 
			
		||||
 | 
			
		||||
    MDEBUG2_ONLY( memset(result, 0xEE, size); )
 | 
			
		||||
 | 
			
		||||
    MDEBUG2_ONLY( *(size_t *)result = realsize; )
 | 
			
		||||
    MDEBUG2_ONLY( result += ALIGN; )
 | 
			
		||||
 | 
			
		||||
    assert(((unsigned long)where->mem + where->n_bytes) % ALIGN == 0);
 | 
			
		||||
 | 
			
		||||
    assert(valid_memblock(where));
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static memblock **find_memblock(unsigned char *mem) {
 | 
			
		||||
    memblock **where;
 | 
			
		||||
 | 
			
		||||
    for (where = &base; *where != NULL; where = &(*where)->next) {
 | 
			
		||||
	memblock *mb = *where;
 | 
			
		||||
        assert(valid_memblock(mb));
 | 
			
		||||
        if (&mb->mem[0] <= mem && (size_t)(mem - mb->mem) < sizeof(mb->mem)) {
 | 
			
		||||
            return where;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_in_memblock(memblock *mb, unsigned char *mem, size_t size) {
 | 
			
		||||
    MDEBUG2_ONLY(size_t *stmem = ((size_t*)mem) - 1;)
 | 
			
		||||
 | 
			
		||||
    assert(mb && mem && size > 0);
 | 
			
		||||
 | 
			
		||||
    mb->n_used_chunks--;
 | 
			
		||||
 | 
			
		||||
    mb->n_used_bytes -= ALIGNEDSIZE(size);
 | 
			
		||||
    mark_bits(mb->free, (unsigned long)(mem - mb->mem) / ALIGN, 
 | 
			
		||||
		ALIGNEDSIZE(size) / ALIGN, 0);
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG2
 | 
			
		||||
    mark_bits(mb->free, (unsigned long)(mem - mb->mem) / ALIGN - 1, 1, 0);
 | 
			
		||||
    mb->n_used_bytes -= ALIGN;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if ((size_t)(mem - mb->mem) + ALIGNEDSIZE(size) == mb->n_bytes) {
 | 
			
		||||
	size_t k = count_free_bits_back(mb->free, mb->n_bytes / ALIGN) * ALIGN;
 | 
			
		||||
	mb->n_bytes -= k;
 | 
			
		||||
	mb->size += k;
 | 
			
		||||
    }
 | 
			
		||||
    if ((size_t)(mem - mb->mem) == mb->n_bytes + mb->size) {
 | 
			
		||||
	mb->size += count_free_bits_after(mb->free, 
 | 
			
		||||
			(mb->n_bytes + mb->size) / ALIGN,
 | 
			
		||||
			sizeof(mb->mem) / ALIGN) * ALIGN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mb->n_productive_bytes -= size;
 | 
			
		||||
 | 
			
		||||
    if (mb->n_used_chunks == 0) {
 | 
			
		||||
        assert(mb->n_productive_bytes == 0);
 | 
			
		||||
        assert(mb->n_used_bytes == 0);
 | 
			
		||||
 | 
			
		||||
        mb->n_bytes = 0;
 | 
			
		||||
	mb->size = sizeof(mb->mem);
 | 
			
		||||
        mb->n_used_bytes = 0;
 | 
			
		||||
        mb->n_productive_bytes = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MDEBUG2_ONLY( memset(mem, 0xAA, size); )
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG2
 | 
			
		||||
    assert((unsigned char*)stmem >= mb->mem && (unsigned char*)stmem < mb->mem + sizeof(mb->mem));
 | 
			
		||||
    assert(*stmem % ALIGN == 0);
 | 
			
		||||
    assert(*stmem == size);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    assert(valid_memblock(mb));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void block_free(void *vmem, size_t size) {
 | 
			
		||||
    memblock **where;
 | 
			
		||||
    MDEBUG1_ONLY(static int free_count = 0;)
 | 
			
		||||
 | 
			
		||||
    if (vmem == NULL) return;
 | 
			
		||||
 | 
			
		||||
    MDEBUG1_ONLY(first_malloc = 1;)
 | 
			
		||||
 | 
			
		||||
    where = find_memblock(vmem);
 | 
			
		||||
    assert(where);
 | 
			
		||||
    free_in_memblock(*where, vmem, size);
 | 
			
		||||
    if ((*where)->n_used_chunks == 0 && *where != base) {
 | 
			
		||||
        memblock *mb = *where;
 | 
			
		||||
        MDEBUG1_ONLY( print_memblock_summary(); )
 | 
			
		||||
        *where = (*where)->next;
 | 
			
		||||
        free(mb);
 | 
			
		||||
        MDEBUG1_ONLY( fprintf(stderr, "Freed memblock\n"); )
 | 
			
		||||
    }
 | 
			
		||||
    MDEBUG1_ONLY( free_count++; free_count %= 10000; )
 | 
			
		||||
    MDEBUG1_ONLY( if (!free_count) print_memblock_summary(); )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *block_realloc(void *vmem, size_t oldsize, size_t newsize) {
 | 
			
		||||
    void *vnewmem;
 | 
			
		||||
 | 
			
		||||
    if (vmem == NULL && newsize == 0) abort();
 | 
			
		||||
    if (vmem == NULL) return block_malloc(newsize);
 | 
			
		||||
    if (newsize == 0) {
 | 
			
		||||
        block_free(vmem, oldsize);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vnewmem = block_malloc(newsize);
 | 
			
		||||
    if (vnewmem) {
 | 
			
		||||
        memcpy(vnewmem, vmem, (oldsize < newsize ? oldsize : newsize));
 | 
			
		||||
        block_free(vmem, oldsize);
 | 
			
		||||
    }
 | 
			
		||||
    return vnewmem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *block_strdup(char *from) {
 | 
			
		||||
    char *result;
 | 
			
		||||
    if (!from) return NULL;
 | 
			
		||||
    result = block_malloc(strlen(from) + 1);
 | 
			
		||||
    strcpy(result, from);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
 | 
			
		||||
 | 
			
		||||
#define M 16
 | 
			
		||||
 | 
			
		||||
void *block_malloc(size_t size) { return malloc(size); }
 | 
			
		||||
void block_free(void *vmem) { free(vmem); }
 | 
			
		||||
void *block_realloc(void *vmem, size_t newsize) { return realloc(vmem, newsize); }
 | 
			
		||||
char *block_strdup(char *from) {
 | 
			
		||||
	char *d; 
 | 
			
		||||
	if (!from) return 0;
 | 
			
		||||
	d = block_malloc(strlen(from+1));
 | 
			
		||||
	if (d) strcpy(d, from);
 | 
			
		||||
	return d; 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_memblock_summary(void) { }
 | 
			
		||||
							
								
								
									
										1328
									
								
								lib/update_out.py
									
									
									
									
									
								
							
							
						
						
									
										1328
									
								
								lib/update_out.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user