import re, time
from zope.interface import implements
from foolscap.api import eventually
-from allmydata.interfaces import IStorageBroker, IServer
+from allmydata.interfaces import IStorageBroker, IDisplayableServer, IServer
from allmydata.util import log, base32
from allmydata.util.assertutil import precondition
from allmydata.util.rrefutil import add_version_to_remote_reference
def test_add_rref(self, serverid, rref, ann):
s = NativeStorageServer(serverid, ann.copy())
s.rref = rref
+ s._is_connected = True
self.servers[serverid] = s
def test_add_server(self, serverid, s):
return frozenset(self.servers.keys())
def get_connected_servers(self):
- return frozenset([s for s in self.servers.values() if s.get_rref()])
+ return frozenset([s for s in self.servers.values() if s.is_connected()])
def get_known_servers(self):
return frozenset(self.servers.values())
return self.servers[serverid].get_nickname()
return None
+ def get_stub_server(self, serverid):
+ if serverid in self.servers:
+ return self.servers[serverid]
+ return StubServer(serverid)
+
+class StubServer:
+ implements(IDisplayableServer)
+ def __init__(self, serverid):
+ self.serverid = serverid # binary tubid
+ def get_serverid(self):
+ return self.serverid
+ def get_name(self):
+ return base32.b2a(self.serverid)[:8]
+ def get_longname(self):
+ return base32.b2a(self.serverid)
+ def get_nickname(self):
+ return "?"
+
class NativeStorageServer:
"""I hold information about a storage server that we want to connect to.
If we are connected, I hold the RemoteReference, their host address, and
VERSION_DEFAULTS = {
"http://allmydata.org/tahoe/protocols/storage/v1" :
- { "maximum-immutable-share-size": 2**32,
+ { "maximum-immutable-share-size": 2**32 - 1,
+ "maximum-mutable-share-size": 2*1000*1000*1000, # maximum prior to v1.9.2
"tolerates-immutable-read-overrun": False,
"delete-mutable-shares-with-zero-length-writev": False,
},
"application-version": "unknown: no get_version()",
}
- def __init__(self, key_s, ann, min_shares=1):
+ def __init__(self, key_s, ann):
self.key_s = key_s
self.announcement = ann
- self.min_shares = min_shares
assert "anonymous-storage-FURL" in ann, ann
furl = str(ann["anonymous-storage-FURL"])
self._short_description = key_s[:8]
else:
self._long_description = tubid_s
- self._short_description = tubid_s[:8]
+ self._short_description = tubid_s[:6]
self.announcement_time = time.time()
self.last_connect_time = None
self.last_loss_time = None
self.remote_host = None
self.rref = None
+ self._is_connected = False
self._reconnector = None
self._trigger_cb = None
+ # Special methods used by copy.copy() and copy.deepcopy(). When those are
+ # used in allmydata.immutable.filenode to copy CheckResults during
+ # repair, we want it to treat the IServer instances as singletons, and
+ # not attempt to duplicate them..
+ def __copy__(self):
+ return self
+ def __deepcopy__(self, memodict):
+ return self
+
def __repr__(self):
return "<NativeStorageServer for %s>" % self.get_name()
def get_serverid(self):
return self._tubid
def get_nickname(self):
- return self.announcement["nickname"].decode("utf-8")
+ return self.announcement["nickname"]
def get_announcement(self):
return self.announcement
def get_remote_host(self):
return self.remote_host
+ def is_connected(self):
+ return self._is_connected
def get_last_connect_time(self):
return self.last_connect_time
def get_last_loss_time(self):
self.last_connect_time = time.time()
self.remote_host = rref.getPeer()
self.rref = rref
+ self._is_connected = True
rref.notifyOnDisconnect(self._lost)
def get_rref(self):
log.msg(format="lost connection to %(name)s", name=self.get_name(),
facility="tahoe.storage_broker", umid="zbRllw")
self.last_loss_time = time.time()
- self.rref = None
+ # self.rref is now stale: all callRemote()s will get a
+ # DeadReferenceError. We leave the stale reference in place so that
+ # uploader/downloader code (which received this IServer through
+ # get_connected_servers() or get_servers_for_psi()) can continue to
+ # use s.get_rref().callRemote() and not worry about it being None.
+ self._is_connected = False
self.remote_host = None
def stop_connecting(self):