use a weakref cache in the client to manage singleton filenodes/dirnodes, to avoid autocollision. Should close #391.

This commit is contained in:
Brian Warner
2008-05-08 18:02:55 -07:00
parent 8f4e409677
commit 26187bfc81
2 changed files with 20 additions and 12 deletions

View File

@ -1,5 +1,5 @@
import os, stat, time, re import os, stat, time, re, weakref
from allmydata.interfaces import RIStorageServer from allmydata.interfaces import RIStorageServer
from allmydata import node from allmydata import node
@ -170,6 +170,7 @@ class Client(node.Node, testutil.PollMixin):
helper_furl = self.get_config("helper.furl") helper_furl = self.get_config("helper.furl")
convergence_s = self.get_or_create_private_config('convergence', _make_secret) convergence_s = self.get_or_create_private_config('convergence', _make_secret)
self.convergence = base32.a2b(convergence_s) self.convergence = base32.a2b(convergence_s)
self._node_cache = weakref.WeakValueDictionary() # uri -> node
self.add_service(Uploader(helper_furl, self.stats_provider)) self.add_service(Uploader(helper_furl, self.stats_provider))
self.add_service(Downloader(self.stats_provider)) self.add_service(Downloader(self.stats_provider))
self.add_service(Checker()) self.add_service(Checker())
@ -292,17 +293,22 @@ class Client(node.Node, testutil.PollMixin):
def create_node_from_uri(self, u): def create_node_from_uri(self, u):
# this returns synchronously. # this returns synchronously.
u = IURI(u) u = IURI(u)
if IReadonlyNewDirectoryURI.providedBy(u): u_s = u.to_string()
# new-style read-only dirnodes if u_s not in self._node_cache:
return NewDirectoryNode(self).init_from_uri(u) if IReadonlyNewDirectoryURI.providedBy(u):
if INewDirectoryURI.providedBy(u): # new-style read-only dirnodes
# new-style dirnodes node = NewDirectoryNode(self).init_from_uri(u)
return NewDirectoryNode(self).init_from_uri(u) elif INewDirectoryURI.providedBy(u):
if IFileURI.providedBy(u): # new-style dirnodes
# CHK node = NewDirectoryNode(self).init_from_uri(u)
return FileNode(u, self) elif IFileURI.providedBy(u):
assert IMutableFileURI.providedBy(u), u # CHK
return MutableFileNode(self).init_from_uri(u) node = FileNode(u, self)
else:
assert IMutableFileURI.providedBy(u), u
node = MutableFileNode(self).init_from_uri(u)
self._node_cache[u_s] = node
return self._node_cache[u_s]
def notify_publish(self, publish_status, size): def notify_publish(self, publish_status, size):
self.getServiceNamed("mutable-watcher").notify_publish(publish_status, self.getServiceNamed("mutable-watcher").notify_publish(publish_status,

View File

@ -702,6 +702,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, testutil.StallMixin,
uri = self._mutable_node_1.get_uri() uri = self._mutable_node_1.get_uri()
log.msg("starting retrieve1") log.msg("starting retrieve1")
newnode = self.clients[0].create_node_from_uri(uri) newnode = self.clients[0].create_node_from_uri(uri)
newnode_2 = self.clients[0].create_node_from_uri(uri)
self.failUnlessIdentical(newnode, newnode_2)
return newnode.download_best_version() return newnode.download_best_version()
d.addCallback(_check_download_1) d.addCallback(_check_download_1)