From 0eb6b324a4fcda2f9309b26281250793f95421f1 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Fri, 21 Nov 2008 17:43:52 -0700 Subject: [PATCH] #538: add remote_get_version() to four main Referenceable objects: Introducer Service, Storage Server, Helper, CHK Upload Helper. Remove unused storage-server get_versions(). --- src/allmydata/control.py | 2 +- src/allmydata/interfaces.py | 32 +++++++++++++------------- src/allmydata/introducer/interfaces.py | 4 +++- src/allmydata/introducer/server.py | 8 +++++++ src/allmydata/offloaded.py | 15 ++++++++++++ src/allmydata/storage.py | 13 +++++------ src/allmydata/test/test_client.py | 5 ++-- 7 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/allmydata/control.py b/src/allmydata/control.py index 28e5c615..b566231f 100644 --- a/src/allmydata/control.py +++ b/src/allmydata/control.py @@ -81,7 +81,7 @@ class ControlServer(Referenceable, service.Service): return results peerid, connection = everyone_left.pop(0) start = time.time() - d = connection.callRemote("get_versions") + d = connection.callRemote("get_version") def _done(ignored): stop = time.time() elapsed = stop - start diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py index 798b4baf..bcfbf626 100644 --- a/src/allmydata/interfaces.py +++ b/src/allmydata/interfaces.py @@ -1,7 +1,7 @@ from zope.interface import Interface from foolscap.schema import StringConstraint, ListOf, TupleOf, SetOf, DictOf, \ - ChoiceOf, IntegerConstraint + ChoiceOf, IntegerConstraint, Any from foolscap import RemoteInterface, Referenceable HASH_SIZE=32 @@ -86,21 +86,11 @@ ReadData = ListOf(ShareData) class RIStorageServer(RemoteInterface): __remote_name__ = "RIStorageServer.tahoe.allmydata.com" - def get_versions(): + def get_version(): """ - Return a tuple of (my_version, oldest_supported) strings. Each string can be parsed by - a pyutil.version_class.Version instance or a distutils.version.LooseVersion instance, - and then compared. The first goal is to make sure that nodes are not confused by - speaking to an incompatible peer. The second goal is to enable the development of - backwards-compatibility code. - - The meaning of the oldest_supported element is that if you treat this storage server as - though it were of that version, then you will not be disappointed. - - The precise meaning of this method might change in incompatible ways until we get the - whole compatibility scheme nailed down. + Return a dictionary of version information. """ - return TupleOf(str, str) + return DictOf(str, Any()) def allocate_buckets(storage_index=StorageIndex, renew_secret=LeaseRenewSecret, @@ -351,8 +341,6 @@ class IStorageBucketReader(Interface): # hm, we need a solution for forward references in schemas -from foolscap.schema import Any - FileNode_ = Any() # TODO: foolscap needs constraints on copyables DirectoryNode_ = Any() # TODO: same AnyNode_ = ChoiceOf(FileNode_, DirectoryNode_) @@ -2077,6 +2065,12 @@ class RIEncryptedUploadable(RemoteInterface): class RICHKUploadHelper(RemoteInterface): __remote_name__ = "RIUploadHelper.tahoe.allmydata.com" + def get_version(): + """ + Return a dictionary of version information. + """ + return DictOf(str, Any()) + def upload(reader=RIEncryptedUploadable): return UploadResults @@ -2084,6 +2078,12 @@ class RICHKUploadHelper(RemoteInterface): class RIHelper(RemoteInterface): __remote_name__ = "RIHelper.tahoe.allmydata.com" + def get_version(): + """ + Return a dictionary of version information. + """ + return DictOf(str, Any()) + def upload_chk(si=StorageIndex): """See if a file with a given storage index needs uploading. The helper will ask the appropriate storage servers to see if the file diff --git a/src/allmydata/introducer/interfaces.py b/src/allmydata/introducer/interfaces.py index d084f498..56b87b16 100644 --- a/src/allmydata/introducer/interfaces.py +++ b/src/allmydata/introducer/interfaces.py @@ -1,6 +1,6 @@ from zope.interface import Interface -from foolscap.schema import StringConstraint, TupleOf, SetOf +from foolscap.schema import StringConstraint, TupleOf, SetOf, DictOf, Any from foolscap import RemoteInterface FURL = StringConstraint(1000) @@ -68,6 +68,8 @@ class RIIntroducerSubscriberService(RemoteInterface): class RIIntroducerPublisherAndSubscriberService(RemoteInterface): __remote_name__ = "RIIntroducerPublisherAndSubscriberService.tahoe.allmydata.com" + def get_version(): + return DictOf(str, Any()) def publish(announcement=Announcement): return None def subscribe(subscriber=RIIntroducerSubscriberClient, service_name=str): diff --git a/src/allmydata/introducer/server.py b/src/allmydata/introducer/server.py index c71237a4..3005b54d 100644 --- a/src/allmydata/introducer/server.py +++ b/src/allmydata/introducer/server.py @@ -3,6 +3,7 @@ import time, os.path from zope.interface import implements from twisted.application import service from foolscap import Referenceable +import allmydata from allmydata import node from allmydata.util import log from allmydata.introducer.interfaces import \ @@ -46,6 +47,10 @@ class IntroducerNode(node.Node): class IntroducerService(service.MultiService, Referenceable): implements(RIIntroducerPublisherAndSubscriberService) name = "introducer" + VERSION = { "http://allmydata.org/tahoe/protocols/introducer/v1": + { }, + "application-version": str(allmydata.__version__), + } def __init__(self, basedir="."): service.MultiService.__init__(self) @@ -64,6 +69,9 @@ class IntroducerService(service.MultiService, Referenceable): def get_subscribers(self): return self._subscribers + def remote_get_version(self): + return self.VERSION + def remote_publish(self, announcement): self.log("introducer: announcement published: %s" % (announcement,) ) index = make_index(announcement) diff --git a/src/allmydata/offloaded.py b/src/allmydata/offloaded.py index 52a9f4fe..048203d7 100644 --- a/src/allmydata/offloaded.py +++ b/src/allmydata/offloaded.py @@ -5,6 +5,7 @@ from twisted.application import service from twisted.internet import defer from foolscap import Referenceable, DeadReferenceError from foolscap.eventual import eventually +import allmydata from allmydata import interfaces, storage, uri from allmydata.immutable import upload from allmydata.immutable.layout import ReadBucketProxy @@ -131,6 +132,10 @@ class CHKUploadHelper(Referenceable, upload.CHKUploader): remote AssistedUploader. """ implements(interfaces.RICHKUploadHelper) + VERSION = { "http://allmydata.org/tahoe/protocols/helper/chk-upload/v1" : + { }, + "application-version": str(allmydata.__version__), + } def __init__(self, storage_index, helper, incoming_file, encoding_file, @@ -186,6 +191,9 @@ class CHKUploadHelper(Referenceable, upload.CHKUploader): self.log("no ciphertext yet", level=log.NOISY) return (self._results, self) + def remote_get_version(self): + return self.VERSION + def remote_upload(self, reader): # reader is an RIEncryptedUploadable. I am specified to return an # UploadResults dictionary. @@ -482,6 +490,10 @@ class Helper(Referenceable, service.MultiService): # helper at random. name = "helper" + VERSION = { "http://allmydata.org/tahoe/protocols/helper/v1" : + { }, + "application-version": str(allmydata.__version__), + } chk_upload_helper_class = CHKUploadHelper MAX_UPLOAD_STATUSES = 10 @@ -554,6 +566,9 @@ class Helper(Referenceable, service.MultiService): stats.update(self._counters) return stats + def remote_get_version(self): + return self.VERSION + def remote_upload_chk(self, storage_index): self.count("chk_upload_helper.upload_requests") r = upload.UploadResults() diff --git a/src/allmydata/storage.py b/src/allmydata/storage.py index 7387daef..526de307 100644 --- a/src/allmydata/storage.py +++ b/src/allmydata/storage.py @@ -1,5 +1,4 @@ import os, re, weakref, stat, struct, time -from distutils.version import LooseVersion from foolscap import Referenceable from twisted.application import service @@ -764,10 +763,10 @@ def create_mutable_sharefile(filename, my_nodeid, write_enabler, parent): class StorageServer(service.MultiService, Referenceable): implements(RIStorageServer, IStatsProducer) name = 'storage' - - # This means that if a client treats me as though I were a 1.0.0 storage server, they will - # not be disappointed. - OLDEST_SUPPORTED_VERSION = LooseVersion("1.0.0") + VERSION = { "http://allmydata.org/tahoe/protocols/storage/v1" : + { "maximum-immutable-share-size": 2**32 }, + "application-version": str(allmydata.__version__), + } def __init__(self, storedir, sizelimit=None, discard_storage=False, readonly_storage=False, @@ -899,8 +898,8 @@ class StorageServer(service.MultiService, Referenceable): space += bw.allocated_size() return space - def remote_get_versions(self): - return (str(allmydata.__version__), str(self.OLDEST_SUPPORTED_VERSION)) + def remote_get_version(self): + return self.VERSION def remote_allocate_buckets(self, storage_index, renew_secret, cancel_secret, diff --git a/src/allmydata/test/test_client.py b/src/allmydata/test/test_client.py index 836cd74f..f38cb32a 100644 --- a/src/allmydata/test/test_client.py +++ b/src/allmydata/test/test_client.py @@ -153,8 +153,9 @@ class Basic(unittest.TestCase): open(os.path.join(basedir, "vdrive.furl"), "w").write("") c = client.Client(basedir) ss = c.getServiceNamed("storage") - mine, oldest = ss.remote_get_versions() - self.failUnlessEqual(mine, str(allmydata.__version__)) + verdict = ss.remote_get_version() + self.failUnlessEqual(verdict["application-version"], + str(allmydata.__version__)) self.failIfEqual(str(allmydata.__version__), "unknown") self.failUnless("." in str(allmydata.__version__), "non-numeric version in '%s'" % allmydata.__version__) -- 2.45.2