# Downloading tiles puts quite much pressure on the server, so this file # implements a class that tries to give a little relief by not opening # a new connection every time. import time import atexit from threading import Thread, Event from Queue import Queue, Empty, Full from httplib import HTTPConnection, ResponseNotReady from tilecache import TileCoord, TileCache class DownloadRequest: def __init__(self, path, userdata = None): self.path = path self.userdata = userdata self.data = None self.doneevent = Event() self.status = None def __eq__(self, other): return self.path == other.path def __repr__(self): return "DownloadRequest(%s)" % (repr(self.path)) class DownloadThread(Thread): def __init__(self, server, queue): Thread.__init__(self) self.requestqueue = queue self.stopevent = Event() self.connection = HTTPConnection(server) def download(self, request): self.connection.request("GET", request.path) response = self.connection.getresponse() if response.status == 200: request.data = response.read() else: request.status = response.status response.read() # To finish the request def run(self): while not self.stopevent.isSet(): try: request = self.requestqueue.get(timeout = 1.0) except Empty: self.connection.close() continue self.download(request) request.doneevent.set() self.connection.close() def stop(self): self.stopevent.set() def join(self): self.stop() Thread.join(self) class TileDownloader: def __init__(self, servers): self.queue = Queue(32) self.threads = [DownloadThread(server, self.queue) for server in servers] self.ongoing_requests = [] for thread in self.threads: atexit.register(thread.stop) thread.start() def process_results(self): for request in self.ongoing_requests: if request.doneevent.isSet(): yield request self.ongoing_requests.remove(request) def put_download(self, request, block, timeout = None): if request in self.ongoing_requests: return False while True: try: self.queue.put(request, block, timeout) break except Full: # Flush the oldest download drop = self.queue.get(block = False) self.ongoing_requests.remove(drop) self.ongoing_requests.append(request) return True if __name__ == "__main__": downloader = TileDownloader(["kapsi.fi"]) for i in range(1, 10): request = DownloadRequest("/~jpa/stuff/other/testfiles/test%d.txt" % i) downloader.put_download(request, True) while downloader.ongoing_requests: for request in downloader.process_results(): print request.path, request.data