Merge lp:~stevenk/launchpad/drop-psc into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Robert Collins
Approved revision: no longer in the source branch.
Merged at revision: 12850
Proposed branch: lp:~stevenk/launchpad/drop-psc
Merge into: lp:launchpad
Diff against target: 340 lines (+0/-212)
3 files modified
database/schema/security.cfg (+0/-3)
lib/lp/scripts/garbo.py (+0/-137)
lib/lp/scripts/tests/test_garbo.py (+0/-72)
To merge this branch: bzr merge lp:~stevenk/launchpad/drop-psc
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
William Grant code* Approve
Review via email: mp+57807@code.launchpad.net

Commit message

[r=lifeless,wgrant][bug=764292] Drop PopulateSPRChangelogs to thank it for its work.

Description of the change

After running for one month, and processing the changelogs for as-near-as-makes-no-difference half a million SPRs, the PopulateSPRChangelogs class in the hourly garbo script has done its dash. So to thank it, we kick it out of the code base.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

You should wait till staging and qastaging are fully migrated too.
Otherwise bad things will happen as you qa stuff :).

Revision history for this message
William Grant (wgrant) wrote :

Looks good. No need to wait.

review: Approve (code*)
Revision history for this message
Robert Collins (lifeless) wrote :

shrug, sure.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'database/schema/security.cfg'
2--- database/schema/security.cfg 2011-04-06 15:35:05 +0000
3+++ database/schema/security.cfg 2011-04-15 05:03:31 +0000
4@@ -2260,9 +2260,6 @@
5 public.job = SELECT, INSERT, DELETE
6 public.branchjob = SELECT, DELETE
7 public.bugjob = SELECT, INSERT
8-public.libraryfilealias = SELECT, INSERT
9-public.libraryfilecontent = SELECT, INSERT
10-public.sourcepackagerelease = SELECT, UPDATE
11
12 [garbo_daily]
13 type=user
14
15=== modified file 'lib/lp/scripts/garbo.py'
16--- lib/lp/scripts/garbo.py 2011-04-12 08:58:38 +0000
17+++ lib/lp/scripts/garbo.py 2011-04-15 05:03:31 +0000
18@@ -13,21 +13,14 @@
19 datetime,
20 timedelta,
21 )
22-from fixtures import TempDir
23 import logging
24 import multiprocessing
25-import os
26-import signal
27-import subprocess
28 import threading
29 import time
30
31 from psycopg2 import IntegrityError
32 import pytz
33-from storm.expr import LeftJoin
34 from storm.locals import (
35- And,
36- Count,
37 Max,
38 Min,
39 SQL,
40@@ -51,7 +44,6 @@
41 from canonical.launchpad.database.oauth import OAuthNonce
42 from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce
43 from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus
44-from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
45 from canonical.launchpad.interfaces.lpstorm import IMasterStore
46 from canonical.launchpad.utilities.looptuner import TunableLoop
47 from canonical.launchpad.webapp.interfaces import (
48@@ -59,9 +51,6 @@
49 MAIN_STORE,
50 MASTER_FLAVOR,
51 )
52-from canonical.librarian.utils import copy_and_close
53-from lp.archiveuploader.dscfile import findFile
54-from lp.archiveuploader.nascentuploadfile import UploadError
55 from lp.bugs.interfaces.bug import IBugSet
56 from lp.bugs.model.bug import Bug
57 from lp.bugs.model.bugattachment import BugAttachment
58@@ -82,14 +71,11 @@
59 from lp.registry.model.person import Person
60 from lp.services.job.model.job import Job
61 from lp.services.log.logger import PrefixFilter
62-from lp.services.memcache.interfaces import IMemcacheClient
63 from lp.services.scripts.base import (
64 LaunchpadCronScript,
65 SilentLaunchpadScriptFailure,
66 )
67 from lp.services.session.model import SessionData
68-from lp.soyuz.model.files import SourcePackageReleaseFile
69-from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
70 from lp.translations.interfaces.potemplate import IPOTemplateSet
71 from lp.translations.model.potranslation import POTranslation
72
73@@ -97,10 +83,6 @@
74 ONE_DAY_IN_SECONDS = 24*60*60
75
76
77-def subprocess_setup():
78- signal.signal(signal.SIGPIPE, signal.SIG_DFL)
79-
80-
81 class BulkPruner(TunableLoop):
82 """A abstract ITunableLoop base class for simple pruners.
83
84@@ -839,124 +821,6 @@
85 self.done = True
86
87
88-class PopulateSPRChangelogs(TunableLoop):
89- maximum_chunk_size = 1
90-
91- def __init__(self, log, abort_time=None):
92- super(PopulateSPRChangelogs, self).__init__(log, abort_time)
93- value = getUtility(IMemcacheClient).get('populate-spr-changelogs')
94- if not value:
95- self.start_at = 0
96- else:
97- self.start_at = value
98- self.finish_at = self.getCandidateSPRs(0).last()
99-
100- def getCandidateSPRs(self, start_at):
101- return IMasterStore(SourcePackageRelease).using(
102- SourcePackageRelease,
103- # Find any SPRFs that have expired (LFA.content IS NULL).
104- LeftJoin(
105- SourcePackageReleaseFile,
106- SourcePackageReleaseFile.sourcepackagereleaseID ==
107- SourcePackageRelease.id),
108- LeftJoin(
109- LibraryFileAlias,
110- And(LibraryFileAlias.id ==
111- SourcePackageReleaseFile.libraryfileID,
112- LibraryFileAlias.content == None)),
113- # And exclude any SPRs that have any expired SPRFs.
114- ).find(
115- SourcePackageRelease.id,
116- SourcePackageRelease.id >= start_at,
117- SourcePackageRelease.changelog == None,
118- ).group_by(SourcePackageRelease.id).having(
119- Count(LibraryFileAlias) == 0
120- ).order_by(SourcePackageRelease.id)
121-
122- def isDone(self):
123- return self.start_at > self.finish_at
124-
125- def __call__(self, chunk_size):
126- for sprid in self.getCandidateSPRs(self.start_at)[:chunk_size]:
127- spr = SourcePackageRelease.get(sprid)
128- with TempDir() as tmp_dir:
129- dsc_file = None
130-
131- # Grab the files from the librarian into a temporary
132- # directory.
133- try:
134- for sprf in spr.files:
135- dest = os.path.join(
136- tmp_dir.path, sprf.libraryfile.filename)
137- dest_file = open(dest, 'w')
138- sprf.libraryfile.open()
139- copy_and_close(sprf.libraryfile, dest_file)
140- if dest.endswith('.dsc'):
141- dsc_file = dest
142- except LookupError:
143- self.log.warning(
144- 'SPR %d (%s %s) has missing library files.' % (
145- spr.id, spr.name, spr.version))
146- continue
147-
148- if dsc_file is None:
149- self.log.warning(
150- 'SPR %d (%s %s) has no DSC.' % (
151- spr.id, spr.name, spr.version))
152- continue
153-
154- # Extract the source package. Throw away stdout/stderr
155- # -- we only really care about the return code.
156- fnull = open('/dev/null', 'w')
157- ret = subprocess.call(
158- ['dpkg-source', '-x', dsc_file, os.path.join(
159- tmp_dir.path, 'extracted')],
160- stdout=fnull, stderr=fnull,
161- preexec_fn=subprocess_setup)
162- fnull.close()
163- if ret != 0:
164- self.log.warning(
165- 'SPR %d (%s %s) failed to unpack: returned %d' % (
166- spr.id, spr.name, spr.version, ret))
167- continue
168-
169- # We have an extracted source package. Let's get the
170- # changelog. findFile ensures that it's not too huge, and
171- # not a symlink.
172- try:
173- changelog_path = findFile(
174- tmp_dir.path, 'debian/changelog')
175- except UploadError, e:
176- changelog_path = None
177- self.log.warning(
178- 'SPR %d (%s %s) changelog could not be '
179- 'imported: %s' % (
180- spr.id, spr.name, spr.version, e))
181- if changelog_path:
182- # The LFA should be restricted only if there aren't any
183- # public publications.
184- restricted = not any(
185- not a.private for a in spr.published_archives)
186- spr.changelog = getUtility(ILibraryFileAliasSet).create(
187- 'changelog',
188- os.stat(changelog_path).st_size,
189- open(changelog_path, "r"),
190- "text/x-debian-source-changelog",
191- restricted=restricted)
192- self.log.info('SPR %d (%s %s) changelog imported.' % (
193- spr.id, spr.name, spr.version))
194- else:
195- self.log.warning('SPR %d (%s %s) had no changelog.' % (
196- spr.id, spr.name, spr.version))
197-
198- self.start_at = spr.id + 1
199- result = getUtility(IMemcacheClient).set(
200- 'populate-spr-changelogs', self.start_at)
201- if not result:
202- self.log.warning('Failed to set start_at in memcache.')
203- transaction.commit()
204-
205-
206 class BaseDatabaseGarbageCollector(LaunchpadCronScript):
207 """Abstract base class to run a collection of TunableLoops."""
208 script_name = None # Script name for locking and database user. Override.
209@@ -1122,7 +986,6 @@
210 UnusedSessionPruner,
211 DuplicateSessionPruner,
212 BugHeatUpdater,
213- PopulateSPRChangelogs,
214 ]
215 experimental_tunable_loops = []
216
217
218=== modified file 'lib/lp/scripts/tests/test_garbo.py'
219--- lib/lp/scripts/tests/test_garbo.py 2011-04-08 14:10:32 +0000
220+++ lib/lp/scripts/tests/test_garbo.py 2011-04-15 05:03:31 +0000
221@@ -10,11 +10,8 @@
222 datetime,
223 timedelta,
224 )
225-from fixtures import TempDir
226 import logging
227-import os
228 from StringIO import StringIO
229-import subprocess
230 import time
231
232 from pytz import UTC
233@@ -42,7 +39,6 @@
234 from canonical.launchpad.database.oauth import OAuthNonce
235 from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce
236 from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus
237-from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet
238 from canonical.launchpad.interfaces.lpstorm import IMasterStore
239 from canonical.launchpad.scripts.tests import run_script
240 from canonical.launchpad.webapp.interfaces import (
241@@ -56,7 +52,6 @@
242 LaunchpadZopelessLayer,
243 ZopelessDatabaseLayer,
244 )
245-from lp.archiveuploader.dscfile import findFile
246 from lp.bugs.model.bugnotification import (
247 BugNotification,
248 BugNotificationRecipient,
249@@ -73,7 +68,6 @@
250 )
251 from lp.code.model.codeimportevent import CodeImportEvent
252 from lp.code.model.codeimportresult import CodeImportResult
253-from lp.registry.interfaces.distribution import IDistributionSet
254 from lp.registry.interfaces.person import (
255 IPersonSet,
256 PersonCreationRationale,
257@@ -93,8 +87,6 @@
258 SessionData,
259 SessionPkgData,
260 )
261-from lp.soyuz.enums import PackagePublishingStatus
262-from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
263 from lp.testing import (
264 TestCase,
265 TestCaseWithFactory,
266@@ -114,13 +106,6 @@
267
268 def test_hourly_script(self):
269 """Ensure garbo-hourly.py actually runs."""
270- # Our sampledata doesn't contain anything that PopulateSPRChangelogs
271- # can process without errors, so it's easier to just set all of the
272- # changelogs to a random LFA. We can't just expire every LFA, since
273- # a bunch of SPRs have no SPRFs at all.
274- IMasterStore(SourcePackageRelease).find(SourcePackageRelease).set(
275- changelogID=1)
276- transaction.commit() # run_script() is a different process.
277 rv, out, err = run_script(
278 "cronscripts/garbo-hourly.py", ["-q"], expect_returncode=0)
279 self.failIf(out.strip(), "Output to stdout: %s" % out)
280@@ -889,60 +874,3 @@
281 """ % sqlbase.quote(template.id)).get_one()
282
283 self.assertEqual(1, count)
284-
285- def upload_to_debian(self, restricted=False):
286- sid = getUtility(IDistributionSet)['debian']['sid']
287- spn = self.factory.makeSourcePackageName('9wm')
288- spr = self.factory.makeSourcePackageRelease(
289- sourcepackagename=spn, version='1.2-7', distroseries=sid)
290- archive = sid.main_archive
291- if restricted:
292- archive = self.factory.makeArchive(
293- distribution=sid.distribution, private=True)
294- self.factory.makeSourcePackagePublishingHistory(
295- sourcepackagerelease=spr, archive=archive,
296- status=PackagePublishingStatus.PUBLISHED)
297- for name in (
298- '9wm_1.2-7.diff.gz', '9wm_1.2.orig.tar.gz', '9wm_1.2-7.dsc'):
299- path = os.path.join(
300- 'lib/lp/soyuz/scripts/tests/gina_test_archive/pool/main/9',
301- '9wm', name)
302- lfa = getUtility(ILibraryFileAliasSet).create(
303- name, os.stat(path).st_size, open(path, 'r'),
304- 'application/octet-stream', restricted=restricted)
305- spr.addFile(lfa)
306- with TempDir() as tmp_dir:
307- fnull = open('/dev/null', 'w')
308- ret = subprocess.call(
309- ['dpkg-source', '-x', path, os.path.join(
310- tmp_dir.path, 'extracted')],
311- stdout=fnull, stderr=fnull)
312- fnull.close()
313- self.assertEqual(0, ret)
314- changelog_path = findFile(tmp_dir.path, 'debian/changelog')
315- changelog = open(changelog_path, 'r').read()
316- transaction.commit() # .runHourly() switches dbuser.
317- return (spr, changelog)
318-
319- def test_populateSPRChangelogs(self):
320- # We set SPR.changelog for imported records from Debian.
321- LaunchpadZopelessLayer.switchDbUser('testadmin')
322- spr, changelog = self.upload_to_debian()
323- collector = self.runHourly()
324- log = self.log_buffer.getvalue()
325- self.assertTrue(
326- 'SPR %d (9wm 1.2-7) changelog imported.' % spr.id in log)
327- self.assertFalse(spr.changelog == None)
328- self.assertFalse(spr.changelog.restricted)
329- self.assertEqual(changelog, spr.changelog.read())
330-
331- def test_populateSPRChangelogs_restricted_sprf(self):
332- LaunchpadZopelessLayer.switchDbUser('testadmin')
333- spr, changelog = self.upload_to_debian(restricted=True)
334- collector = self.runHourly()
335- log = self.log_buffer.getvalue()
336- self.assertTrue(
337- 'SPR %d (9wm 1.2-7) changelog imported.' % spr.id in log)
338- self.assertFalse(spr.changelog == None)
339- self.assertTrue(spr.changelog.restricted)
340- self.assertEqual(changelog, spr.changelog.read())