~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/soyuz/model/distroseriesdifferencejob.py

Merged packageset-picker-4 into packageset-picker-5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
    'DistroSeriesDifferenceJob',
9
9
    ]
10
10
 
11
 
from storm.expr import And
12
11
from zope.component import getUtility
13
12
from zope.interface import (
14
13
    classProvides,
15
14
    implements,
16
15
    )
17
16
 
18
 
from canonical.database.sqlbase import sqlvalues
 
17
from canonical.database.sqlbase import quote
19
18
from canonical.launchpad.interfaces.lpstorm import (
20
19
    IMasterStore,
21
20
    IStore,
23
22
from lp.registry.interfaces.distroseriesdifference import (
24
23
    IDistroSeriesDifferenceSource,
25
24
    )
26
 
from lp.registry.interfaces.distroseriesparent import IDistroSeriesParentSet
27
25
from lp.registry.interfaces.pocket import PackagePublishingPocket
28
26
from lp.registry.model.distroseries import DistroSeries
29
27
from lp.registry.model.distroseriesdifference import DistroSeriesDifference
48
46
FEATURE_FLAG_ENABLE_MODULE = u"soyuz.derived_series_jobs.enabled"
49
47
 
50
48
 
51
 
def make_metadata(sourcepackagename, parent_series):
52
 
    """Return JSON metadata for a job on `sourcepackagename`."""
 
49
def make_metadata(sourcepackagename_id, parent_series_id):
 
50
    """Return JSON metadata for a job on `sourcepackagename_id`."""
53
51
    return {
54
 
        'sourcepackagename': sourcepackagename.id,
55
 
        'parent_series': parent_series.id,
 
52
        'sourcepackagename': sourcepackagename_id,
 
53
        'parent_series': parent_series_id,
56
54
    }
57
55
 
58
56
 
70
68
    job = DistributionJob(
71
69
        distribution=derived_series.distribution, distroseries=derived_series,
72
70
        job_type=DistributionJobType.DISTROSERIESDIFFERENCE,
73
 
        metadata=make_metadata(sourcepackagename, parent_series))
 
71
        metadata=make_metadata(sourcepackagename.id, parent_series.id))
74
72
    IMasterStore(DistributionJob).add(job)
75
73
    return DistroSeriesDifferenceJob(job)
76
74
 
77
75
 
 
76
def compose_job_insertion_tuple(derived_series, parent_series,
 
77
                                sourcepackagename_id, job_id):
 
78
    """Compose tuple for insertion into `DistributionJob`.
 
79
 
 
80
    :param derived_series: Derived `DistroSeries`.
 
81
    :param parent_series: Parent `DistroSeries`.
 
82
    :param sourcepackagename_id: ID of `SourcePackageName`.
 
83
    :param job_id: associated `Job` id.
 
84
    :return: A tuple of: derived distribution id, derived distroseries id,
 
85
        job type, job id, JSON data map.
 
86
    """
 
87
    json = DistributionJob.serializeMetadata(make_metadata(
 
88
        sourcepackagename_id, parent_series.id))
 
89
    return (
 
90
        derived_series.distribution.id,
 
91
        derived_series.id,
 
92
        DistributionJobType.DISTROSERIESDIFFERENCE,
 
93
        job_id,
 
94
        json,
 
95
        )
 
96
 
 
97
 
78
98
def create_multiple_jobs(derived_series, parent_series):
79
 
    """Create a `DistroSeriesDifferenceJob` for all the source packages in
80
 
    archive.
 
99
    """Create `DistroSeriesDifferenceJob`s between parent and derived series.
81
100
 
82
101
    :param derived_series: A `DistroSeries` that is assumed to be derived
83
102
        from another one.
84
103
    :param parent_series: A `DistroSeries` that is a parent of
85
104
        `derived_series`.
 
105
    :return: A list of newly-created `DistributionJob` ids.
86
106
    """
87
107
    store = IStore(SourcePackageRelease)
88
108
    source_package_releases = store.find(
89
109
        SourcePackageRelease,
90
 
        And(
91
 
            SourcePackagePublishingHistory.sourcepackagerelease ==
92
 
                SourcePackageRelease.id,
93
 
            SourcePackagePublishingHistory.distroseries == derived_series.id,
94
 
            SourcePackagePublishingHistory.status.is_in(
95
 
                active_publishing_status)))
 
110
        SourcePackagePublishingHistory.sourcepackagerelease ==
 
111
            SourcePackageRelease.id,
 
112
        SourcePackagePublishingHistory.distroseries == derived_series.id,
 
113
        SourcePackagePublishingHistory.status.is_in(active_publishing_status))
96
114
    nb_jobs = source_package_releases.count()
97
115
    sourcepackagenames = source_package_releases.values(
98
116
        SourcePackageRelease.sourcepackagenameID)
99
117
    job_ids = Job.createMultiple(store, nb_jobs)
100
118
 
101
 
    def composeJobInsertionTuple(derived_series, parent_series,
102
 
                                 sourcepackagename, job_id):
103
 
        data = (
104
 
            derived_series.distribution.id, derived_series.id,
105
 
            DistributionJobType.DISTROSERIESDIFFERENCE, job_id,
106
 
            DistributionJob.serializeMetadata(
107
 
                {'sourcepackagename': sourcepackagename,
108
 
                 'parent_series': parent_series.id}))
109
 
        format_string = "(%s)" % ", ".join(["%s"] * len(data))
110
 
        return format_string % sqlvalues(*data)
111
 
 
112
 
    job_contents = [
113
 
        composeJobInsertionTuple(
114
 
            derived_series, parent_series, sourcepackagename, job_id)
115
 
        for job_id, sourcepackagename in
116
 
            zip(job_ids, sourcepackagenames)]
 
119
    job_tuples = [
 
120
        quote(compose_job_insertion_tuple(
 
121
            derived_series, parent_series, sourcepackagename, job_id))
 
122
        for job_id, sourcepackagename in zip(job_ids, sourcepackagenames)]
117
123
 
118
124
    store = IStore(DistributionJob)
119
125
    result = store.execute("""
121
127
            distribution, distroseries, job_type, job, json_data)
122
128
        VALUES %s
123
129
        RETURNING id
124
 
        """ % ", ".join(job_contents))
 
130
        """ % ", ".join(job_tuples))
125
131
    return [job_id for job_id, in result]
126
132
 
127
133
 
132
138
    # optimization.  It's not actually disastrous to create
133
139
    # redundant jobs occasionally.
134
140
    json_metadata = DistributionJob.serializeMetadata(
135
 
        make_metadata(sourcepackagename, parent_series))
 
141
        make_metadata(sourcepackagename.id, parent_series.id))
136
142
 
137
143
    # Use master store because we don't like outdated information
138
144
    # here.
161
167
    runner some unnecessary work, but we don't expect a bit of
162
168
    unnecessary work to be a big problem.
163
169
    """
164
 
    if derived_series is None:
165
 
        return False
166
 
    dsp = getUtility(IDistroSeriesParentSet).getByDerivedSeries(
167
 
        derived_series)
168
 
    if dsp.count() == 0:
169
 
        return False
170
 
    for parent in dsp:
171
 
        if parent.parent_series.distribution == derived_series.distribution:
172
 
            # Differences within a distribution are not tracked.
173
 
            return False
 
170
    if parent_series.distribution == derived_series.distribution:
 
171
        # Differences within a distribution are not tracked.
 
172
        return False
174
173
    existing_jobs = find_waiting_jobs(
175
174
        derived_series, sourcepackagename, parent_series)
176
175
    return len(existing_jobs) == 0
204
203
            PackagePublishingPocket.BACKPORTS,
205
204
            PackagePublishingPocket.PROPOSED):
206
205
            return
207
 
        jobs = []
208
 
        parent_series = derived_series.getParentSeries()
209
 
        # Create jobs for DSDs between the derived_series and its
210
 
        # parents.
211
 
        for parent in parent_series:
212
 
            if may_require_job(
213
 
                derived_series, sourcepackagename, parent):
214
 
                jobs.append(create_job(
215
 
                    derived_series, sourcepackagename, parent))
 
206
 
 
207
        # Create jobs for DSDs between the derived_series' parents and
 
208
        # the derived_series itself.
 
209
        parent_series_jobs = [
 
210
            create_job(derived_series, sourcepackagename, parent)
 
211
            for parent in derived_series.getParentSeries()
 
212
                if may_require_job(derived_series, sourcepackagename, parent)]
 
213
 
216
214
        # Create jobs for DSDs between the derived_series and its
217
215
        # children.
218
 
        for child in derived_series.getDerivedSeries():
219
 
            if may_require_job(
220
 
                child, sourcepackagename, derived_series):
221
 
                jobs.append(create_job(
222
 
                    child, sourcepackagename, derived_series))
223
 
        return jobs
 
216
        derived_series_jobs = [
 
217
            create_job(child, sourcepackagename, derived_series)
 
218
            for child in derived_series.getDerivedSeries()
 
219
                if may_require_job(child, sourcepackagename, derived_series)]
 
220
 
 
221
        return parent_series_jobs + derived_series_jobs
224
222
 
225
223
    @classmethod
226
224
    def massCreateForSeries(cls, derived_series):
327
325
 
328
326
        ds_diff = self.getMatchingDSD()
329
327
        if ds_diff is None:
330
 
            ds_diff = getUtility(IDistroSeriesDifferenceSource).new(
 
328
            getUtility(IDistroSeriesDifferenceSource).new(
331
329
                self.distroseries, self.sourcepackagename, self.parent_series)
332
330
        else:
333
331
            ds_diff.update()