aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmproxy/console/common.py9
-rw-r--r--libmproxy/console/flowview.py15
-rw-r--r--libmproxy/utils.py53
-rw-r--r--test/test_utils.py26
-rwxr-xr-xtest/tools/testpatt10
5 files changed, 47 insertions, 66 deletions
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py
index a0590bb1..2f143f01 100644
--- a/libmproxy/console/common.py
+++ b/libmproxy/console/common.py
@@ -327,11 +327,7 @@ def ask_save_body(part, master, state, flow):
signals.status_message.send(message="No content to save.")
-class FlowCache:
- @utils.LRUCache(200)
- def format_flow(self, *args):
- return raw_format_flow(*args)
-flowcache = FlowCache()
+flowcache = utils.LRUCache(800)
def format_flow(f, focus, extended=False, hostheader=False, padding=2):
@@ -370,6 +366,7 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2):
d["resp_ctype"] = t[0].split(";")[0]
else:
d["resp_ctype"] = ""
- return flowcache.format_flow(
+ return flowcache.get(
+ raw_format_flow,
tuple(sorted(d.items())), focus, extended, padding
)
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index e864cf47..2c847fba 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -107,16 +107,7 @@ class FlowViewHeader(urwid.WidgetWrap):
)
-class CallbackCache:
- @utils.LRUCache(200)
- def _callback(self, method, *args, **kwargs):
- return getattr(self.obj, method)(*args, **kwargs)
-
- def callback(self, obj, method, *args, **kwargs):
- # obj varies!
- self.obj = obj
- return self._callback(method, *args, **kwargs)
-cache = CallbackCache()
+cache = utils.LRUCache(200)
class FlowView(urwid.WidgetWrap):
@@ -158,8 +149,8 @@ class FlowView(urwid.WidgetWrap):
limit = sys.maxint
else:
limit = contentview.VIEW_CUTOFF
- description, text_objects = cache.callback(
- self, "_cached_content_view",
+ description, text_objects = cache.get(
+ self._cached_content_view,
viewmode,
tuple(tuple(i) for i in conn.headers.lst),
conn.content,
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index 51f2dc26..5ed70a45 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -119,40 +119,33 @@ pkg_data = Data(__name__)
class LRUCache:
"""
- A decorator that implements a self-expiring LRU cache for class
- methods (not functions!).
-
- Cache data is tracked as attributes on the object itself. There is
- therefore a separate cache for each object instance.
+ A simple LRU cache for generated values.
"""
def __init__(self, size=100):
self.size = size
+ self.cache = {}
+ self.cacheList = []
+
+ def get(self, gen, *args):
+ """
+ gen: A (presumably expensive) generator function. The identity of
+ gen is NOT taken into account by the cache.
+ *args: A list of immutable arguments, used to establish identiy by
+ *the cache, and passed to gen to generate values.
+ """
+ if self.cache.has_key(args):
+ self.cacheList.remove(args)
+ self.cacheList.insert(0, args)
+ return self.cache[args]
+ else:
+ ret = gen(*args)
+ self.cacheList.insert(0, args)
+ self.cache[args] = ret
+ if len(self.cacheList) > self.size:
+ d = self.cacheList.pop()
+ self.cache.pop(d)
+ return ret
- def __call__(self, f):
- cacheName = "_cached_%s"%f.__name__
- cacheListName = "_cachelist_%s"%f.__name__
- size = self.size
-
- @functools.wraps(f)
- def wrap(self, *args):
- if not hasattr(self, cacheName):
- setattr(self, cacheName, {})
- setattr(self, cacheListName, [])
- cache = getattr(self, cacheName)
- cacheList = getattr(self, cacheListName)
- if cache.has_key(args):
- cacheList.remove(args)
- cacheList.insert(0, args)
- return cache[args]
- else:
- ret = f(self, *args)
- cacheList.insert(0, args)
- cache[args] = ret
- if len(cacheList) > size:
- d = cacheList.pop()
- cache.pop(d)
- return ret
- return wrap
def parse_content_type(c):
"""
diff --git a/test/test_utils.py b/test/test_utils.py
index 78d1c072..1678a7de 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -62,38 +62,39 @@ def test_pretty_duration():
assert utils.pretty_duration(10) == "10.0s"
assert utils.pretty_duration(100) == "100s"
assert utils.pretty_duration(1000) == "1000s"
- assert utils.pretty_duration(10000) == "10000s"
+ assert utils.pretty_duration(10000) == "10000s"
assert utils.pretty_duration(1.123) == "1.12s"
assert utils.pretty_duration(0.123) == "123ms"
def test_LRUCache():
+ cache = utils.LRUCache(2)
class Foo:
ran = False
- @utils.LRUCache(2)
- def one(self, x):
+ def gen(self, x):
self.ran = True
return x
-
f = Foo()
- assert f.one(1) == 1
+
+ assert not f.ran
+ assert cache.get(f.gen, 1) == 1
assert f.ran
f.ran = False
- assert f.one(1) == 1
+ assert cache.get(f.gen, 1) == 1
assert not f.ran
f.ran = False
- assert f.one(1) == 1
+ assert cache.get(f.gen, 1) == 1
assert not f.ran
- assert f.one(2) == 2
- assert f.one(3) == 3
+ assert cache.get(f.gen, 2) == 2
+ assert cache.get(f.gen, 3) == 3
assert f.ran
f.ran = False
- assert f.one(1) == 1
+ assert cache.get(f.gen, 1) == 1
assert f.ran
- assert len(f._cached_one) == 2
- assert len(f._cachelist_one) == 2
+ assert len(cache.cacheList) == 2
+ assert len(cache.cache) == 2
def test_unparse_url():
@@ -128,4 +129,3 @@ def test_safe_subn():
def test_urlencode():
assert utils.urlencode([('foo','bar')])
-
diff --git a/test/tools/testpatt b/test/tools/testpatt
index d4546d48..5ee1ea02 100755
--- a/test/tools/testpatt
+++ b/test/tools/testpatt
@@ -2,8 +2,8 @@
# Generate a test pattern with pathoc
PATHOD=http://localhost:9999
-pathoc localhost:8080 "get:'$PATHOD/p/200:p0,1:b@200b':b@200b"
-pathoc localhost:8080 "get:'$PATHOD/p/300:p0,1:b@200b':b@200b"
-pathoc localhost:8080 "get:'$PATHOD/p/400:p0,1:b@200b':b@200b"
-pathoc localhost:8080 "get:'$PATHOD/p/500:p0,1:b@200b':b@200b"
-pathoc localhost:8080 "get:'$PATHOD/p/600:p0,1:b@200b':b@200b"
+pathoc localhost:8080 "get:'$PATHOD/p/200:p0,1:b@2048b':b@2048b"
+pathoc localhost:8080 "get:'$PATHOD/p/300:p0,1:b@2048b':b@2048b"
+pathoc localhost:8080 "get:'$PATHOD/p/400:p0,1:b@2048b':b@2048b"
+pathoc localhost:8080 "get:'$PATHOD/p/500:p0,1:b@2048b':b@2048b"
+pathoc localhost:8080 "get:'$PATHOD/p/600:p0,1:b@2048b':b@2048b"