]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/interfaces.py
Simplify immutable download API: use just filenode.read(consumer, offset, size)
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / interfaces.py
1
2 from zope.interface import Interface
3 from foolscap.api import StringConstraint, ListOf, TupleOf, SetOf, DictOf, \
4      ChoiceOf, IntegerConstraint, Any, RemoteInterface, Referenceable
5
6 HASH_SIZE=32
7
8 Hash = StringConstraint(maxLength=HASH_SIZE,
9                         minLength=HASH_SIZE)# binary format 32-byte SHA256 hash
10 Nodeid = StringConstraint(maxLength=20,
11                           minLength=20) # binary format 20-byte SHA1 hash
12 FURL = StringConstraint(1000)
13 StorageIndex = StringConstraint(16)
14 URI = StringConstraint(300) # kind of arbitrary
15
16 MAX_BUCKETS = 256  # per peer -- zfec offers at most 256 shares per file
17
18 ShareData = StringConstraint(None)
19 URIExtensionData = StringConstraint(1000)
20 Number = IntegerConstraint(8) # 2**(8*8) == 16EiB ~= 18e18 ~= 18 exabytes
21 Offset = Number
22 ReadSize = int # the 'int' constraint is 2**31 == 2Gib -- large files are processed in not-so-large increments
23 WriteEnablerSecret = Hash # used to protect mutable bucket modifications
24 LeaseRenewSecret = Hash # used to protect bucket lease renewal requests
25 LeaseCancelSecret = Hash # used to protect bucket lease cancellation requests
26
27 class RIStubClient(RemoteInterface):
28     """Each client publishes a service announcement for a dummy object called
29     the StubClient. This object doesn't actually offer any services, but the
30     announcement helps the Introducer keep track of which clients are
31     subscribed (so the grid admin can keep track of things like the size of
32     the grid and the client versions in use. This is the (empty)
33     RemoteInterface for the StubClient."""
34
35 class RIBucketWriter(RemoteInterface):
36     """ Objects of this kind live on the server side. """
37     def write(offset=Offset, data=ShareData):
38         return None
39
40     def close():
41         """
42         If the data that has been written is incomplete or inconsistent then
43         the server will throw the data away, else it will store it for future
44         retrieval.
45         """
46         return None
47
48     def abort():
49         """Abandon all the data that has been written.
50         """
51         return None
52
53 class RIBucketReader(RemoteInterface):
54     def read(offset=Offset, length=ReadSize):
55         return ShareData
56
57     def advise_corrupt_share(reason=str):
58         """Clients who discover hash failures in shares that they have
59         downloaded from me will use this method to inform me about the
60         failures. I will record their concern so that my operator can
61         manually inspect the shares in question. I return None.
62
63         This is a wrapper around RIStorageServer.advise_corrupt_share(),
64         which is tied to a specific share, and therefore does not need the
65         extra share-identifying arguments. Please see that method for full
66         documentation.
67         """
68
69 TestVector = ListOf(TupleOf(Offset, ReadSize, str, str))
70 # elements are (offset, length, operator, specimen)
71 # operator is one of "lt, le, eq, ne, ge, gt"
72 # nop always passes and is used to fetch data while writing.
73 # you should use length==len(specimen) for everything except nop
74 DataVector = ListOf(TupleOf(Offset, ShareData))
75 # (offset, data). This limits us to 30 writes of 1MiB each per call
76 TestAndWriteVectorsForShares = DictOf(int,
77                                       TupleOf(TestVector,
78                                               DataVector,
79                                               ChoiceOf(None, Offset), # new_length
80                                               ))
81 ReadVector = ListOf(TupleOf(Offset, ReadSize))
82 ReadData = ListOf(ShareData)
83 # returns data[offset:offset+length] for each element of TestVector
84
85 class RIStorageServer(RemoteInterface):
86     __remote_name__ = "RIStorageServer.tahoe.allmydata.com"
87
88     def get_version():
89         """
90         Return a dictionary of version information.
91         """
92         return DictOf(str, Any())
93
94     def allocate_buckets(storage_index=StorageIndex,
95                          renew_secret=LeaseRenewSecret,
96                          cancel_secret=LeaseCancelSecret,
97                          sharenums=SetOf(int, maxLength=MAX_BUCKETS),
98                          allocated_size=Offset, canary=Referenceable):
99         """
100         @param storage_index: the index of the bucket to be created or
101                               increfed.
102         @param sharenums: these are the share numbers (probably between 0 and
103                           99) that the sender is proposing to store on this
104                           server.
105         @param renew_secret: This is the secret used to protect bucket refresh
106                              This secret is generated by the client and
107                              stored for later comparison by the server. Each
108                              server is given a different secret.
109         @param cancel_secret: Like renew_secret, but protects bucket decref.
110         @param canary: If the canary is lost before close(), the bucket is
111                        deleted.
112         @return: tuple of (alreadygot, allocated), where alreadygot is what we
113                  already have and allocated is what we hereby agree to accept.
114                  New leases are added for shares in both lists.
115         """
116         return TupleOf(SetOf(int, maxLength=MAX_BUCKETS),
117                        DictOf(int, RIBucketWriter, maxKeys=MAX_BUCKETS))
118
119     def add_lease(storage_index=StorageIndex,
120                   renew_secret=LeaseRenewSecret,
121                   cancel_secret=LeaseCancelSecret):
122         """
123         Add a new lease on the given bucket. If the renew_secret matches an
124         existing lease, that lease will be renewed instead. If there is no
125         bucket for the given storage_index, return silently. (note that in
126         tahoe-1.3.0 and earlier, IndexError was raised if there was no
127         bucket)
128         """
129         return Any() # returns None now, but future versions might change
130
131     def renew_lease(storage_index=StorageIndex, renew_secret=LeaseRenewSecret):
132         """
133         Renew the lease on a given bucket, resetting the timer to 31 days.
134         Some networks will use this, some will not. If there is no bucket for
135         the given storage_index, IndexError will be raised.
136
137         For mutable shares, if the given renew_secret does not match an
138         existing lease, IndexError will be raised with a note listing the
139         server-nodeids on the existing leases, so leases on migrated shares
140         can be renewed or cancelled. For immutable shares, IndexError
141         (without the note) will be raised.
142         """
143         return Any()
144
145     def cancel_lease(storage_index=StorageIndex,
146                      cancel_secret=LeaseCancelSecret):
147         """
148         Cancel the lease on a given bucket. If this was the last lease on the
149         bucket, the bucket will be deleted. If there is no bucket for the
150         given storage_index, IndexError will be raised.
151
152         For mutable shares, if the given cancel_secret does not match an
153         existing lease, IndexError will be raised with a note listing the
154         server-nodeids on the existing leases, so leases on migrated shares
155         can be renewed or cancelled. For immutable shares, IndexError
156         (without the note) will be raised.
157         """
158         return Any()
159
160     def get_buckets(storage_index=StorageIndex):
161         return DictOf(int, RIBucketReader, maxKeys=MAX_BUCKETS)
162
163
164
165     def slot_readv(storage_index=StorageIndex,
166                    shares=ListOf(int), readv=ReadVector):
167         """Read a vector from the numbered shares associated with the given
168         storage index. An empty shares list means to return data from all
169         known shares. Returns a dictionary with one key per share."""
170         return DictOf(int, ReadData) # shnum -> results
171
172     def slot_testv_and_readv_and_writev(storage_index=StorageIndex,
173                                         secrets=TupleOf(WriteEnablerSecret,
174                                                         LeaseRenewSecret,
175                                                         LeaseCancelSecret),
176                                         tw_vectors=TestAndWriteVectorsForShares,
177                                         r_vector=ReadVector,
178                                         ):
179         """General-purpose test-and-set operation for mutable slots. Perform
180         a bunch of comparisons against the existing shares. If they all pass,
181         then apply a bunch of write vectors to those shares. Then use the
182         read vectors to extract data from all the shares and return the data.
183
184         This method is, um, large. The goal is to allow clients to update all
185         the shares associated with a mutable file in a single round trip.
186
187         @param storage_index: the index of the bucket to be created or
188                               increfed.
189         @param write_enabler: a secret that is stored along with the slot.
190                               Writes are accepted from any caller who can
191                               present the matching secret. A different secret
192                               should be used for each slot*server pair.
193         @param renew_secret: This is the secret used to protect bucket refresh
194                              This secret is generated by the client and
195                              stored for later comparison by the server. Each
196                              server is given a different secret.
197         @param cancel_secret: Like renew_secret, but protects bucket decref.
198
199         The 'secrets' argument is a tuple of (write_enabler, renew_secret,
200         cancel_secret). The first is required to perform any write. The
201         latter two are used when allocating new shares. To simply acquire a
202         new lease on existing shares, use an empty testv and an empty writev.
203
204         Each share can have a separate test vector (i.e. a list of
205         comparisons to perform). If all vectors for all shares pass, then all
206         writes for all shares are recorded. Each comparison is a 4-tuple of
207         (offset, length, operator, specimen), which effectively does a bool(
208         (read(offset, length)) OPERATOR specimen ) and only performs the
209         write if all these evaluate to True. Basic test-and-set uses 'eq'.
210         Write-if-newer uses a seqnum and (offset, length, 'lt', specimen).
211         Write-if-same-or-newer uses 'le'.
212
213         Reads from the end of the container are truncated, and missing shares
214         behave like empty ones, so to assert that a share doesn't exist (for
215         use when creating a new share), use (0, 1, 'eq', '').
216
217         The write vector will be applied to the given share, expanding it if
218         necessary. A write vector applied to a share number that did not
219         exist previously will cause that share to be created.
220
221         Each write vector is accompanied by a 'new_length' argument. If
222         new_length is not None, use it to set the size of the container. This
223         can be used to pre-allocate space for a series of upcoming writes, or
224         truncate existing data. If the container is growing, new_length will
225         be applied before datav. If the container is shrinking, it will be
226         applied afterwards. If new_length==0, the share will be deleted.
227
228         The read vector is used to extract data from all known shares,
229         *before* any writes have been applied. The same vector is used for
230         all shares. This captures the state that was tested by the test
231         vector.
232
233         This method returns two values: a boolean and a dict. The boolean is
234         True if the write vectors were applied, False if not. The dict is
235         keyed by share number, and each value contains a list of strings, one
236         for each element of the read vector.
237
238         If the write_enabler is wrong, this will raise BadWriteEnablerError.
239         To enable share migration (using update_write_enabler), the exception
240         will have the nodeid used for the old write enabler embedded in it,
241         in the following string::
242
243          The write enabler was recorded by nodeid '%s'.
244
245         Note that the nodeid here is encoded using the same base32 encoding
246         used by Foolscap and allmydata.util.idlib.nodeid_b2a().
247
248         """
249         return TupleOf(bool, DictOf(int, ReadData))
250
251     def advise_corrupt_share(share_type=str, storage_index=StorageIndex,
252                              shnum=int, reason=str):
253         """Clients who discover hash failures in shares that they have
254         downloaded from me will use this method to inform me about the
255         failures. I will record their concern so that my operator can
256         manually inspect the shares in question. I return None.
257
258         'share_type' is either 'mutable' or 'immutable'. 'storage_index' is a
259         (binary) storage index string, and 'shnum' is the integer share
260         number. 'reason' is a human-readable explanation of the problem,
261         probably including some expected hash values and the computed ones
262         which did not match. Corruption advisories for mutable shares should
263         include a hash of the public key (the same value that appears in the
264         mutable-file verify-cap), since the current share format does not
265         store that on disk.
266         """
267
268 class IStorageBucketWriter(Interface):
269     """
270     Objects of this kind live on the client side.
271     """
272     def put_block(segmentnum=int, data=ShareData):
273         """@param data: For most segments, this data will be 'blocksize'
274         bytes in length. The last segment might be shorter.
275         @return: a Deferred that fires (with None) when the operation completes
276         """
277
278     def put_plaintext_hashes(hashes=ListOf(Hash)):
279         """
280         @return: a Deferred that fires (with None) when the operation completes
281         """
282
283     def put_crypttext_hashes(hashes=ListOf(Hash)):
284         """
285         @return: a Deferred that fires (with None) when the operation completes
286         """
287
288     def put_block_hashes(blockhashes=ListOf(Hash)):
289         """
290         @return: a Deferred that fires (with None) when the operation completes
291         """
292
293     def put_share_hashes(sharehashes=ListOf(TupleOf(int, Hash))):
294         """
295         @return: a Deferred that fires (with None) when the operation completes
296         """
297
298     def put_uri_extension(data=URIExtensionData):
299         """This block of data contains integrity-checking information (hashes
300         of plaintext, crypttext, and shares), as well as encoding parameters
301         that are necessary to recover the data. This is a serialized dict
302         mapping strings to other strings. The hash of this data is kept in
303         the URI and verified before any of the data is used. All buckets for
304         a given file contain identical copies of this data.
305
306         The serialization format is specified with the following pseudocode:
307         for k in sorted(dict.keys()):
308             assert re.match(r'^[a-zA-Z_\-]+$', k)
309             write(k + ':' + netstring(dict[k]))
310
311         @return: a Deferred that fires (with None) when the operation completes
312         """
313
314     def close():
315         """Finish writing and close the bucket. The share is not finalized
316         until this method is called: if the uploading client disconnects
317         before calling close(), the partially-written share will be
318         discarded.
319
320         @return: a Deferred that fires (with None) when the operation completes
321         """
322
323 class IStorageBucketReader(Interface):
324
325     def get_block_data(blocknum=int, blocksize=int, size=int):
326         """Most blocks will be the same size. The last block might be shorter
327         than the others.
328
329         @return: ShareData
330         """
331
332     def get_crypttext_hashes():
333         """
334         @return: ListOf(Hash)
335         """
336
337     def get_block_hashes(at_least_these=SetOf(int)):
338         """
339         @return: ListOf(Hash)
340         """
341
342     def get_share_hashes(at_least_these=SetOf(int)):
343         """
344         @return: ListOf(TupleOf(int, Hash))
345         """
346
347     def get_uri_extension():
348         """
349         @return: URIExtensionData
350         """
351
352 class IStorageBroker(Interface):
353     def get_servers_for_index(peer_selection_index):
354         """
355         @return: list of (peerid, versioned-rref) tuples
356         """
357     def get_all_servers():
358         """
359         @return: frozenset of (peerid, versioned-rref) tuples
360         """
361     def get_all_serverids():
362         """
363         @return: frozenset of serverid strings
364         """
365     def get_nickname_for_serverid(serverid):
366         """
367         @return: unicode nickname, or None
368         """
369
370     # methods moved from IntroducerClient, need review
371     def get_all_connections():
372         """Return a frozenset of (nodeid, service_name, rref) tuples, one for
373         each active connection we've established to a remote service. This is
374         mostly useful for unit tests that need to wait until a certain number
375         of connections have been made."""
376
377     def get_all_connectors():
378         """Return a dict that maps from (nodeid, service_name) to a
379         RemoteServiceConnector instance for all services that we are actively
380         trying to connect to. Each RemoteServiceConnector has the following
381         public attributes::
382
383           service_name: the type of service provided, like 'storage'
384           announcement_time: when we first heard about this service
385           last_connect_time: when we last established a connection
386           last_loss_time: when we last lost a connection
387
388           version: the peer's version, from the most recent connection
389           oldest_supported: the peer's oldest supported version, same
390
391           rref: the RemoteReference, if connected, otherwise None
392           remote_host: the IAddress, if connected, otherwise None
393
394         This method is intended for monitoring interfaces, such as a web page
395         which describes connecting and connected peers.
396         """
397
398     def get_all_peerids():
399         """Return a frozenset of all peerids to whom we have a connection (to
400         one or more services) established. Mostly useful for unit tests."""
401
402     def get_all_connections_for(service_name):
403         """Return a frozenset of (nodeid, service_name, rref) tuples, one
404         for each active connection that provides the given SERVICE_NAME."""
405
406     def get_permuted_peers(service_name, key):
407         """Returns an ordered list of (peerid, rref) tuples, selecting from
408         the connections that provide SERVICE_NAME, using a hash-based
409         permutation keyed by KEY. This randomizes the service list in a
410         repeatable way, to distribute load over many peers.
411         """
412
413
414 class IURI(Interface):
415     def init_from_string(uri):
416         """Accept a string (as created by my to_string() method) and populate
417         this instance with its data. I am not normally called directly,
418         please use the module-level uri.from_string() function to convert
419         arbitrary URI strings into IURI-providing instances."""
420
421     def is_readonly():
422         """Return False if this URI be used to modify the data. Return True
423         if this URI cannot be used to modify the data."""
424
425     def is_mutable():
426         """Return True if the data can be modified by *somebody* (perhaps
427         someone who has a more powerful URI than this one)."""
428
429     def get_readonly():
430         """Return another IURI instance, which represents a read-only form of
431         this one. If is_readonly() is True, this returns self."""
432
433     def get_verify_cap():
434         """Return an instance that provides IVerifierURI, which can be used
435         to check on the availability of the file or directory, without
436         providing enough capabilities to actually read or modify the
437         contents. This may return None if the file does not need checking or
438         verification (e.g. LIT URIs).
439         """
440
441     def to_string():
442         """Return a string of printable ASCII characters, suitable for
443         passing into init_from_string."""
444
445 class IVerifierURI(Interface, IURI):
446     def init_from_string(uri):
447         """Accept a string (as created by my to_string() method) and populate
448         this instance with its data. I am not normally called directly,
449         please use the module-level uri.from_string() function to convert
450         arbitrary URI strings into IURI-providing instances."""
451
452     def to_string():
453         """Return a string of printable ASCII characters, suitable for
454         passing into init_from_string."""
455
456 class IDirnodeURI(Interface):
457     """I am a URI which represents a dirnode."""
458
459
460 class IFileURI(Interface):
461     """I am a URI which represents a filenode."""
462     def get_size():
463         """Return the length (in bytes) of the file that I represent."""
464
465 class IImmutableFileURI(IFileURI):
466     pass
467
468 class IMutableFileURI(Interface):
469     """I am a URI which represents a mutable filenode."""
470 class IDirectoryURI(Interface):
471     pass
472 class IReadonlyDirectoryURI(Interface):
473     pass
474
475 class CannotPackUnknownNodeError(Exception):
476     """UnknownNodes (using filecaps from the future that we don't understand)
477     cannot yet be copied safely, so I refuse to copy them."""
478
479 class UnhandledCapTypeError(Exception):
480     """I recognize the cap/URI, but I cannot create an IFilesystemNode for
481     it."""
482
483 class NotDeepImmutableError(Exception):
484     """Deep-immutable directories can only contain deep-immutable children"""
485
486 # The hierarchy looks like this:
487 #  IFilesystemNode
488 #   IFileNode
489 #    IMutableFileNode
490 #    IImmutableFileNode
491 #   IDirectoryNode
492
493 class IFilesystemNode(Interface):
494     def get_cap():
495         """Return the strongest 'cap instance' associated with this node.
496         (writecap for writeable-mutable files/directories, readcap for
497         immutable or readonly-mutable files/directories). To convert this
498         into a string, call .to_string() on the result."""
499
500     def get_readcap():
501         """Return a readonly cap instance for this node. For immutable or
502         readonly nodes, get_cap() and get_readcap() return the same thing."""
503
504     def get_repair_cap():
505         """Return an IURI instance that can be used to repair the file, or
506         None if this node cannot be repaired (either because it is not
507         distributed, like a LIT file, or because the node does not represent
508         sufficient authority to create a repair-cap, like a read-only RSA
509         mutable file node [which cannot create the correct write-enablers]).
510         """
511
512     def get_verify_cap():
513         """Return an IVerifierURI instance that represents the
514         'verifiy/refresh capability' for this node. The holder of this
515         capability will be able to renew the lease for this node, protecting
516         it from garbage-collection. They will also be able to ask a server if
517         it holds a share for the file or directory.
518         """
519
520     def get_uri():
521         """
522         Return the URI string that can be used by others to get access to
523         this node. If this node is read-only, the URI will only offer
524         read-only access. If this node is read-write, the URI will offer
525         read-write access.
526
527         If you have read-write access to a node and wish to share merely
528         read-only access with others, use get_readonly_uri().
529         """
530
531     def get_readonly_uri():
532         """Return the URI string that can be used by others to get read-only
533         access to this node. The result is a read-only URI, regardless of
534         whether this node is read-only or read-write.
535
536         If you have merely read-only access to this node, get_readonly_uri()
537         will return the same thing as get_uri().
538         """
539
540     def get_storage_index():
541         """Return a string with the (binary) storage index in use on this
542         download. This may be None if there is no storage index (i.e. LIT
543         files)."""
544
545     def is_readonly():
546         """Return True if this reference provides mutable access to the given
547         file or directory (i.e. if you can modify it), or False if not. Note
548         that even if this reference is read-only, someone else may hold a
549         read-write reference to it."""
550
551     def is_mutable():
552         """Return True if this file or directory is mutable (by *somebody*,
553         not necessarily you), False if it is is immutable. Note that a file
554         might be mutable overall, but your reference to it might be
555         read-only. On the other hand, all references to an immutable file
556         will be read-only; there are no read-write references to an immutable
557         file.
558         """
559
560     def get_size():
561         """Return the length (in bytes) of the data this node represents. For
562         directory nodes, I return the size of the backing store. I return
563         synchronously and do not consult the network, so for mutable objects,
564         I will return the most recently observed size for the object, or None
565         if I don't remember a size. Use get_current_size, which returns a
566         Deferred, if you want more up-to-date information."""
567
568     def get_current_size():
569         """I return a Deferred that fires with the length (in bytes) of the
570         data this node represents.
571         """
572
573 class IFileNode(IFilesystemNode):
574     """I am a node which represents a file: a sequence of bytes. I am not a
575     container, like IDirectoryNode."""
576
577 class IImmutableFileNode(IFileNode):
578     def read(consumer, offset=0, size=None):
579         """Download a portion (possibly all) of the file's contents, making
580         them available to the given IConsumer. Return a Deferred that fires
581         (with the consumer) when the consumer is unregistered (either because
582         the last byte has been given to it, or because the consumer threw an
583         exception during write(), possibly because it no longer wants to
584         receive data). The portion downloaded will start at 'offset' and
585         contain 'size' bytes (or the remainder of the file if size==None).
586
587         The consumer will be used in non-streaming mode: an IPullProducer
588         will be attached to it.
589
590         The consumer will not receive data right away: several network trips
591         must occur first. The order of events will be::
592
593          consumer.registerProducer(p, streaming)
594           (if streaming == False)::
595            consumer does p.resumeProducing()
596             consumer.write(data)
597            consumer does p.resumeProducing()
598             consumer.write(data).. (repeat until all data is written)
599          consumer.unregisterProducer()
600          deferred.callback(consumer)
601
602         If a download error occurs, or an exception is raised by
603         consumer.registerProducer() or consumer.write(), I will call
604         consumer.unregisterProducer() and then deliver the exception via
605         deferred.errback(). To cancel the download, the consumer should call
606         p.stopProducing(), which will result in an exception being delivered
607         via deferred.errback().
608
609         See src/allmydata/util/consumer.py for an example of a simple
610         download-to-memory consumer.
611         """
612
613 class IMutableFileNode(IFileNode):
614     """I provide access to a 'mutable file', which retains its identity
615     regardless of what contents are put in it.
616
617     The consistency-vs-availability problem means that there might be
618     multiple versions of a file present in the grid, some of which might be
619     unrecoverable (i.e. have fewer than 'k' shares). These versions are
620     loosely ordered: each has a sequence number and a hash, and any version
621     with seqnum=N was uploaded by a node which has seen at least one version
622     with seqnum=N-1.
623
624     The 'servermap' (an instance of IMutableFileServerMap) is used to
625     describe the versions that are known to be present in the grid, and which
626     servers are hosting their shares. It is used to represent the 'state of
627     the world', and is used for this purpose by my test-and-set operations.
628     Downloading the contents of the mutable file will also return a
629     servermap. Uploading a new version into the mutable file requires a
630     servermap as input, and the semantics of the replace operation is
631     'replace the file with my new version if it looks like nobody else has
632     changed the file since my previous download'. Because the file is
633     distributed, this is not a perfect test-and-set operation, but it will do
634     its best. If the replace process sees evidence of a simultaneous write,
635     it will signal an UncoordinatedWriteError, so that the caller can take
636     corrective action.
637
638
639     Most readers will want to use the 'best' current version of the file, and
640     should use my 'download_best_version()' method.
641
642     To unconditionally replace the file, callers should use overwrite(). This
643     is the mode that user-visible mutable files will probably use.
644
645     To apply some delta to the file, call modify() with a callable modifier
646     function that can apply the modification that you want to make. This is
647     the mode that dirnodes will use, since most directory modification
648     operations can be expressed in terms of deltas to the directory state.
649
650
651     Three methods are available for users who need to perform more complex
652     operations. The first is get_servermap(), which returns an up-to-date
653     servermap using a specified mode. The second is download_version(), which
654     downloads a specific version (not necessarily the 'best' one). The third
655     is 'upload', which accepts new contents and a servermap (which must have
656     been updated with MODE_WRITE). The upload method will attempt to apply
657     the new contents as long as no other node has modified the file since the
658     servermap was updated. This might be useful to a caller who wants to
659     merge multiple versions into a single new one.
660
661     Note that each time the servermap is updated, a specific 'mode' is used,
662     which determines how many peers are queried. To use a servermap for my
663     replace() method, that servermap must have been updated in MODE_WRITE.
664     These modes are defined in allmydata.mutable.common, and consist of
665     MODE_READ, MODE_WRITE, MODE_ANYTHING, and MODE_CHECK. Please look in
666     allmydata/mutable/servermap.py for details about the differences.
667
668     Mutable files are currently limited in size (about 3.5MB max) and can
669     only be retrieved and updated all-at-once, as a single big string. Future
670     versions of our mutable files will remove this restriction.
671     """
672
673     def download_best_version():
674         """Download the 'best' available version of the file, meaning one of
675         the recoverable versions with the highest sequence number. If no
676         uncoordinated writes have occurred, and if enough shares are
677         available, then this will be the most recent version that has been
678         uploaded.
679
680         I update an internal servermap with MODE_READ, determine which
681         version of the file is indicated by
682         servermap.best_recoverable_version(), and return a Deferred that
683         fires with its contents. If no version is recoverable, the Deferred
684         will errback with UnrecoverableFileError.
685         """
686
687     def get_size_of_best_version():
688         """Find the size of the version that would be downloaded with
689         download_best_version(), without actually downloading the whole file.
690
691         I return a Deferred that fires with an integer.
692         """
693
694     def overwrite(new_contents):
695         """Unconditionally replace the contents of the mutable file with new
696         ones. This simply chains get_servermap(MODE_WRITE) and upload(). This
697         is only appropriate to use when the new contents of the file are
698         completely unrelated to the old ones, and you do not care about other
699         clients' changes.
700
701         I return a Deferred that fires (with a PublishStatus object) when the
702         update has completed.
703         """
704
705     def modify(modifier_cb):
706         """Modify the contents of the file, by downloading the current
707         version, applying the modifier function (or bound method), then
708         uploading the new version. I return a Deferred that fires (with a
709         PublishStatus object) when the update is complete.
710
711         The modifier callable will be given three arguments: a string (with
712         the old contents), a 'first_time' boolean, and a servermap. As with
713         download_best_version(), the old contents will be from the best
714         recoverable version, but the modifier can use the servermap to make
715         other decisions (such as refusing to apply the delta if there are
716         multiple parallel versions, or if there is evidence of a newer
717         unrecoverable version). 'first_time' will be True the first time the
718         modifier is called, and False on any subsequent calls.
719
720         The callable should return a string with the new contents. The
721         callable must be prepared to be called multiple times, and must
722         examine the input string to see if the change that it wants to make
723         is already present in the old version. If it does not need to make
724         any changes, it can either return None, or return its input string.
725
726         If the modifier raises an exception, it will be returned in the
727         errback.
728         """
729
730
731     def get_servermap(mode):
732         """Return a Deferred that fires with an IMutableFileServerMap
733         instance, updated using the given mode.
734         """
735
736     def download_version(servermap, version):
737         """Download a specific version of the file, using the servermap
738         as a guide to where the shares are located.
739
740         I return a Deferred that fires with the requested contents, or
741         errbacks with UnrecoverableFileError. Note that a servermap which was
742         updated with MODE_ANYTHING or MODE_READ may not know about shares for
743         all versions (those modes stop querying servers as soon as they can
744         fulfil their goals), so you may want to use MODE_CHECK (which checks
745         everything) to get increased visibility.
746         """
747
748     def upload(new_contents, servermap):
749         """Replace the contents of the file with new ones. This requires a
750         servermap that was previously updated with MODE_WRITE.
751
752         I attempt to provide test-and-set semantics, in that I will avoid
753         modifying any share that is different than the version I saw in the
754         servermap. However, if another node is writing to the file at the
755         same time as me, I may manage to update some shares while they update
756         others. If I see any evidence of this, I will signal
757         UncoordinatedWriteError, and the file will be left in an inconsistent
758         state (possibly the version you provided, possibly the old version,
759         possibly somebody else's version, and possibly a mix of shares from
760         all of these).
761
762         The recommended response to UncoordinatedWriteError is to either
763         return it to the caller (since they failed to coordinate their
764         writes), or to attempt some sort of recovery. It may be sufficient to
765         wait a random interval (with exponential backoff) and repeat your
766         operation. If I do not signal UncoordinatedWriteError, then I was
767         able to write the new version without incident.
768
769         I return a Deferred that fires (with a PublishStatus object) when the
770         publish has completed. I will update the servermap in-place with the
771         location of all new shares.
772         """
773
774     def get_writekey():
775         """Return this filenode's writekey, or None if the node does not have
776         write-capability. This may be used to assist with data structures
777         that need to make certain data available only to writers, such as the
778         read-write child caps in dirnodes. The recommended process is to have
779         reader-visible data be submitted to the filenode in the clear (where
780         it will be encrypted by the filenode using the readkey), but encrypt
781         writer-visible data using this writekey.
782         """
783
784 class NotEnoughSharesError(Exception):
785     """Download was unable to get enough shares, or upload was unable to
786     place 'shares_of_happiness' shares."""
787
788 class NoSharesError(Exception):
789     """Upload or Download was unable to get any shares at all."""
790
791 class UnableToFetchCriticalDownloadDataError(Exception):
792     """I was unable to fetch some piece of critical data which is supposed to
793     be identically present in all shares."""
794
795 class NoServersError(Exception):
796     """Upload wasn't given any servers to work with, usually indicating a
797     network or Introducer problem."""
798
799 class ExistingChildError(Exception):
800     """A directory node was asked to add or replace a child that already
801     exists, and overwrite= was set to False."""
802
803 class NoSuchChildError(Exception):
804     """A directory node was asked to fetch a child which does not exist."""
805
806 class IDirectoryNode(IFilesystemNode):
807     """I represent a filesystem node that is a container, with a
808     name-to-child mapping, holding the tahoe equivalent of a directory. All
809     child names are unicode strings, and all children are some sort of
810     IFilesystemNode (either files or subdirectories).
811     """
812
813     def get_uri():
814         """
815         The dirnode ('1') URI returned by this method can be used in
816         set_uri() on a different directory ('2') to 'mount' a reference to
817         this directory ('1') under the other ('2'). This URI is just a
818         string, so it can be passed around through email or other out-of-band
819         protocol.
820         """
821
822     def get_readonly_uri():
823         """
824         The dirnode ('1') URI returned by this method can be used in
825         set_uri() on a different directory ('2') to 'mount' a reference to
826         this directory ('1') under the other ('2'). This URI is just a
827         string, so it can be passed around through email or other out-of-band
828         protocol.
829         """
830
831     def list():
832         """I return a Deferred that fires with a dictionary mapping child
833         name (a unicode string) to (node, metadata_dict) tuples, in which
834         'node' is an IFilesystemNode (either IFileNode or IDirectoryNode),
835         and 'metadata_dict' is a dictionary of metadata."""
836
837     def has_child(name):
838         """I return a Deferred that fires with a boolean, True if there
839         exists a child of the given name, False if not. The child name must
840         be a unicode string."""
841
842     def get(name):
843         """I return a Deferred that fires with a specific named child node,
844         either an IFileNode or an IDirectoryNode. The child name must be a
845         unicode string. I raise NoSuchChildError if I do not have a child by
846         that name."""
847
848     def get_metadata_for(name):
849         """I return a Deferred that fires with the metadata dictionary for a
850         specific named child node. This metadata is stored in the *edge*, not
851         in the child, so it is attached to the parent dirnode rather than the
852         child dir-or-file-node. The child name must be a unicode string. I
853         raise NoSuchChildError if I do not have a child by that name."""
854
855     def set_metadata_for(name, metadata):
856         """I replace any existing metadata for the named child with the new
857         metadata. The child name must be a unicode string. This metadata is
858         stored in the *edge*, not in the child, so it is attached to the
859         parent dirnode rather than the child dir-or-file-node. I return a
860         Deferred (that fires with this dirnode) when the operation is
861         complete. I raise NoSuchChildError if I do not have a child by that
862         name."""
863
864     def get_child_at_path(path):
865         """Transform a child path into an IFilesystemNode.
866
867         I perform a recursive series of 'get' operations to find the named
868         descendant node. I return a Deferred that fires with the node, or
869         errbacks with NoSuchChildError if the node could not be found.
870
871         The path can be either a single string (slash-separated) or a list of
872         path-name elements. All elements must be unicode strings.
873         """
874
875     def get_child_and_metadata_at_path(path):
876         """Transform a child path into an IFilesystemNode and metadata.
877
878         I am like get_child_at_path(), but my Deferred fires with a tuple of
879         (node, metadata). The metadata comes from the last edge. If the path
880         is empty, the metadata will be an empty dictionary.
881         """
882
883     def set_uri(name, writecap, readcap=None, metadata=None, overwrite=True):
884         """I add a child (by writecap+readcap) at the specific name. I return
885         a Deferred that fires when the operation finishes. If overwrite= is
886         True, I will replace any existing child of the same name, otherwise
887         an existing child will cause me to return ExistingChildError. The
888         child name must be a unicode string.
889
890         The child caps could be for a file, or for a directory. If the new
891         child is read/write, you will provide both writecap and readcap. If
892         the child is read-only, you will provide the readcap write (i.e. the
893         writecap= and readcap= arguments will both be the child's readcap).
894         The filecaps are typically obtained from an IFilesystemNode with
895         get_uri() and get_readonly_uri().
896
897         If metadata= is provided, I will use it as the metadata for the named
898         edge. This will replace any existing metadata. If metadata= is left
899         as the default value of None, I will set ['mtime'] to the current
900         time, and I will set ['ctime'] to the current time if there was not
901         already a child by this name present. This roughly matches the
902         ctime/mtime semantics of traditional filesystems.
903
904         If this directory node is read-only, the Deferred will errback with a
905         NotMutableError."""
906
907     def set_children(entries, overwrite=True):
908         """Add multiple children (by writecap+readcap) to a directory node.
909         Takes a dictionary, with childname as keys and (writecap, readcap)
910         tuples (or (writecap, readcap, metadata) triples) as values. Returns
911         a Deferred that fires (with this dirnode) when the operation
912         finishes. This is equivalent to calling set_uri() multiple times, but
913         is much more efficient. All child names must be unicode strings.
914         """
915
916     def set_node(name, child, metadata=None, overwrite=True):
917         """I add a child at the specific name. I return a Deferred that fires
918         when the operation finishes. This Deferred will fire with the child
919         node that was just added. I will replace any existing child of the
920         same name. The child name must be a unicode string. The 'child'
921         instance must be an instance providing IFilesystemNode.
922
923         If metadata= is provided, I will use it as the metadata for the named
924         edge. This will replace any existing metadata. If metadata= is left
925         as the default value of None, I will set ['mtime'] to the current
926         time, and I will set ['ctime'] to the current time if there was not
927         already a child by this name present. This roughly matches the
928         ctime/mtime semantics of traditional filesystems.
929
930         If this directory node is read-only, the Deferred will errback with a
931         NotMutableError."""
932
933     def set_nodes(entries, overwrite=True):
934         """Add multiple children to a directory node. Takes a dict mapping
935         unicode childname to (child_node, metdata) tuples. If metdata=None,
936         the original metadata is left unmodified. Returns a Deferred that
937         fires (with this dirnode) when the operation finishes. This is
938         equivalent to calling set_node() multiple times, but is much more
939         efficient."""
940
941     def add_file(name, uploadable, metadata=None, overwrite=True):
942         """I upload a file (using the given IUploadable), then attach the
943         resulting ImmutableFileNode to the directory at the given name. I set
944         metadata the same way as set_uri and set_node. The child name must be
945         a unicode string.
946
947         I return a Deferred that fires (with the IFileNode of the uploaded
948         file) when the operation completes."""
949
950     def delete(name):
951         """I remove the child at the specific name. I return a Deferred that
952         fires when the operation finishes. The child name must be a unicode
953         string. I raise NoSuchChildError if I do not have a child by that
954         name."""
955
956     def create_subdirectory(name, initial_children={}, overwrite=True):
957         """I create and attach a directory at the given name. The new
958         directory can be empty, or it can be populated with children
959         according to 'initial_children', which takes a dictionary in the same
960         format as set_nodes (i.e. mapping unicode child name to (childnode,
961         metadata) tuples). The child name must be a unicode string. I return
962         a Deferred that fires (with the new directory node) when the
963         operation finishes."""
964
965     def move_child_to(current_child_name, new_parent, new_child_name=None,
966                       overwrite=True):
967         """I take one of my children and move them to a new parent. The child
968         is referenced by name. On the new parent, the child will live under
969         'new_child_name', which defaults to 'current_child_name'. TODO: what
970         should we do about metadata? I return a Deferred that fires when the
971         operation finishes. The child name must be a unicode string. I raise
972         NoSuchChildError if I do not have a child by that name."""
973
974     def build_manifest():
975         """I generate a table of everything reachable from this directory.
976         I also compute deep-stats as described below.
977
978         I return a Monitor. The Monitor's results will be a dictionary with
979         four elements:
980
981          res['manifest']: a list of (path, cap) tuples for all nodes
982                           (directories and files) reachable from this one.
983                           'path' will be a tuple of unicode strings. The
984                           origin dirnode will be represented by an empty path
985                           tuple.
986          res['verifycaps']: a list of (printable) verifycap strings, one for
987                             each reachable non-LIT node. This is a set:
988                             it will contain no duplicates.
989          res['storage-index']: a list of (base32) storage index strings,
990                                one for each reachable non-LIT node. This is
991                                a set: it will contain no duplicates.
992          res['stats']: a dictionary, the same that is generated by
993                        start_deep_stats() below.
994
995         The Monitor will also have an .origin_si attribute with the (binary)
996         storage index of the starting point.
997         """
998
999     def start_deep_stats():
1000         """Return a Monitor, examining all nodes (directories and files)
1001         reachable from this one. The Monitor's results will be a dictionary
1002         with the following keys::
1003
1004            count-immutable-files: count of how many CHK files are in the set
1005            count-mutable-files: same, for mutable files (does not include
1006                                 directories)
1007            count-literal-files: same, for LIT files
1008            count-files: sum of the above three
1009
1010            count-directories: count of directories
1011
1012            size-immutable-files: total bytes for all CHK files in the set
1013            size-mutable-files (TODO): same, for current version of all mutable
1014                                       files, does not include directories
1015            size-literal-files: same, for LIT files
1016            size-directories: size of mutable files used by directories
1017
1018            largest-directory: number of bytes in the largest directory
1019            largest-directory-children: number of children in the largest
1020                                        directory
1021            largest-immutable-file: number of bytes in the largest CHK file
1022
1023         size-mutable-files is not yet implemented, because it would involve
1024         even more queries than deep_stats does.
1025
1026         The Monitor will also have an .origin_si attribute with the (binary)
1027         storage index of the starting point.
1028
1029         This operation will visit every directory node underneath this one,
1030         and can take a long time to run. On a typical workstation with good
1031         bandwidth, this can examine roughly 15 directories per second (and
1032         takes several minutes of 100% CPU for ~1700 directories).
1033         """
1034
1035 class ICodecEncoder(Interface):
1036     def set_params(data_size, required_shares, max_shares):
1037         """Set up the parameters of this encoder.
1038
1039         This prepares the encoder to perform an operation that converts a
1040         single block of data into a number of shares, such that a future
1041         ICodecDecoder can use a subset of these shares to recover the
1042         original data. This operation is invoked by calling encode(). Once
1043         the encoding parameters are set up, the encode operation can be
1044         invoked multiple times.
1045
1046         set_params() prepares the encoder to accept blocks of input data that
1047         are exactly 'data_size' bytes in length. The encoder will be prepared
1048         to produce 'max_shares' shares for each encode() operation (although
1049         see the 'desired_share_ids' to use less CPU). The encoding math will
1050         be chosen such that the decoder can get by with as few as
1051         'required_shares' of these shares and still reproduce the original
1052         data. For example, set_params(1000, 5, 5) offers no redundancy at
1053         all, whereas set_params(1000, 1, 10) provides 10x redundancy.
1054
1055         Numerical Restrictions: 'data_size' is required to be an integral
1056         multiple of 'required_shares'. In general, the caller should choose
1057         required_shares and max_shares based upon their reliability
1058         requirements and the number of peers available (the total storage
1059         space used is roughly equal to max_shares*data_size/required_shares),
1060         then choose data_size to achieve the memory footprint desired (larger
1061         data_size means more efficient operation, smaller data_size means
1062         smaller memory footprint).
1063
1064         In addition, 'max_shares' must be equal to or greater than
1065         'required_shares'. Of course, setting them to be equal causes
1066         encode() to degenerate into a particularly slow form of the 'split'
1067         utility.
1068
1069         See encode() for more details about how these parameters are used.
1070
1071         set_params() must be called before any other ICodecEncoder methods
1072         may be invoked.
1073         """
1074
1075     def get_params():
1076         """Return the 3-tuple of data_size, required_shares, max_shares"""
1077
1078     def get_encoder_type():
1079         """Return a short string that describes the type of this encoder.
1080
1081         There is required to be a global table of encoder classes. This method
1082         returns an index into this table; the value at this index is an
1083         encoder class, and this encoder is an instance of that class.
1084         """
1085
1086     def get_block_size():
1087         """Return the length of the shares that encode() will produce.
1088         """
1089
1090     def encode_proposal(data, desired_share_ids=None):
1091         """Encode some data.
1092
1093         'data' must be a string (or other buffer object), and len(data) must
1094         be equal to the 'data_size' value passed earlier to set_params().
1095
1096         This will return a Deferred that will fire with two lists. The first
1097         is a list of shares, each of which is a string (or other buffer
1098         object) such that len(share) is the same as what get_share_size()
1099         returned earlier. The second is a list of shareids, in which each is
1100         an integer. The lengths of the two lists will always be equal to each
1101         other. The user should take care to keep each share closely
1102         associated with its shareid, as one is useless without the other.
1103
1104         The length of this output list will normally be the same as the value
1105         provided to the 'max_shares' parameter of set_params(). This may be
1106         different if 'desired_share_ids' is provided.
1107
1108         'desired_share_ids', if provided, is required to be a sequence of
1109         ints, each of which is required to be >= 0 and < max_shares. If not
1110         provided, encode() will produce 'max_shares' shares, as if
1111         'desired_share_ids' were set to range(max_shares). You might use this
1112         if you initially thought you were going to use 10 peers, started
1113         encoding, and then two of the peers dropped out: you could use
1114         desired_share_ids= to skip the work (both memory and CPU) of
1115         producing shares for the peers which are no longer available.
1116
1117         """
1118
1119     def encode(inshares, desired_share_ids=None):
1120         """Encode some data. This may be called multiple times. Each call is
1121         independent.
1122
1123         inshares is a sequence of length required_shares, containing buffers
1124         (i.e. strings), where each buffer contains the next contiguous
1125         non-overlapping segment of the input data. Each buffer is required to
1126         be the same length, and the sum of the lengths of the buffers is
1127         required to be exactly the data_size promised by set_params(). (This
1128         implies that the data has to be padded before being passed to
1129         encode(), unless of course it already happens to be an even multiple
1130         of required_shares in length.)
1131
1132          ALSO: the requirement to break up your data into 'required_shares'
1133          chunks before calling encode() feels a bit surprising, at least from
1134          the point of view of a user who doesn't know how FEC works. It feels
1135          like an implementation detail that has leaked outside the
1136          abstraction barrier. Can you imagine a use case in which the data to
1137          be encoded might already be available in pre-segmented chunks, such
1138          that it is faster or less work to make encode() take a list rather
1139          than splitting a single string?
1140
1141          ALSO ALSO: I think 'inshares' is a misleading term, since encode()
1142          is supposed to *produce* shares, so what it *accepts* should be
1143          something other than shares. Other places in this interface use the
1144          word 'data' for that-which-is-not-shares.. maybe we should use that
1145          term?
1146
1147         'desired_share_ids', if provided, is required to be a sequence of
1148         ints, each of which is required to be >= 0 and < max_shares. If not
1149         provided, encode() will produce 'max_shares' shares, as if
1150         'desired_share_ids' were set to range(max_shares). You might use this
1151         if you initially thought you were going to use 10 peers, started
1152         encoding, and then two of the peers dropped out: you could use
1153         desired_share_ids= to skip the work (both memory and CPU) of
1154         producing shares for the peers which are no longer available.
1155
1156         For each call, encode() will return a Deferred that fires with two
1157         lists, one containing shares and the other containing the shareids.
1158         The get_share_size() method can be used to determine the length of
1159         the share strings returned by encode(). Each shareid is a small
1160         integer, exactly as passed into 'desired_share_ids' (or
1161         range(max_shares), if desired_share_ids was not provided).
1162
1163         The shares and their corresponding shareids are required to be kept
1164         together during storage and retrieval. Specifically, the share data is
1165         useless by itself: the decoder needs to be told which share is which
1166         by providing it with both the shareid and the actual share data.
1167
1168         This function will allocate an amount of memory roughly equal to::
1169
1170          (max_shares - required_shares) * get_share_size()
1171
1172         When combined with the memory that the caller must allocate to
1173         provide the input data, this leads to a memory footprint roughly
1174         equal to the size of the resulting encoded shares (i.e. the expansion
1175         factor times the size of the input segment).
1176         """
1177
1178         # rejected ideas:
1179         #
1180         #  returning a list of (shareidN,shareN) tuples instead of a pair of
1181         #  lists (shareids..,shares..). Brian thought the tuples would
1182         #  encourage users to keep the share and shareid together throughout
1183         #  later processing, Zooko pointed out that the code to iterate
1184         #  through two lists is not really more complicated than using a list
1185         #  of tuples and there's also a performance improvement
1186         #
1187         #  having 'data_size' not required to be an integral multiple of
1188         #  'required_shares'. Doing this would require encode() to perform
1189         #  padding internally, and we'd prefer to have any padding be done
1190         #  explicitly by the caller. Yes, it is an abstraction leak, but
1191         #  hopefully not an onerous one.
1192
1193
1194 class ICodecDecoder(Interface):
1195     def set_params(data_size, required_shares, max_shares):
1196         """Set the params. They have to be exactly the same ones that were
1197         used for encoding."""
1198
1199     def get_needed_shares():
1200         """Return the number of shares needed to reconstruct the data.
1201         set_params() is required to be called before this."""
1202
1203     def decode(some_shares, their_shareids):
1204         """Decode a partial list of shares into data.
1205
1206         'some_shares' is required to be a sequence of buffers of sharedata, a
1207         subset of the shares returned by ICodecEncode.encode(). Each share is
1208         required to be of the same length.  The i'th element of their_shareids
1209         is required to be the shareid of the i'th buffer in some_shares.
1210
1211         This returns a Deferred which fires with a sequence of buffers. This
1212         sequence will contain all of the segments of the original data, in
1213         order. The sum of the lengths of all of the buffers will be the
1214         'data_size' value passed into the original ICodecEncode.set_params()
1215         call. To get back the single original input block of data, use
1216         ''.join(output_buffers), or you may wish to simply write them in
1217         order to an output file.
1218
1219         Note that some of the elements in the result sequence may be
1220         references to the elements of the some_shares input sequence. In
1221         particular, this means that if those share objects are mutable (e.g.
1222         arrays) and if they are changed, then both the input (the
1223         'some_shares' parameter) and the output (the value given when the
1224         deferred is triggered) will change.
1225
1226         The length of 'some_shares' is required to be exactly the value of
1227         'required_shares' passed into the original ICodecEncode.set_params()
1228         call.
1229         """
1230
1231 class IEncoder(Interface):
1232     """I take an object that provides IEncryptedUploadable, which provides
1233     encrypted data, and a list of shareholders. I then encode, hash, and
1234     deliver shares to those shareholders. I will compute all the necessary
1235     Merkle hash trees that are necessary to validate the crypttext that
1236     eventually comes back from the shareholders. I provide the URI Extension
1237     Block Hash, and the encoding parameters, both of which must be included
1238     in the URI.
1239
1240     I do not choose shareholders, that is left to the IUploader. I must be
1241     given a dict of RemoteReferences to storage buckets that are ready and
1242     willing to receive data.
1243     """
1244
1245     def set_size(size):
1246         """Specify the number of bytes that will be encoded. This must be
1247         peformed before get_serialized_params() can be called.
1248         """
1249     def set_params(params):
1250         """Override the default encoding parameters. 'params' is a tuple of
1251         (k,d,n), where 'k' is the number of required shares, 'd' is the
1252         shares_of_happiness, and 'n' is the total number of shares that will
1253         be created.
1254
1255         Encoding parameters can be set in three ways. 1: The Encoder class
1256         provides defaults (3/7/10). 2: the Encoder can be constructed with
1257         an 'options' dictionary, in which the
1258         needed_and_happy_and_total_shares' key can be a (k,d,n) tuple. 3:
1259         set_params((k,d,n)) can be called.
1260
1261         If you intend to use set_params(), you must call it before
1262         get_share_size or get_param are called.
1263         """
1264
1265     def set_encrypted_uploadable(u):
1266         """Provide a source of encrypted upload data. 'u' must implement
1267         IEncryptedUploadable.
1268
1269         When this is called, the IEncryptedUploadable will be queried for its
1270         length and the storage_index that should be used.
1271
1272         This returns a Deferred that fires with this Encoder instance.
1273
1274         This must be performed before start() can be called.
1275         """
1276
1277     def get_param(name):
1278         """Return an encoding parameter, by name.
1279
1280         'storage_index': return a string with the (16-byte truncated SHA-256
1281                          hash) storage index to which these shares should be
1282                          pushed.
1283
1284         'share_counts': return a tuple describing how many shares are used:
1285                         (needed_shares, shares_of_happiness, total_shares)
1286
1287         'num_segments': return an int with the number of segments that
1288                         will be encoded.
1289
1290         'segment_size': return an int with the size of each segment.
1291
1292         'block_size': return the size of the individual blocks that will
1293                       be delivered to a shareholder's put_block() method. By
1294                       knowing this, the shareholder will be able to keep all
1295                       blocks in a single file and still provide random access
1296                       when reading them. # TODO: can we avoid exposing this?
1297
1298         'share_size': an int with the size of the data that will be stored
1299                       on each shareholder. This is aggregate amount of data
1300                       that will be sent to the shareholder, summed over all
1301                       the put_block() calls I will ever make. It is useful to
1302                       determine this size before asking potential
1303                       shareholders whether they will grant a lease or not,
1304                       since their answers will depend upon how much space we
1305                       need. TODO: this might also include some amount of
1306                       overhead, like the size of all the hashes. We need to
1307                       decide whether this is useful or not.
1308
1309         'serialized_params': a string with a concise description of the
1310                              codec name and its parameters. This may be passed
1311                              into the IUploadable to let it make sure that
1312                              the same file encoded with different parameters
1313                              will result in different storage indexes.
1314
1315         Once this is called, set_size() and set_params() may not be called.
1316         """
1317
1318     def set_shareholders(shareholders):
1319         """Tell the encoder where to put the encoded shares. 'shareholders'
1320         must be a dictionary that maps share number (an integer ranging from
1321         0 to n-1) to an instance that provides IStorageBucketWriter. This
1322         must be performed before start() can be called."""
1323
1324     def start():
1325         """Begin the encode/upload process. This involves reading encrypted
1326         data from the IEncryptedUploadable, encoding it, uploading the shares
1327         to the shareholders, then sending the hash trees.
1328
1329         set_encrypted_uploadable() and set_shareholders() must be called
1330         before this can be invoked.
1331
1332         This returns a Deferred that fires with a verify cap when the upload
1333         process is complete. The verifycap, plus the encryption key, is
1334         sufficient to construct the read cap.
1335         """
1336
1337 class IDecoder(Interface):
1338     """I take a list of shareholders and some setup information, then
1339     download, validate, decode, and decrypt data from them, writing the
1340     results to an output file.
1341
1342     I do not locate the shareholders, that is left to the IDownloader. I must
1343     be given a dict of RemoteReferences to storage buckets that are ready to
1344     send data.
1345     """
1346
1347     def setup(outfile):
1348         """I take a file-like object (providing write and close) to which all
1349         the plaintext data will be written.
1350
1351         TODO: producer/consumer . Maybe write() should return a Deferred that
1352         indicates when it will accept more data? But probably having the
1353         IDecoder be a producer is easier to glue to IConsumer pieces.
1354         """
1355
1356     def set_shareholders(shareholders):
1357         """I take a dictionary that maps share identifiers (small integers)
1358         to RemoteReferences that provide RIBucketReader. This must be called
1359         before start()."""
1360
1361     def start():
1362         """I start the download. This process involves retrieving data and
1363         hash chains from the shareholders, using the hashes to validate the
1364         data, decoding the shares into segments, decrypting the segments,
1365         then writing the resulting plaintext to the output file.
1366
1367         I return a Deferred that will fire (with self) when the download is
1368         complete.
1369         """
1370
1371 class IDownloadTarget(Interface):
1372     # Note that if the IDownloadTarget is also an IConsumer, the downloader
1373     # will register itself as a producer. This allows the target to invoke
1374     # downloader.pauseProducing, resumeProducing, and stopProducing.
1375     def open(size):
1376         """Called before any calls to write() or close(). If an error
1377         occurs before any data is available, fail() may be called without
1378         a previous call to open().
1379
1380         'size' is the length of the file being downloaded, in bytes."""
1381
1382     def write(data):
1383         """Output some data to the target."""
1384     def close():
1385         """Inform the target that there is no more data to be written."""
1386     def fail(why):
1387         """fail() is called to indicate that the download has failed. 'why'
1388         is a Failure object indicating what went wrong. No further methods
1389         will be invoked on the IDownloadTarget after fail()."""
1390     def register_canceller(cb):
1391         """The CiphertextDownloader uses this to register a no-argument function
1392         that the target can call to cancel the download. Once this canceller
1393         is invoked, no further calls to write() or close() will be made."""
1394     def finish():
1395         """When the CiphertextDownloader is done, this finish() function will be
1396         called. Whatever it returns will be returned to the invoker of
1397         Downloader.download.
1398         """
1399     # The following methods are just because that target might be a
1400     # repairer.DownUpConnector, and just because the current CHKUpload object
1401     # expects to find the storage index and encoding parameters in its
1402     # Uploadable.
1403     def set_storageindex(storageindex):
1404         """ Set the storage index. """
1405     def set_encodingparams(encodingparams):
1406         """ Set the encoding parameters. """
1407
1408 class IDownloader(Interface):
1409     def download(uri, target):
1410         """Perform a CHK download, sending the data to the given target.
1411         'target' must provide IDownloadTarget.
1412
1413         Returns a Deferred that fires (with the results of target.finish)
1414         when the download is finished, or errbacks if something went wrong."""
1415
1416 class IEncryptedUploadable(Interface):
1417     def set_upload_status(upload_status):
1418         """Provide an IUploadStatus object that should be filled with status
1419         information. The IEncryptedUploadable is responsible for setting
1420         key-determination progress ('chk'), size, storage_index, and
1421         ciphertext-fetch progress. It may delegate some of this
1422         responsibility to others, in particular to the IUploadable."""
1423
1424     def get_size():
1425         """This behaves just like IUploadable.get_size()."""
1426
1427     def get_all_encoding_parameters():
1428         """Return a Deferred that fires with a tuple of
1429         (k,happy,n,segment_size). The segment_size will be used as-is, and
1430         must match the following constraints: it must be a multiple of k, and
1431         it shouldn't be unreasonably larger than the file size (if
1432         segment_size is larger than filesize, the difference must be stored
1433         as padding).
1434
1435         This usually passes through to the IUploadable method of the same
1436         name.
1437
1438         The encoder strictly obeys the values returned by this method. To
1439         make an upload use non-default encoding parameters, you must arrange
1440         to control the values that this method returns.
1441         """
1442
1443     def get_storage_index():
1444         """Return a Deferred that fires with a 16-byte storage index.
1445         """
1446
1447     def read_encrypted(length, hash_only):
1448         """This behaves just like IUploadable.read(), but returns crypttext
1449         instead of plaintext. If hash_only is True, then this discards the
1450         data (and returns an empty list); this improves efficiency when
1451         resuming an interrupted upload (where we need to compute the
1452         plaintext hashes, but don't need the redundant encrypted data)."""
1453
1454     def get_plaintext_hashtree_leaves(first, last, num_segments):
1455         """OBSOLETE; Get the leaf nodes of a merkle hash tree over the
1456         plaintext segments, i.e. get the tagged hashes of the given segments.
1457         The segment size is expected to be generated by the
1458         IEncryptedUploadable before any plaintext is read or ciphertext
1459         produced, so that the segment hashes can be generated with only a
1460         single pass.
1461
1462         This returns a Deferred which fires with a sequence of hashes, using:
1463
1464          tuple(segment_hashes[first:last])
1465
1466         'num_segments' is used to assert that the number of segments that the
1467         IEncryptedUploadable handled matches the number of segments that the
1468         encoder was expecting.
1469
1470         This method must not be called until the final byte has been read
1471         from read_encrypted(). Once this method is called, read_encrypted()
1472         can never be called again.
1473         """
1474
1475     def get_plaintext_hash():
1476         """OBSOLETE; Get the hash of the whole plaintext.
1477
1478         This returns a Deferred which fires with a tagged SHA-256 hash of the
1479         whole plaintext, obtained from hashutil.plaintext_hash(data).
1480         """
1481
1482     def close():
1483         """Just like IUploadable.close()."""
1484
1485 class IUploadable(Interface):
1486     def set_upload_status(upload_status):
1487         """Provide an IUploadStatus object that should be filled with status
1488         information. The IUploadable is responsible for setting
1489         key-determination progress ('chk')."""
1490
1491     def set_default_encoding_parameters(params):
1492         """Set the default encoding parameters, which must be a dict mapping
1493         strings to ints. The meaningful keys are 'k', 'happy', 'n', and
1494         'max_segment_size'. These might have an influence on the final
1495         encoding parameters returned by get_all_encoding_parameters(), if the
1496         Uploadable doesn't have more specific preferences.
1497
1498         This call is optional: if it is not used, the Uploadable will use
1499         some built-in defaults. If used, this method must be called before
1500         any other IUploadable methods to have any effect.
1501         """
1502
1503     def get_size():
1504         """Return a Deferred that will fire with the length of the data to be
1505         uploaded, in bytes. This will be called before the data is actually
1506         used, to compute encoding parameters.
1507         """
1508
1509     def get_all_encoding_parameters():
1510         """Return a Deferred that fires with a tuple of
1511         (k,happy,n,segment_size). The segment_size will be used as-is, and
1512         must match the following constraints: it must be a multiple of k, and
1513         it shouldn't be unreasonably larger than the file size (if
1514         segment_size is larger than filesize, the difference must be stored
1515         as padding).
1516
1517         The relative values of k and n allow some IUploadables to request
1518         better redundancy than others (in exchange for consuming more space
1519         in the grid).
1520
1521         Larger values of segment_size reduce hash overhead, while smaller
1522         values reduce memory footprint and cause data to be delivered in
1523         smaller pieces (which may provide a smoother and more predictable
1524         download experience).
1525
1526         The encoder strictly obeys the values returned by this method. To
1527         make an upload use non-default encoding parameters, you must arrange
1528         to control the values that this method returns. One way to influence
1529         them may be to call set_encoding_parameters() before calling
1530         get_all_encoding_parameters().
1531         """
1532
1533     def get_encryption_key():
1534         """Return a Deferred that fires with a 16-byte AES key. This key will
1535         be used to encrypt the data. The key will also be hashed to derive
1536         the StorageIndex.
1537
1538         Uploadables which want to achieve convergence should hash their file
1539         contents and the serialized_encoding_parameters to form the key
1540         (which of course requires a full pass over the data). Uploadables can
1541         use the upload.ConvergentUploadMixin class to achieve this
1542         automatically.
1543
1544         Uploadables which do not care about convergence (or do not wish to
1545         make multiple passes over the data) can simply return a
1546         strongly-random 16 byte string.
1547
1548         get_encryption_key() may be called multiple times: the IUploadable is
1549         required to return the same value each time.
1550         """
1551
1552     def read(length):
1553         """Return a Deferred that fires with a list of strings (perhaps with
1554         only a single element) which, when concatenated together, contain the
1555         next 'length' bytes of data. If EOF is near, this may provide fewer
1556         than 'length' bytes. The total number of bytes provided by read()
1557         before it signals EOF must equal the size provided by get_size().
1558
1559         If the data must be acquired through multiple internal read
1560         operations, returning a list instead of a single string may help to
1561         reduce string copies.
1562
1563         'length' will typically be equal to (min(get_size(),1MB)/req_shares),
1564         so a 10kB file means length=3kB, 100kB file means length=30kB,
1565         and >=1MB file means length=300kB.
1566
1567         This method provides for a single full pass through the data. Later
1568         use cases may desire multiple passes or access to only parts of the
1569         data (such as a mutable file making small edits-in-place). This API
1570         will be expanded once those use cases are better understood.
1571         """
1572
1573     def close():
1574         """The upload is finished, and whatever filehandle was in use may be
1575         closed."""
1576
1577 class IUploadResults(Interface):
1578     """I am returned by upload() methods. I contain a number of public
1579     attributes which can be read to determine the results of the upload. Some
1580     of these are functional, some are timing information. All of these may be
1581     None.
1582
1583      .file_size : the size of the file, in bytes
1584      .uri : the CHK read-cap for the file
1585      .ciphertext_fetched : how many bytes were fetched by the helper
1586      .sharemap: dict mapping share identifier to set of serverids
1587                    (binary strings). This indicates which servers were given
1588                    which shares. For immutable files, the shareid is an
1589                    integer (the share number, from 0 to N-1). For mutable
1590                    files, it is a string of the form 'seq%d-%s-sh%d',
1591                    containing the sequence number, the roothash, and the
1592                    share number.
1593      .servermap : dict mapping server peerid to a set of share numbers
1594      .timings : dict of timing information, mapping name to seconds (float)
1595        total : total upload time, start to finish
1596        storage_index : time to compute the storage index
1597        peer_selection : time to decide which peers will be used
1598        contacting_helper : initial helper query to upload/no-upload decision
1599        existence_check : helper pre-upload existence check
1600        helper_total : initial helper query to helper finished pushing
1601        cumulative_fetch : helper waiting for ciphertext requests
1602        total_fetch : helper start to last ciphertext response
1603        cumulative_encoding : just time spent in zfec
1604        cumulative_sending : just time spent waiting for storage servers
1605        hashes_and_close : last segment push to shareholder close
1606        total_encode_and_push : first encode to shareholder close
1607
1608     """
1609
1610 class IDownloadResults(Interface):
1611     """I am created internally by download() methods. I contain a number of
1612     public attributes which contain details about the download process.::
1613
1614      .file_size : the size of the file, in bytes
1615      .servers_used : set of server peerids that were used during download
1616      .server_problems : dict mapping server peerid to a problem string. Only
1617                         servers that had problems (bad hashes, disconnects)
1618                         are listed here.
1619      .servermap : dict mapping server peerid to a set of share numbers. Only
1620                   servers that had any shares are listed here.
1621      .timings : dict of timing information, mapping name to seconds (float)
1622        peer_selection : time to ask servers about shares
1623        servers_peer_selection : dict of peerid to DYHB-query time
1624        uri_extension : time to fetch a copy of the URI extension block
1625        hashtrees : time to fetch the hash trees
1626        segments : time to fetch, decode, and deliver segments
1627        cumulative_fetch : time spent waiting for storage servers
1628        cumulative_decode : just time spent in zfec
1629        cumulative_decrypt : just time spent in decryption
1630        total : total download time, start to finish
1631        fetch_per_server : dict of peerid to list of per-segment fetch times
1632
1633     """
1634
1635 class IUploader(Interface):
1636     def upload(uploadable):
1637         """Upload the file. 'uploadable' must impement IUploadable. This
1638         returns a Deferred which fires with an IUploadResults instance, from
1639         which the URI of the file can be obtained as results.uri ."""
1640
1641     def upload_ssk(write_capability, new_version, uploadable):
1642         """TODO: how should this work?"""
1643
1644 class ICheckable(Interface):
1645     def check(monitor, verify=False, add_lease=False):
1646         """Check upon my health, optionally repairing any problems.
1647
1648         This returns a Deferred that fires with an instance that provides
1649         ICheckResults, or None if the object is non-distributed (i.e. LIT
1650         files).
1651
1652         The monitor will be checked periodically to see if the operation has
1653         been cancelled. If so, no new queries will be sent, and the Deferred
1654         will fire (with a OperationCancelledError) immediately.
1655
1656         Filenodes and dirnodes (which provide IFilesystemNode) are also
1657         checkable. Instances that represent verifier-caps will be checkable
1658         but not downloadable. Some objects (like LIT files) do not actually
1659         live in the grid, and their checkers return None (non-distributed
1660         files are always healthy).
1661
1662         If verify=False, a relatively lightweight check will be performed: I
1663         will ask all servers if they have a share for me, and I will believe
1664         whatever they say. If there are at least N distinct shares on the
1665         grid, my results will indicate r.is_healthy()==True. This requires a
1666         roundtrip to each server, but does not transfer very much data, so
1667         the network bandwidth is fairly low.
1668
1669         If verify=True, a more resource-intensive check will be performed:
1670         every share will be downloaded, and the hashes will be validated on
1671         every bit. I will ignore any shares that failed their hash checks. If
1672         there are at least N distinct valid shares on the grid, my results
1673         will indicate r.is_healthy()==True. This requires N/k times as much
1674         download bandwidth (and server disk IO) as a regular download. If a
1675         storage server is holding a corrupt share, or is experiencing memory
1676         failures during retrieval, or is malicious or buggy, then
1677         verification will detect the problem, but checking will not.
1678
1679         If add_lease=True, I will ensure that an up-to-date lease is present
1680         on each share. The lease secrets will be derived from by node secret
1681         (in BASEDIR/private/secret), so either I will add a new lease to the
1682         share, or I will merely renew the lease that I already had. In a
1683         future version of the storage-server protocol (once Accounting has
1684         been implemented), there may be additional options here to define the
1685         kind of lease that is obtained (which account number to claim, etc).
1686
1687         TODO: any problems seen during checking will be reported to the
1688         health-manager.furl, a centralized object which is responsible for
1689         figuring out why files are unhealthy so corrective action can be
1690         taken.
1691         """
1692
1693     def check_and_repair(monitor, verify=False, add_lease=False):
1694         """Like check(), but if the file/directory is not healthy, attempt to
1695         repair the damage.
1696
1697         Any non-healthy result will cause an immediate repair operation, to
1698         generate and upload new shares. After repair, the file will be as
1699         healthy as we can make it. Details about what sort of repair is done
1700         will be put in the check-and-repair results. The Deferred will not
1701         fire until the repair is complete.
1702
1703         This returns a Deferred which fires with an instance of
1704         ICheckAndRepairResults."""
1705
1706 class IDeepCheckable(Interface):
1707     def start_deep_check(verify=False, add_lease=False):
1708         """Check upon the health of me and everything I can reach.
1709
1710         This is a recursive form of check(), useable only on dirnodes.
1711
1712         I return a Monitor, with results that are an IDeepCheckResults
1713         object.
1714
1715         TODO: If any of the directories I traverse are unrecoverable, the
1716         Monitor will report failure. If any of the files I check upon are
1717         unrecoverable, those problems will be reported in the
1718         IDeepCheckResults as usual, and the Monitor will not report a
1719         failure.
1720         """
1721
1722     def start_deep_check_and_repair(verify=False, add_lease=False):
1723         """Check upon the health of me and everything I can reach. Repair
1724         anything that isn't healthy.
1725
1726         This is a recursive form of check_and_repair(), useable only on
1727         dirnodes.
1728
1729         I return a Monitor, with results that are an
1730         IDeepCheckAndRepairResults object.
1731
1732         TODO: If any of the directories I traverse are unrecoverable, the
1733         Monitor will report failure. If any of the files I check upon are
1734         unrecoverable, those problems will be reported in the
1735         IDeepCheckResults as usual, and the Monitor will not report a
1736         failure.
1737         """
1738
1739 class ICheckResults(Interface):
1740     """I contain the detailed results of a check/verify operation.
1741     """
1742
1743     def get_storage_index():
1744         """Return a string with the (binary) storage index."""
1745     def get_storage_index_string():
1746         """Return a string with the (printable) abbreviated storage index."""
1747     def get_uri():
1748         """Return the (string) URI of the object that was checked."""
1749
1750     def is_healthy():
1751         """Return a boolean, True if the file/dir is fully healthy, False if
1752         it is damaged in any way. Non-distributed LIT files always return
1753         True."""
1754
1755     def is_recoverable():
1756         """Return a boolean, True if the file/dir can be recovered, False if
1757         not. Unrecoverable files are obviously unhealthy. Non-distributed LIT
1758         files always return True."""
1759
1760     def needs_rebalancing():
1761         """Return a boolean, True if the file/dir's reliability could be
1762         improved by moving shares to new servers. Non-distributed LIT files
1763         always return False."""
1764
1765
1766     def get_data():
1767         """Return a dictionary that describes the state of the file/dir. LIT
1768         files always return an empty dictionary. Normal files and directories
1769         return a dictionary with the following keys (note that these use
1770         binary strings rather than base32-encoded ones) (also note that for
1771         mutable files, these counts are for the 'best' version):
1772
1773          count-shares-good: the number of distinct good shares that were found
1774          count-shares-needed: 'k', the number of shares required for recovery
1775          count-shares-expected: 'N', the number of total shares generated
1776          count-good-share-hosts: the number of distinct storage servers with
1777                                  good shares. If this number is less than
1778                                  count-shares-good, then some shares are
1779                                  doubled up, increasing the correlation of
1780                                  failures. This indicates that one or more
1781                                  shares should be moved to an otherwise unused
1782                                  server, if one is available.
1783          count-corrupt-shares: the number of shares with integrity failures
1784          list-corrupt-shares: a list of 'share locators', one for each share
1785                               that was found to be corrupt. Each share
1786                               locator is a list of (serverid, storage_index,
1787                               sharenum).
1788          count-incompatible-shares: the number of shares which are of a share
1789                                     format unknown to this checker
1790          list-incompatible-shares: a list of 'share locators', one for each
1791                                    share that was found to be of an unknown
1792                                    format. Each share locator is a list of
1793                                    (serverid, storage_index, sharenum).
1794          servers-responding: list of (binary) storage server identifiers,
1795                              one for each server which responded to the share
1796                              query (even if they said they didn't have
1797                              shares, and even if they said they did have
1798                              shares but then didn't send them when asked, or
1799                              dropped the connection, or returned a Failure,
1800                              and even if they said they did have shares and
1801                              sent incorrect ones when asked)
1802          sharemap: dict mapping share identifier to list of serverids
1803                    (binary strings). This indicates which servers are holding
1804                    which shares. For immutable files, the shareid is an
1805                    integer (the share number, from 0 to N-1). For mutable
1806                    files, it is a string of the form 'seq%d-%s-sh%d',
1807                    containing the sequence number, the roothash, and the
1808                    share number.
1809
1810         The following keys are most relevant for mutable files, but immutable
1811         files will provide sensible values too::
1812
1813          count-wrong-shares: the number of shares for versions other than the
1814                              'best' one (which is defined as being the
1815                              recoverable version with the highest sequence
1816                              number, then the highest roothash). These are
1817                              either leftover shares from an older version
1818                              (perhaps on a server that was offline when an
1819                              update occurred), shares from an unrecoverable
1820                              newer version, or shares from an alternate
1821                              current version that results from an
1822                              uncoordinated write collision. For a healthy
1823                              file, this will equal 0.
1824
1825          count-recoverable-versions: the number of recoverable versions of
1826                                      the file. For a healthy file, this will
1827                                      equal 1.
1828
1829          count-unrecoverable-versions: the number of unrecoverable versions
1830                                        of the file. For a healthy file, this
1831                                        will be 0.
1832
1833         """
1834
1835     def get_summary():
1836         """Return a string with a brief (one-line) summary of the results."""
1837
1838     def get_report():
1839         """Return a list of strings with more detailed results."""
1840
1841 class ICheckAndRepairResults(Interface):
1842     """I contain the detailed results of a check/verify/repair operation.
1843
1844     The IFilesystemNode.check()/verify()/repair() methods all return
1845     instances that provide ICheckAndRepairResults.
1846     """
1847
1848     def get_storage_index():
1849         """Return a string with the (binary) storage index."""
1850     def get_storage_index_string():
1851         """Return a string with the (printable) abbreviated storage index."""
1852     def get_repair_attempted():
1853         """Return a boolean, True if a repair was attempted. We might not
1854         attempt to repair the file because it was healthy, or healthy enough
1855         (i.e. some shares were missing but not enough to exceed some
1856         threshold), or because we don't know how to repair this object."""
1857     def get_repair_successful():
1858         """Return a boolean, True if repair was attempted and the file/dir
1859         was fully healthy afterwards. False if no repair was attempted or if
1860         a repair attempt failed."""
1861     def get_pre_repair_results():
1862         """Return an ICheckResults instance that describes the state of the
1863         file/dir before any repair was attempted."""
1864     def get_post_repair_results():
1865         """Return an ICheckResults instance that describes the state of the
1866         file/dir after any repair was attempted. If no repair was attempted,
1867         the pre-repair and post-repair results will be identical."""
1868
1869
1870 class IDeepCheckResults(Interface):
1871     """I contain the results of a deep-check operation.
1872
1873     This is returned by a call to ICheckable.deep_check().
1874     """
1875
1876     def get_root_storage_index_string():
1877         """Return the storage index (abbreviated human-readable string) of
1878         the first object checked."""
1879     def get_counters():
1880         """Return a dictionary with the following keys::
1881
1882              count-objects-checked: count of how many objects were checked
1883              count-objects-healthy: how many of those objects were completely
1884                                     healthy
1885              count-objects-unhealthy: how many were damaged in some way
1886              count-objects-unrecoverable: how many were unrecoverable
1887              count-corrupt-shares: how many shares were found to have
1888                                    corruption, summed over all objects
1889                                    examined
1890         """
1891
1892     def get_corrupt_shares():
1893         """Return a set of (serverid, storage_index, sharenum) for all shares
1894         that were found to be corrupt. Both serverid and storage_index are
1895         binary.
1896         """
1897     def get_all_results():
1898         """Return a dictionary mapping pathname (a tuple of strings, ready to
1899         be slash-joined) to an ICheckResults instance, one for each object
1900         that was checked."""
1901
1902     def get_results_for_storage_index(storage_index):
1903         """Retrive the ICheckResults instance for the given (binary)
1904         storage index. Raises KeyError if there are no results for that
1905         storage index."""
1906
1907     def get_stats():
1908         """Return a dictionary with the same keys as
1909         IDirectoryNode.deep_stats()."""
1910
1911 class IDeepCheckAndRepairResults(Interface):
1912     """I contain the results of a deep-check-and-repair operation.
1913
1914     This is returned by a call to ICheckable.deep_check_and_repair().
1915     """
1916
1917     def get_root_storage_index_string():
1918         """Return the storage index (abbreviated human-readable string) of
1919         the first object checked."""
1920     def get_counters():
1921         """Return a dictionary with the following keys::
1922
1923              count-objects-checked: count of how many objects were checked
1924              count-objects-healthy-pre-repair: how many of those objects were
1925                                                completely healthy (before any
1926                                                repair)
1927              count-objects-unhealthy-pre-repair: how many were damaged in
1928                                                  some way
1929              count-objects-unrecoverable-pre-repair: how many were unrecoverable
1930              count-objects-healthy-post-repair: how many of those objects were
1931                                                 completely healthy (after any
1932                                                 repair)
1933              count-objects-unhealthy-post-repair: how many were damaged in
1934                                                   some way
1935              count-objects-unrecoverable-post-repair: how many were
1936                                                       unrecoverable
1937              count-repairs-attempted: repairs were attempted on this many
1938                                       objects. The count-repairs- keys will
1939                                       always be provided, however unless
1940                                       repair=true is present, they will all
1941                                       be zero.
1942              count-repairs-successful: how many repairs resulted in healthy
1943                                        objects
1944              count-repairs-unsuccessful: how many repairs resulted did not
1945                                          results in completely healthy objects
1946              count-corrupt-shares-pre-repair: how many shares were found to
1947                                               have corruption, summed over all
1948                                               objects examined (before any
1949                                               repair)
1950              count-corrupt-shares-post-repair: how many shares were found to
1951                                                have corruption, summed over all
1952                                                objects examined (after any
1953                                                repair)
1954         """
1955
1956     def get_stats():
1957         """Return a dictionary with the same keys as
1958         IDirectoryNode.deep_stats()."""
1959
1960     def get_corrupt_shares():
1961         """Return a set of (serverid, storage_index, sharenum) for all shares
1962         that were found to be corrupt before any repair was attempted. Both
1963         serverid and storage_index are binary.
1964         """
1965     def get_remaining_corrupt_shares():
1966         """Return a set of (serverid, storage_index, sharenum) for all shares
1967         that were found to be corrupt after any repair was completed. Both
1968         serverid and storage_index are binary. These are shares that need
1969         manual inspection and probably deletion.
1970         """
1971     def get_all_results():
1972         """Return a dictionary mapping pathname (a tuple of strings, ready to
1973         be slash-joined) to an ICheckAndRepairResults instance, one for each
1974         object that was checked."""
1975
1976     def get_results_for_storage_index(storage_index):
1977         """Retrive the ICheckAndRepairResults instance for the given (binary)
1978         storage index. Raises KeyError if there are no results for that
1979         storage index."""
1980
1981
1982 class IRepairable(Interface):
1983     def repair(check_results):
1984         """Attempt to repair the given object. Returns a Deferred that fires
1985         with a IRepairResults object.
1986
1987         I must be called with an object that implements ICheckResults, as
1988         proof that you have actually discovered a problem with this file. I
1989         will use the data in the checker results to guide the repair process,
1990         such as which servers provided bad data and should therefore be
1991         avoided. The ICheckResults object is inside the
1992         ICheckAndRepairResults object, which is returned by the
1993         ICheckable.check() method::
1994
1995          d = filenode.check(repair=False)
1996          def _got_results(check_and_repair_results):
1997              check_results = check_and_repair_results.get_pre_repair_results()
1998              return filenode.repair(check_results)
1999          d.addCallback(_got_results)
2000          return d
2001         """
2002
2003 class IRepairResults(Interface):
2004     """I contain the results of a repair operation."""
2005
2006
2007 class IClient(Interface):
2008     def upload(uploadable):
2009         """Upload some data into a CHK, get back the UploadResults for it.
2010         @param uploadable: something that implements IUploadable
2011         @return: a Deferred that fires with the UploadResults instance.
2012                  To get the URI for this file, use results.uri .
2013         """
2014
2015     def create_mutable_file(contents=""):
2016         """Create a new mutable file (with initial) contents, get back the
2017         URI string.
2018
2019         @param contents: (bytestring, callable, or None): this provides the
2020         initial contents of the mutable file. If 'contents' is a bytestring,
2021         it will be used as-is. If 'contents' is a callable, it will be
2022         invoked with the new MutableFileNode instance and is expected to
2023         return a bytestring with the initial contents of the file (the
2024         callable can use node.get_writekey() to decide how to encrypt the
2025         initial contents, e.g. for a brand new dirnode with initial
2026         children). contents=None is equivalent to an empty string. Using
2027         content_maker= is more efficient than creating a mutable file and
2028         setting its contents in two separate operations.
2029
2030         @return: a Deferred that fires with tne (string) SSK URI for the new
2031                  file.
2032         """
2033
2034     def create_dirnode(initial_children={}):
2035         """Create a new unattached dirnode, possibly with initial children.
2036
2037         @param initial_children: dict with keys that are unicode child names,
2038         and values that are (childnode, metadata) tuples.
2039
2040         @return: a Deferred that fires with the new IDirectoryNode instance.
2041         """
2042
2043     def create_node_from_uri(uri, rouri):
2044         """Create a new IFilesystemNode instance from the uri, synchronously.
2045         @param uri: a string or IURI-providing instance, or None. This could
2046                     be for a LiteralFileNode, a CHK file node, a mutable file
2047                     node, or a directory node
2048         @param rouri: a string or IURI-providing instance, or None. If the
2049                       main uri is None, I will use the rouri instead. If I
2050                       recognize the format of the main uri, I will ignore the
2051                       rouri (because it can be derived from the writecap).
2052
2053         @return: an instance that provides IFilesystemNode (or more usefully
2054                  one of its subclasses). File-specifying URIs will result in
2055                  IFileNode-providing instances, like ImmutableFileNode,
2056                  LiteralFileNode, or MutableFileNode. Directory-specifying
2057                  URIs will result in IDirectoryNode-providing instances, like
2058                  DirectoryNode.
2059         """
2060
2061 class INodeMaker(Interface):
2062     """The NodeMaker is used to create IFilesystemNode instances. It can
2063     accept a filecap/dircap string and return the node right away. It can
2064     also create new nodes (i.e. upload a file, or create a mutable file)
2065     asynchronously. Once you have one of these nodes, you can use other
2066     methods to determine whether it is a file or directory, and to download
2067     or modify its contents.
2068
2069     The NodeMaker encapsulates all the authorities that these
2070     IFilesystemNodes require (like references to the StorageFarmBroker). Each
2071     Tahoe process will typically have a single NodeMaker, but unit tests may
2072     create simplified/mocked forms for testing purposes.
2073     """
2074     def create_from_cap(writecap, readcap=None):
2075         """I create an IFilesystemNode from the given writecap/readcap. I can
2076         only provide nodes for existing file/directory objects: use my other
2077         methods to create new objects. I return synchronously."""
2078
2079     def create_mutable_file(contents=None, keysize=None):
2080         """I create a new mutable file, and return a Deferred which will fire
2081         with the IMutableFileNode instance when it is ready. If contents= is
2082         provided (a bytestring), it will be used as the initial contents of
2083         the new file, otherwise the file will contain zero bytes. keysize= is
2084         for use by unit tests, to create mutable files that are smaller than
2085         usual."""
2086
2087     def create_new_mutable_directory(initial_children={}):
2088         """I create a new mutable directory, and return a Deferred which will
2089         fire with the IDirectoryNode instance when it is ready. If
2090         initial_children= is provided (a dict mapping unicode child name to
2091         (childnode, metadata_dict) tuples), the directory will be populated
2092         with those children, otherwise it will be empty."""
2093
2094 class IClientStatus(Interface):
2095     def list_all_uploads():
2096         """Return a list of uploader objects, one for each upload which
2097         currently has an object available (tracked with weakrefs). This is
2098         intended for debugging purposes."""
2099     def list_active_uploads():
2100         """Return a list of active IUploadStatus objects."""
2101     def list_recent_uploads():
2102         """Return a list of IUploadStatus objects for the most recently
2103         started uploads."""
2104
2105     def list_all_downloads():
2106         """Return a list of downloader objects, one for each download which
2107         currently has an object available (tracked with weakrefs). This is
2108         intended for debugging purposes."""
2109     def list_active_downloads():
2110         """Return a list of active IDownloadStatus objects."""
2111     def list_recent_downloads():
2112         """Return a list of IDownloadStatus objects for the most recently
2113         started downloads."""
2114
2115 class IUploadStatus(Interface):
2116     def get_started():
2117         """Return a timestamp (float with seconds since epoch) indicating
2118         when the operation was started."""
2119     def get_storage_index():
2120         """Return a string with the (binary) storage index in use on this
2121         upload. Returns None if the storage index has not yet been
2122         calculated."""
2123     def get_size():
2124         """Return an integer with the number of bytes that will eventually
2125         be uploaded for this file. Returns None if the size is not yet known.
2126         """
2127     def using_helper():
2128         """Return True if this upload is using a Helper, False if not."""
2129     def get_status():
2130         """Return a string describing the current state of the upload
2131         process."""
2132     def get_progress():
2133         """Returns a tuple of floats, (chk, ciphertext, encode_and_push),
2134         each from 0.0 to 1.0 . 'chk' describes how much progress has been
2135         made towards hashing the file to determine a CHK encryption key: if
2136         non-convergent encryption is in use, this will be trivial, otherwise
2137         the whole file must be hashed. 'ciphertext' describes how much of the
2138         ciphertext has been pushed to the helper, and is '1.0' for non-helper
2139         uploads. 'encode_and_push' describes how much of the encode-and-push
2140         process has finished: for helper uploads this is dependent upon the
2141         helper providing progress reports. It might be reasonable to add all
2142         three numbers and report the sum to the user."""
2143     def get_active():
2144         """Return True if the upload is currently active, False if not."""
2145     def get_results():
2146         """Return an instance of UploadResults (which contains timing and
2147         sharemap information). Might return None if the upload is not yet
2148         finished."""
2149     def get_counter():
2150         """Each upload status gets a unique number: this method returns that
2151         number. This provides a handle to this particular upload, so a web
2152         page can generate a suitable hyperlink."""
2153
2154 class IDownloadStatus(Interface):
2155     def get_started():
2156         """Return a timestamp (float with seconds since epoch) indicating
2157         when the operation was started."""
2158     def get_storage_index():
2159         """Return a string with the (binary) storage index in use on this
2160         download. This may be None if there is no storage index (i.e. LIT
2161         files)."""
2162     def get_size():
2163         """Return an integer with the number of bytes that will eventually be
2164         retrieved for this file. Returns None if the size is not yet known.
2165         """
2166     def using_helper():
2167         """Return True if this download is using a Helper, False if not."""
2168     def get_status():
2169         """Return a string describing the current state of the download
2170         process."""
2171     def get_progress():
2172         """Returns a float (from 0.0 to 1.0) describing the amount of the
2173         download that has completed. This value will remain at 0.0 until the
2174         first byte of plaintext is pushed to the download target."""
2175     def get_active():
2176         """Return True if the download is currently active, False if not."""
2177     def get_counter():
2178         """Each download status gets a unique number: this method returns
2179         that number. This provides a handle to this particular download, so a
2180         web page can generate a suitable hyperlink."""
2181
2182 class IServermapUpdaterStatus(Interface):
2183     pass
2184 class IPublishStatus(Interface):
2185     pass
2186 class IRetrieveStatus(Interface):
2187     pass
2188
2189 class NotCapableError(Exception):
2190     """You have tried to write to a read-only node."""
2191
2192 class BadWriteEnablerError(Exception):
2193     pass
2194
2195 class RIControlClient(RemoteInterface):
2196
2197     def wait_for_client_connections(num_clients=int):
2198         """Do not return until we have connections to at least NUM_CLIENTS
2199         storage servers.
2200         """
2201
2202     def upload_from_file_to_uri(filename=str,
2203                                 convergence=ChoiceOf(None,
2204                                                      StringConstraint(2**20))):
2205         """Upload a file to the grid. This accepts a filename (which must be
2206         absolute) that points to a file on the node's local disk. The node will
2207         read the contents of this file, upload it to the grid, then return the
2208         URI at which it was uploaded.  If convergence is None then a random
2209         encryption key will be used, else the plaintext will be hashed, then
2210         that hash will be mixed together with the "convergence" string to form
2211         the encryption key.
2212         """
2213         return URI
2214
2215     def download_from_uri_to_file(uri=URI, filename=str):
2216         """Download a file from the grid, placing it on the node's local disk
2217         at the given filename (which must be absolute[?]). Returns the
2218         absolute filename where the file was written."""
2219         return str
2220
2221     # debug stuff
2222
2223     def get_memory_usage():
2224         """Return a dict describes the amount of memory currently in use. The
2225         keys are 'VmPeak', 'VmSize', and 'VmData'. The values are integers,
2226         measuring memory consupmtion in bytes."""
2227         return DictOf(str, int)
2228
2229     def speed_test(count=int, size=int, mutable=Any()):
2230         """Write 'count' tempfiles to disk, all of the given size. Measure
2231         how long (in seconds) it takes to upload them all to the servers.
2232         Then measure how long it takes to download all of them. If 'mutable'
2233         is 'create', time creation of mutable files. If 'mutable' is
2234         'upload', then time access to the same mutable file instead of
2235         creating one.
2236
2237         Returns a tuple of (upload_time, download_time).
2238         """
2239         return (float, float)
2240
2241     def measure_peer_response_time():
2242         """Send a short message to each connected peer, and measure the time
2243         it takes for them to respond to it. This is a rough measure of the
2244         application-level round trip time.
2245
2246         @return: a dictionary mapping peerid to a float (RTT time in seconds)
2247         """
2248
2249         return DictOf(Nodeid, float)
2250
2251 UploadResults = Any() #DictOf(str, str)
2252
2253 class RIEncryptedUploadable(RemoteInterface):
2254     __remote_name__ = "RIEncryptedUploadable.tahoe.allmydata.com"
2255
2256     def get_size():
2257         return Offset
2258
2259     def get_all_encoding_parameters():
2260         return (int, int, int, long)
2261
2262     def read_encrypted(offset=Offset, length=ReadSize):
2263         return ListOf(str)
2264
2265     def close():
2266         return None
2267
2268
2269 class RICHKUploadHelper(RemoteInterface):
2270     __remote_name__ = "RIUploadHelper.tahoe.allmydata.com"
2271
2272     def get_version():
2273         """
2274         Return a dictionary of version information.
2275         """
2276         return DictOf(str, Any())
2277
2278     def upload(reader=RIEncryptedUploadable):
2279         return UploadResults
2280
2281
2282 class RIHelper(RemoteInterface):
2283     __remote_name__ = "RIHelper.tahoe.allmydata.com"
2284
2285     def get_version():
2286         """
2287         Return a dictionary of version information.
2288         """
2289         return DictOf(str, Any())
2290
2291     def upload_chk(si=StorageIndex):
2292         """See if a file with a given storage index needs uploading. The
2293         helper will ask the appropriate storage servers to see if the file
2294         has already been uploaded. If so, the helper will return a set of
2295         'upload results' that includes whatever hashes are needed to build
2296         the read-cap, and perhaps a truncated sharemap.
2297
2298         If the file has not yet been uploaded (or if it was only partially
2299         uploaded), the helper will return an empty upload-results dictionary
2300         and also an RICHKUploadHelper object that will take care of the
2301         upload process. The client should call upload() on this object and
2302         pass it a reference to an RIEncryptedUploadable object that will
2303         provide ciphertext. When the upload is finished, the upload() method
2304         will finish and return the upload results.
2305         """
2306         return (UploadResults, ChoiceOf(RICHKUploadHelper, None))
2307
2308
2309 class RIStatsProvider(RemoteInterface):
2310     __remote_name__ = "RIStatsProvider.tahoe.allmydata.com"
2311     """
2312     Provides access to statistics and monitoring information.
2313     """
2314
2315     def get_stats():
2316         """
2317         returns a dictionary containing 'counters' and 'stats', each a
2318         dictionary with string counter/stat name keys, and numeric values.
2319         counters are monotonically increasing measures of work done, and
2320         stats are instantaneous measures (potentially time averaged
2321         internally)
2322         """
2323         return DictOf(str, DictOf(str, ChoiceOf(float, int, long)))
2324
2325 class RIStatsGatherer(RemoteInterface):
2326     __remote_name__ = "RIStatsGatherer.tahoe.allmydata.com"
2327     """
2328     Provides a monitoring service for centralised collection of stats
2329     """
2330
2331     def provide(provider=RIStatsProvider, nickname=str):
2332         """
2333         @param provider: a stats collector instance which should be polled
2334                          periodically by the gatherer to collect stats.
2335         @param nickname: a name useful to identify the provided client
2336         """
2337         return None
2338
2339
2340 class IStatsProducer(Interface):
2341     def get_stats():
2342         """
2343         returns a dictionary, with str keys representing the names of stats
2344         to be monitored, and numeric values.
2345         """
2346
2347 class RIKeyGenerator(RemoteInterface):
2348     __remote_name__ = "RIKeyGenerator.tahoe.allmydata.com"
2349     """
2350     Provides a service offering to make RSA key pairs.
2351     """
2352
2353     def get_rsa_key_pair(key_size=int):
2354         """
2355         @param key_size: the size of the signature key.
2356         @return: tuple(verifying_key, signing_key)
2357         """
2358         return TupleOf(str, str)
2359
2360
2361 class FileTooLargeError(Exception):
2362     pass
2363
2364 class IValidatedThingProxy(Interface):
2365     def start():
2366         """ Acquire a thing and validate it. Return a deferred which is
2367         eventually fired with self if the thing is valid or errbacked if it
2368         can't be acquired or validated."""
2369
2370 class InsufficientVersionError(Exception):
2371     def __init__(self, needed, got):
2372         self.needed = needed
2373         self.got = got
2374     def __repr__(self):
2375         return "InsufficientVersionError(need '%s', got %s)" % (self.needed,
2376                                                                 self.got)