Added modification time tracking to the MirrorManager cache.
[quix0rs-apt-p2p.git] / apt_dht / apt_dht.py
1
2 from twisted.internet import defer
3 from twisted.web2 import server, http, http_headers
4 from twisted.python import log
5
6 from apt_dht_conf import config
7 from PeerManager import PeerManager
8 from HTTPServer import TopLevel
9 from MirrorManager import MirrorManager
10
11 class AptDHT:
12     def __init__(self, dht):
13         log.msg('Initializing the main apt_dht application')
14         self.dht = dht
15         self.http_server = TopLevel(config.get('DEFAULT', 'cache_dir'), self)
16         self.http_site = server.Site(self.http_server)
17         self.peers = PeerManager()
18         self.mirrors = MirrorManager(config.get('DEFAULT', 'cache_dir'))
19     
20     def getSite(self):
21         return self.http_site
22     
23     def check_freshness(self, path, modtime, resp):
24         log.msg('Checking if %s is still fresh' % path)
25         d = self.peers.get([path], "HEAD", modtime)
26         d.addCallback(self.check_freshness_done, path, resp)
27         return d
28     
29     def check_freshness_done(self, resp, path, orig_resp):
30         if resp.code == 304:
31             log.msg('Still fresh, returning: %s' % path)
32             return orig_resp
33         else:
34             log.msg('Stale, need to redownload: %s' % path)
35             return self.get_resp(path)
36     
37     def get_resp(self, path):
38         d = defer.Deferred()
39         
40         log.msg('Trying to find hash for %s' % path)
41         findDefer = self.mirrors.findHash(path)
42         
43         findDefer.addCallback(self.findHash_done, path, d)
44         findDefer.addErrback(self.findHash_error, path, d)
45         return d
46     
47     def findHash_error(self, failure, path, d):
48         log.err(failure)
49         self.findHash_done((None, None), path, d)
50         
51     def findHash_done(self, (hash, size), path, d):
52         if hash is None:
53             log.msg('Hash for %s was not found' % path)
54             self.download_file([path], hash, size, path, d)
55         else:
56             log.msg('Found hash %s for %s' % (hash, path))
57             # Lookup hash from DHT
58             lookupDefer = self.dht.getValue(hash)
59             lookupDefer.addCallback(self.lookupHash_done, hash, size, path, d)
60             
61     def lookupHash_done(self, locations, hash, size, path, d):
62         if not locations:
63             log.msg('Peers for %s were not found' % path)
64             self.download_file([path], hash, size, path, d)
65         else:
66             log.msg('Found peers for $s: %r' % (path, locations))
67             # Download from the found peers
68             self.download_file(locations, hash, size, path, d)
69             
70     def download_file(self, locations, hash, size, path, d):
71         getDefer = self.peers.get(locations)
72         getDefer.addCallback(self.mirrors.save_file, hash, size, path)
73         getDefer.addErrback(self.mirrors.save_error, path)
74         getDefer.addCallbacks(d.callback, d.errback)