]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
webapi: pass client through constructor arguments, remove IClient, should make it...
authorBrian Warner <warner@lothar.com>
Fri, 20 Feb 2009 19:15:54 +0000 (12:15 -0700)
committerBrian Warner <warner@lothar.com>
Fri, 20 Feb 2009 19:15:54 +0000 (12:15 -0700)
14 files changed:
src/allmydata/client.py
src/allmydata/introducer/server.py
src/allmydata/test/test_web.py
src/allmydata/web/check_results.py
src/allmydata/web/common.py
src/allmydata/web/directory.py
src/allmydata/web/filenode.py
src/allmydata/web/helper.xhtml
src/allmydata/web/introweb.py
src/allmydata/web/root.py
src/allmydata/web/statistics.xhtml
src/allmydata/web/status.py
src/allmydata/web/unlinked.py
src/allmydata/webish.py

index a77bda4f8172dfc1bc2670af83b4fd3a36ce1977..766cae047eff087ac81613a03d21c24676a2608a 100644 (file)
@@ -91,6 +91,8 @@ class Client(node.Node, pollmixin.PollMixin):
             hotline = TimerService(1.0, self._check_hotline, hotline_file)
             hotline.setServiceParent(self)
 
             hotline = TimerService(1.0, self._check_hotline, hotline_file)
             hotline.setServiceParent(self)
 
+        # this needs to happen last, so it can use getServiceNamed() to
+        # acquire references to StorageServer and other web-statusable things
         webport = self.get_config("node", "web.port", None)
         if webport:
             self.init_web(webport) # strports string
         webport = self.get_config("node", "web.port", None)
         if webport:
             self.init_web(webport) # strports string
@@ -269,7 +271,7 @@ class Client(node.Node, pollmixin.PollMixin):
         nodeurl_path = os.path.join(self.basedir, "node.url")
         staticdir = self.get_config("node", "web.static", "public_html")
         staticdir = os.path.expanduser(staticdir)
         nodeurl_path = os.path.join(self.basedir, "node.url")
         staticdir = self.get_config("node", "web.static", "public_html")
         staticdir = os.path.expanduser(staticdir)
-        ws = WebishServer(webport, nodeurl_path, staticdir)
+        ws = WebishServer(self, webport, nodeurl_path, staticdir)
         self.add_service(ws)
 
     def init_ftp_server(self):
         self.add_service(ws)
 
     def init_ftp_server(self):
index 5e519533d7b68d035ade4be23451918220e66797..d0ed6412f87241f4781af34187fc2b5372bc12ed 100644 (file)
@@ -41,7 +41,7 @@ class IntroducerNode(node.Node):
 
         from allmydata.webish import IntroducerWebishServer
         nodeurl_path = os.path.join(self.basedir, "node.url")
 
         from allmydata.webish import IntroducerWebishServer
         nodeurl_path = os.path.join(self.basedir, "node.url")
-        ws = IntroducerWebishServer(webport, nodeurl_path)
+        ws = IntroducerWebishServer(self, webport, nodeurl_path)
         self.add_service(ws)
 
 class IntroducerService(service.MultiService, Referenceable):
         self.add_service(ws)
 
 class IntroducerService(service.MultiService, Referenceable):
index 940a1c8be379543b89c4ee03f2ec90d580900250..e2ae8fc426ad91b487f3da8d413809d75f36b4d7 100644 (file)
@@ -33,6 +33,11 @@ class FakeIntroducerClient:
     def get_all_peerids(self):
         return frozenset()
 
     def get_all_peerids(self):
         return frozenset()
 
+class FakeStatsProvider:
+    def get_stats(self):
+        stats = {'stats': {}, 'counters': {}}
+        return stats
+
 class FakeClient(service.MultiService):
     nodeid = "fake_nodeid"
     nickname = "fake_nickname"
 class FakeClient(service.MultiService):
     nodeid = "fake_nodeid"
     nickname = "fake_nickname"
@@ -51,6 +56,7 @@ class FakeClient(service.MultiService):
     _all_publish_statuses = [publish.PublishStatus()]
     _all_retrieve_statuses = [retrieve.RetrieveStatus()]
     convergence = "some random string"
     _all_publish_statuses = [publish.PublishStatus()]
     _all_retrieve_statuses = [retrieve.RetrieveStatus()]
     convergence = "some random string"
+    stats_provider = FakeStatsProvider()
 
     def connected_to_introducer(self):
         return False
 
     def connected_to_introducer(self):
         return False
@@ -134,7 +140,7 @@ class WebMixin(object):
         self.s = FakeClient()
         self.s.startService()
         self.staticdir = self.mktemp()
         self.s = FakeClient()
         self.s.startService()
         self.staticdir = self.mktemp()
-        self.ws = s = webish.WebishServer("0", staticdir=self.staticdir)
+        self.ws = s = webish.WebishServer(self.s, "0", staticdir=self.staticdir)
         s.setServiceParent(self.s)
         self.webish_port = port = s.listener._port.getHost().port
         self.webish_url = "http://localhost:%d" % port
         s.setServiceParent(self.s)
         self.webish_port = port = s.listener._port.getHost().port
         self.webish_url = "http://localhost:%d" % port
index bf7d75db0269646d5f246d99bf3b311e497c1ae1..eeb30709d52f4e5c2021d2a1464a576be3b73e5c 100644 (file)
@@ -3,8 +3,7 @@ import time
 import simplejson
 from nevow import rend, inevow, tags as T
 from twisted.web import http, html
 import simplejson
 from nevow import rend, inevow, tags as T
 from twisted.web import http, html
-from allmydata.web.common import getxmlfile, get_arg, get_root, \
-     IClient, WebError
+from allmydata.web.common import getxmlfile, get_arg, get_root, WebError
 from allmydata.web.operations import ReloadMixin
 from allmydata.interfaces import ICheckAndRepairResults, ICheckResults
 from allmydata.util import base32, idlib
 from allmydata.web.operations import ReloadMixin
 from allmydata.interfaces import ICheckAndRepairResults, ICheckResults
 from allmydata.util import base32, idlib
@@ -68,6 +67,9 @@ def json_check_and_repair_results(r):
     return data
 
 class ResultsBase:
     return data
 
 class ResultsBase:
+    # self.client must point to the Client, so we can get nicknames and
+    # determine the permuted peer order
+
     def _join_pathstring(self, path):
         if path:
             pathstring = "/".join(self._html(path))
     def _join_pathstring(self, path):
         if path:
             pathstring = "/".join(self._html(path))
@@ -77,7 +79,7 @@ class ResultsBase:
 
     def _render_results(self, ctx, cr):
         assert ICheckResults(cr)
 
     def _render_results(self, ctx, cr):
         assert ICheckResults(cr)
-        c = IClient(ctx)
+        c = self.client
         data = cr.get_data()
         r = []
         def add(name, value):
         data = cr.get_data()
         r = []
         def add(name, value):
@@ -178,6 +180,10 @@ class ResultsBase:
 class LiteralCheckResults(rend.Page, ResultsBase):
     docFactory = getxmlfile("literal-check-results.xhtml")
 
 class LiteralCheckResults(rend.Page, ResultsBase):
     docFactory = getxmlfile("literal-check-results.xhtml")
 
+    def __init__(self, client):
+        self.client = client
+        rend.Page.__init__(self, client)
+
     def renderHTTP(self, ctx):
         if self.want_json(ctx):
             return self.json(ctx)
     def renderHTTP(self, ctx):
         if self.want_json(ctx):
             return self.json(ctx)
@@ -217,8 +223,10 @@ class CheckerBase:
 class CheckResults(CheckerBase, rend.Page, ResultsBase):
     docFactory = getxmlfile("check-results.xhtml")
 
 class CheckResults(CheckerBase, rend.Page, ResultsBase):
     docFactory = getxmlfile("check-results.xhtml")
 
-    def __init__(self, results):
+    def __init__(self, client, results):
+        self.client = client
         self.r = ICheckResults(results)
         self.r = ICheckResults(results)
+        rend.Page.__init__(self, results)
 
     def json(self, ctx):
         inevow.IRequest(ctx).setHeader("content-type", "text/plain")
 
     def json(self, ctx):
         inevow.IRequest(ctx).setHeader("content-type", "text/plain")
@@ -227,18 +235,18 @@ class CheckResults(CheckerBase, rend.Page, ResultsBase):
 
     def render_summary(self, ctx, data):
         results = []
 
     def render_summary(self, ctx, data):
         results = []
-        if self.r.is_healthy():
+        if data.is_healthy():
             results.append("Healthy")
             results.append("Healthy")
-        elif self.r.is_recoverable():
+        elif data.is_recoverable():
             results.append("Not Healthy!")
         else:
             results.append("Not Recoverable!")
         results.append(" : ")
             results.append("Not Healthy!")
         else:
             results.append("Not Recoverable!")
         results.append(" : ")
-        results.append(self._html(self.r.get_summary()))
+        results.append(self._html(data.get_summary()))
         return ctx.tag[results]
 
     def render_repair(self, ctx, data):
         return ctx.tag[results]
 
     def render_repair(self, ctx, data):
-        if self.r.is_healthy():
+        if data.is_healthy():
             return ""
         repair = T.form(action=".", method="post",
                         enctype="multipart/form-data")[
             return ""
         repair = T.form(action=".", method="post",
                         enctype="multipart/form-data")[
@@ -250,14 +258,16 @@ class CheckResults(CheckerBase, rend.Page, ResultsBase):
         return ctx.tag[repair]
 
     def render_results(self, ctx, data):
         return ctx.tag[repair]
 
     def render_results(self, ctx, data):
-        cr = self._render_results(ctx, self.r)
+        cr = self._render_results(ctx, data)
         return ctx.tag[cr]
 
 class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
     docFactory = getxmlfile("check-and-repair-results.xhtml")
 
         return ctx.tag[cr]
 
 class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
     docFactory = getxmlfile("check-and-repair-results.xhtml")
 
-    def __init__(self, results):
+    def __init__(self, client, results):
+        self.client = client
         self.r = ICheckAndRepairResults(results)
         self.r = ICheckAndRepairResults(results)
+        rend.Page.__init__(self, results)
 
     def json(self, ctx):
         inevow.IRequest(ctx).setHeader("content-type", "text/plain")
 
     def json(self, ctx):
         inevow.IRequest(ctx).setHeader("content-type", "text/plain")
@@ -265,7 +275,7 @@ class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
         return simplejson.dumps(data, indent=1) + "\n"
 
     def render_summary(self, ctx, data):
         return simplejson.dumps(data, indent=1) + "\n"
 
     def render_summary(self, ctx, data):
-        cr = self.r.get_post_repair_results()
+        cr = data.get_post_repair_results()
         results = []
         if cr.is_healthy():
             results.append("Healthy")
         results = []
         if cr.is_healthy():
             results.append("Healthy")
@@ -278,20 +288,20 @@ class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
         return ctx.tag[results]
 
     def render_repair_results(self, ctx, data):
         return ctx.tag[results]
 
     def render_repair_results(self, ctx, data):
-        if self.r.get_repair_attempted():
-            if self.r.get_repair_successful():
+        if data.get_repair_attempted():
+            if data.get_repair_successful():
                 return ctx.tag["Repair successful"]
             else:
                 return ctx.tag["Repair unsuccessful"]
         return ctx.tag["No repair necessary"]
 
     def render_post_repair_results(self, ctx, data):
                 return ctx.tag["Repair successful"]
             else:
                 return ctx.tag["Repair unsuccessful"]
         return ctx.tag["No repair necessary"]
 
     def render_post_repair_results(self, ctx, data):
-        cr = self._render_results(ctx, self.r.get_post_repair_results())
+        cr = self._render_results(ctx, data.get_post_repair_results())
         return ctx.tag[T.div["Post-Repair Checker Results:"], cr]
 
     def render_maybe_pre_repair_results(self, ctx, data):
         return ctx.tag[T.div["Post-Repair Checker Results:"], cr]
 
     def render_maybe_pre_repair_results(self, ctx, data):
-        if self.r.get_repair_attempted():
-            cr = self._render_results(ctx, self.r.get_pre_repair_results())
+        if data.get_repair_attempted():
+            cr = self._render_results(ctx, data.get_pre_repair_results())
             return ctx.tag[T.div["Pre-Repair Checker Results:"], cr]
         return ""
 
             return ctx.tag[T.div["Pre-Repair Checker Results:"], cr]
         return ""
 
@@ -299,7 +309,8 @@ class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
 class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
     docFactory = getxmlfile("deep-check-results.xhtml")
 
 class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
     docFactory = getxmlfile("deep-check-results.xhtml")
 
-    def __init__(self, monitor):
+    def __init__(self, client, monitor):
+        self.client = client
         self.monitor = monitor
 
     def childFactory(self, ctx, name):
         self.monitor = monitor
 
     def childFactory(self, ctx, name):
@@ -310,7 +321,8 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
         si = base32.a2b(name)
         r = self.monitor.get_status()
         try:
         si = base32.a2b(name)
         r = self.monitor.get_status()
         try:
-            return CheckResults(r.get_results_for_storage_index(si))
+            return CheckResults(self.client,
+                                r.get_results_for_storage_index(si))
         except KeyError:
             raise WebError("No detailed results for SI %s" % html.escape(name),
                            http.NOT_FOUND)
         except KeyError:
             raise WebError("No detailed results for SI %s" % html.escape(name),
                            http.NOT_FOUND)
@@ -397,8 +409,7 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
     def render_server_problem(self, ctx, data):
         serverid = data
         data = [idlib.shortnodeid_b2a(serverid)]
     def render_server_problem(self, ctx, data):
         serverid = data
         data = [idlib.shortnodeid_b2a(serverid)]
-        c = IClient(ctx)
-        nickname = c.get_nickname_for_peerid(serverid)
+        nickname = self.client.get_nickname_for_peerid(serverid)
         if nickname:
             data.append(" (%s)" % self._html(nickname))
         return ctx.tag[data]
         if nickname:
             data.append(" (%s)" % self._html(nickname))
         return ctx.tag[data]
@@ -412,7 +423,7 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
         return self.monitor.get_status().get_corrupt_shares()
     def render_share_problem(self, ctx, data):
         serverid, storage_index, sharenum = data
         return self.monitor.get_status().get_corrupt_shares()
     def render_share_problem(self, ctx, data):
         serverid, storage_index, sharenum = data
-        nickname = IClient(ctx).get_nickname_for_peerid(serverid)
+        nickname = self.client.get_nickname_for_peerid(serverid)
         ctx.fillSlots("serverid", idlib.shortnodeid_b2a(serverid))
         if nickname:
             ctx.fillSlots("nickname", self._html(nickname))
         ctx.fillSlots("serverid", idlib.shortnodeid_b2a(serverid))
         if nickname:
             ctx.fillSlots("nickname", self._html(nickname))
@@ -450,9 +461,8 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
 class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
     docFactory = getxmlfile("deep-check-and-repair-results.xhtml")
 
 class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
     docFactory = getxmlfile("deep-check-and-repair-results.xhtml")
 
-    def __init__(self, monitor):
-        #assert IDeepCheckAndRepairResults(results)
-        #self.r = results
+    def __init__(self, client, monitor):
+        self.client = client
         self.monitor = monitor
 
     def childFactory(self, ctx, name):
         self.monitor = monitor
 
     def childFactory(self, ctx, name):
@@ -463,7 +473,8 @@ class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
         si = base32.a2b(name)
         r = self.monitor.get_status()
         try:
         si = base32.a2b(name)
         r = self.monitor.get_status()
         try:
-            return CheckAndRepairResults(r.get_results_for_storage_index(si))
+            return CheckAndRepairResults(self.client,
+                                         r.get_results_for_storage_index(si))
         except KeyError:
             raise WebError("No detailed results for SI %s" % html.escape(name),
                            http.NOT_FOUND)
         except KeyError:
             raise WebError("No detailed results for SI %s" % html.escape(name),
                            http.NOT_FOUND)
index a831b80d6036640d8a10a87eff5ae823d2fcbd3a..ec86d46a5785d8230eb4438194990e05d5b215cb 100644 (file)
@@ -7,8 +7,6 @@ from nevow.util import resource_filename
 from allmydata.interfaces import ExistingChildError, NoSuchChildError, \
      FileTooLargeError, NotEnoughSharesError
 
 from allmydata.interfaces import ExistingChildError, NoSuchChildError, \
      FileTooLargeError, NotEnoughSharesError
 
-class IClient(Interface):
-    pass
 class IOpHandleTable(Interface):
     pass
 
 class IOpHandleTable(Interface):
     pass
 
index e8ce3f7a44d6f14dadc6a8c93d81692923795821..d47986652fcdda84f5cbdd587c4f22ec9a7cdfb5 100644 (file)
@@ -20,7 +20,7 @@ from allmydata.interfaces import IDirectoryNode, IFileNode, IMutableFileNode, \
 from allmydata.monitor import Monitor, OperationCancelledError
 from allmydata import dirnode
 from allmydata.web.common import text_plain, WebError, \
 from allmydata.monitor import Monitor, OperationCancelledError
 from allmydata import dirnode
 from allmydata.web.common import text_plain, WebError, \
-     IClient, IOpHandleTable, NeedOperationHandleError, \
+     IOpHandleTable, NeedOperationHandleError, \
      boolean_of_arg, get_arg, get_root, \
      should_create_intermediate_directories, \
      getxmlfile, RenderMixin
      boolean_of_arg, get_arg, get_root, \
      should_create_intermediate_directories, \
      getxmlfile, RenderMixin
@@ -38,22 +38,23 @@ class BlockingFileError(Exception):
     """We cannot auto-create a parent directory, because there is a file in
     the way"""
 
     """We cannot auto-create a parent directory, because there is a file in
     the way"""
 
-def make_handler_for(node, parentnode=None, name=None):
+def make_handler_for(node, client, parentnode=None, name=None):
     if parentnode:
         assert IDirectoryNode.providedBy(parentnode)
     if IMutableFileNode.providedBy(node):
     if parentnode:
         assert IDirectoryNode.providedBy(parentnode)
     if IMutableFileNode.providedBy(node):
-        return FileNodeHandler(node, parentnode, name)
+        return FileNodeHandler(client, node, parentnode, name)
     if IFileNode.providedBy(node):
     if IFileNode.providedBy(node):
-        return FileNodeHandler(node, parentnode, name)
+        return FileNodeHandler(client, node, parentnode, name)
     if IDirectoryNode.providedBy(node):
     if IDirectoryNode.providedBy(node):
-        return DirectoryNodeHandler(node, parentnode, name)
+        return DirectoryNodeHandler(client, node, parentnode, name)
     raise WebError("Cannot provide handler for '%s'" % node)
 
 class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
     addSlash = True
 
     raise WebError("Cannot provide handler for '%s'" % node)
 
 class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
     addSlash = True
 
-    def __init__(self, node, parentnode=None, name=None):
+    def __init__(self, client, node, parentnode=None, name=None):
         rend.Page.__init__(self)
         rend.Page.__init__(self)
+        self.client = client
         assert node
         self.node = node
         self.parentnode = parentnode
         assert node
         self.node = node
         self.parentnode = parentnode
@@ -87,7 +88,8 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                     # create intermediate directories
                     if DEBUG: print " making intermediate directory"
                     d = self.node.create_empty_directory(name)
                     # create intermediate directories
                     if DEBUG: print " making intermediate directory"
                     d = self.node.create_empty_directory(name)
-                    d.addCallback(make_handler_for, self.node, name)
+                    d.addCallback(make_handler_for,
+                                  self.client, self.node, name)
                     return d
             else:
                 if DEBUG: print " terminal"
                     return d
             else:
                 if DEBUG: print " terminal"
@@ -96,7 +98,8 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                     if DEBUG: print " making final directory"
                     # final directory
                     d = self.node.create_empty_directory(name)
                     if DEBUG: print " making final directory"
                     # final directory
                     d = self.node.create_empty_directory(name)
-                    d.addCallback(make_handler_for, self.node, name)
+                    d.addCallback(make_handler_for,
+                                  self.client, self.node, name)
                     return d
                 if (method,t) in ( ("PUT",""), ("PUT","uri"), ):
                     if DEBUG: print " PUT, making leaf placeholder"
                     return d
                 if (method,t) in ( ("PUT",""), ("PUT","uri"), ):
                     if DEBUG: print " PUT, making leaf placeholder"
@@ -105,7 +108,7 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                     # since that's the leaf node that we're about to create.
                     # We make a dummy one, which will respond to the PUT
                     # request by replacing itself.
                     # since that's the leaf node that we're about to create.
                     # We make a dummy one, which will respond to the PUT
                     # request by replacing itself.
-                    return PlaceHolderNodeHandler(self.node, name)
+                    return PlaceHolderNodeHandler(self.client, self.node, name)
             if DEBUG: print " 404"
             # otherwise, we just return a no-such-child error
             return rend.FourOhFour()
             if DEBUG: print " 404"
             # otherwise, we just return a no-such-child error
             return rend.FourOhFour()
@@ -120,7 +123,7 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                                "a file was in the way" % name,
                                http.CONFLICT)
         if DEBUG: print "good child"
                                "a file was in the way" % name,
                                http.CONFLICT)
         if DEBUG: print "good child"
-        return make_handler_for(node, self.node, name)
+        return make_handler_for(node, self.client, self.node, name)
 
     def render_DELETE(self, ctx):
         assert self.parentnode and self.name
 
     def render_DELETE(self, ctx):
         assert self.parentnode and self.name
@@ -129,7 +132,6 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         return d
 
     def render_GET(self, ctx):
         return d
 
     def render_GET(self, ctx):
-        client = IClient(ctx)
         req = IRequest(ctx)
         # This is where all of the directory-related ?t=* code goes.
         t = get_arg(req, "t", "").strip()
         req = IRequest(ctx)
         # This is where all of the directory-related ?t=* code goes.
         t = get_arg(req, "t", "").strip()
@@ -164,7 +166,7 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                 # they're trying to set_uri and that name is already occupied
                 # (by us).
                 raise ExistingChildError()
                 # they're trying to set_uri and that name is already occupied
                 # (by us).
                 raise ExistingChildError()
-            d = self.replace_me_with_a_childcap(ctx, replace)
+            d = self.replace_me_with_a_childcap(req, self.client, replace)
             # TODO: results
             return d
 
             # TODO: results
             return d
 
@@ -279,10 +281,10 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
                 f = node_or_failure
                 f.trap(NoSuchChildError)
                 # create a placeholder which will see POST t=upload
                 f = node_or_failure
                 f.trap(NoSuchChildError)
                 # create a placeholder which will see POST t=upload
-                return PlaceHolderNodeHandler(self.node, name)
+                return PlaceHolderNodeHandler(self.client, self.node, name)
             else:
                 node = node_or_failure
             else:
                 node = node_or_failure
-                return make_handler_for(node, self.node, name)
+                return make_handler_for(node, self.client, self.node, name)
         d.addBoth(_maybe_got_node)
         # now we have a placeholder or a filenodehandler, and we can just
         # delegate to it. We could return the resource back out of
         d.addBoth(_maybe_got_node)
         # now we have a placeholder or a filenodehandler, and we can just
         # delegate to it. We could return the resource back out of
@@ -358,10 +360,10 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         add_lease = boolean_of_arg(get_arg(req, "add-lease", "false"))
         if repair:
             d = self.node.check_and_repair(Monitor(), verify, add_lease)
         add_lease = boolean_of_arg(get_arg(req, "add-lease", "false"))
         if repair:
             d = self.node.check_and_repair(Monitor(), verify, add_lease)
-            d.addCallback(lambda res: CheckAndRepairResults(res))
+            d.addCallback(lambda res: CheckAndRepairResults(self.client, res))
         else:
             d = self.node.check(Monitor(), verify, add_lease)
         else:
             d = self.node.check(Monitor(), verify, add_lease)
-            d.addCallback(lambda res: CheckResults(res))
+            d.addCallback(lambda res: CheckResults(self.client, res))
         return d
 
     def _start_operation(self, monitor, renderer, ctx):
         return d
 
     def _start_operation(self, monitor, renderer, ctx):
@@ -378,10 +380,10 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         add_lease = boolean_of_arg(get_arg(ctx, "add-lease", "false"))
         if repair:
             monitor = self.node.start_deep_check_and_repair(verify, add_lease)
         add_lease = boolean_of_arg(get_arg(ctx, "add-lease", "false"))
         if repair:
             monitor = self.node.start_deep_check_and_repair(verify, add_lease)
-            renderer = DeepCheckAndRepairResults(monitor)
+            renderer = DeepCheckAndRepairResults(self.client, monitor)
         else:
             monitor = self.node.start_deep_check(verify, add_lease)
         else:
             monitor = self.node.start_deep_check(verify, add_lease)
-            renderer = DeepCheckResults(monitor)
+            renderer = DeepCheckResults(self.client, monitor)
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_stream_deep_check(self, ctx):
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_stream_deep_check(self, ctx):
@@ -408,21 +410,21 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.build_manifest()
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.build_manifest()
-        renderer = ManifestResults(monitor)
+        renderer = ManifestResults(self.client, monitor)
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_start_deep_size(self, ctx):
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.start_deep_stats()
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_start_deep_size(self, ctx):
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.start_deep_stats()
-        renderer = DeepSizeResults(monitor)
+        renderer = DeepSizeResults(self.client, monitor)
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_start_deep_stats(self, ctx):
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.start_deep_stats()
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_start_deep_stats(self, ctx):
         if not get_arg(ctx, "ophandle"):
             raise NeedOperationHandleError("slow operation requires ophandle=")
         monitor = self.node.start_deep_stats()
-        renderer = DeepStatsResults(monitor)
+        renderer = DeepStatsResults(self.client, monitor)
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_stream_manifest(self, ctx):
         return self._start_operation(monitor, renderer, ctx)
 
     def _POST_stream_manifest(self, ctx):
@@ -761,15 +763,17 @@ class RenameForm(rend.Page):
 class ManifestResults(rend.Page, ReloadMixin):
     docFactory = getxmlfile("manifest.xhtml")
 
 class ManifestResults(rend.Page, ReloadMixin):
     docFactory = getxmlfile("manifest.xhtml")
 
-    def __init__(self, monitor):
+    def __init__(self, client, monitor):
+        self.client = client
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
-        output = get_arg(inevow.IRequest(ctx), "output", "html").lower()
+        req = inevow.IRequest(ctx)
+        output = get_arg(req, "output", "html").lower()
         if output == "text":
         if output == "text":
-            return self.text(ctx)
+            return self.text(req)
         if output == "json":
         if output == "json":
-            return self.json(ctx)
+            return self.json(req)
         return rend.Page.renderHTTP(self, ctx)
 
     def slashify_path(self, path):
         return rend.Page.renderHTTP(self, ctx)
 
     def slashify_path(self, path):
@@ -777,8 +781,8 @@ class ManifestResults(rend.Page, ReloadMixin):
             return ""
         return "/".join([p.encode("utf-8") for p in path])
 
             return ""
         return "/".join([p.encode("utf-8") for p in path])
 
-    def text(self, ctx):
-        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
+    def text(self, req):
+        req.setHeader("content-type", "text/plain")
         lines = []
         is_finished = self.monitor.is_finished()
         lines.append("finished: " + {True: "yes", False: "no"}[is_finished])
         lines = []
         is_finished = self.monitor.is_finished()
         lines.append("finished: " + {True: "yes", False: "no"}[is_finished])
@@ -786,8 +790,8 @@ class ManifestResults(rend.Page, ReloadMixin):
             lines.append(self.slashify_path(path) + " " + cap)
         return "\n".join(lines) + "\n"
 
             lines.append(self.slashify_path(path) + " " + cap)
         return "\n".join(lines) + "\n"
 
-    def json(self, ctx):
-        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
+    def json(self, req):
+        req.setHeader("content-type", "text/plain")
         m = self.monitor
         s = m.get_status()
 
         m = self.monitor
         s = m.get_status()
 
@@ -839,14 +843,16 @@ class ManifestResults(rend.Page, ReloadMixin):
         return ctx.tag
 
 class DeepSizeResults(rend.Page):
         return ctx.tag
 
 class DeepSizeResults(rend.Page):
-    def __init__(self, monitor):
+    def __init__(self, client, monitor):
+        self.client = client
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
-        output = get_arg(inevow.IRequest(ctx), "output", "html").lower()
-        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
+        req = inevow.IRequest(ctx)
+        output = get_arg(req, "output", "html").lower()
+        req.setHeader("content-type", "text/plain")
         if output == "json":
         if output == "json":
-            return self.json(ctx)
+            return self.json(req)
         # plain text
         is_finished = self.monitor.is_finished()
         output = "finished: " + {True: "yes", False: "no"}[is_finished] + "\n"
         # plain text
         is_finished = self.monitor.is_finished()
         output = "finished: " + {True: "yes", False: "no"}[is_finished] + "\n"
@@ -858,14 +864,15 @@ class DeepSizeResults(rend.Page):
             output += "size: %d\n" % total
         return output
 
             output += "size: %d\n" % total
         return output
 
-    def json(self, ctx):
+    def json(self, req):
         status = {"finished": self.monitor.is_finished(),
                   "size": self.monitor.get_status(),
                   }
         return simplejson.dumps(status)
 
 class DeepStatsResults(rend.Page):
         status = {"finished": self.monitor.is_finished(),
                   "size": self.monitor.get_status(),
                   }
         return simplejson.dumps(status)
 
 class DeepStatsResults(rend.Page):
-    def __init__(self, monitor):
+    def __init__(self, client, monitor):
+        self.client = client
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
         self.monitor = monitor
 
     def renderHTTP(self, ctx):
index 0a2081a787b872560a68d47de4de4612b27a028a..78e235b60cedb7e762b01cb3752dcb01621baee9 100644 (file)
@@ -12,7 +12,7 @@ from allmydata.immutable.upload import FileHandle
 from allmydata.immutable.filenode import LiteralFileNode
 from allmydata.util import log, base32
 
 from allmydata.immutable.filenode import LiteralFileNode
 from allmydata.util import log, base32
 
-from allmydata.web.common import text_plain, WebError, IClient, RenderMixin, \
+from allmydata.web.common import text_plain, WebError, RenderMixin, \
      boolean_of_arg, get_arg, should_create_intermediate_directories
 from allmydata.web.check_results import CheckResults, \
      CheckAndRepairResults, LiteralCheckResults
      boolean_of_arg, get_arg, should_create_intermediate_directories
 from allmydata.web.check_results import CheckResults, \
      CheckAndRepairResults, LiteralCheckResults
@@ -20,10 +20,8 @@ from allmydata.web.info import MoreInfo
 
 class ReplaceMeMixin:
 
 
 class ReplaceMeMixin:
 
-    def replace_me_with_a_child(self, ctx, replace):
+    def replace_me_with_a_child(self, req, client, replace):
         # a new file is being uploaded in our place.
         # a new file is being uploaded in our place.
-        req = IRequest(ctx)
-        client = IClient(ctx)
         mutable = boolean_of_arg(get_arg(req, "mutable", "false"))
         if mutable:
             req.content.seek(0)
         mutable = boolean_of_arg(get_arg(req, "mutable", "false"))
         if mutable:
             req.content.seek(0)
@@ -53,11 +51,9 @@ class ReplaceMeMixin:
         d.addCallback(_done)
         return d
 
         d.addCallback(_done)
         return d
 
-    def replace_me_with_a_childcap(self, ctx, replace):
-        req = IRequest(ctx)
+    def replace_me_with_a_childcap(self, req, client, replace):
         req.content.seek(0)
         childcap = req.content.read()
         req.content.seek(0)
         childcap = req.content.read()
-        client = IClient(ctx)
         childnode = client.create_node_from_uri(childcap)
         d = self.parentnode.set_node(self.name, childnode, overwrite=replace)
         d.addCallback(lambda res: childnode.get_uri())
         childnode = client.create_node_from_uri(childcap)
         d = self.parentnode.set_node(self.name, childnode, overwrite=replace)
         d.addCallback(lambda res: childnode.get_uri())
@@ -71,10 +67,8 @@ class ReplaceMeMixin:
         data = contents.file.read()
         return data
 
         data = contents.file.read()
         return data
 
-    def replace_me_with_a_formpost(self, ctx, replace):
+    def replace_me_with_a_formpost(self, req, client, replace):
         # create a new file, maybe mutable, maybe immutable
         # create a new file, maybe mutable, maybe immutable
-        req = IRequest(ctx)
-        client = IClient(ctx)
         mutable = boolean_of_arg(get_arg(req, "mutable", "false"))
 
         if mutable:
         mutable = boolean_of_arg(get_arg(req, "mutable", "false"))
 
         if mutable:
@@ -95,8 +89,9 @@ class ReplaceMeMixin:
         return d
 
 class PlaceHolderNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         return d
 
 class PlaceHolderNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
-    def __init__(self, parentnode, name):
+    def __init__(self, client, parentnode, name):
         rend.Page.__init__(self)
         rend.Page.__init__(self)
+        self.client = client
         assert parentnode
         self.parentnode = parentnode
         self.name = name
         assert parentnode
         self.parentnode = parentnode
         self.name = name
@@ -111,9 +106,9 @@ class PlaceHolderNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
             raise WebError("Content-Range in PUT not yet supported",
                            http.NOT_IMPLEMENTED)
         if not t:
             raise WebError("Content-Range in PUT not yet supported",
                            http.NOT_IMPLEMENTED)
         if not t:
-            return self.replace_me_with_a_child(ctx, replace)
+            return self.replace_me_with_a_child(req, self.client, replace)
         if t == "uri":
         if t == "uri":
-            return self.replace_me_with_a_childcap(ctx, replace)
+            return self.replace_me_with_a_childcap(req, self.client, replace)
 
         raise WebError("PUT to a file: bad t=%s" % t)
 
 
         raise WebError("PUT to a file: bad t=%s" % t)
 
@@ -127,7 +122,7 @@ class PlaceHolderNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
             # or POST /uri/path/file?t=upload, or
             # POST /uri/path/dir?t=upload&name=foo . All have the same
             # behavior, we just ignore any name= argument
             # or POST /uri/path/file?t=upload, or
             # POST /uri/path/dir?t=upload&name=foo . All have the same
             # behavior, we just ignore any name= argument
-            d = self.replace_me_with_a_formpost(ctx, replace)
+            d = self.replace_me_with_a_formpost(req, self.client, replace)
         else:
             # t=mkdir is handled in DirectoryNodeHandler._POST_mkdir, so
             # there are no other t= values left to be handled by the
         else:
             # t=mkdir is handled in DirectoryNodeHandler._POST_mkdir, so
             # there are no other t= values left to be handled by the
@@ -141,8 +136,9 @@ class PlaceHolderNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
 
 
 class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
 
 
 class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
-    def __init__(self, node, parentnode=None, name=None):
+    def __init__(self, client, node, parentnode=None, name=None):
         rend.Page.__init__(self)
         rend.Page.__init__(self)
+        self.client = client
         assert node
         self.node = node
         self.parentnode = parentnode
         assert node
         self.node = node
         self.parentnode = parentnode
@@ -210,19 +206,19 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         replace = boolean_of_arg(get_arg(req, "replace", "true"))
         if not t:
             if self.node.is_mutable():
         replace = boolean_of_arg(get_arg(req, "replace", "true"))
         if not t:
             if self.node.is_mutable():
-                return self.replace_my_contents(ctx)
+                return self.replace_my_contents(req)
             if not replace:
                 # this is the early trap: if someone else modifies the
                 # directory while we're uploading, the add_file(overwrite=)
                 # call in replace_me_with_a_child will do the late trap.
                 raise ExistingChildError()
             assert self.parentnode and self.name
             if not replace:
                 # this is the early trap: if someone else modifies the
                 # directory while we're uploading, the add_file(overwrite=)
                 # call in replace_me_with_a_child will do the late trap.
                 raise ExistingChildError()
             assert self.parentnode and self.name
-            return self.replace_me_with_a_child(ctx, replace)
+            return self.replace_me_with_a_child(req, self.client, replace)
         if t == "uri":
             if not replace:
                 raise ExistingChildError()
             assert self.parentnode and self.name
         if t == "uri":
             if not replace:
                 raise ExistingChildError()
             assert self.parentnode and self.name
-            return self.replace_me_with_a_childcap(ctx, replace)
+            return self.replace_me_with_a_childcap(req, self.client, replace)
 
         raise WebError("PUT to a file: bad t=%s" % t)
 
 
         raise WebError("PUT to a file: bad t=%s" % t)
 
@@ -239,12 +235,12 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
             # POST /uri/path/dir?t=upload&name=foo . All have the same
             # behavior, we just ignore any name= argument
             if self.node.is_mutable():
             # POST /uri/path/dir?t=upload&name=foo . All have the same
             # behavior, we just ignore any name= argument
             if self.node.is_mutable():
-                d = self.replace_my_contents_with_a_formpost(ctx)
+                d = self.replace_my_contents_with_a_formpost(req)
             else:
                 if not replace:
                     raise ExistingChildError()
                 assert self.parentnode and self.name
             else:
                 if not replace:
                     raise ExistingChildError()
                 assert self.parentnode and self.name
-                d = self.replace_me_with_a_formpost(ctx, replace)
+                d = self.replace_me_with_a_formpost(req, self.client, replace)
         else:
             raise WebError("POST to file: bad t=%s" % t)
 
         else:
             raise WebError("POST to file: bad t=%s" % t)
 
@@ -258,13 +254,13 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         repair = boolean_of_arg(get_arg(req, "repair", "false"))
         add_lease = boolean_of_arg(get_arg(req, "add-lease", "false"))
         if isinstance(self.node, LiteralFileNode):
         repair = boolean_of_arg(get_arg(req, "repair", "false"))
         add_lease = boolean_of_arg(get_arg(req, "add-lease", "false"))
         if isinstance(self.node, LiteralFileNode):
-            return defer.succeed(LiteralCheckResults())
+            return defer.succeed(LiteralCheckResults(self.client))
         if repair:
             d = self.node.check_and_repair(Monitor(), verify, add_lease)
         if repair:
             d = self.node.check_and_repair(Monitor(), verify, add_lease)
-            d.addCallback(lambda res: CheckAndRepairResults(res))
+            d.addCallback(lambda res: CheckAndRepairResults(self.client, res))
         else:
             d = self.node.check(Monitor(), verify, add_lease)
         else:
             d = self.node.check(Monitor(), verify, add_lease)
-            d.addCallback(lambda res: CheckResults(res))
+            d.addCallback(lambda res: CheckResults(self.client, res))
         return d
 
     def render_DELETE(self, ctx):
         return d
 
     def render_DELETE(self, ctx):
@@ -273,18 +269,16 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
         d.addCallback(lambda res: self.node.get_uri())
         return d
 
         d.addCallback(lambda res: self.node.get_uri())
         return d
 
-    def replace_my_contents(self, ctx):
-        req = IRequest(ctx)
+    def replace_my_contents(self, req):
         req.content.seek(0)
         new_contents = req.content.read()
         d = self.node.overwrite(new_contents)
         d.addCallback(lambda res: self.node.get_uri())
         return d
 
         req.content.seek(0)
         new_contents = req.content.read()
         d = self.node.overwrite(new_contents)
         d.addCallback(lambda res: self.node.get_uri())
         return d
 
-    def replace_my_contents_with_a_formpost(self, ctx):
+    def replace_my_contents_with_a_formpost(self, req):
         # we have a mutable file. Get the data from the formpost, and replace
         # the mutable file's contents with it.
         # we have a mutable file. Get the data from the formpost, and replace
         # the mutable file's contents with it.
-        req = IRequest(ctx)
         new_contents = self._read_data_from_formpost(req)
         d = self.node.overwrite(new_contents)
         d.addCallback(lambda res: self.node.get_uri())
         new_contents = self._read_data_from_formpost(req)
         d = self.node.overwrite(new_contents)
         d.addCallback(lambda res: self.node.get_uri())
@@ -449,4 +443,4 @@ def FileReadOnlyURI(ctx, filenode):
 
 class FileNodeDownloadHandler(FileNodeHandler):
     def childFactory(self, ctx, name):
 
 class FileNodeDownloadHandler(FileNodeHandler):
     def childFactory(self, ctx, name):
-        return FileNodeDownloadHandler(self.node, name=name)
+        return FileNodeDownloadHandler(self.client, self.node, name=name)
index bea580171c498bbee90f817ec1920a3c7feb4edc..f5c9e298a5a4897189063c570de7a74ec0793c50 100644 (file)
@@ -11,7 +11,7 @@
 <h1>Helper Status</h1>
 
 <h2>Immutable Uploads</h2>
 <h1>Helper Status</h1>
 
 <h2>Immutable Uploads</h2>
-<ul>
+<ul n:data="helper_stats">
   <li>Active: <span n:render="active_uploads" /></li>
   <li>--</li>
   <li>Bytes Fetched: <span n:render="upload_bytes_fetched" /></li>
   <li>Active: <span n:render="active_uploads" /></li>
   <li>--</li>
   <li>Bytes Fetched: <span n:render="upload_bytes_fetched" /></li>
index f1a6ad02638ddb68f3ddc3d69deccb3efdcc6ff9..3210fda156297297a9ed128cef1bfad101a82aca 100644 (file)
@@ -7,7 +7,7 @@ import allmydata
 import simplejson
 from allmydata import get_package_versions_string
 from allmydata.util import idlib
 import simplejson
 from allmydata import get_package_versions_string
 from allmydata.util import idlib
-from common import getxmlfile, get_arg, IClient
+from common import getxmlfile, get_arg
 
 class IntroducerRoot(rend.Page):
 
 
 class IntroducerRoot(rend.Page):
 
@@ -16,6 +16,11 @@ class IntroducerRoot(rend.Page):
 
     child_operations = None
 
 
     child_operations = None
 
+    def __init__(self, introducer_node):
+        self.introducer_node = introducer_node
+        self.introducer_service = introducer_node.getServiceNamed("introducer")
+        rend.Page.__init__(self, introducer_node)
+
     def renderHTTP(self, ctx):
         t = get_arg(inevow.IRequest(ctx), "t")
         if t == "json":
     def renderHTTP(self, ctx):
         t = get_arg(inevow.IRequest(ctx), "t")
         if t == "json":
@@ -23,16 +28,15 @@ class IntroducerRoot(rend.Page):
         return rend.Page.renderHTTP(self, ctx)
 
     def render_JSON(self, ctx):
         return rend.Page.renderHTTP(self, ctx)
 
     def render_JSON(self, ctx):
-        i = IClient(ctx).getServiceNamed("introducer")
         res = {}
         res = {}
-        clients = i.get_subscribers()
+        clients = self.introducer_service.get_subscribers()
         subscription_summary = dict([ (name, len(clients[name]))
                                       for name in clients ])
         res["subscription_summary"] = subscription_summary
 
         announcement_summary = {}
         service_hosts = {}
         subscription_summary = dict([ (name, len(clients[name]))
                                       for name in clients ])
         res["subscription_summary"] = subscription_summary
 
         announcement_summary = {}
         service_hosts = {}
-        for (ann,when) in i.get_announcements().values():
+        for (ann,when) in self.introducer_service.get_announcements().values():
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
             if service_name not in announcement_summary:
                 announcement_summary[service_name] = 0
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
             if service_name not in announcement_summary:
                 announcement_summary[service_name] = 0
@@ -65,12 +69,11 @@ class IntroducerRoot(rend.Page):
     def data_import_path(self, ctx, data):
         return str(allmydata)
     def data_my_nodeid(self, ctx, data):
     def data_import_path(self, ctx, data):
         return str(allmydata)
     def data_my_nodeid(self, ctx, data):
-        return idlib.nodeid_b2a(IClient(ctx).nodeid)
+        return idlib.nodeid_b2a(self.introducer_node.nodeid)
 
     def render_announcement_summary(self, ctx, data):
 
     def render_announcement_summary(self, ctx, data):
-        i = IClient(ctx).getServiceNamed("introducer")
         services = {}
         services = {}
-        for (ann,when) in i.get_announcements().values():
+        for (ann,when) in self.introducer_service.get_announcements().values():
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
             if service_name not in services:
                 services[service_name] = 0
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
             if service_name not in services:
                 services[service_name] = 0
@@ -81,17 +84,16 @@ class IntroducerRoot(rend.Page):
                           for service_name in service_names])
 
     def render_client_summary(self, ctx, data):
                           for service_name in service_names])
 
     def render_client_summary(self, ctx, data):
-        i = IClient(ctx).getServiceNamed("introducer")
-        clients = i.get_subscribers()
+        clients = self.introducer_service.get_subscribers()
         service_names = clients.keys()
         service_names.sort()
         return ", ".join(["%s: %d" % (service_name, len(clients[service_name]))
                           for service_name in service_names])
 
     def data_services(self, ctx, data):
         service_names = clients.keys()
         service_names.sort()
         return ", ".join(["%s: %d" % (service_name, len(clients[service_name]))
                           for service_name in service_names])
 
     def data_services(self, ctx, data):
-        i = IClient(ctx).getServiceNamed("introducer")
+        introsvc = self.introducer_service
         ann = [(since,a)
         ann = [(since,a)
-               for (a,since) in i.get_announcements().values()
+               for (a,since) in introsvc.get_announcements().values()
                if a[1] != "stub_client"]
         ann.sort(lambda a,b: cmp( (a[1][1], a), (b[1][1], b) ) )
         return ann
                if a[1] != "stub_client"]
         ann.sort(lambda a,b: cmp( (a[1][1], a), (b[1][1], b) ) )
         return ann
@@ -112,10 +114,9 @@ class IntroducerRoot(rend.Page):
         return ctx.tag
 
     def data_subscribers(self, ctx, data):
         return ctx.tag
 
     def data_subscribers(self, ctx, data):
-        i = IClient(ctx).getServiceNamed("introducer")
         # use the "stub_client" announcements to get information per nodeid
         clients = {}
         # use the "stub_client" announcements to get information per nodeid
         clients = {}
-        for (ann,when) in i.get_announcements().values():
+        for (ann,when) in self.introducer_service.get_announcements().values():
             if ann[1] != "stub_client":
                 continue
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
             if ann[1] != "stub_client":
                 continue
             (furl, service_name, ri_name, nickname, ver, oldest) = ann
@@ -125,7 +126,8 @@ class IntroducerRoot(rend.Page):
 
         # then we actually provide information per subscriber
         s = []
 
         # then we actually provide information per subscriber
         s = []
-        for service_name, subscribers in i.get_subscribers().items():
+        introsvc = self.introducer_service
+        for service_name, subscribers in introsvc.get_subscribers().items():
             for (rref, timestamp) in subscribers.items():
                 sr = rref.getSturdyRef()
                 nodeid = sr.tubID
             for (rref, timestamp) in subscribers.items():
                 sr = rref.getSturdyRef()
                 nodeid = sr.tubID
index f429e05f5befec824104c0f07dc4af443b42a042..e82d575812055eae11ea65c686e8a88d043fb970 100644 (file)
@@ -14,15 +14,19 @@ from allmydata import provisioning
 from allmydata.util import idlib, log
 from allmydata.interfaces import IFileNode
 from allmydata.web import filenode, directory, unlinked, status, operations
 from allmydata.util import idlib, log
 from allmydata.interfaces import IFileNode
 from allmydata.web import filenode, directory, unlinked, status, operations
-from allmydata.web import reliability
-from allmydata.web.common import abbreviate_size, IClient, \
-     getxmlfile, WebError, get_arg, RenderMixin
+from allmydata.web import reliability, storage
+from allmydata.web.common import abbreviate_size, getxmlfile, WebError, \
+     get_arg, RenderMixin
 
 
 class URIHandler(RenderMixin, rend.Page):
     # I live at /uri . There are several operations defined on /uri itself,
     # mostly involved with creation of unlinked files and directories.
 
 
 
 class URIHandler(RenderMixin, rend.Page):
     # I live at /uri . There are several operations defined on /uri itself,
     # mostly involved with creation of unlinked files and directories.
 
+    def __init__(self, client):
+        rend.Page.__init__(self, client)
+        self.client = client
+
     def render_GET(self, ctx):
         req = IRequest(ctx)
         uri = get_arg(req, "uri", None)
     def render_GET(self, ctx):
         req = IRequest(ctx)
         uri = get_arg(req, "uri", None)
@@ -43,11 +47,11 @@ class URIHandler(RenderMixin, rend.Page):
         if t == "":
             mutable = bool(get_arg(req, "mutable", "").strip())
             if mutable:
         if t == "":
             mutable = bool(get_arg(req, "mutable", "").strip())
             if mutable:
-                return unlinked.PUTUnlinkedSSK(ctx)
+                return unlinked.PUTUnlinkedSSK(req, self.client)
             else:
             else:
-                return unlinked.PUTUnlinkedCHK(ctx)
+                return unlinked.PUTUnlinkedCHK(req, self.client)
         if t == "mkdir":
         if t == "mkdir":
-            return unlinked.PUTUnlinkedCreateDirectory(ctx)
+            return unlinked.PUTUnlinkedCreateDirectory(req, self.client)
         errmsg = ("/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, "
                   "and POST?t=mkdir")
         raise WebError(errmsg, http.BAD_REQUEST)
         errmsg = ("/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, "
                   "and POST?t=mkdir")
         raise WebError(errmsg, http.BAD_REQUEST)
@@ -61,21 +65,20 @@ class URIHandler(RenderMixin, rend.Page):
         if t in ("", "upload"):
             mutable = bool(get_arg(req, "mutable", "").strip())
             if mutable:
         if t in ("", "upload"):
             mutable = bool(get_arg(req, "mutable", "").strip())
             if mutable:
-                return unlinked.POSTUnlinkedSSK(ctx)
+                return unlinked.POSTUnlinkedSSK(req, self.client)
             else:
             else:
-                return unlinked.POSTUnlinkedCHK(ctx)
+                return unlinked.POSTUnlinkedCHK(req, self.client)
         if t == "mkdir":
         if t == "mkdir":
-            return unlinked.POSTUnlinkedCreateDirectory(ctx)
+            return unlinked.POSTUnlinkedCreateDirectory(req, self.client)
         errmsg = ("/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, "
                   "and POST?t=mkdir")
         raise WebError(errmsg, http.BAD_REQUEST)
 
     def childFactory(self, ctx, name):
         # 'name' is expected to be a URI
         errmsg = ("/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, "
                   "and POST?t=mkdir")
         raise WebError(errmsg, http.BAD_REQUEST)
 
     def childFactory(self, ctx, name):
         # 'name' is expected to be a URI
-        client = IClient(ctx)
         try:
         try:
-            node = client.create_node_from_uri(name)
-            return directory.make_handler_for(node)
+            node = self.client.create_node_from_uri(name)
+            return directory.make_handler_for(node, self.client)
         except (TypeError, AssertionError):
             raise WebError("'%s' is not a valid file- or directory- cap"
                            % name)
         except (TypeError, AssertionError):
             raise WebError("'%s' is not a valid file- or directory- cap"
                            % name)
@@ -84,20 +87,23 @@ class FileHandler(rend.Page):
     # I handle /file/$FILECAP[/IGNORED] , which provides a URL from which a
     # file can be downloaded correctly by tools like "wget".
 
     # I handle /file/$FILECAP[/IGNORED] , which provides a URL from which a
     # file can be downloaded correctly by tools like "wget".
 
+    def __init__(self, client):
+        rend.Page.__init__(self, client)
+        self.client = client
+
     def childFactory(self, ctx, name):
         req = IRequest(ctx)
         if req.method not in ("GET", "HEAD"):
             raise WebError("/file can only be used with GET or HEAD")
         # 'name' must be a file URI
     def childFactory(self, ctx, name):
         req = IRequest(ctx)
         if req.method not in ("GET", "HEAD"):
             raise WebError("/file can only be used with GET or HEAD")
         # 'name' must be a file URI
-        client = IClient(ctx)
         try:
         try:
-            node = client.create_node_from_uri(name)
+            node = self.client.create_node_from_uri(name)
         except (TypeError, AssertionError):
             raise WebError("'%s' is not a valid file- or directory- cap"
                            % name)
         if not IFileNode.providedBy(node):
             raise WebError("'%s' is not a file-cap" % name)
         except (TypeError, AssertionError):
             raise WebError("'%s' is not a valid file- or directory- cap"
                            % name)
         if not IFileNode.providedBy(node):
             raise WebError("'%s' is not a file-cap" % name)
-        return filenode.FileNodeDownloadHandler(node)
+        return filenode.FileNodeDownloadHandler(self.client, node)
 
     def renderHTTP(self, ctx):
         raise WebError("/file must be followed by a file-cap and a name",
 
     def renderHTTP(self, ctx):
         raise WebError("/file must be followed by a file-cap and a name",
@@ -132,14 +138,27 @@ class Root(rend.Page):
     addSlash = True
     docFactory = getxmlfile("welcome.xhtml")
 
     addSlash = True
     docFactory = getxmlfile("welcome.xhtml")
 
-    def __init__(self, original=None):
-        rend.Page.__init__(self, original)
+    def __init__(self, client):
+        rend.Page.__init__(self, client)
+        self.client = client
         self.child_operations = operations.OphandleTable()
 
         self.child_operations = operations.OphandleTable()
 
-    child_uri = URIHandler()
-    child_cap = URIHandler()
-    child_file = FileHandler()
-    child_named = FileHandler()
+        self.child_uri = URIHandler(client)
+        self.child_cap = URIHandler(client)
+
+        self.child_file = FileHandler(client)
+        self.child_named = FileHandler(client)
+        self.child_status = status.Status(client) # TODO: use client.history
+        self.child_statistics = status.Statistics(client.stats_provider)
+
+    def child_helper_status(self, ctx):
+        # the Helper isn't attached until after the Tub starts, so this child
+        # needs to created on each request
+        try:
+            helper = self.client.getServiceNamed("helper")
+        except KeyError:
+            helper = None
+        return status.HelperStatus(helper)
 
     child_webform_css = webform.defaultCSS
     child_tahoe_css = nevow_File(resource_filename('allmydata.web', 'tahoe.css'))
 
     child_webform_css = webform.defaultCSS
     child_tahoe_css = nevow_File(resource_filename('allmydata.web', 'tahoe.css'))
@@ -149,9 +168,6 @@ class Root(rend.Page):
         child_reliability = reliability.ReliabilityTool()
     else:
         child_reliability = NoReliability()
         child_reliability = reliability.ReliabilityTool()
     else:
         child_reliability = NoReliability()
-    child_status = status.Status()
-    child_helper_status = status.HelperStatus()
-    child_statistics = status.Statistics()
 
     child_report_incident = IncidentReporter()
 
 
     child_report_incident = IncidentReporter()
 
@@ -160,15 +176,14 @@ class Root(rend.Page):
     def data_import_path(self, ctx, data):
         return str(allmydata)
     def data_my_nodeid(self, ctx, data):
     def data_import_path(self, ctx, data):
         return str(allmydata)
     def data_my_nodeid(self, ctx, data):
-        return idlib.nodeid_b2a(IClient(ctx).nodeid)
+        return idlib.nodeid_b2a(self.client.nodeid)
     def data_my_nickname(self, ctx, data):
     def data_my_nickname(self, ctx, data):
-        return IClient(ctx).nickname
+        return self.client.nickname
 
     def render_services(self, ctx, data):
         ul = T.ul()
 
     def render_services(self, ctx, data):
         ul = T.ul()
-        client = IClient(ctx)
         try:
         try:
-            ss = client.getServiceNamed("storage")
+            ss = self.client.getServiceNamed("storage")
             allocated_s = abbreviate_size(ss.allocated_size())
             allocated = "about %s allocated" % allocated_s
             reserved = "%s reserved" % abbreviate_size(ss.reserved_space)
             allocated_s = abbreviate_size(ss.allocated_size())
             allocated = "about %s allocated" % allocated_s
             reserved = "%s reserved" % abbreviate_size(ss.reserved_space)
@@ -177,7 +192,7 @@ class Root(rend.Page):
             ul[T.li["Not running storage server"]]
 
         try:
             ul[T.li["Not running storage server"]]
 
         try:
-            h = client.getServiceNamed("helper")
+            h = self.client.getServiceNamed("helper")
             stats = h.get_stats()
             active_uploads = stats["chk_upload_helper.active_uploads"]
             ul[T.li["Helper: %d active uploads" % (active_uploads,)]]
             stats = h.get_stats()
             active_uploads = stats["chk_upload_helper.active_uploads"]
             ul[T.li["Helper: %d active uploads" % (active_uploads,)]]
@@ -187,22 +202,22 @@ class Root(rend.Page):
         return ctx.tag[ul]
 
     def data_introducer_furl(self, ctx, data):
         return ctx.tag[ul]
 
     def data_introducer_furl(self, ctx, data):
-        return IClient(ctx).introducer_furl
+        return self.client.introducer_furl
     def data_connected_to_introducer(self, ctx, data):
     def data_connected_to_introducer(self, ctx, data):
-        if IClient(ctx).connected_to_introducer():
+        if self.client.connected_to_introducer():
             return "yes"
         return "no"
 
     def data_helper_furl(self, ctx, data):
         try:
             return "yes"
         return "no"
 
     def data_helper_furl(self, ctx, data):
         try:
-            uploader = IClient(ctx).getServiceNamed("uploader")
+            uploader = self.client.getServiceNamed("uploader")
         except KeyError:
             return None
         furl, connected = uploader.get_helper_info()
         return furl
     def data_connected_to_helper(self, ctx, data):
         try:
         except KeyError:
             return None
         furl, connected = uploader.get_helper_info()
         return furl
     def data_connected_to_helper(self, ctx, data):
         try:
-            uploader = IClient(ctx).getServiceNamed("uploader")
+            uploader = self.client.getServiceNamed("uploader")
         except KeyError:
             return "no" # we don't even have an Uploader
         furl, connected = uploader.get_helper_info()
         except KeyError:
             return "no" # we don't even have an Uploader
         furl, connected = uploader.get_helper_info()
@@ -211,18 +226,18 @@ class Root(rend.Page):
         return "no"
 
     def data_known_storage_servers(self, ctx, data):
         return "no"
 
     def data_known_storage_servers(self, ctx, data):
-        ic = IClient(ctx).introducer_client
+        ic = self.client.introducer_client
         servers = [c
                    for c in ic.get_all_connectors().values()
                    if c.service_name == "storage"]
         return len(servers)
 
     def data_connected_storage_servers(self, ctx, data):
         servers = [c
                    for c in ic.get_all_connectors().values()
                    if c.service_name == "storage"]
         return len(servers)
 
     def data_connected_storage_servers(self, ctx, data):
-        ic = IClient(ctx).introducer_client
+        ic = self.client.introducer_client
         return len(ic.get_all_connections_for("storage"))
 
     def data_services(self, ctx, data):
         return len(ic.get_all_connections_for("storage"))
 
     def data_services(self, ctx, data):
-        ic = IClient(ctx).introducer_client
+        ic = self.client.introducer_client
         c = [ (service_name, nodeid, rsc)
               for (nodeid, service_name), rsc
               in ic.get_all_connectors().items() ]
         c = [ (service_name, nodeid, rsc)
               for (nodeid, service_name), rsc
               in ic.get_all_connectors().items() ]
@@ -235,7 +250,7 @@ class Root(rend.Page):
         ctx.fillSlots("nickname", rsc.nickname)
         if rsc.rref:
             rhost = rsc.remote_host
         ctx.fillSlots("nickname", rsc.nickname)
         if rsc.rref:
             rhost = rsc.remote_host
-            if nodeid == IClient(ctx).nodeid:
+            if nodeid == self.client.nodeid:
                 rhost_s = "(loopback)"
             elif isinstance(rhost, address.IPv4Address):
                 rhost_s = "%s:%d" % (rhost.host, rhost.port)
                 rhost_s = "(loopback)"
             elif isinstance(rhost, address.IPv4Address):
                 rhost_s = "%s:%d" % (rhost.host, rhost.port)
index fa956ab7785c90c3bca4f9065dfedc9a9fb95bfd..bbd7c1849aa0978e9388ae12a3381a75962cf202 100644 (file)
@@ -6,7 +6,7 @@
     <link href="/webform_css" rel="stylesheet" type="text/css"/>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   </head>
     <link href="/webform_css" rel="stylesheet" type="text/css"/>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   </head>
-  <body>
+  <body n:data="get_stats">
 
 <h1>Node Statistics</h1>
 
 
 <h1>Node Statistics</h1>
 
index 01bfa284dfa76254300c1fb154c9a20802d3db95..d5ce1c697b1cf3693590a086238275dd30b1f391 100644 (file)
@@ -4,8 +4,8 @@ import simplejson
 from twisted.internet import defer
 from nevow import rend, inevow, tags as T
 from allmydata.util import base32, idlib
 from twisted.internet import defer
 from nevow import rend, inevow, tags as T
 from allmydata.util import base32, idlib
-from allmydata.web.common import IClient, getxmlfile, abbreviate_time, \
-     abbreviate_rate, abbreviate_size, get_arg
+from allmydata.web.common import getxmlfile, get_arg, \
+     abbreviate_time, abbreviate_rate, abbreviate_size
 from allmydata.interfaces import IUploadStatus, IDownloadStatus, \
      IPublishStatus, IRetrieveStatus, IServermapUpdaterStatus
 
 from allmydata.interfaces import IUploadStatus, IDownloadStatus, \
      IPublishStatus, IRetrieveStatus, IServermapUpdaterStatus
 
@@ -773,18 +773,22 @@ class Status(rend.Page):
     docFactory = getxmlfile("status.xhtml")
     addSlash = True
 
     docFactory = getxmlfile("status.xhtml")
     addSlash = True
 
+    def __init__(self, client):
+        rend.Page.__init__(self, client)
+        self.client = client
+
     def renderHTTP(self, ctx):
     def renderHTTP(self, ctx):
-        t = get_arg(inevow.IRequest(ctx), "t")
+        req = inevow.IRequest(ctx)
+        t = get_arg(req, "t")
         if t == "json":
         if t == "json":
-            return self.json(ctx)
+            return self.json(req)
         return rend.Page.renderHTTP(self, ctx)
 
         return rend.Page.renderHTTP(self, ctx)
 
-    def json(self, ctx):
-        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
-        client = IClient(ctx)
+    def json(self, req):
+        req.setHeader("content-type", "text/plain")
         data = {}
         data["active"] = active = []
         data = {}
         data["active"] = active = []
-        for s in self.data_active_operations(ctx, None):
+        for s in self._get_active_operations():
             si_s = base32.b2a_or_none(s.get_storage_index())
             size = s.get_size()
             status = s.get_status()
             si_s = base32.b2a_or_none(s.get_storage_index())
             size = s.get_size()
             status = s.get_status()
@@ -808,26 +812,31 @@ class Status(rend.Page):
 
         return simplejson.dumps(data, indent=1) + "\n"
 
 
         return simplejson.dumps(data, indent=1) + "\n"
 
-    def _get_all_statuses(self, client):
-        return itertools.chain(client.list_all_upload_statuses(),
-                               client.list_all_download_statuses(),
-                               client.list_all_mapupdate_statuses(),
-                               client.list_all_publish_statuses(),
-                               client.list_all_retrieve_statuses(),
-                               client.list_all_helper_statuses(),
+    def _get_all_statuses(self):
+        c = self.client
+        return itertools.chain(c.list_all_upload_statuses(),
+                               c.list_all_download_statuses(),
+                               c.list_all_mapupdate_statuses(),
+                               c.list_all_publish_statuses(),
+                               c.list_all_retrieve_statuses(),
+                               c.list_all_helper_statuses(),
                                )
 
     def data_active_operations(self, ctx, data):
                                )
 
     def data_active_operations(self, ctx, data):
-        client = IClient(ctx)
+        return self._get_active_operations()
+
+    def _get_active_operations(self):
         active = [s
         active = [s
-                  for s in self._get_all_statuses(client)
+                  for s in self._get_all_statuses()
                   if s.get_active()]
         return active
 
     def data_recent_operations(self, ctx, data):
                   if s.get_active()]
         return active
 
     def data_recent_operations(self, ctx, data):
-        client = IClient(ctx)
+        return self._get_recent_operations()
+
+    def _get_recent_operations(self):
         recent = [s
         recent = [s
-                  for s in self._get_all_statuses(client)
+                  for s in self._get_all_statuses()
                   if not s.get_active()]
         recent.sort(lambda a,b: cmp(a.get_started(), b.get_started()))
         recent.reverse()
                   if not s.get_active()]
         recent.sort(lambda a,b: cmp(a.get_started(), b.get_started()))
         recent.reverse()
@@ -887,7 +896,7 @@ class Status(rend.Page):
         return ctx.tag
 
     def childFactory(self, ctx, name):
         return ctx.tag
 
     def childFactory(self, ctx, name):
-        client = IClient(ctx)
+        client = self.client
         stype,count_s = name.split("-")
         count = int(count_s)
         if stype == "up":
         stype,count_s = name.split("-")
         count = int(count_s)
         if stype == "up":
@@ -918,24 +927,26 @@ class Status(rend.Page):
 class HelperStatus(rend.Page):
     docFactory = getxmlfile("helper.xhtml")
 
 class HelperStatus(rend.Page):
     docFactory = getxmlfile("helper.xhtml")
 
+    def __init__(self, helper):
+        rend.Page.__init__(self, helper)
+        self.helper = helper
+
     def renderHTTP(self, ctx):
     def renderHTTP(self, ctx):
-        t = get_arg(inevow.IRequest(ctx), "t")
+        req = inevow.IRequest(ctx)
+        t = get_arg(req, "t")
         if t == "json":
         if t == "json":
-            return self.render_JSON(ctx)
-        # is there a better way to provide 'data' to all rendering methods?
-        helper = IClient(ctx).getServiceNamed("helper")
-        self.original = helper.get_stats()
+            return self.render_JSON(req)
         return rend.Page.renderHTTP(self, ctx)
 
         return rend.Page.renderHTTP(self, ctx)
 
-    def render_JSON(self, ctx):
-        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
-        try:
-            h = IClient(ctx).getServiceNamed("helper")
-        except KeyError:
-            return simplejson.dumps({}) + "\n"
+    def data_helper_stats(self, ctx, data):
+        return self.helper.get_stats()
 
 
-        stats = h.get_stats()
-        return simplejson.dumps(stats, indent=1) + "\n"
+    def render_JSON(self, req):
+        req.setHeader("content-type", "text/plain")
+        if self.helper:
+            stats = self.helper.get_stats()
+            return simplejson.dumps(stats, indent=1) + "\n"
+        return simplejson.dumps({}) + "\n"
 
     def render_active_uploads(self, ctx, data):
         return data["chk_upload_helper.active_uploads"]
 
     def render_active_uploads(self, ctx, data):
         return data["chk_upload_helper.active_uploads"]
@@ -967,19 +978,22 @@ class HelperStatus(rend.Page):
 class Statistics(rend.Page):
     docFactory = getxmlfile("statistics.xhtml")
 
 class Statistics(rend.Page):
     docFactory = getxmlfile("statistics.xhtml")
 
+    def __init__(self, provider):
+        rend.Page.__init__(self, provider)
+        self.provider = provider
+
     def renderHTTP(self, ctx):
     def renderHTTP(self, ctx):
-        provider = IClient(ctx).stats_provider
-        stats = {'stats': {}, 'counters': {}}
-        if provider:
-            stats = provider.get_stats()
-        t = get_arg(inevow.IRequest(ctx), "t")
+        req = inevow.IRequest(ctx)
+        t = get_arg(req, "t")
         if t == "json":
         if t == "json":
-            inevow.IRequest(ctx).setHeader("content-type", "text/plain")
+            stats = self.provider.get_stats()
+            req.setHeader("content-type", "text/plain")
             return simplejson.dumps(stats, indent=1) + "\n"
             return simplejson.dumps(stats, indent=1) + "\n"
-        # is there a better way to provide 'data' to all rendering methods?
-        self.original = stats
         return rend.Page.renderHTTP(self, ctx)
 
         return rend.Page.renderHTTP(self, ctx)
 
+    def data_get_stats(self, ctx, data):
+        return self.provider.get_stats()
+
     def render_load_average(self, ctx, data):
         return str(data["stats"].get("load_monitor.avg_load"))
 
     def render_load_average(self, ctx, data):
         return str(data["stats"].get("load_monitor.avg_load"))
 
index 3b8d95380377eb0e616eab9425663b3a1fafcabc..d3ef96f67148db175ab77d89c325c238e7d14593 100644 (file)
@@ -3,42 +3,35 @@ import urllib
 from twisted.web import http
 from twisted.internet import defer
 from nevow import rend, url, tags as T
 from twisted.web import http
 from twisted.internet import defer
 from nevow import rend, url, tags as T
-from nevow.inevow import IRequest
 from allmydata.immutable.upload import FileHandle
 from allmydata.immutable.upload import FileHandle
-from allmydata.web.common import IClient, getxmlfile, get_arg, boolean_of_arg
+from allmydata.web.common import getxmlfile, get_arg, boolean_of_arg
 from allmydata.web import status
 
 from allmydata.web import status
 
-def PUTUnlinkedCHK(ctx):
-    req = IRequest(ctx)
+def PUTUnlinkedCHK(req, client):
     # "PUT /uri", to create an unlinked file.
     # "PUT /uri", to create an unlinked file.
-    client = IClient(ctx)
     uploadable = FileHandle(req.content, client.convergence)
     d = client.upload(uploadable)
     d.addCallback(lambda results: results.uri)
     # that fires with the URI of the new file
     return d
 
     uploadable = FileHandle(req.content, client.convergence)
     d = client.upload(uploadable)
     d.addCallback(lambda results: results.uri)
     # that fires with the URI of the new file
     return d
 
-def PUTUnlinkedSSK(ctx):
-    req = IRequest(ctx)
+def PUTUnlinkedSSK(req, client):
     # SDMF: files are small, and we can only upload data
     req.content.seek(0)
     data = req.content.read()
     # SDMF: files are small, and we can only upload data
     req.content.seek(0)
     data = req.content.read()
-    d = IClient(ctx).create_mutable_file(data)
+    d = client.create_mutable_file(data)
     d.addCallback(lambda n: n.get_uri())
     return d
 
     d.addCallback(lambda n: n.get_uri())
     return d
 
-def PUTUnlinkedCreateDirectory(ctx):
-    req = IRequest(ctx)
+def PUTUnlinkedCreateDirectory(req, client):
     # "PUT /uri?t=mkdir", to create an unlinked directory.
     # "PUT /uri?t=mkdir", to create an unlinked directory.
-    d = IClient(ctx).create_empty_dirnode()
+    d = client.create_empty_dirnode()
     d.addCallback(lambda dirnode: dirnode.get_uri())
     # XXX add redirect_to_result
     return d
 
 
     d.addCallback(lambda dirnode: dirnode.get_uri())
     # XXX add redirect_to_result
     return d
 
 
-def POSTUnlinkedCHK(ctx):
-    req = IRequest(ctx)
-    client = IClient(ctx)
+def POSTUnlinkedCHK(req, client):
     fileobj = req.fields["file"].file
     uploadable = FileHandle(fileobj, client.convergence)
     d = client.upload(uploadable)
     fileobj = req.fields["file"].file
     uploadable = FileHandle(fileobj, client.convergence)
     d = client.upload(uploadable)
@@ -54,7 +47,7 @@ def POSTUnlinkedCHK(ctx):
         d.addCallback(_done, when_done)
     else:
         # return the Upload Results page, which includes the URI
         d.addCallback(_done, when_done)
     else:
         # return the Upload Results page, which includes the URI
-        d.addCallback(UploadResultsPage, ctx)
+        d.addCallback(UploadResultsPage)
     return d
 
 
     return d
 
 
@@ -62,7 +55,7 @@ class UploadResultsPage(status.UploadResultsRendererMixin, rend.Page):
     """'POST /uri', to create an unlinked file."""
     docFactory = getxmlfile("upload-results.xhtml")
 
     """'POST /uri', to create an unlinked file."""
     docFactory = getxmlfile("upload-results.xhtml")
 
-    def __init__(self, upload_results, ctx):
+    def __init__(self, upload_results):
         rend.Page.__init__(self)
         self.results = upload_results
 
         rend.Page.__init__(self)
         self.results = upload_results
 
@@ -85,21 +78,19 @@ class UploadResultsPage(status.UploadResultsRendererMixin, rend.Page):
                       ["/uri/" + res.uri])
         return d
 
                       ["/uri/" + res.uri])
         return d
 
-def POSTUnlinkedSSK(ctx):
-    req = IRequest(ctx)
+def POSTUnlinkedSSK(req, client):
     # "POST /uri", to create an unlinked file.
     # SDMF: files are small, and we can only upload data
     contents = req.fields["file"]
     contents.file.seek(0)
     data = contents.file.read()
     # "POST /uri", to create an unlinked file.
     # SDMF: files are small, and we can only upload data
     contents = req.fields["file"]
     contents.file.seek(0)
     data = contents.file.read()
-    d = IClient(ctx).create_mutable_file(data)
+    d = client.create_mutable_file(data)
     d.addCallback(lambda n: n.get_uri())
     return d
 
     d.addCallback(lambda n: n.get_uri())
     return d
 
-def POSTUnlinkedCreateDirectory(ctx):
-    req = IRequest(ctx)
+def POSTUnlinkedCreateDirectory(req, client):
     # "POST /uri?t=mkdir", to create an unlinked directory.
     # "POST /uri?t=mkdir", to create an unlinked directory.
-    d = IClient(ctx).create_empty_dirnode()
+    d = client.create_empty_dirnode()
     redirect = get_arg(req, "redirect_to_result", "false")
     if boolean_of_arg(redirect):
         def _then_redir(res):
     redirect = get_arg(req, "redirect_to_result", "false")
     if boolean_of_arg(redirect):
         def _then_redir(res):
index e3f560709bcad33468c0f6196d8af1921d79c0ba..57b84ca582e0d4a913ff274eafcb289a3aba8ff8 100644 (file)
@@ -6,7 +6,7 @@ from nevow import appserver, inevow, static
 from allmydata.util import log
 
 from allmydata.web import introweb, root
 from allmydata.util import log
 
 from allmydata.web import introweb, root
-from allmydata.web.common import IClient, IOpHandleTable, MyExceptionHandler
+from allmydata.web.common import IOpHandleTable, MyExceptionHandler
 
 # we must override twisted.web.http.Request.requestReceived with a version
 # that doesn't use cgi.parse_multipart() . Since we actually use Nevow, we
 
 # we must override twisted.web.http.Request.requestReceived with a version
 # that doesn't use cgi.parse_multipart() . Since we actually use Nevow, we
@@ -120,17 +120,21 @@ class MyRequest(appserver.NevowRequest):
 
 class WebishServer(service.MultiService):
     name = "webish"
 
 class WebishServer(service.MultiService):
     name = "webish"
-    root_class = root.Root
 
 
-    def __init__(self, webport, nodeurl_path=None, staticdir=None):
+    def __init__(self, client, webport, nodeurl_path=None, staticdir=None):
         service.MultiService.__init__(self)
         service.MultiService.__init__(self)
-        self.webport = webport
-        self.root = self.root_class()
-        self.site = site = appserver.NevowSite(self.root)
-        self.site.requestFactory = MyRequest
+        # the 'data' argument to all render() methods default to the Client
+        self.root = root.Root(client)
+        self.buildServer(webport, nodeurl_path, staticdir)
         if self.root.child_operations:
             self.site.remember(self.root.child_operations, IOpHandleTable)
             self.root.child_operations.setServiceParent(self)
         if self.root.child_operations:
             self.site.remember(self.root.child_operations, IOpHandleTable)
             self.root.child_operations.setServiceParent(self)
+
+    def buildServer(self, webport, nodeurl_path, staticdir):
+        self.webport = webport
+        self.site = site = appserver.NevowSite(self.root)
+        self.site.requestFactory = MyRequest
+        self.site.remember(MyExceptionHandler(), inevow.ICanHandleException)
         if staticdir:
             self.root.putChild("static", static.File(staticdir))
         s = strports.service(webport, site)
         if staticdir:
             self.root.putChild("static", static.File(staticdir))
         s = strports.service(webport, site)
@@ -142,15 +146,6 @@ class WebishServer(service.MultiService):
 
     def startService(self):
         service.MultiService.startService(self)
 
     def startService(self):
         service.MultiService.startService(self)
-        # to make various services available to render_* methods, we stash a
-        # reference to the client on the NevowSite. This will be available by
-        # adapting the 'context' argument to a special marker interface named
-        # IClient.
-        self.site.remember(self.parent, IClient)
-        # I thought you could do the same with an existing interface, but
-        # apparently 'ISite' does not exist
-        #self.site._client = self.parent
-        self.site.remember(MyExceptionHandler(), inevow.ICanHandleException)
         self._started.callback(None)
 
     def _write_nodeurl_file(self, junk, nodeurl_path):
         self._started.callback(None)
 
     def _write_nodeurl_file(self, junk, nodeurl_path):
@@ -169,4 +164,8 @@ class WebishServer(service.MultiService):
             f.close()
 
 class IntroducerWebishServer(WebishServer):
             f.close()
 
 class IntroducerWebishServer(WebishServer):
-    root_class = introweb.IntroducerRoot
+    def __init__(self, introducer, webport, nodeurl_path=None, staticdir=None):
+        service.MultiService.__init__(self)
+        self.root = introweb.IntroducerRoot(introducer)
+        self.buildServer(webport, nodeurl_path, staticdir)
+