From 3920e6d1e7c39935c760df509ff7d6326e5694a8 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Wed, 14 Jan 2009 16:14:24 -0700
Subject: [PATCH] immutable/download.py move recent-downloads history out of
 Downloader and into a separate class. upload/etc will follow soon.

---
 src/allmydata/client.py             |  8 ++++++--
 src/allmydata/history.py            | 23 +++++++++++++++++++++++
 src/allmydata/immutable/download.py | 26 +++++++-------------------
 src/allmydata/immutable/filenode.py |  7 +++++--
 4 files changed, 41 insertions(+), 23 deletions(-)
 create mode 100644 src/allmydata/history.py

diff --git a/src/allmydata/client.py b/src/allmydata/client.py
index d1465d6d..f8ecef7a 100644
--- a/src/allmydata/client.py
+++ b/src/allmydata/client.py
@@ -24,6 +24,7 @@ from allmydata.uri import LiteralFileURI
 from allmydata.dirnode import NewDirectoryNode
 from allmydata.mutable.filenode import MutableFileNode, MutableWatcher
 from allmydata.stats import StatsProvider
+from allmydata.history import History
 from allmydata.interfaces import IURI, INewDirectoryURI, IStatsProducer, \
      IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, RIStubClient
 
@@ -188,6 +189,7 @@ class Client(node.Node, pollmixin.PollMixin):
         convergence_s = self.get_or_create_private_config('convergence', _make_secret)
         self.convergence = base32.a2b(convergence_s)
         self._node_cache = weakref.WeakValueDictionary() # uri -> node
+        self.add_service(History())
         self.add_service(Uploader(helper_furl, self.stats_provider))
         download_cachedir = os.path.join(self.basedir,
                                          "private", "cache", "download")
@@ -208,6 +210,9 @@ class Client(node.Node, pollmixin.PollMixin):
         d.addErrback(log.err, facility="tahoe.init",
                      level=log.BAD, umid="OEHq3g")
 
+    def get_history(self):
+        return self.getServiceNamed("history")
+
     def init_control(self):
         d = self.when_tub_ready()
         def _publish(res):
@@ -414,8 +419,7 @@ class Client(node.Node, pollmixin.PollMixin):
         return uploader.list_all_upload_statuses()
 
     def list_all_download_statuses(self):
-        downloader = self.getServiceNamed("downloader")
-        return downloader.list_all_download_statuses()
+        return self.get_history().list_all_download_statuses()
 
     def list_all_mapupdate_statuses(self):
         watcher = self.getServiceNamed("mutable-watcher")
diff --git a/src/allmydata/history.py b/src/allmydata/history.py
new file mode 100644
index 00000000..b2c023c9
--- /dev/null
+++ b/src/allmydata/history.py
@@ -0,0 +1,23 @@
+
+import weakref
+from twisted.application import service
+
+class History(service.Service):
+    """Keep track of recent operations, for a status display."""
+
+    name = "history"
+    MAX_DOWNLOAD_STATUSES = 10
+
+    def __init__(self):
+        self.all_downloads_statuses = weakref.WeakKeyDictionary()
+        self.recent_download_statuses = []
+
+    def add_download(self, download_status):
+        self.all_downloads_statuses[download_status] = None
+        self.recent_download_statuses.append(download_status)
+        while len(self.recent_download_statuses) > self.MAX_DOWNLOAD_STATUSES:
+            self.recent_download_statuses.pop(0)
+
+    def list_all_download_statuses(self):
+        for ds in self.all_downloads_statuses:
+            yield ds
diff --git a/src/allmydata/immutable/download.py b/src/allmydata/immutable/download.py
index 4f6ad852..945c8790 100644
--- a/src/allmydata/immutable/download.py
+++ b/src/allmydata/immutable/download.py
@@ -1164,16 +1164,13 @@ class Downloader(service.MultiService):
     # It is scheduled to go away, to be replaced by filenode.download()
     implements(IDownloader)
     name = "downloader"
-    MAX_DOWNLOAD_STATUSES = 10
 
     def __init__(self, stats_provider=None):
         service.MultiService.__init__(self)
         self.stats_provider = stats_provider
         self._all_downloads = weakref.WeakKeyDictionary() # for debugging
-        self._all_download_statuses = weakref.WeakKeyDictionary()
-        self._recent_download_statuses = []
 
-    def download(self, u, t, _log_msg_id=None, monitor=None):
+    def download(self, u, t, _log_msg_id=None, monitor=None, history=None):
         assert self.parent
         assert self.running
         u = IFileURI(u)
@@ -1192,26 +1189,17 @@ class Downloader(service.MultiService):
         if not monitor:
             monitor=Monitor()
         dl = CiphertextDownloader(self.parent, u.get_verify_cap(), target, monitor=monitor)
-        self._add_download(dl)
+        self._all_downloads[dl] = None
+        s = dl.get_download_status()
+        if history:
+            history.add_download(s)
         d = dl.start()
         return d
 
     # utility functions
-    def download_to_data(self, uri, _log_msg_id=None):
-        return self.download(uri, Data(), _log_msg_id=_log_msg_id)
+    def download_to_data(self, uri, _log_msg_id=None, history=None):
+        return self.download(uri, Data(), _log_msg_id=_log_msg_id, history=history)
     def download_to_filename(self, uri, filename, _log_msg_id=None):
         return self.download(uri, FileName(filename), _log_msg_id=_log_msg_id)
     def download_to_filehandle(self, uri, filehandle, _log_msg_id=None):
         return self.download(uri, FileHandle(filehandle), _log_msg_id=_log_msg_id)
-
-    def _add_download(self, downloader):
-        self._all_downloads[downloader] = None
-        s = downloader.get_download_status()
-        self._all_download_statuses[s] = None
-        self._recent_download_statuses.append(s)
-        while len(self._recent_download_statuses) > self.MAX_DOWNLOAD_STATUSES:
-            self._recent_download_statuses.pop(0)
-
-    def list_all_download_statuses(self):
-        for ds in self._all_download_statuses:
-            yield ds
diff --git a/src/allmydata/immutable/filenode.py b/src/allmydata/immutable/filenode.py
index b2b63c5b..b8df90ce 100644
--- a/src/allmydata/immutable/filenode.py
+++ b/src/allmydata/immutable/filenode.py
@@ -266,11 +266,14 @@ class FileNode(_ImmutableFileNodeBase, log.PrefixingLogMixin):
 
     def download(self, target):
         downloader = self._client.getServiceNamed("downloader")
-        return downloader.download(self.get_uri(), target, self._parentmsgid)
+        history = self._client.get_history()
+        return downloader.download(self.get_uri(), target, self._parentmsgid,
+                                   history=history)
 
     def download_to_data(self):
         downloader = self._client.getServiceNamed("downloader")
-        return downloader.download_to_data(self.get_uri())
+        history = self._client.get_history()
+        return downloader.download_to_data(self.get_uri(), history=history)
 
 class LiteralProducer:
     implements(IPushProducer)
-- 
2.45.2