check_memory: add download-GET-slow, to simulate memory usage of a node feeding downloaded data via HTTP GET to a slow client

This commit is contained in:
Brian Warner 2007-09-18 20:35:27 -07:00
parent a5fab9935b
commit 08cc32bb77
2 changed files with 65 additions and 11 deletions

View File

@ -181,6 +181,8 @@ check-memory: build
$(PYTHON) src/allmydata/test/check_memory.py download $(PYTHON) src/allmydata/test/check_memory.py download
$(PP) \ $(PP) \
$(PYTHON) src/allmydata/test/check_memory.py download-GET $(PYTHON) src/allmydata/test/check_memory.py download-GET
$(PP) \
$(PYTHON) src/allmydata/test/check_memory.py download-GET-slow
test-darcs-boringfile: test-darcs-boringfile:

View File

@ -4,7 +4,7 @@ import os, shutil, sys, urllib
from cStringIO import StringIO from cStringIO import StringIO
from twisted.internet import defer, reactor, protocol, error from twisted.internet import defer, reactor, protocol, error
from twisted.application import service, internet from twisted.application import service, internet
from twisted.web.client import getPage, downloadPage from twisted.web import client as tw_client
from allmydata import client, introducer_and_vdrive from allmydata import client, introducer_and_vdrive
from allmydata.scripts import create_node from allmydata.scripts import create_node
from allmydata.util import testutil, fileutil from allmydata.util import testutil, fileutil
@ -12,6 +12,50 @@ import foolscap
from foolscap import eventual from foolscap import eventual
from twisted.python import log from twisted.python import log
class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter):
full_speed_ahead = False
_bytes_so_far = 0
stalled = None
def handleResponsePart(self, data):
self._bytes_so_far += len(data)
if not self.factory.do_stall:
return
if self.full_speed_ahead:
return
if self._bytes_so_far > 1e6+100:
if not self.stalled:
print "STALLING"
self.transport.pauseProducing()
self.stalled = reactor.callLater(10.0, self._resume_speed)
def _resume_speed(self):
print "RESUME SPEED"
self.stalled = None
self.full_speed_ahead = True
self.transport.resumeProducing()
def handleResponseEnd(self):
if self.stalled:
print "CANCEL"
self.stalled.cancel()
self.stalled = None
return tw_client.HTTPPageGetter.handleResponseEnd(self)
class StallableDiscardingHTTPClientFactory(tw_client.HTTPClientFactory):
protocol = StallableHTTPGetterDiscarder
def discardPage(url, stall=False, *args, **kwargs):
"""Start fetching the URL, but stall our pipe after the first 1MB.
Wait 10 seconds, then resume downloading (and discarding) everything.
"""
# adapted from twisted.web.client.getPage . We can't just wrap or
# subclass because it provides no way to override the HTTPClientFactory
# that it creates.
scheme, host, port, path = tw_client._parse(url)
factory = StallableDiscardingHTTPClientFactory(url, *args, **kwargs)
factory.do_stall = stall
assert scheme == 'http'
reactor.connectTCP(host, port, factory)
return factory.deferred
class SystemFramework(testutil.PollMixin): class SystemFramework(testutil.PollMixin):
numnodes = 5 numnodes = 5
@ -30,7 +74,7 @@ class SystemFramework(testutil.PollMixin):
self.tub.setServiceParent(self.sparent) self.tub.setServiceParent(self.sparent)
self.discard_shares = True self.discard_shares = True
self.mode = mode self.mode = mode
if mode in ("download", "download-GET"): if mode in ("download", "download-GET", "download-GET-slow"):
self.discard_shares = False self.discard_shares = False
self.failed = False self.failed = False
@ -272,13 +316,12 @@ this file are ignored.
body = "\r\n".join(form) + "\r\n" body = "\r\n".join(form) + "\r\n"
headers = {"content-type": "multipart/form-data; boundary=%s" % sepbase, headers = {"content-type": "multipart/form-data; boundary=%s" % sepbase,
} }
return getPage(url, method="POST", postdata=body, return tw_client.getPage(url, method="POST", postdata=body,
headers=headers, followRedirect=False) headers=headers, followRedirect=False)
def GET_discard(self, urlpath): def GET_discard(self, urlpath, stall):
# TODO: Slow
url = self.webish_url + urlpath + "?filename=dummy-get.out" url = self.webish_url + urlpath + "?filename=dummy-get.out"
return downloadPage(url, os.path.join(self.basedir, "dummy-get.out")) return discardPage(url, stall)
def _print_usage(self, res=None): def _print_usage(self, res=None):
d = self.control_rref.callRemote("get_memory_usage") d = self.control_rref.callRemote("get_memory_usage")
@ -306,7 +349,7 @@ this file are ignored.
data = "a" * size data = "a" * size
url = "/vdrive/global" url = "/vdrive/global"
d = self.POST(url, t="upload", file=("%d.data" % size, data)) d = self.POST(url, t="upload", file=("%d.data" % size, data))
elif self.mode in ("download", "download-GET"): elif self.mode in ("download", "download-GET", "download-GET-slow"):
# upload the data from a local peer, then have the # upload the data from a local peer, then have the
# client-under-test download it. # client-under-test download it.
files[name] = self.create_data(name, size) files[name] = self.create_data(name, size)
@ -321,17 +364,26 @@ this file are ignored.
return d return d
def _do_download(self, res, size, uris): def _do_download(self, res, size, uris):
if self.mode not in ("download", "download-GET"): if self.mode not in ("download", "download-GET", "download-GET-slow"):
return return
name = '%d' % size name = '%d' % size
print "downloading %s" % name
uri = uris[name] uri = uris[name]
if self.mode == "download": if self.mode == "download":
d = self.control_rref.callRemote("download_from_uri_to_file", d = self.control_rref.callRemote("download_from_uri_to_file",
uri, "dummy.out") uri, "dummy.out")
if self.mode == "download-GET": elif self.mode == "download-GET":
url = "/uri/%s" % uri url = "/uri/%s" % uri
d = self.GET_discard(urllib.quote(url)) d = self.GET_discard(urllib.quote(url), stall=False)
elif self.mode == "download-GET-slow":
url = "/uri/%s" % uri
d = self.GET_discard(urllib.quote(url), stall=True)
def _complete(res):
print "downloaded %s" % name
return res
d.addCallback(_complete)
return d return d
def do_test(self): def do_test(self):