2006-12-02 02:17:50 +00:00
|
|
|
|
2007-01-05 04:52:51 +00:00
|
|
|
from zope.interface import Interface
|
2006-12-02 02:17:50 +00:00
|
|
|
from foolscap.schema import StringConstraint, ListOf, TupleOf, Any, Nothing
|
|
|
|
from foolscap import RemoteInterface
|
|
|
|
|
2006-12-02 23:26:26 +00:00
|
|
|
Nodeid = StringConstraint(20) # binary format 20-byte SHA1 hash
|
|
|
|
PBURL = StringConstraint(150)
|
|
|
|
Verifierid = StringConstraint(20)
|
2006-12-04 12:14:31 +00:00
|
|
|
ShareData = StringConstraint(100000)
|
2006-12-03 00:25:57 +00:00
|
|
|
# these four are here because Foolscap does not yet support the kind of
|
2006-12-02 02:17:50 +00:00
|
|
|
# restriction I really want to apply to these.
|
2006-12-02 23:03:09 +00:00
|
|
|
RIClient_ = Any()
|
|
|
|
Referenceable_ = Any()
|
|
|
|
RIBucketWriter_ = Any()
|
2006-12-03 00:25:57 +00:00
|
|
|
RIBucketReader_ = Any()
|
2006-12-04 02:07:41 +00:00
|
|
|
RIMutableDirectoryNode_ = Any()
|
|
|
|
RIMutableFileNode_ = Any()
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
class RIQueenRoster(RemoteInterface):
|
|
|
|
def hello(nodeid=Nodeid, node=RIClient_, pburl=PBURL):
|
2006-12-04 02:07:41 +00:00
|
|
|
return RIMutableDirectoryNode_ # the virtual drive root
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
class RIClient(RemoteInterface):
|
|
|
|
def get_service(name=str):
|
|
|
|
return Referenceable_
|
|
|
|
def add_peers(new_peers=ListOf(TupleOf(Nodeid, PBURL), maxLength=100)):
|
2006-12-02 23:03:09 +00:00
|
|
|
return Nothing()
|
2006-12-02 02:17:50 +00:00
|
|
|
def lost_peers(lost_peers=ListOf(Nodeid)):
|
2006-12-02 23:03:09 +00:00
|
|
|
return Nothing()
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
class RIStorageServer(RemoteInterface):
|
2006-12-02 23:26:26 +00:00
|
|
|
def allocate_bucket(verifierid=Verifierid, bucket_num=int, size=int,
|
2006-12-04 02:07:41 +00:00
|
|
|
leaser=Nodeid, canary=Referenceable_):
|
|
|
|
# if the canary is lost before close(), the bucket is deleted
|
2006-12-02 02:17:50 +00:00
|
|
|
return RIBucketWriter_
|
2006-12-03 10:01:43 +00:00
|
|
|
def get_buckets(verifierid=Verifierid):
|
|
|
|
return ListOf(TupleOf(int, RIBucketReader_))
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
class RIBucketWriter(RemoteInterface):
|
2006-12-02 23:03:09 +00:00
|
|
|
def write(data=ShareData):
|
|
|
|
return Nothing()
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
def close():
|
2006-12-02 23:03:09 +00:00
|
|
|
return Nothing()
|
2006-12-02 02:17:50 +00:00
|
|
|
|
|
|
|
|
2006-12-03 00:25:57 +00:00
|
|
|
class RIBucketReader(RemoteInterface):
|
|
|
|
def read():
|
|
|
|
return ShareData
|
|
|
|
|
|
|
|
|
2006-12-04 02:07:41 +00:00
|
|
|
class RIMutableDirectoryNode(RemoteInterface):
|
|
|
|
def list():
|
|
|
|
return ListOf( TupleOf(str, # name, relative to directory
|
|
|
|
(RIMutableDirectoryNode_, Verifierid)),
|
|
|
|
maxLength=100,
|
|
|
|
)
|
|
|
|
|
2006-12-04 11:03:29 +00:00
|
|
|
def get(name=str):
|
|
|
|
return (RIMutableDirectoryNode_, Verifierid)
|
|
|
|
|
2006-12-04 02:07:41 +00:00
|
|
|
def add_directory(name=str):
|
|
|
|
return RIMutableDirectoryNode_
|
|
|
|
|
|
|
|
def add_file(name=str, data=Verifierid):
|
|
|
|
return Nothing()
|
|
|
|
|
|
|
|
def remove(name=str):
|
|
|
|
return Nothing()
|
|
|
|
|
|
|
|
# need more to move directories
|
2006-12-07 21:58:23 +00:00
|
|
|
|
2007-01-05 04:52:51 +00:00
|
|
|
|
|
|
|
class IEncoder(Interface):
|
|
|
|
def set_params(data_size, required_shares, total_shares):
|
|
|
|
"""Set up the parameters of this encoder.
|
|
|
|
|
|
|
|
See encode() for a description of how these parameters are used.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def get_encoder_type():
|
|
|
|
"""Return an integer that describes the type of this encoder.
|
|
|
|
|
|
|
|
There must be a global table of encoder classes. This method returns
|
|
|
|
an index into this table; the value at this index is an encoder
|
|
|
|
class, and this encoder is an instance of that class.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def get_serialized_params(): # TODO: maybe, maybe not
|
|
|
|
"""Return a string that describes the parameters of this encoder.
|
|
|
|
|
|
|
|
This string can be passed to the decoder to prepare it for handling
|
|
|
|
the encoded shares we create. It might contain more information than
|
|
|
|
was presented to set_params(), if there is some flexibility of
|
|
|
|
parameter choice.
|
|
|
|
|
|
|
|
This string is intended to be embedded in the URI, so there are
|
|
|
|
several restrictions on its contents. At the moment I'm thinking that
|
|
|
|
this means it may contain hex digits and colons, and nothing else.
|
|
|
|
The idea is that the URI contains '%d:%s.' %
|
|
|
|
(encoder.get_encoder_type(), encoder.get_serialized_params()), and
|
|
|
|
this is enough information to construct a compatible decoder.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def get_share_size():
|
|
|
|
"""Return the length of the shares that encode() will produce.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def encode(data):
|
|
|
|
"""Encode a chunk of data. This may be called multiple times. Each
|
|
|
|
call is independent.
|
|
|
|
|
|
|
|
The data must be a string with a length that exactly matches the
|
|
|
|
data_size promised by set_params().
|
|
|
|
|
|
|
|
For each call, encode() will return a Deferred that fires with a list
|
|
|
|
of 'total_shares' tuples. Each tuple is of the form (sharenum,
|
|
|
|
share), where sharenum is an int (from 0 total_shares-1), and share
|
|
|
|
is a string. The get_share_size() method can be used to determine the
|
|
|
|
length of the 'share' strings returned by encode().
|
|
|
|
|
|
|
|
The memory usage of this function is expected to be on the order of
|
|
|
|
total_shares * get_share_size().
|
|
|
|
"""
|
|
|
|
|
|
|
|
class IDecoder(Interface):
|
|
|
|
def set_serialized_params(params):
|
|
|
|
"""Set up the parameters of this encoder, from a string returned by
|
|
|
|
encoder.get_serialized_params()."""
|
|
|
|
|
|
|
|
def decode(some_shares):
|
|
|
|
"""Decode a partial list of shares into data.
|
|
|
|
|
|
|
|
'some_shares' must be a list of (sharenum, share) tuples, a subset of
|
|
|
|
the shares returned by IEncoder.encode(). Each share must be of the
|
|
|
|
same length. The share tuples may appear in any order, but of course
|
|
|
|
each tuple must have a sharenum that correctly matches the associated
|
|
|
|
share data string.
|
|
|
|
|
|
|
|
This returns a Deferred which fires with a string. This string will
|
|
|
|
always have a length equal to the 'data_size' value passed into the
|
|
|
|
original IEncoder.set_params() call.
|
|
|
|
|
|
|
|
The length of 'some_shares' must be equal or greater than the value
|
|
|
|
of 'required_shares' passed into the original IEncoder.set_params()
|
|
|
|
call.
|
|
|
|
"""
|