-Reduce the memory footprint by clearing the AptPackages caches.
-
-The memory usage is a little bit high due to keeping the AptPackages
-caches always. Instead, they should timeout after a period of inactivity
-(say 15 minutes), and unload themselves from meory. It only takes a few
-seconds to reload, so this should not be an issue.
-
-
Packages.diff files need to be considered.
The Packages.diff/Index files contain hashes of Packages.diff/rred.gz
# Whether it's OK to use an IP addres from a known local/private range
LOCAL_OK = no
+# Unload the packages cache after an interval of inactivity this long.
+# The packages cache uses a lot of memory, and only takes a few seconds
+# to reload when a new request arrives.
+UNLOAD_PACKAGES_CACHE = 5m
+
# Which DHT implementation to use.
# It must be possile to do "from <DHT>.DHT import DHT" to get a class that
# implements the IDHT interface. There should also be a similarly named
from copy import deepcopy
from UserDict import DictMixin
-from twisted.internet import threads, defer
+from twisted.internet import threads, defer, reactor
from twisted.python import log
from twisted.python.filepath import FilePath
from twisted.trial import unittest
'apt/lists/partial')
essential_files = ('apt/dpkg/status', 'apt/etc/sources.list',)
- def __init__(self, cache_dir):
+ def __init__(self, cache_dir, unload_delay):
"""Construct a new packages manager.
@param cache_dir: cache directory from config file
"""
self.cache_dir = cache_dir
+ self.unload_delay = unload_delay
self.apt_config = deepcopy(self.DEFAULT_APT_CONFIG)
for dir in self.essential_dirs:
self.packages = PackageFileList(cache_dir)
self.loaded = 0
self.loading = None
+ self.unload_later = None
def __del__(self):
self.cleanup()
def load(self):
"""Make sure the package is initialized and loaded."""
+ if self.unload_later and self.unload_later.active():
+ self.unload_later.reset(self.unload_delay)
+ else:
+ self.unload_later = reactor.callLater(self.unload_delay, self.unload)
if self.loading is None:
+ log.msg('Loading the packages cache')
self.loading = threads.deferToThread(self._load)
self.loading.addCallback(self.doneLoading)
return self.loading
def unload(self):
"""Tries to make the packages server quit."""
+ if self.unload_later and self.unload_later.active():
+ self.unload_later.cancel()
+ self.unload_later = None
if self.loaded:
+ log.msg('Unloading the packages cache')
del self.cache
del self.records
del self.srcrecords
releaseFile = ''
def setUp(self):
- self.client = AptPackages(FilePath('/tmp/.apt-dht'))
+ self.client = AptPackages(FilePath('/tmp/.apt-dht'), 300)
self.packagesFile = os.popen('ls -Sr /var/lib/apt/lists/ | grep -E "_main_.*Packages$" | tail -n 1').read().rstrip('\n')
self.sourcesFile = os.popen('ls -Sr /var/lib/apt/lists/ | grep -E "_main_.*Sources$" | tail -n 1').read().rstrip('\n')
class MirrorManager:
"""Manages all requests for mirror objects."""
- def __init__(self, cache_dir):
+ def __init__(self, cache_dir, unload_delay):
self.cache_dir = cache_dir
+ self.unload_delay = unload_delay
self.apt_caches = {}
def extractPath(self, url):
if baseDir not in self.apt_caches[site]:
site_cache = self.cache_dir.child(aptpkg_dir).child('mirrors').child(site + baseDir.replace('/', '_'))
site_cache.makedirs
- self.apt_caches[site][baseDir] = AptPackages(site_cache)
+ self.apt_caches[site][baseDir] = AptPackages(site_cache, self.unload_delay)
def updatedFile(self, url, file_path):
site, baseDir, path = self.extractPath(url)
client = None
def setUp(self):
- self.client = MirrorManager(FilePath('/tmp/.apt-dht'))
+ self.client = MirrorManager(FilePath('/tmp/.apt-dht'), 300)
def test_extractPath(self):
site, baseDir, path = self.client.extractPath('http://ftp.us.debian.org/debian/dists/unstable/Release')
self.http_server = TopLevel(self.cache_dir.child(download_dir), self.db, self)
self.getHTTPFactory = self.http_server.getHTTPFactory
self.peers = PeerManager()
- self.mirrors = MirrorManager(self.cache_dir)
+ self.mirrors = MirrorManager(self.cache_dir, config.gettime('DEFAULT', 'UNLOAD_PACKAGES_CACHE'))
other_dirs = [FilePath(f) for f in config.getstringlist('DEFAULT', 'OTHER_DIRS')]
self.cache = CacheManager(self.cache_dir.child(download_dir), self.db, other_dirs, self)
self.my_addr = None
# Whether it's OK to use an IP addres from a known local/private range
'LOCAL_OK': 'no',
+ # Unload the packages cache after an interval of inactivity this long.
+ # The packages cache uses a lot of memory, and only takes a few seconds
+ # to reload when a new request arrives.
+ 'UNLOAD_PACKAGES_CACHE': '5m',
+
# Which DHT implementation to use.
# It must be possile to do "from <DHT>.DHT import DHT" to get a class that
# implements the IDHT interface.
(Default is false)</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>UNLOAD_PACKAGES_CACHE = <replaceable>time</replaceable></option></term>
+ <listitem>
+ <para>The <replaceable>time</replaceable> of inactivity to wait for before unloading the
+ packages cache. The packages cache uses a lot of memory, and only takes a few seconds
+ to reload when a new request arrives. (Default is 5 minutes.)</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><option>DHT = <replaceable>string</replaceable></option></term>
<listitem>
# Whether it's OK to use an IP addres from a known local/private range
LOCAL_OK = yes
+# Unload the packages cache after an interval of inactivity this long.
+# The packages cache uses a lot of memory, and only takes a few seconds
+# to reload when a new request arrives.
+UNLOAD_PACKAGES_CACHE = 5m
+
# Which DHT implementation to use.
# It must be possile to do "from <DHT>.DHT import DHT" to get a class that
# implements the IDHT interface.