summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2013-09-10 09:39:40 +0200
committerHelmut Grohne <helmut@subdivi.de>2013-09-10 09:39:40 +0200
commitca65a78a9ace0aeb2565df0da171727c04c33970 (patch)
tree99ec772b4fbee3334ce9aac9b0c04cf57d09c393
parent49cac8bdae0ec787372d227545411ef14905d6a8 (diff)
downloaddebian-dedup-ca65a78a9ace0aeb2565df0da171727c04c33970.tar.gz
webapp: close database cursors
Leaking them can result in running out of available filedescriptors.
-rwxr-xr-xwebapp.py98
1 files changed, 50 insertions, 48 deletions
diff --git a/webapp.py b/webapp.py
index d5f076e..4478ba0 100755
--- a/webapp.py
+++ b/webapp.py
@@ -1,5 +1,6 @@
#!/usr/bin/python
+import contextlib
import datetime
import optparse
import sqlite3
@@ -98,42 +99,43 @@ class Application(object):
return e
def get_details(self, package):
- cur = self.db.cursor()
- cur.execute("SELECT id, version, architecture FROM package WHERE name = ?;",
- (package,))
- row = cur.fetchone()
- if not row:
- raise NotFound()
- pid, version, architecture = row
- details = dict(pid=pid,
- package=package,
- version=version,
- architecture=architecture)
- cur.execute("SELECT count(filename), sum(size) FROM content WHERE pid = ?;",
- (pid,))
- num_files, total_size = cur.fetchone()
+ with contextlib.closing(self.db.cursor()) as cur:
+ cur.execute("SELECT id, version, architecture FROM package WHERE name = ?;",
+ (package,))
+ row = cur.fetchone()
+ if not row:
+ raise NotFound()
+ pid, version, architecture = row
+ details = dict(pid=pid,
+ package=package,
+ version=version,
+ architecture=architecture)
+ cur.execute("SELECT count(filename), sum(size) FROM content WHERE pid = ?;",
+ (pid,))
+ num_files, total_size = cur.fetchone()
if total_size is None:
total_size = 0
details.update(dict(num_files=num_files, total_size=total_size))
return details
def get_dependencies(self, pid):
- cur = self.db.cursor()
- cur.execute("SELECT required FROM dependency WHERE pid = ?;",
- (pid,))
- return set(row[0] for row in fetchiter(cur))
+ with contextlib.closing(self.db.cursor()) as cur:
+ cur.execute("SELECT required FROM dependency WHERE pid = ?;",
+ (pid,))
+ return set(row[0] for row in fetchiter(cur))
def cached_sharedstats(self, pid):
- cur = self.db.cursor()
sharedstats = {}
- cur.execute("SELECT pid2, package.name, f1.name, f2.name, files, size FROM sharing JOIN package ON sharing.pid2 = package.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE pid1 = ? AND f1.eqclass = f2.eqclass;",
- (pid,))
- for pid2, package2, func1, func2, files, size in fetchiter(cur):
- curstats = sharedstats.setdefault(
- function_combination(func1, func2), list())
- if pid2 == pid:
- package2 = None
- curstats.append(dict(package=package2, duplicate=files, savable=size))
+ with contextlib.closing(self.db.cursor()) as cur:
+ cur.execute("SELECT pid2, package.name, f1.name, f2.name, files, size FROM sharing JOIN package ON sharing.pid2 = package.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE pid1 = ? AND f1.eqclass = f2.eqclass;",
+ (pid,))
+ for pid2, package2, func1, func2, files, size in fetchiter(cur):
+ curstats = sharedstats.setdefault(
+ function_combination(func1, func2), list())
+ if pid2 == pid:
+ package2 = None
+ curstats.append(dict(package=package2, duplicate=files,
+ savable=size))
return sharedstats
def show_package(self, package):
@@ -206,12 +208,12 @@ class Application(object):
return html_response(detail_template.stream(params))
def show_hash(self, function, hashvalue):
- cur = self.db.cursor()
- cur.execute("SELECT package.name, content.filename, content.size, f2.name FROM hash JOIN content ON hash.cid = content.id JOIN package ON content.pid = package.id JOIN function AS f2 ON hash.fid = f2.id JOIN function AS f1 ON f2.eqclass = f1.eqclass WHERE f1.name = ? AND hash = ?;",
- (function, hashvalue,))
- entries = [dict(package=package, filename=filename, size=size,
- function=otherfunc)
- for package, filename, size, otherfunc in fetchiter(cur)]
+ with contextlib.closing(self.db.cursor()) as cur:
+ cur.execute("SELECT package.name, content.filename, content.size, f2.name FROM hash JOIN content ON hash.cid = content.id JOIN package ON content.pid = package.id JOIN function AS f2 ON hash.fid = f2.id JOIN function AS f1 ON f2.eqclass = f1.eqclass WHERE f1.name = ? AND hash = ?;",
+ (function, hashvalue,))
+ entries = [dict(package=package, filename=filename, size=size,
+ function=otherfunc)
+ for package, filename, size, otherfunc in fetchiter(cur)]
if not entries:
raise NotFound()
params = dict(function=function, hashvalue=hashvalue, entries=entries,
@@ -219,21 +221,21 @@ class Application(object):
return html_response(hash_template.render(params))
def show_source(self, package):
- cur = self.db.cursor()
- cur.execute("SELECT name FROM package WHERE source = ?;",
- (package,))
- binpkgs = dict.fromkeys(pkg for pkg, in fetchiter(cur))
- if not binpkgs:
- raise NotFound
- cur.execute("SELECT p1.name, p2.name, f1.name, f2.name, sharing.files, sharing.size FROM sharing JOIN package AS p1 ON sharing.pid1 = p1.id JOIN package AS p2 ON sharing.pid2 = p2.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE p1.source = ?;",
- (package,))
- for binary, otherbin, func1, func2, files, size in fetchiter(cur):
- entry = dict(package=otherbin,
- funccomb=function_combination(func1, func2),
- duplicate=files, savable=size)
- oldentry = binpkgs.get(binary)
- if not (oldentry and oldentry["savable"] >= size):
- binpkgs[binary] = entry
+ with contextlib.closing(self.db.cursor()) as cur:
+ cur.execute("SELECT name FROM package WHERE source = ?;",
+ (package,))
+ binpkgs = dict.fromkeys(pkg for pkg, in fetchiter(cur))
+ if not binpkgs:
+ raise NotFound
+ cur.execute("SELECT p1.name, p2.name, f1.name, f2.name, sharing.files, sharing.size FROM sharing JOIN package AS p1 ON sharing.pid1 = p1.id JOIN package AS p2 ON sharing.pid2 = p2.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE p1.source = ?;",
+ (package,))
+ for binary, otherbin, func1, func2, files, size in fetchiter(cur):
+ entry = dict(package=otherbin,
+ funccomb=function_combination(func1, func2),
+ duplicate=files, savable=size)
+ oldentry = binpkgs.get(binary)
+ if not (oldentry and oldentry["savable"] >= size):
+ binpkgs[binary] = entry
params = dict(source=package, packages=binpkgs, urlroot="..")
return html_response(source_template.render(params))