summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--docs/index.rst4
-rw-r--r--routes/lru.py70
-rw-r--r--routes/util.py24
-rw-r--r--setup.py2
5 files changed, 87 insertions, 17 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 8d6046d..89ee4b4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
Routes Changelog
========================
+-- 1.11 (**tip**)
+* Added optional LRU object for use with Routes when URL's change too often
+ for the Routes urlcache dict to be a viable option.
+
-- 1.10.3 (February 8, 2009)
* Tweak to use WebOb Request rather than Paste.
* Performance tweaks for URL recognition.
diff --git a/docs/index.rst b/docs/index.rst
index d288fcd..ad7b722 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,7 +1,3 @@
-.. Routes documentation master file, created by sphinx-quickstart on Sun Apr 20 19:13:41 2008.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
Routes Reference
================
diff --git a/routes/lru.py b/routes/lru.py
new file mode 100644
index 0000000..2633159
--- /dev/null
+++ b/routes/lru.py
@@ -0,0 +1,70 @@
+"""LRU caching class and decorator"""
+import threading
+
+_marker = object()
+
+class LRUCache(object):
+ def __init__(self, size):
+ """ Implements a psueudo-LRU algorithm (CLOCK) """
+ if size < 1:
+ raise ValueError('size must be >1')
+ self.clock = []
+ for i in xrange(0, size):
+ self.clock.append({'key':_marker, 'ref':False})
+ self.size = size
+ self.maxpos = size - 1
+ self.hand = 0
+ self.data = {}
+ self.lock = threading.Lock()
+
+ def __contains__(self, key):
+ return key in self.data
+
+ def _getitem__(self, key, default=None):
+ try:
+ datum = self.data[key]
+ except KeyError:
+ return default
+ pos, val = datum
+ self.clock[pos]['ref'] = True
+ hand = pos + 1
+ if hand > self.maxpos:
+ hand = 0
+ self.hand = hand
+ return val
+
+ def __setitem__(self, key, val, _marker=_marker):
+ hand = self.hand
+ maxpos = self.maxpos
+ clock = self.clock
+ data = self.data
+ lock = self.lock
+
+ end = hand - 1
+ if end < 0:
+ end = maxpos
+
+ while 1:
+ current = clock[hand]
+ ref = current['ref']
+ if ref is True:
+ current['ref'] = False
+ hand = hand + 1
+ if hand > maxpos:
+ hand = 0
+ elif ref is False or hand == end:
+ lock.acquire()
+ try:
+ oldkey = current['key']
+ if oldkey in data:
+ del data[oldkey]
+ current['key'] = key
+ current['ref'] = True
+ data[key] = (hand, val)
+ hand += 1
+ if hand > maxpos:
+ hand = 0
+ self.hand = hand
+ finally:
+ lock.release()
+ break \ No newline at end of file
diff --git a/routes/util.py b/routes/util.py
index 702759d..94d5e6d 100644
--- a/routes/util.py
+++ b/routes/util.py
@@ -11,6 +11,18 @@ import urllib
from routes import request_config
+class RoutesException(Exception):
+ """Tossed during Route exceptions"""
+
+
+class MatchException(RoutesException):
+ """Tossed during URL matching exceptions"""
+
+
+class GenerationException(RoutesException):
+ """Tossed during URL generation exceptions"""
+
+
def _screenargs(kargs, mapper, environ):
"""
Private function that takes a dict, and screens it against the current
@@ -495,15 +507,3 @@ def controller_scan(directory=None):
controllers = find_controllers(directory)
controllers.sort(longest_first)
return controllers
-
-
-class RoutesException(Exception):
- """Tossed during Route exceptions"""
-
-
-class MatchException(RoutesException):
- """Tossed during URL matching exceptions"""
-
-
-class GenerationException(RoutesException):
- """Tossed during URL generation exceptions"""
diff --git a/setup.py b/setup.py
index f92b1a9..caa9efb 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ except ImportError:
use_setuptools()
from setuptools import setup, find_packages
-version = '1.10.4'
+version = '1.11'
setup(name="Routes",
version=version,