~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/python2.4
#
# Copyright 2009 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

# pylint: disable-msg=C0103,W0403

# This script updates the cached source package information in the system.
# We use this for fast source package searching (as opposed to joining
# through gazillions of publishing tables).

import _pythonpath

from zope.component import getUtility

from canonical.config import config
from canonical.launchpad.interfaces import IDistributionSet
from lp.services.scripts.base import LaunchpadCronScript


class PackageCacheUpdater(LaunchpadCronScript):
    """Helper class for updating package caches.

    It iterates over all distributions, distroseries and archives (including
    PPAs) updating the package caches to reflect what is currently published
    in those locations.
    """

    def updateDistributionPackageCounters(self, distribution):
        """Update package counters for a given distribution."""
        for distroseries in distribution:
            distroseries.updatePackageCount()
            self.txn.commit()
            for arch in distroseries.architectures:
                arch.updatePackageCount()
                self.txn.commit()

    def updateDistributionCache(self, distribution, archive):
        """Update package caches for the given location.

        'archive' can be one of the main archives (PRIMARY, PARTNER or
        EMBARGOED) or even a PPA.

        This method commits the transaction frequently since it deal with
        a huge amount of data.

        PPA archives caches are consolidated in a Archive row to optimize
        searches across PPAs.
        """
        for distroseries in distribution.serieses:
            self.updateDistroSeriesCache(distroseries, archive)

        distribution.removeOldCacheItems(archive, log=self.logger)

        updates = distribution.updateCompleteSourcePackageCache(
            archive=archive, ztm=self.txn, log=self.logger)

        if updates > 0:
            self.txn.commit()

    def updateDistroSeriesCache(self, distroseries, archive):
        """Update package caches for the given location."""
        self.logger.info('%s %s %s starting' % (
            distroseries.distribution.name, distroseries.name,
            archive.displayname))

        distroseries.removeOldCacheItems(archive=archive, log=self.logger)

        updates = distroseries.updateCompletePackageCache(
            archive=archive, ztm=self.txn, log=self.logger)

        if updates > 0:
            self.txn.commit()

    def main(self):
        self.logger.debug('Starting the package cache update')

        # Do the package counter and cache update for each distribution.
        distroset = getUtility(IDistributionSet)
        for distribution in distroset:
            self.logger.info(
                'Updating %s package counters' % distribution.name)
            self.updateDistributionPackageCounters(distribution)

            self.logger.info(
                'Updating %s main archives' % distribution.name)
            for archive in distribution.all_distro_archives:
                self.updateDistributionCache(distribution, archive)

            self.logger.info(
                'Updating %s PPAs' % distribution.name)
            for archive in distribution.getAllPPAs():
                self.updateDistributionCache(distribution, archive)
                archive.updateArchiveCache()

            # Commit any remaining update for a distribution.
            self.txn.commit()
            self.logger.info('%s done' % distribution.name)

        self.logger.debug('Finished the package cache update')

if __name__ == '__main__':
    script = PackageCacheUpdater(
        'update-cache', dbuser=config.statistician.dbuser)
    script.lock_and_run()