Merge lp:~mvo/software-center/expunge-cache into lp:software-center

Proposed by Michael Vogt
Status: Merged
Merged at revision: 2796
Proposed branch: lp:~mvo/software-center/expunge-cache
Merge into: lp:software-center
Diff against target: 178 lines (+132/-0)
4 files modified
setup.py (+2/-0)
softwarecenter/ui/gtk3/app.py (+14/-0)
test/test_utils.py (+36/-0)
utils/expunge-cache.py (+80/-0)
To merge this branch: bzr merge lp:~mvo/software-center/expunge-cache
Reviewer Review Type Date Requested Status
Gary Lasker (community) Approve
Review via email: mp+95219@code.launchpad.net

Description of the change

This adds a helper that keeps the cache clean from cached 301/404 etc responses.
It also offers cleanup by mtime but that is currently not used (only tested)

To post a comment you must log in.
Revision history for this message
Gary Lasker (gary-lasker) wrote :

Nice work, thanks mvo!!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added symlink 'data/expunge-cache.py'
=== target is u'../utils/expunge-cache.py'
=== modified file 'setup.py'
--- setup.py 2012-01-27 10:47:16 +0000
+++ setup.py 2012-02-29 17:32:19 +0000
@@ -94,6 +94,8 @@
94 "utils/update-software-center",94 "utils/update-software-center",
95 "utils/update-software-center-channels",95 "utils/update-software-center-channels",
96 "utils/update-software-center-agent",96 "utils/update-software-center-agent",
97 # generic helpers
98 "utils/expunge-cache.py",
97 ] + glob.glob("utils/piston-helpers/*.py"),99 ] + glob.glob("utils/piston-helpers/*.py"),
98 packages=['softwarecenter',100 packages=['softwarecenter',
99 'softwarecenter.backend',101 'softwarecenter.backend',
100102
=== modified file 'softwarecenter/ui/gtk3/app.py'
--- softwarecenter/ui/gtk3/app.py 2012-02-29 07:15:46 +0000
+++ softwarecenter/ui/gtk3/app.py 2012-02-29 17:32:19 +0000
@@ -390,6 +390,10 @@
390 # running the agent will trigger a db reload so we do it later390 # running the agent will trigger a db reload so we do it later
391 GObject.timeout_add_seconds(30, self._run_software_center_agent)391 GObject.timeout_add_seconds(30, self._run_software_center_agent)
392392
393
394 # keep the cache clean
395 GObject.timeout_add_seconds(15, self._run_expunge_cache_helper)
396
393 # TODO: Remove the following two lines once we have remove repository397 # TODO: Remove the following two lines once we have remove repository
394 # support in aptdaemon (see LP: #723911)398 # support in aptdaemon (see LP: #723911)
395 file_menu = self.builder.get_object("menu1")399 file_menu = self.builder.get_object("menu1")
@@ -419,6 +423,16 @@
419 GObject.child_watch_add(423 GObject.child_watch_add(
420 pid, self._on_update_software_center_agent_finished)424 pid, self._on_update_software_center_agent_finished)
421425
426 def _run_expunge_cache_helper(self):
427 """ helper that expires the piston-mini-client cache """
428 sc_expunge_cache = os.path.join(
429 self.datadir, "expunge-cache.py")
430 (pid, stdin, stdout, stderr) = GObject.spawn_async(
431 [sc_expunge_cache,
432 "--by-unsuccessful-http-states",
433 softwarecenter.paths.SOFTWARE_CENTER_CACHE_DIR,
434 ])
435
422 def _rebuild_and_reopen_local_db(self, pathname):436 def _rebuild_and_reopen_local_db(self, pathname):
423 """ helper that rebuilds a db and reopens it """437 """ helper that rebuilds a db and reopens it """
424 from softwarecenter.db.update import rebuild_database438 from softwarecenter.db.update import rebuild_database
425439
=== modified file 'test/test_utils.py'
--- test/test_utils.py 2012-02-12 20:03:56 +0000
+++ test/test_utils.py 2012-02-29 17:32:19 +0000
@@ -124,6 +124,42 @@
124 uuid = get_uuid()124 uuid = get_uuid()
125 self.assertTrue(uuid and len(uuid) > 0)125 self.assertTrue(uuid and len(uuid) > 0)
126126
127class TestExpungeCache(unittest.TestCase):
128
129 def test_expunge_cache(self):
130 import subprocess
131 import tempfile
132 dirname = tempfile.mkdtemp('s-c-testsuite')
133 for name, content in [ ("foo-301", "status: 301"),
134 ("foo-200", "status: 200"),
135 ("foo-random", "random"),
136 ]:
137 fullpath = os.path.join(dirname, name)
138 open(fullpath, "w").write(content)
139 # set to 1970+1s time to ensure the cleaner finds it
140 os.utime(fullpath, (1,1))
141 res = subprocess.call(["../utils/expunge-cache.py", dirname])
142 # no arguments
143 self.assertEqual(res, 1)
144 # by status
145 res = subprocess.call(["../utils/expunge-cache.py",
146 "--debug",
147 "--by-unsuccessful-http-states",
148 dirname])
149 self.assertFalse(os.path.exists(os.path.join(dirname, "foo-301")))
150 self.assertTrue(os.path.exists(os.path.join(dirname, "foo-200")))
151 self.assertTrue(os.path.exists(os.path.join(dirname, "foo-random")))
152
153 # by time
154 res = subprocess.call(["../utils/expunge-cache.py",
155 "--debug",
156 "--by-days", "1",
157 dirname])
158 # now we expect the old file to be gone but the unknown one not to
159 # be touched
160 self.assertFalse(os.path.exists(os.path.join(dirname, "foo-200")))
161 self.assertTrue(os.path.exists(os.path.join(dirname, "foo-random")))
162
127163
128if __name__ == "__main__":164if __name__ == "__main__":
129 import logging165 import logging
130166
=== added file 'utils/expunge-cache.py'
--- utils/expunge-cache.py 1970-01-01 00:00:00 +0000
+++ utils/expunge-cache.py 2012-02-29 17:32:19 +0000
@@ -0,0 +1,80 @@
1#!/usr/bin/python
2
3"""
4Expunge httplib2 caches
5"""
6
7import argparse
8import logging
9import os
10import time
11import sys
12
13class ExpungeCache(object):
14 def __init__(self, dirs, args):
15 self.dirs = dirs
16 # days to keep data in the cache (0 == disabled)
17 self.keep_time = 60*60*24* args.by_days
18 self.keep_only_http200 = args.by_unsuccessful_http_states
19 self.dry_run = args.dry_run
20
21 def _rm(self, f):
22 if self.dry_run:
23 print "Would delete: %s" % f
24 else:
25 logging.debug("Deleting: %s" % f)
26 os.unlink(f)
27
28 def clean(self):
29 # go over the directories
30 now = time.time()
31 for d in self.dirs:
32 for root, dirs, files in os.walk(d):
33 for f in files:
34 fullpath = os.path.join(root, f)
35 header = open(fullpath).readline().strip()
36 if not header.startswith("status:"):
37 logging.debug(
38 "Skipping files with unknown header: '%s'" % f)
39 continue
40 if self.keep_only_http200 and header != "status: 200":
41 self._rm(fullpath)
42 if self.keep_time:
43 mtime = os.path.getmtime(fullpath)
44 logging.debug("mtime of '%s': '%s" % (f, mtime))
45 if (mtime + self.keep_time) < now:
46 self._rm(fullpath)
47
48if __name__ == "__main__":
49 parser = argparse.ArgumentParser(
50 description='clean software-center httplib2 cache')
51 parser.add_argument(
52 '--debug', action="store_true",
53 help='show debug output')
54 parser.add_argument(
55 '--dry-run', action="store_true",
56 help='do not act, just show what would be done')
57 parser.add_argument(
58 'directories', metavar='directory', nargs='+', type=str,
59 help='directories to be checked')
60 parser.add_argument(
61 '--by-days', type=int, default=0,
62 help='expire everything older than N days')
63 parser.add_argument(
64 '--by-unsuccessful-http-states', action="store_true",
65 help='expire any non 200 status responses')
66 args = parser.parse_args()
67
68 if args.debug:
69 logging.basicConfig(level=logging.DEBUG)
70 else:
71 logging.basicConfig(level=logging.INFO)
72
73 # sanity checking
74 if args.by_days == 0 and not args.by_unsuccessful_http_states:
75 print "Need either --by-days or --by-unsuccessful-http-states argument"
76 sys.exit(1)
77
78 # do it
79 cleaner = ExpungeCache(args.directories, args)
80 cleaner.clean()

Subscribers

People subscribed via source and target branches