-from foolscap.api import DeadReferenceError
+from foolscap.api import DeadReferenceError, RemoteException
from twisted.internet import defer
from allmydata import hashtree
from allmydata.check_results import CheckResults
from allmydata.immutable import download
from allmydata.uri import CHKFileVerifierURI
from allmydata.util.assertutil import precondition
-from allmydata.util import base32, deferredutil, dictutil, log, rrefutil
+from allmydata.util import base32, deferredutil, dictutil, log
from allmydata.util.hashutil import file_renewal_secret_hash, \
file_cancel_secret_hash, bucket_renewal_secret_hash, \
bucket_cancel_secret_hash
assert precondition(isinstance(servers, (set, frozenset)), servers)
for (serverid, serverrref) in servers:
assert precondition(isinstance(serverid, str))
- assert precondition(isinstance(serverrref, rrefutil.WrappedRemoteReference), serverrref)
prefix = "%s" % base32.b2a_l(verifycap.storage_index[:8], 60)
log.PrefixingLogMixin.__init__(self, facility="tahoe.immutable.checker", prefix=prefix)
def _done(res):
[(get_success, get_result),
(addlease_success, addlease_result)] = res
- if (not addlease_success and
- not rrefutil.check_remote(addlease_result, IndexError)):
- # tahoe=1.3.0 raised IndexError on non-existant buckets,
- # which we ignore. But report others, including the
- # unfortunate internal KeyError bug that <1.3.0 had.
- return addlease_result # propagate error
- return get_result
+ # ignore remote IndexError on the add_lease call. Propagate
+ # local errors and remote non-IndexErrors
+ if addlease_success:
+ return get_result
+ if not addlease_result.check(RemoteException):
+ # Propagate local errors
+ return addlease_result
+ if addlease_result.value.failure.check(IndexError):
+ # tahoe=1.3.0 raised IndexError on non-existant
+ # buckets, which we ignore
+ return get_result
+ # propagate remote errors that aren't IndexError, including
+ # the unfortunate internal KeyError bug that <1.3.0 had.
+ return addlease_result
dl.addCallback(_done)
d = dl
def _wrap_results(res):
- for k in res:
- res[k] = rrefutil.WrappedRemoteReference(res[k])
return (res, serverid, True)
def _trap_errs(f):
d = veup.start()
def _errb(f):
- # Okay, we didn't succeed at fetching and verifying all the
- # blocks of this share. Now we need to handle different reasons
- # for failure differently. If the failure isn't one of the
- # following four classes then it will get re-raised.
- failtype = f.trap(DeadReferenceError,
- rrefutil.ServerFailure,
- layout.LayoutInvalid,
- layout.RidiculouslyLargeURIExtensionBlock,
- layout.ShareVersionIncompatible,
- download.BadOrMissingHash,
- download.BadURIExtensionHashValue)
+ # We didn't succeed at fetching and verifying all the blocks of
+ # this share. Handle each reason for failure differently.
if f.check(DeadReferenceError):
return (False, sharenum, 'disconnect')
- elif f.check(rrefutil.ServerFailure):
+ elif f.check(RemoteException):
return (False, sharenum, 'failure')
elif f.check(layout.ShareVersionIncompatible):
return (False, sharenum, 'incompatible')
- else:
+ elif f.check(layout.LayoutInvalid,
+ layout.RidiculouslyLargeURIExtensionBlock,
+ download.BadOrMissingHash,
+ download.BadURIExtensionHashValue):
return (False, sharenum, 'corrupt')
+ # if it wasn't one of those reasons, re-raise the error
+ return f
+
def _got_ueb(vup):
self._share_hash_tree = hashtree.IncompleteHashTree(self._verifycap.total_shares)
self._share_hash_tree.set_hashes({0: vup.share_root_hash})
return dl
def _err(f):
- f.trap(rrefutil.ServerFailure)
+ f.trap(RemoteException, DeadReferenceError)
return (set(), serverid, set(), set(), False)
d.addCallbacks(_got_buckets, _err)
from twisted.internet import defer
from twisted.internet.interfaces import IPushProducer, IConsumer
from twisted.application import service
-from foolscap.api import DeadReferenceError, eventually
+from foolscap.api import DeadReferenceError, RemoteException, eventually
from allmydata.util import base32, deferredutil, hashutil, log, mathutil
from allmydata.util.assertutil import _assert, precondition
-from allmydata.util.rrefutil import ServerFailure
from allmydata import codec, hashtree, uri
from allmydata.interfaces import IDownloadTarget, IDownloader, IFileURI, IVerifierURI, \
IDownloadStatus, IDownloadResults, IValidatedThingProxy, NotEnoughSharesError, \
self._log_id = log_id
def _bad(self, f, validatedthingproxy):
- failtype = f.trap(ServerFailure, IntegrityCheckReject, layout.LayoutInvalid, layout.ShareVersionIncompatible, DeadReferenceError)
+ failtype = f.trap(RemoteException, DeadReferenceError,
+ IntegrityCheckReject, layout.LayoutInvalid,
+ layout.ShareVersionIncompatible)
level = log.WEIRD
if f.check(DeadReferenceError):
level = log.UNUSUAL
- elif f.check(ServerFailure):
+ elif f.check(RemoteException):
level = log.WEIRD
else:
level = log.SCARY
self.parent.hold_block(self.blocknum, data)
def _got_block_error(self, f):
- failtype = f.trap(ServerFailure, IntegrityCheckReject, layout.LayoutInvalid, layout.ShareVersionIncompatible)
- if f.check(ServerFailure):
+ failtype = f.trap(RemoteException, DeadReferenceError,
+ IntegrityCheckReject,
+ layout.LayoutInvalid, layout.ShareVersionIncompatible)
+ if f.check(RemoteException, DeadReferenceError):
level = log.UNUSUAL
else:
level = log.WEIRD
from allmydata.immutable import encode
from allmydata.util import base32, dictutil, idlib, log, mathutil
from allmydata.util.assertutil import precondition
-from allmydata.util.rrefutil import get_versioned_remote_reference
+from allmydata.util.rrefutil import add_version_to_remote_reference
from allmydata.interfaces import IUploadable, IUploader, IUploadResults, \
IEncryptedUploadable, RIEncryptedUploadable, IUploadStatus, \
NotEnoughSharesError, InsufficientVersionError, NoServersError
{ },
"application-version": "unknown: no get_version()",
}
- d = get_versioned_remote_reference(helper, default)
+ d = add_version_to_remote_reference(helper, default)
d.addCallback(self._got_versioned_helper)
def _got_versioned_helper(self, helper):
from allmydata.introducer.interfaces import RIIntroducerSubscriberClient, \
IIntroducerClient
from allmydata.util import log, idlib
-from allmydata.util.rrefutil import get_versioned_remote_reference
+from allmydata.util.rrefutil import add_version_to_remote_reference
from allmydata.introducer.common import make_index
self.log("got connection to %s, getting versions" % self._nodeid_s)
default = self.VERSION_DEFAULTS.get(self.service_name, {})
- d = get_versioned_remote_reference(rref, default)
+ d = add_version_to_remote_reference(rref, default)
d.addCallback(self._got_versioned_service)
def _got_versioned_service(self, rref):
self.log("connected to %s, version %s" % (self._nodeid_s, rref.version))
self.last_connect_time = time.time()
- self.remote_host = rref.rref.tracker.broker.transport.getPeer()
+ self.remote_host = rref.tracker.broker.transport.getPeer()
self.rref = rref
{ },
"application-version": "unknown: no get_version()",
}
- d = get_versioned_remote_reference(publisher, default)
+ d = add_version_to_remote_reference(publisher, default)
d.addCallback(self._got_versioned_introducer)
d.addErrback(self._got_error)
service.MultiService.__init__(self)
self.basedir = basedir
self.tub = Tub(certFile=os.path.join(self.basedir, 'key_generator.pem'))
+ self.tub.setOption("expose-remote-exception-types", False)
self.tub.setServiceParent(self)
self.key_generator = KeyGenerator(default_key_size=default_key_size)
self.key_generator.setServiceParent(self)
from itertools import count
from twisted.internet import defer
from twisted.python import failure
-from foolscap.api import DeadReferenceError, eventually
-from allmydata.util import base32, hashutil, idlib, log, rrefutil
+from foolscap.api import DeadReferenceError, RemoteException, eventually
+from allmydata.util import base32, hashutil, idlib, log
from allmydata.storage.server import si_b2a
from allmydata.interfaces import IServermapUpdaterStatus
from pycryptopp.publickey import rsa
def _done(res):
[(readv_success, readv_result),
(addlease_success, addlease_result)] = res
- if (not addlease_success and
- not rrefutil.check_remote(addlease_result, IndexError)):
- # tahoe 1.3.0 raised IndexError on non-existant buckets,
- # which we ignore. Unfortunately tahoe <1.3.0 had a bug
- # and raised KeyError, which we report.
- return addlease_result # propagate error
- return readv_result
+ # ignore remote IndexError on the add_lease call. Propagate
+ # local errors and remote non-IndexErrors
+ if addlease_success:
+ return readv_result
+ if not addlease_result.check(RemoteException):
+ # Propagate local errors
+ return addlease_result
+ if addlease_result.value.failure.check(IndexError):
+ # tahoe=1.3.0 raised IndexError on non-existant
+ # buckets, which we ignore
+ return readv_result
+ # propagate remote errors that aren't IndexError, including
+ # the unfortunate internal KeyError bug that <1.3.0 had.
+ return addlease_result
dl.addCallback(_done)
return dl
return d
self.tub = Tub(certFile=certfile)
self.tub.setOption("logLocalFailures", True)
self.tub.setOption("logRemoteFailures", True)
+ self.tub.setOption("expose-remote-exception-types", False)
# see #521 for a discussion of how to pick these timeout values.
keepalive_timeout_s = self.get_config("node", "timeout.keepalive", "")
self.tub.setServiceParent(self)
self.tub.setOption("logLocalFailures", True)
self.tub.setOption("logRemoteFailures", True)
+ self.tub.setOption("expose-remote-exception-types", False)
self.stats_gatherer = PickleStatsGatherer(self.basedir, verbose)
self.stats_gatherer.setServiceParent(self)
self.sparent.startService()
self.proc = None
self.tub = Tub()
+ self.tub.setOption("expose-remote-exception-types", False)
self.tub.setServiceParent(self.sparent)
self.mode = mode
self.failed = False
def setUp(self):
self.base_service.startService()
self.tub = Tub()
+ self.tub.setOption("expose-remote-exception-types", False)
self.tub.setServiceParent(self.base_service)
d = self.tub.getReference(self.control_furl)
def _gotref(rref):
import sha
from twisted.application import service
from twisted.internet import reactor
-from foolscap.api import Referenceable, fireEventually
+from twisted.python.failure import Failure
+from foolscap.api import Referenceable, fireEventually, RemoteException
from base64 import b32encode
from allmydata import uri as tahoe_uri
from allmydata.client import Client
from allmydata.storage.server import StorageServer, storage_index_to_dir
-from allmydata.util import fileutil, idlib, hashutil, rrefutil
+from allmydata.util import fileutil, idlib, hashutil
from allmydata.introducer.client import RemoteServiceConnector
from allmydata.test.common_web import HTTPClientGETFactory
return meth(*args, **kwargs)
d = fireEventually()
d.addCallback(lambda res: _call())
+ def _wrap_exception(f):
+ return Failure(RemoteException(f))
+ d.addErrback(_wrap_exception)
def _return_membrane(res):
# rather than complete the difficult task of building a
# fully-general Membrane (which would locate all Referenceable
del self.disconnectors[marker]
def wrap(original, service_name):
- # The code in immutable.checker insists upon asserting the truth of
- # isinstance(rref, rrefutil.WrappedRemoteReference). Much of the
- # upload/download code uses rref.version (which normally comes from
- # rrefutil.VersionedRemoteReference). To avoid using a network, we want a
- # LocalWrapper here. Try to satisfy all these constraints at the same
- # time.
- local = LocalWrapper(original)
- wrapped = rrefutil.WrappedRemoteReference(local)
+ # Much of the upload/download code uses rref.version (which normally
+ # comes from rrefutil.add_version_to_remote_reference). To avoid using a
+ # network, we want a LocalWrapper here. Try to satisfy all these
+ # constraints at the same time.
+ wrapper = LocalWrapper(original)
try:
version = original.remote_get_version()
except AttributeError:
version = RemoteServiceConnector.VERSION_DEFAULTS[service_name]
- wrapped.version = version
- return wrapped
+ wrapper.version = version
+ return wrapper
class NoNetworkClient(Client):
self.s.startService()
self.tub = t = Tub()
+ t.setOption("expose-remote-exception-types", False)
t.setServiceParent(self.s)
self.s.tub = t
# we never actually use this for network traffic, so it can use a
self.central_tub = tub = Tub()
#tub.setOption("logLocalFailures", True)
#tub.setOption("logRemoteFailures", True)
+ tub.setOption("expose-remote-exception-types", False)
tub.setServiceParent(self.parent)
l = tub.listenOn("tcp:0")
portnum = l.getPortnum()
tub = Tub()
#tub.setOption("logLocalFailures", True)
#tub.setOption("logRemoteFailures", True)
+ tub.setOption("expose-remote-exception-types", False)
tub.setServiceParent(self.parent)
l = tub.listenOn("tcp:0")
portnum = l.getPortnum()
self.introducer_furl = self.central_tub.registerReference(i)
tub = Tub()
+ tub.setOption("expose-remote-exception-types", False)
tub.setServiceParent(self.parent)
l = tub.listenOn("tcp:0")
portnum = l.getPortnum()
self.parent.startService()
self.tub = t = Tub()
+ t.setOption("expose-remote-exception-types", False)
t.setServiceParent(self.parent)
t.listenOn("tcp:0")
t.setLocationAutomatically()
from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
from allmydata.util import assertutil, fileutil, deferredutil, abbreviate
from allmydata.util import limiter, time_format, pollmixin, cachedir
-from allmydata.util import statistics, dictutil, rrefutil, pipeline
-from allmydata.util.rrefutil import ServerFailure
+from allmydata.util import statistics, dictutil, pipeline
class Base32(unittest.TestCase):
def test_b2a_matches_Pythons(self):
self.failUnlessEqual(x, "b")
self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
-class FakeRemoteReference:
- def callRemote(self, methname, *args, **kwargs):
- return defer.maybeDeferred(self.oops)
- def oops(self):
- raise IndexError("remote missing key")
-
-class RemoteFailures(unittest.TestCase):
- def test_check(self):
- check_local = rrefutil.check_local
- check_remote = rrefutil.check_remote
- try:
- raise IndexError("local missing key")
- except IndexError:
- localf = Failure()
-
- self.failUnlessEqual(localf.check(IndexError, KeyError), IndexError)
- self.failUnlessEqual(localf.check(ValueError, KeyError), None)
- self.failUnlessEqual(localf.check(ServerFailure), None)
- self.failUnlessEqual(check_local(localf, IndexError, KeyError),
- IndexError)
- self.failUnlessEqual(check_local(localf, ValueError, KeyError), None)
- self.failUnlessEqual(check_remote(localf, IndexError, KeyError), None)
- self.failUnlessEqual(check_remote(localf, ValueError, KeyError), None)
-
- frr = FakeRemoteReference()
- wrr = rrefutil.WrappedRemoteReference(frr)
- d = wrr.callRemote("oops")
- def _check(f):
- self.failUnlessEqual(f.check(IndexError, KeyError), None)
- self.failUnlessEqual(f.check(ServerFailure, KeyError),
- ServerFailure)
- self.failUnlessEqual(check_remote(f, IndexError, KeyError),
- IndexError)
- self.failUnlessEqual(check_remote(f, ValueError, KeyError), None)
- self.failUnlessEqual(check_local(f, IndexError, KeyError), None)
- self.failUnlessEqual(check_local(f, ValueError, KeyError), None)
- d.addErrback(_check)
- return d
-
- def test_is_remote(self):
- try:
- raise IndexError("local missing key")
- except IndexError:
- localf = Failure()
- self.failIf(rrefutil.is_remote(localf))
- self.failUnless(rrefutil.is_local(localf))
-
- frr = FakeRemoteReference()
- wrr = rrefutil.WrappedRemoteReference(frr)
- d = wrr.callRemote("oops")
- def _check(f):
- self.failUnless(rrefutil.is_remote(f))
- self.failIf(rrefutil.is_local(f))
- d.addErrback(_check)
- return d
-
- def test_trap(self):
- try:
- raise IndexError("local missing key")
- except IndexError:
- localf = Failure()
-
- self.failUnlessRaises(Failure, localf.trap, ValueError, KeyError)
- self.failUnlessRaises(Failure, localf.trap, ServerFailure)
- self.failUnlessEqual(localf.trap(IndexError, KeyError), IndexError)
- self.failUnlessEqual(rrefutil.trap_local(localf, IndexError, KeyError),
- IndexError)
- self.failUnlessRaises(Failure,
- rrefutil.trap_remote, localf, ValueError, KeyError)
-
- frr = FakeRemoteReference()
- wrr = rrefutil.WrappedRemoteReference(frr)
- d = wrr.callRemote("oops")
- def _check(f):
- self.failUnlessRaises(Failure,
- f.trap, ValueError, KeyError)
- self.failUnlessRaises(Failure,
- f.trap, IndexError)
- self.failUnlessEqual(f.trap(ServerFailure), ServerFailure)
- self.failUnlessRaises(Failure,
- rrefutil.trap_remote, f, ValueError, KeyError)
- self.failUnlessEqual(rrefutil.trap_remote(f, IndexError, KeyError),
- IndexError)
- self.failUnlessRaises(Failure,
- rrefutil.trap_local, f, ValueError, KeyError)
- self.failUnlessRaises(Failure,
- rrefutil.trap_local, f, IndexError)
- d.addErrback(_check)
- return d
-
class Pipeline(unittest.TestCase):
def pause(self, *args, **kwargs):
d = defer.Deferred()
self.failUnless(f.check(pipeline.PipelineError))
f2 = f.value.error
self.failUnless(f2.check(ValueError))
-
def test_errors2(self):
self.calls = []
-import exceptions
-from foolscap.api import Violation
+from foolscap.api import Violation, RemoteException
-class ServerFailure(exceptions.Exception):
- # If the server returns a Failure instead of the normal response to a
- # protocol, then this exception will be raised, with the Failure that the
- # server returned as its .remote_failure attribute.
- def __init__(self, remote_failure):
- self.remote_failure = remote_failure
- def __repr__(self):
- return repr(self.remote_failure)
- def __str__(self):
- return str(self.remote_failure)
-
-def is_remote(f):
- if isinstance(f.value, ServerFailure):
- return True
- return False
-
-def is_local(f):
- return not is_remote(f)
-
-def check_remote(f, *errorTypes):
- if is_remote(f):
- return f.value.remote_failure.check(*errorTypes)
- return None
-
-def check_local(f, *errorTypes):
- if is_local(f):
- return f.check(*errorTypes)
- return None
-
-def trap_remote(f, *errorTypes):
- if is_remote(f):
- return f.value.remote_failure.trap(*errorTypes)
- raise f
-
-def trap_local(f, *errorTypes):
- if is_local(f):
- return f.trap(*errorTypes)
- raise f
-
-def _wrap_server_failure(f):
- raise ServerFailure(f)
-
-class WrappedRemoteReference(object):
- """I intercept any errback from the server and wrap it in a
- ServerFailure."""
-
- def __init__(self, original):
- self.rref = original
-
- def callRemote(self, *args, **kwargs):
- d = self.rref.callRemote(*args, **kwargs)
- d.addErrback(_wrap_server_failure)
- return d
-
- def callRemoteOnly(self, *args, **kwargs):
- return self.rref.callRemoteOnly(*args, **kwargs)
-
- def notifyOnDisconnect(self, *args, **kwargs):
- return self.rref.notifyOnDisconnect(*args, **kwargs)
-
- def dontNotifyOnDisconnect(self, *args, **kwargs):
- return self.rref.dontNotifyOnDisconnect(*args, **kwargs)
-
-class VersionedRemoteReference(WrappedRemoteReference):
- """I wrap a RemoteReference, and add a .version attribute. I also
- intercept any errback from the server and wrap it in a ServerFailure."""
-
- def __init__(self, original, version):
- WrappedRemoteReference.__init__(self, original)
- self.version = version
-
-def get_versioned_remote_reference(rref, default):
- """I return a Deferred that fires with a VersionedRemoteReference"""
+def add_version_to_remote_reference(rref, default):
+ """I try to add a .version attribute to the given RemoteReference. I call
+ the remote get_version() method to learn its version. I'll add the
+ default value if the remote side doesn't appear to have a get_version()
+ method."""
d = rref.callRemote("get_version")
- def _no_get_version(f):
- f.trap(Violation, AttributeError)
- return default
- d.addErrback(_no_get_version)
def _got_version(version):
- return VersionedRemoteReference(rref, version)
- d.addCallback(_got_version)
+ rref.version = version
+ return rref
+ def _no_get_version(f):
+ f.trap(Violation, RemoteException)
+ rref.version = default
+ return rref
+ d.addCallbacks(_got_version, _no_get_version)
return d