]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/interfaces.py
b9e50abc1513c0db038ffd40d4f2f6b19fb8295d
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / interfaces.py
1
2 from zope.interface import Interface
3 from foolscap.schema import StringConstraint, ListOf, TupleOf, SetOf, DictOf, \
4      ChoiceOf
5 from foolscap import RemoteInterface, Referenceable
6
7 HASH_SIZE=32
8
9 Hash = StringConstraint(maxLength=HASH_SIZE,
10                         minLength=HASH_SIZE)# binary format 32-byte SHA256 hash
11 Nodeid = StringConstraint(maxLength=20,
12                           minLength=20) # binary format 20-byte SHA1 hash
13 FURL = StringConstraint(1000)
14 StorageIndex = StringConstraint(16)
15 URI = StringConstraint(300) # kind of arbitrary
16
17 MAX_BUCKETS = 200  # per peer
18
19 # MAX_SEGMENT_SIZE in encode.py is 1 MiB (this constraint allows k = 1)
20 ShareData = StringConstraint(2**20)
21 URIExtensionData = StringConstraint(1000)
22 LeaseRenewSecret = Hash # used to protect bucket lease renewal requests
23 LeaseCancelSecret = Hash # used to protect bucket lease cancellation requests
24
25 # Announcements are (FURL, service_name, remoteinterface_name,
26 #                    nickname, my_version, oldest_supported)
27 #  the (FURL, service_name, remoteinterface_name) refer to the service being
28 #  announced. The (nickname, my_version, oldest_supported) refer to the
29 #  client as a whole. The my_version/oldest_supported strings can be parsed
30 #  by an allmydata.util.version.Version instance, and then compared. The
31 #  first goal is to make sure that nodes are not confused by speaking to an
32 #  incompatible peer. The second goal is to enable the development of
33 #  backwards-compatibility code.
34
35 Announcement = TupleOf(FURL, str, str,
36                        str, str, str)
37
38 class RIIntroducerSubscriberClient(RemoteInterface):
39     __remote_name__ = "RIIntroducerSubscriberClient.tahoe.allmydata.com"
40
41     def announce(announcements=SetOf(Announcement)):
42         """I accept announcements from the publisher."""
43         return None
44
45     def set_encoding_parameters(parameters=(int, int, int)):
46         """Advise the client of the recommended k-of-n encoding parameters
47         for this grid. 'parameters' is a tuple of (k, desired, n), where 'n'
48         is the total number of shares that will be created for any given
49         file, while 'k' is the number of shares that must be retrieved to
50         recover that file, and 'desired' is the minimum number of shares that
51         must be placed before the uploader will consider its job a success.
52         n/k is the expansion ratio, while k determines the robustness.
53
54         Introducers should specify 'n' according to the expected size of the
55         grid (there is no point to producing more shares than there are
56         peers), and k according to the desired reliability-vs-overhead goals.
57
58         Note that setting k=1 is equivalent to simple replication.
59         """
60         return None
61
62 # When Foolscap can handle multiple interfaces (Foolscap#17), the
63 # full-powered introducer will implement both RIIntroducerPublisher and
64 # RIIntroducerSubscriberService. Until then, we define
65 # RIIntroducerPublisherAndSubscriberService as a combination of the two, and
66 # make everybody use that.
67
68 class RIIntroducerPublisher(RemoteInterface):
69     """To publish a service to the world, connect to me and give me your
70     announcement message. I will deliver a copy to all connected subscribers."""
71     __remote_name__ = "RIIntroducerPublisher.tahoe.allmydata.com"
72
73     def publish(announcement=Announcement):
74         # canary?
75         return None
76
77 class RIIntroducerSubscriberService(RemoteInterface):
78     __remote_name__ = "RIIntroducerSubscriberService.tahoe.allmydata.com"
79
80     def subscribe(subscriber=RIIntroducerSubscriberClient, service_name=str):
81         """Give me a subscriber reference, and I will call its new_peers()
82         method will any announcements that match the desired service name. I
83         will ignore duplicate subscriptions.
84         """
85         return None
86
87 class RIIntroducerPublisherAndSubscriberService(RemoteInterface):
88     __remote_name__ = "RIIntroducerPublisherAndSubscriberService.tahoe.allmydata.com"
89     def publish(announcement=Announcement):
90         return None
91     def subscribe(subscriber=RIIntroducerSubscriberClient, service_name=str):
92         return None
93
94 class IIntroducerClient(Interface):
95     """I provide service introduction facilities for a node. I help nodes
96     publish their services to the rest of the world, and I help them learn
97     about services available on other nodes."""
98
99     def publish(furl, service_name, remoteinterface_name):
100         """Once you call this, I will tell the world that the Referenceable
101         available at FURL is available to provide a service named
102         SERVICE_NAME. The precise definition of the service being provided is
103         identified by the Foolscap 'remote interface name' in the last
104         parameter: this is supposed to be a globally-unique string that
105         identifies the RemoteInterface that is implemented."""
106
107     def subscribe_to(service_name):
108         """Call this if you will eventually want to use services with the
109         given SERVICE_NAME. This will prompt me to subscribe to announcements
110         of those services. You can pick up the announcements later by calling
111         get_all_connections_for() or get_permuted_peers().
112         """
113
114     def get_all_connections():
115         """Return a frozenset of (nodeid, service_name, rref) tuples, one for
116         each active connection we've established to a remote service. This is
117         mostly useful for unit tests that need to wait until a certain number
118         of connections have been made."""
119
120     def get_all_connectors():
121         """Return a dict that maps from (nodeid, service_name) to a
122         RemoteServiceConnector instance for all services that we are actively
123         trying to connect to. Each RemoteServiceConnector has the following
124         public attributes::
125
126           announcement_time: when we first heard about this service
127           last_connect_time: when we last established a connection
128           last_loss_time: when we last lost a connection
129
130           version: the peer's version, from the most recent connection
131           oldest_supported: the peer's oldest supported version, same
132
133           rref: the RemoteReference, if connected, otherwise None
134           remote_host: the IAddress, if connected, otherwise None
135
136         This method is intended for monitoring interfaces, such as a web page
137         which describes connecting and connected peers.
138         """
139
140     def get_all_peerids():
141         """Return a frozenset of all peerids to whom we have a connection (to
142         one or more services) established. Mostly useful for unit tests."""
143
144     def get_all_connections_for(service_name):
145         """Return a frozenset of (nodeid, service_name, rref) tuples, one
146         for each active connection that provides the given SERVICE_NAME."""
147
148     def get_permuted_peers(service_name, key):
149         """Returns an ordered list of (peerid, rref) tuples, selecting from
150         the connections that provide SERVICE_NAME, using a hash-based
151         permutation keyed by KEY. This randomizes the service list in a
152         repeatable way, to distribute load over many peers.
153         """
154
155     def connected_to_introducer():
156         """Returns a boolean, True if we are currently connected to the
157         introducer, False if not."""
158
159
160 class RIBucketWriter(RemoteInterface):
161     def write(offset=int, data=ShareData):
162         return None
163
164     def close():
165         """
166         If the data that has been written is incomplete or inconsistent then
167         the server will throw the data away, else it will store it for future
168         retrieval.
169         """
170         return None
171
172     def abort():
173         """Abandon all the data that has been written.
174         """
175         return None
176
177 class RIBucketReader(RemoteInterface):
178     def read(offset=int, length=int):
179         return ShareData
180
181 TestVector = ListOf(TupleOf(int, int, str, str))
182 # elements are (offset, length, operator, specimen)
183 # operator is one of "lt, le, eq, ne, ge, gt"
184 # nop always passes and is used to fetch data while writing.
185 # you should use length==len(specimen) for everything except nop
186 DataVector = ListOf(TupleOf(int, ShareData))
187 # (offset, data). This limits us to 30 writes of 1MiB each per call
188 TestAndWriteVectorsForShares = DictOf(int,
189                                       TupleOf(TestVector,
190                                               DataVector,
191                                               ChoiceOf(None, int))) # new_length
192 ReadVector = ListOf(TupleOf(int, int))
193 ReadData = ListOf(ShareData)
194 # returns data[offset:offset+length] for each element of TestVector
195
196 class RIStorageServer(RemoteInterface):
197     __remote_name__ = "RIStorageServer.tahoe.allmydata.com"
198
199     def get_versions():
200         """Return a tuple of (my_version, oldest_supported) strings.
201         Each string can be parsed by an allmydata.util.version.Version
202         instance, and then compared. The first goal is to make sure that
203         nodes are not confused by speaking to an incompatible peer. The
204         second goal is to enable the development of backwards-compatibility
205         code.
206
207         This method is likely to change in incompatible ways until we get the
208         whole compatibility scheme nailed down.
209         """
210         return TupleOf(str, str)
211
212     def allocate_buckets(storage_index=StorageIndex,
213                          renew_secret=LeaseRenewSecret,
214                          cancel_secret=LeaseCancelSecret,
215                          sharenums=SetOf(int, maxLength=MAX_BUCKETS),
216                          allocated_size=int, canary=Referenceable):
217         """
218         @param storage_index: the index of the bucket to be created or
219                               increfed.
220         @param sharenums: these are the share numbers (probably between 0 and
221                           99) that the sender is proposing to store on this
222                           server.
223         @param renew_secret: This is the secret used to protect bucket refresh
224                              This secret is generated by the client and
225                              stored for later comparison by the server. Each
226                              server is given a different secret.
227         @param cancel_secret: Like renew_secret, but protects bucket decref.
228         @param canary: If the canary is lost before close(), the bucket is
229                        deleted.
230         @return: tuple of (alreadygot, allocated), where alreadygot is what we
231                  already have and is what we hereby agree to accept. New
232                  leases are added for shares in both lists.
233         """
234         return TupleOf(SetOf(int, maxLength=MAX_BUCKETS),
235                        DictOf(int, RIBucketWriter, maxKeys=MAX_BUCKETS))
236
237     def renew_lease(storage_index=StorageIndex, renew_secret=LeaseRenewSecret):
238         """
239         Renew the lease on a given bucket. Some networks will use this, some
240         will not.
241         """
242
243     def cancel_lease(storage_index=StorageIndex,
244                      cancel_secret=LeaseCancelSecret):
245         """
246         Cancel the lease on a given bucket. If this was the last lease on the
247         bucket, the bucket will be deleted.
248         """
249
250     def get_buckets(storage_index=StorageIndex):
251         return DictOf(int, RIBucketReader, maxKeys=MAX_BUCKETS)
252
253
254
255     def slot_readv(storage_index=StorageIndex,
256                    shares=ListOf(int), readv=ReadVector):
257         """Read a vector from the numbered shares associated with the given
258         storage index. An empty shares list means to return data from all
259         known shares. Returns a dictionary with one key per share."""
260         return DictOf(int, ReadData) # shnum -> results
261
262     def slot_testv_and_readv_and_writev(storage_index=StorageIndex,
263                                         secrets=TupleOf(Hash, Hash, Hash),
264                                         tw_vectors=TestAndWriteVectorsForShares,
265                                         r_vector=ReadVector,
266                                         ):
267         """General-purpose test-and-set operation for mutable slots. Perform
268         a bunch of comparisons against the existing shares. If they all pass,
269         then apply a bunch of write vectors to those shares. Then use the
270         read vectors to extract data from all the shares and return the data.
271
272         This method is, um, large. The goal is to allow clients to update all
273         the shares associated with a mutable file in a single round trip.
274
275         @param storage_index: the index of the bucket to be created or
276                               increfed.
277         @param write_enabler: a secret that is stored along with the slot.
278                               Writes are accepted from any caller who can
279                               present the matching secret. A different secret
280                               should be used for each slot*server pair.
281         @param renew_secret: This is the secret used to protect bucket refresh
282                              This secret is generated by the client and
283                              stored for later comparison by the server. Each
284                              server is given a different secret.
285         @param cancel_secret: Like renew_secret, but protects bucket decref.
286
287         The 'secrets' argument is a tuple of (write_enabler, renew_secret,
288         cancel_secret). The first is required to perform any write. The
289         latter two are used when allocating new shares. To simply acquire a
290         new lease on existing shares, use an empty testv and an empty writev.
291
292         Each share can have a separate test vector (i.e. a list of
293         comparisons to perform). If all vectors for all shares pass, then all
294         writes for all shares are recorded. Each comparison is a 4-tuple of
295         (offset, length, operator, specimen), which effectively does a bool(
296         (read(offset, length)) OPERATOR specimen ) and only performs the
297         write if all these evaluate to True. Basic test-and-set uses 'eq'.
298         Write-if-newer uses a seqnum and (offset, length, 'lt', specimen).
299         Write-if-same-or-newer uses 'le'.
300
301         Reads from the end of the container are truncated, and missing shares
302         behave like empty ones, so to assert that a share doesn't exist (for
303         use when creating a new share), use (0, 1, 'eq', '').
304
305         The write vector will be applied to the given share, expanding it if
306         necessary. A write vector applied to a share number that did not
307         exist previously will cause that share to be created.
308
309         Each write vector is accompanied by a 'new_length' argument. If
310         new_length is not None, use it to set the size of the container. This
311         can be used to pre-allocate space for a series of upcoming writes, or
312         truncate existing data. If the container is growing, new_length will
313         be applied before datav. If the container is shrinking, it will be
314         applied afterwards.
315
316         The read vector is used to extract data from all known shares,
317         *before* any writes have been applied. The same vector is used for
318         all shares. This captures the state that was tested by the test
319         vector.
320
321         This method returns two values: a boolean and a dict. The boolean is
322         True if the write vectors were applied, False if not. The dict is
323         keyed by share number, and each value contains a list of strings, one
324         for each element of the read vector.
325
326         If the write_enabler is wrong, this will raise BadWriteEnablerError.
327         To enable share migration, the exception will have the nodeid used
328         for the old write enabler embedded in it, in the following string::
329
330          The write enabler was recorded by nodeid '%s'.
331
332         Note that the nodeid here is encoded using the same base32 encoding
333         used by Foolscap and allmydata.util.idlib.nodeid_b2a().
334
335         """
336         return TupleOf(bool, DictOf(int, ReadData))
337
338 class IStorageBucketWriter(Interface):
339     def put_block(segmentnum=int, data=ShareData):
340         """@param data: For most segments, this data will be 'blocksize'
341         bytes in length. The last segment might be shorter.
342         @return: a Deferred that fires (with None) when the operation completes
343         """
344
345     def put_plaintext_hashes(hashes=ListOf(Hash, maxLength=2**20)):
346         """
347         @return: a Deferred that fires (with None) when the operation completes
348         """
349
350     def put_crypttext_hashes(hashes=ListOf(Hash, maxLength=2**20)):
351         """
352         @return: a Deferred that fires (with None) when the operation completes
353         """
354
355     def put_block_hashes(blockhashes=ListOf(Hash, maxLength=2**20)):
356         """
357         @return: a Deferred that fires (with None) when the operation completes
358         """
359
360     def put_share_hashes(sharehashes=ListOf(TupleOf(int, Hash),
361                                             maxLength=2**20)):
362         """
363         @return: a Deferred that fires (with None) when the operation completes
364         """
365
366     def put_uri_extension(data=URIExtensionData):
367         """This block of data contains integrity-checking information (hashes
368         of plaintext, crypttext, and shares), as well as encoding parameters
369         that are necessary to recover the data. This is a serialized dict
370         mapping strings to other strings. The hash of this data is kept in
371         the URI and verified before any of the data is used. All buckets for
372         a given file contain identical copies of this data.
373
374         The serialization format is specified with the following pseudocode:
375         for k in sorted(dict.keys()):
376             assert re.match(r'^[a-zA-Z_\-]+$', k)
377             write(k + ':' + netstring(dict[k]))
378
379         @return: a Deferred that fires (with None) when the operation completes
380         """
381
382     def close():
383         """Finish writing and close the bucket. The share is not finalized
384         until this method is called: if the uploading client disconnects
385         before calling close(), the partially-written share will be
386         discarded.
387
388         @return: a Deferred that fires (with None) when the operation completes
389         """
390
391 class IStorageBucketReader(Interface):
392
393     def get_block(blocknum=int):
394         """Most blocks will be the same size. The last block might be shorter
395         than the others.
396
397         @return: ShareData
398         """
399
400     def get_plaintext_hashes():
401         """
402         @return: ListOf(Hash, maxLength=2**20)
403         """
404
405     def get_crypttext_hashes():
406         """
407         @return: ListOf(Hash, maxLength=2**20)
408         """
409
410     def get_block_hashes():
411         """
412         @return: ListOf(Hash, maxLength=2**20)
413         """
414
415     def get_share_hashes():
416         """
417         @return: ListOf(TupleOf(int, Hash), maxLength=2**20)
418         """
419
420     def get_uri_extension():
421         """
422         @return: URIExtensionData
423         """
424
425
426
427 # hm, we need a solution for forward references in schemas
428 from foolscap.schema import Any
429
430 FileNode_ = Any() # TODO: foolscap needs constraints on copyables
431 DirectoryNode_ = Any() # TODO: same
432 AnyNode_ = ChoiceOf(FileNode_, DirectoryNode_)
433 EncryptedThing = str
434
435 class IURI(Interface):
436     def init_from_string(uri):
437         """Accept a string (as created by my to_string() method) and populate
438         this instance with its data. I am not normally called directly,
439         please use the module-level uri.from_string() function to convert
440         arbitrary URI strings into IURI-providing instances."""
441
442     def is_readonly():
443         """Return False if this URI be used to modify the data. Return True
444         if this URI cannot be used to modify the data."""
445
446     def is_mutable():
447         """Return True if the data can be modified by *somebody* (perhaps
448         someone who has a more powerful URI than this one)."""
449
450     def get_readonly():
451         """Return another IURI instance, which represents a read-only form of
452         this one. If is_readonly() is True, this returns self."""
453
454     def get_verifier():
455         """Return an instance that provides IVerifierURI, which can be used
456         to check on the availability of the file or directory, without
457         providing enough capabilities to actually read or modify the
458         contents. This may return None if the file does not need checking or
459         verification (e.g. LIT URIs).
460         """
461
462     def to_string():
463         """Return a string of printable ASCII characters, suitable for
464         passing into init_from_string."""
465
466 class IVerifierURI(Interface):
467     def init_from_string(uri):
468         """Accept a string (as created by my to_string() method) and populate
469         this instance with its data. I am not normally called directly,
470         please use the module-level uri.from_string() function to convert
471         arbitrary URI strings into IURI-providing instances."""
472
473     def to_string():
474         """Return a string of printable ASCII characters, suitable for
475         passing into init_from_string."""
476
477 class IDirnodeURI(Interface):
478     """I am a URI which represents a dirnode."""
479
480
481 class IFileURI(Interface):
482     """I am a URI which represents a filenode."""
483     def get_size():
484         """Return the length (in bytes) of the file that I represent."""
485
486 class IMutableFileURI(Interface):
487     """I am a URI which represents a mutable filenode."""
488     pass
489 class INewDirectoryURI(Interface):
490     pass
491 class IReadonlyNewDirectoryURI(Interface):
492     pass
493
494
495 class IFilesystemNode(Interface):
496     def get_uri():
497         """
498         Return the URI that can be used by others to get access to this
499         node. If this node is read-only, the URI will only offer read-only
500         access. If this node is read-write, the URI will offer read-write
501         access.
502
503         If you have read-write access to a node and wish to share merely
504         read-only access with others, use get_readonly_uri().
505         """
506
507     def get_readonly_uri():
508         """Return the directory URI that can be used by others to get
509         read-only access to this directory node. The result is a read-only
510         URI, regardless of whether this dirnode is read-only or read-write.
511
512         If you have merely read-only access to this dirnode,
513         get_readonly_uri() will return the same thing as get_uri().
514         """
515
516     def get_verifier():
517         """Return an IVerifierURI instance that represents the
518         'verifiy/refresh capability' for this node. The holder of this
519         capability will be able to renew the lease for this node, protecting
520         it from garbage-collection. They will also be able to ask a server if
521         it holds a share for the file or directory.
522         """
523
524     def check():
525         """Perform a file check. See IChecker.check for details."""
526
527     def is_readonly():
528         """Return True if this reference provides mutable access to the given
529         file or directory (i.e. if you can modify it), or False if not. Note
530         that even if this reference is read-only, someone else may hold a
531         read-write reference to it."""
532
533     def is_mutable():
534         """Return True if this file or directory is mutable (by *somebody*,
535         not necessarily you), False if it is is immutable. Note that a file
536         might be mutable overall, but your reference to it might be
537         read-only. On the other hand, all references to an immutable file
538         will be read-only; there are no read-write references to an immutable
539         file.
540         """
541
542 class IMutableFilesystemNode(IFilesystemNode):
543     pass
544
545 class IFileNode(IFilesystemNode):
546     def download(target):
547         """Download the file's contents to a given IDownloadTarget"""
548
549     def download_to_data():
550         """Download the file's contents. Return a Deferred that fires
551         with those contents."""
552
553     def get_size():
554         """Return the length (in bytes) of the data this node represents."""
555
556 class IMutableFileNode(IFileNode, IMutableFilesystemNode):
557     def download_to_data():
558         """Download the file's contents. Return a Deferred that fires with
559         those contents. If there are multiple retrievable versions in the
560         grid (because you failed to avoid simultaneous writes, see
561         docs/mutable.txt), this will return the first version that it can
562         reconstruct, and will silently ignore the others. In the future, a
563         more advanced API will signal and provide access to the multiple
564         heads."""
565
566     def replace(newdata):
567         """Replace the old contents with the new data. Returns a Deferred
568         that fires (with None) when the operation is complete.
569
570         If the node detects that there are multiple outstanding versions of
571         the file, this will raise ConsistencyError, and may leave the
572         distributed file in an unusual state (the node will try to ensure
573         that at least one version of the file remains retrievable, but it may
574         or may not be the one you just tried to upload). You should respond
575         to this by downloading the current contents of the file and retrying
576         the replace() operation.
577         """
578
579     def get_writekey():
580         """Return this filenode's writekey, or None if the node does not have
581         write-capability. This may be used to assist with data structures
582         that need to make certain data available only to writers, such as the
583         read-write child caps in dirnodes. The recommended process is to have
584         reader-visible data be submitted to the filenode in the clear (where
585         it will be encrypted by the filenode using the readkey), but encrypt
586         writer-visible data using this writekey.
587         """
588
589 class IDirectoryNode(IMutableFilesystemNode):
590     def get_uri():
591         """
592         The dirnode ('1') URI returned by this method can be used in
593         set_uri() on a different directory ('2') to 'mount' a reference to
594         this directory ('1') under the other ('2'). This URI is just a
595         string, so it can be passed around through email or other out-of-band
596         protocol.
597         """
598
599     def get_readonly_uri():
600         """
601         The dirnode ('1') URI returned by this method can be used in
602         set_uri() on a different directory ('2') to 'mount' a reference to
603         this directory ('1') under the other ('2'). This URI is just a
604         string, so it can be passed around through email or other out-of-band
605         protocol.
606         """
607
608     def list():
609         """I return a Deferred that fires with a dictionary mapping child
610         name to (node, metadata_dict) tuples, in which 'node' is either an
611         IFileNode or IDirectoryNode, and 'metadata_dict' is a dictionary of
612         metadata."""
613
614     def has_child(name):
615         """I return a Deferred that fires with a boolean, True if there
616         exists a child of the given name, False if not."""
617
618     def get(name):
619         """I return a Deferred that fires with a specific named child node,
620         either an IFileNode or an IDirectoryNode."""
621
622     def get_child_at_path(path):
623         """Transform a child path into an IDirectoryNode or IFileNode.
624
625         I perform a recursive series of 'get' operations to find the named
626         descendant node. I return a Deferred that fires with the node, or
627         errbacks with IndexError if the node could not be found.
628
629         The path can be either a single string (slash-separated) or a list of
630         path-name elements.
631         """
632
633     def set_uri(name, child_uri):
634         """I add a child (by URI) at the specific name. I return a Deferred
635         that fires when the operation finishes. I will replace any existing
636         child of the same name.
637
638         The child_uri could be for a file, or for a directory (either
639         read-write or read-only, using a URI that came from get_uri() ).
640
641         If this directory node is read-only, the Deferred will errback with a
642         NotMutableError."""
643
644     def set_uris(entries):
645         """Add multiple (name, child_uri) pairs to a directory node. Returns
646         a Deferred that fires (with None) when the operation finishes. This
647         is equivalent to calling set_uri() multiple times, but is much more
648         efficient.
649         """
650
651     def set_node(name, child):
652         """I add a child at the specific name. I return a Deferred that fires
653         when the operation finishes. This Deferred will fire with the child
654         node that was just added. I will replace any existing child of the
655         same name.
656
657         If this directory node is read-only, the Deferred will errback with a
658         NotMutableError."""
659
660     def set_nodes(entries):
661         """Add multiple (name, child_node) pairs to a directory node. Returns
662         a Deferred that fires (with None) when the operation finishes. This
663         is equivalent to calling set_node() multiple times, but is much more
664         efficient."""
665
666
667     def add_file(name, uploadable):
668         """I upload a file (using the given IUploadable), then attach the
669         resulting FileNode to the directory at the given name. I return a
670         Deferred that fires (with the IFileNode of the uploaded file) when
671         the operation completes."""
672
673     def delete(name):
674         """I remove the child at the specific name. I return a Deferred that
675         fires when the operation finishes."""
676
677     def create_empty_directory(name):
678         """I create and attach an empty directory at the given name. I return
679         a Deferred that fires when the operation finishes."""
680
681     def move_child_to(current_child_name, new_parent, new_child_name=None):
682         """I take one of my children and move them to a new parent. The child
683         is referenced by name. On the new parent, the child will live under
684         'new_child_name', which defaults to 'current_child_name'. I return a
685         Deferred that fires when the operation finishes."""
686
687     def build_manifest():
688         """Return a frozenset of verifier-capability strings for all nodes
689         (directories and files) reachable from this one."""
690
691 class ICodecEncoder(Interface):
692     def set_params(data_size, required_shares, max_shares):
693         """Set up the parameters of this encoder.
694
695         This prepares the encoder to perform an operation that converts a
696         single block of data into a number of shares, such that a future
697         ICodecDecoder can use a subset of these shares to recover the
698         original data. This operation is invoked by calling encode(). Once
699         the encoding parameters are set up, the encode operation can be
700         invoked multiple times.
701
702         set_params() prepares the encoder to accept blocks of input data that
703         are exactly 'data_size' bytes in length. The encoder will be prepared
704         to produce 'max_shares' shares for each encode() operation (although
705         see the 'desired_share_ids' to use less CPU). The encoding math will
706         be chosen such that the decoder can get by with as few as
707         'required_shares' of these shares and still reproduce the original
708         data. For example, set_params(1000, 5, 5) offers no redundancy at
709         all, whereas set_params(1000, 1, 10) provides 10x redundancy.
710
711         Numerical Restrictions: 'data_size' is required to be an integral
712         multiple of 'required_shares'. In general, the caller should choose
713         required_shares and max_shares based upon their reliability
714         requirements and the number of peers available (the total storage
715         space used is roughly equal to max_shares*data_size/required_shares),
716         then choose data_size to achieve the memory footprint desired (larger
717         data_size means more efficient operation, smaller data_size means
718         smaller memory footprint).
719
720         In addition, 'max_shares' must be equal to or greater than
721         'required_shares'. Of course, setting them to be equal causes
722         encode() to degenerate into a particularly slow form of the 'split'
723         utility.
724
725         See encode() for more details about how these parameters are used.
726
727         set_params() must be called before any other ICodecEncoder methods
728         may be invoked.
729         """
730
731     def get_encoder_type():
732         """Return a short string that describes the type of this encoder.
733
734         There is required to be a global table of encoder classes. This method
735         returns an index into this table; the value at this index is an
736         encoder class, and this encoder is an instance of that class.
737         """
738
739     def get_serialized_params(): # TODO: maybe, maybe not
740         """Return a string that describes the parameters of this encoder.
741
742         This string can be passed to the decoder to prepare it for handling
743         the encoded shares we create. It might contain more information than
744         was presented to set_params(), if there is some flexibility of
745         parameter choice.
746
747         This string is intended to be embedded in the URI, so there are
748         several restrictions on its contents. At the moment I'm thinking that
749         this means it may contain hex digits and hyphens, and nothing else.
750         The idea is that the URI contains something like '%s:%s:%s' %
751         (encoder.get_encoder_name(), encoder.get_serialized_params(),
752         b2a(crypttext_hash)), and this is enough information to construct a
753         compatible decoder.
754         """
755
756     def get_block_size():
757         """Return the length of the shares that encode() will produce.
758         """
759
760     def encode_proposal(data, desired_share_ids=None):
761         """Encode some data.
762
763         'data' must be a string (or other buffer object), and len(data) must
764         be equal to the 'data_size' value passed earlier to set_params().
765
766         This will return a Deferred that will fire with two lists. The first
767         is a list of shares, each of which is a string (or other buffer
768         object) such that len(share) is the same as what get_share_size()
769         returned earlier. The second is a list of shareids, in which each is
770         an integer. The lengths of the two lists will always be equal to each
771         other. The user should take care to keep each share closely
772         associated with its shareid, as one is useless without the other.
773
774         The length of this output list will normally be the same as the value
775         provided to the 'max_shares' parameter of set_params(). This may be
776         different if 'desired_share_ids' is provided.
777
778         'desired_share_ids', if provided, is required to be a sequence of
779         ints, each of which is required to be >= 0 and < max_shares. If not
780         provided, encode() will produce 'max_shares' shares, as if
781         'desired_share_ids' were set to range(max_shares). You might use this
782         if you initially thought you were going to use 10 peers, started
783         encoding, and then two of the peers dropped out: you could use
784         desired_share_ids= to skip the work (both memory and CPU) of
785         producing shares for the peers which are no longer available.
786
787         """
788
789     def encode(inshares, desired_share_ids=None):
790         """Encode some data. This may be called multiple times. Each call is
791         independent.
792
793         inshares is a sequence of length required_shares, containing buffers
794         (i.e. strings), where each buffer contains the next contiguous
795         non-overlapping segment of the input data. Each buffer is required to
796         be the same length, and the sum of the lengths of the buffers is
797         required to be exactly the data_size promised by set_params(). (This
798         implies that the data has to be padded before being passed to
799         encode(), unless of course it already happens to be an even multiple
800         of required_shares in length.)
801
802          ALSO: the requirement to break up your data into 'required_shares'
803          chunks before calling encode() feels a bit surprising, at least from
804          the point of view of a user who doesn't know how FEC works. It feels
805          like an implementation detail that has leaked outside the
806          abstraction barrier. Can you imagine a use case in which the data to
807          be encoded might already be available in pre-segmented chunks, such
808          that it is faster or less work to make encode() take a list rather
809          than splitting a single string?
810
811          ALSO ALSO: I think 'inshares' is a misleading term, since encode()
812          is supposed to *produce* shares, so what it *accepts* should be
813          something other than shares. Other places in this interface use the
814          word 'data' for that-which-is-not-shares.. maybe we should use that
815          term?
816
817         'desired_share_ids', if provided, is required to be a sequence of
818         ints, each of which is required to be >= 0 and < max_shares. If not
819         provided, encode() will produce 'max_shares' shares, as if
820         'desired_share_ids' were set to range(max_shares). You might use this
821         if you initially thought you were going to use 10 peers, started
822         encoding, and then two of the peers dropped out: you could use
823         desired_share_ids= to skip the work (both memory and CPU) of
824         producing shares for the peers which are no longer available.
825
826         For each call, encode() will return a Deferred that fires with two
827         lists, one containing shares and the other containing the shareids.
828         The get_share_size() method can be used to determine the length of
829         the share strings returned by encode(). Each shareid is a small
830         integer, exactly as passed into 'desired_share_ids' (or
831         range(max_shares), if desired_share_ids was not provided).
832
833         The shares and their corresponding shareids are required to be kept
834         together during storage and retrieval. Specifically, the share data is
835         useless by itself: the decoder needs to be told which share is which
836         by providing it with both the shareid and the actual share data.
837
838         This function will allocate an amount of memory roughly equal to::
839
840          (max_shares - required_shares) * get_share_size()
841
842         When combined with the memory that the caller must allocate to
843         provide the input data, this leads to a memory footprint roughly
844         equal to the size of the resulting encoded shares (i.e. the expansion
845         factor times the size of the input segment).
846         """
847
848         # rejected ideas:
849         #
850         #  returning a list of (shareidN,shareN) tuples instead of a pair of
851         #  lists (shareids..,shares..). Brian thought the tuples would
852         #  encourage users to keep the share and shareid together throughout
853         #  later processing, Zooko pointed out that the code to iterate
854         #  through two lists is not really more complicated than using a list
855         #  of tuples and there's also a performance improvement
856         #
857         #  having 'data_size' not required to be an integral multiple of
858         #  'required_shares'. Doing this would require encode() to perform
859         #  padding internally, and we'd prefer to have any padding be done
860         #  explicitly by the caller. Yes, it is an abstraction leak, but
861         #  hopefully not an onerous one.
862
863
864 class ICodecDecoder(Interface):
865     def set_serialized_params(params):
866         """Set up the parameters of this encoder, from a string returned by
867         encoder.get_serialized_params()."""
868
869     def get_needed_shares():
870         """Return the number of shares needed to reconstruct the data.
871         set_serialized_params() is required to be called before this."""
872
873     def decode(some_shares, their_shareids):
874         """Decode a partial list of shares into data.
875
876         'some_shares' is required to be a sequence of buffers of sharedata, a
877         subset of the shares returned by ICodecEncode.encode(). Each share is
878         required to be of the same length.  The i'th element of their_shareids
879         is required to be the shareid of the i'th buffer in some_shares.
880
881         This returns a Deferred which fires with a sequence of buffers. This
882         sequence will contain all of the segments of the original data, in
883         order. The sum of the lengths of all of the buffers will be the
884         'data_size' value passed into the original ICodecEncode.set_params()
885         call. To get back the single original input block of data, use
886         ''.join(output_buffers), or you may wish to simply write them in
887         order to an output file.
888
889         Note that some of the elements in the result sequence may be
890         references to the elements of the some_shares input sequence. In
891         particular, this means that if those share objects are mutable (e.g.
892         arrays) and if they are changed, then both the input (the
893         'some_shares' parameter) and the output (the value given when the
894         deferred is triggered) will change.
895
896         The length of 'some_shares' is required to be exactly the value of
897         'required_shares' passed into the original ICodecEncode.set_params()
898         call.
899         """
900
901 class IEncoder(Interface):
902     """I take an object that provides IEncryptedUploadable, which provides
903     encrypted data, and a list of shareholders. I then encode, hash, and
904     deliver shares to those shareholders. I will compute all the necessary
905     Merkle hash trees that are necessary to validate the crypttext that
906     eventually comes back from the shareholders. I provide the URI Extension
907     Block Hash, and the encoding parameters, both of which must be included
908     in the URI.
909
910     I do not choose shareholders, that is left to the IUploader. I must be
911     given a dict of RemoteReferences to storage buckets that are ready and
912     willing to receive data.
913     """
914
915     def set_size(size):
916         """Specify the number of bytes that will be encoded. This must be
917         peformed before get_serialized_params() can be called.
918         """
919     def set_params(params):
920         """Override the default encoding parameters. 'params' is a tuple of
921         (k,d,n), where 'k' is the number of required shares, 'd' is the
922         shares_of_happiness, and 'n' is the total number of shares that will
923         be created.
924
925         Encoding parameters can be set in three ways. 1: The Encoder class
926         provides defaults (3/7/10). 2: the Encoder can be constructed with
927         an 'options' dictionary, in which the
928         needed_and_happy_and_total_shares' key can be a (k,d,n) tuple. 3:
929         set_params((k,d,n)) can be called.
930
931         If you intend to use set_params(), you must call it before
932         get_share_size or get_param are called.
933         """
934
935     def set_encrypted_uploadable(u):
936         """Provide a source of encrypted upload data. 'u' must implement
937         IEncryptedUploadable.
938
939         When this is called, the IEncryptedUploadable will be queried for its
940         length and the storage_index that should be used.
941
942         This returns a Deferred that fires with this Encoder instance.
943
944         This must be performed before start() can be called.
945         """
946
947     def get_param(name):
948         """Return an encoding parameter, by name.
949
950         'storage_index': return a string with the (16-byte truncated SHA-256
951                          hash) storage index to which these shares should be
952                          pushed.
953
954         'share_counts': return a tuple describing how many shares are used:
955                         (needed_shares, shares_of_happiness, total_shares)
956
957         'num_segments': return an int with the number of segments that
958                         will be encoded.
959
960         'segment_size': return an int with the size of each segment.
961
962         'block_size': return the size of the individual blocks that will
963                       be delivered to a shareholder's put_block() method. By
964                       knowing this, the shareholder will be able to keep all
965                       blocks in a single file and still provide random access
966                       when reading them. # TODO: can we avoid exposing this?
967
968         'share_size': an int with the size of the data that will be stored
969                       on each shareholder. This is aggregate amount of data
970                       that will be sent to the shareholder, summed over all
971                       the put_block() calls I will ever make. It is useful to
972                       determine this size before asking potential
973                       shareholders whether they will grant a lease or not,
974                       since their answers will depend upon how much space we
975                       need. TODO: this might also include some amount of
976                       overhead, like the size of all the hashes. We need to
977                       decide whether this is useful or not.
978
979         'serialized_params': a string with a concise description of the
980                              codec name and its parameters. This may be passed
981                              into the IUploadable to let it make sure that
982                              the same file encoded with different parameters
983                              will result in different storage indexes.
984
985         Once this is called, set_size() and set_params() may not be called.
986         """
987
988     def set_shareholders(shareholders):
989         """Tell the encoder where to put the encoded shares. 'shareholders'
990         must be a dictionary that maps share number (an integer ranging from
991         0 to n-1) to an instance that provides IStorageBucketWriter. This
992         must be performed before start() can be called."""
993
994     def start():
995         """Begin the encode/upload process. This involves reading encrypted
996         data from the IEncryptedUploadable, encoding it, uploading the shares
997         to the shareholders, then sending the hash trees.
998
999         set_encrypted_uploadable() and set_shareholders() must be called
1000         before this can be invoked.
1001
1002         This returns a Deferred that fires with a tuple of
1003         (uri_extension_hash, needed_shares, total_shares, size) when the
1004         upload process is complete. This information, plus the encryption
1005         key, is sufficient to construct the URI.
1006         """
1007
1008 class IDecoder(Interface):
1009     """I take a list of shareholders and some setup information, then
1010     download, validate, decode, and decrypt data from them, writing the
1011     results to an output file.
1012
1013     I do not locate the shareholders, that is left to the IDownloader. I must
1014     be given a dict of RemoteReferences to storage buckets that are ready to
1015     send data.
1016     """
1017
1018     def setup(outfile):
1019         """I take a file-like object (providing write and close) to which all
1020         the plaintext data will be written.
1021
1022         TODO: producer/consumer . Maybe write() should return a Deferred that
1023         indicates when it will accept more data? But probably having the
1024         IDecoder be a producer is easier to glue to IConsumer pieces.
1025         """
1026
1027     def set_shareholders(shareholders):
1028         """I take a dictionary that maps share identifiers (small integers)
1029         to RemoteReferences that provide RIBucketReader. This must be called
1030         before start()."""
1031
1032     def start():
1033         """I start the download. This process involves retrieving data and
1034         hash chains from the shareholders, using the hashes to validate the
1035         data, decoding the shares into segments, decrypting the segments,
1036         then writing the resulting plaintext to the output file.
1037
1038         I return a Deferred that will fire (with self) when the download is
1039         complete.
1040         """
1041
1042 class IDownloadTarget(Interface):
1043     def open(size):
1044         """Called before any calls to write() or close(). If an error
1045         occurs before any data is available, fail() may be called without
1046         a previous call to open().
1047
1048         'size' is the length of the file being downloaded, in bytes."""
1049
1050     def write(data):
1051         """Output some data to the target."""
1052     def close():
1053         """Inform the target that there is no more data to be written."""
1054     def fail(why):
1055         """fail() is called to indicate that the download has failed. 'why'
1056         is a Failure object indicating what went wrong. No further methods
1057         will be invoked on the IDownloadTarget after fail()."""
1058     def register_canceller(cb):
1059         """The FileDownloader uses this to register a no-argument function
1060         that the target can call to cancel the download. Once this canceller
1061         is invoked, no further calls to write() or close() will be made."""
1062     def finish():
1063         """When the FileDownloader is done, this finish() function will be
1064         called. Whatever it returns will be returned to the invoker of
1065         Downloader.download.
1066         """
1067
1068 class IDownloader(Interface):
1069     def download(uri, target):
1070         """Perform a CHK download, sending the data to the given target.
1071         'target' must provide IDownloadTarget.
1072
1073         Returns a Deferred that fires (with the results of target.finish)
1074         when the download is finished, or errbacks if something went wrong."""
1075
1076 class IEncryptedUploadable(Interface):
1077     def get_size():
1078         """This behaves just like IUploadable.get_size()."""
1079
1080     def get_all_encoding_parameters():
1081         """Return a Deferred that fires with a tuple of
1082         (k,happy,n,segment_size). The segment_size will be used as-is, and
1083         must match the following constraints: it must be a multiple of k, and
1084         it shouldn't be unreasonably larger than the file size (if
1085         segment_size is larger than filesize, the difference must be stored
1086         as padding).
1087
1088         The encoder strictly obeys the values returned by this method. To
1089         make an upload use non-default encoding parameters, you must arrange
1090         to control the values that this method returns.
1091         """
1092
1093     def get_storage_index():
1094         """Return a Deferred that fires with a 16-byte storage index.
1095         """
1096
1097     def read_encrypted(length, hash_only):
1098         """This behaves just like IUploadable.read(), but returns crypttext
1099         instead of plaintext. If hash_only is True, then this discards the
1100         data (and returns an empty list); this improves efficiency when
1101         resuming an interrupted upload (where we need to compute the
1102         plaintext hashes, but don't need the redundant encrypted data)."""
1103
1104     def get_plaintext_hashtree_leaves(first, last, num_segments):
1105         """Get the leaf nodes of a merkle hash tree over the plaintext
1106         segments, i.e. get the tagged hashes of the given segments. The
1107         segment size is expected to be generated by the IEncryptedUploadable
1108         before any plaintext is read or ciphertext produced, so that the
1109         segment hashes can be generated with only a single pass.
1110
1111         This returns a Deferred which fires with a sequence of hashes, using:
1112
1113          tuple(segment_hashes[first:last])
1114
1115         'num_segments' is used to assert that the number of segments that the
1116         IEncryptedUploadable handled matches the number of segments that the
1117         encoder was expecting.
1118
1119         This method must not be called until the final byte has been read
1120         from read_encrypted(). Once this method is called, read_encrypted()
1121         can never be called again.
1122         """
1123
1124     def get_plaintext_hash():
1125         """Get the hash of the whole plaintext.
1126
1127         This returns a Deferred which fires with a tagged SHA-256 hash of the
1128         whole plaintext, obtained from hashutil.plaintext_hash(data).
1129         """
1130
1131     def close():
1132         """Just like IUploadable.close()."""
1133
1134 class IUploadable(Interface):
1135     def get_size():
1136         """Return a Deferred that will fire with the length of the data to be
1137         uploaded, in bytes. This will be called before the data is actually
1138         used, to compute encoding parameters.
1139         """
1140
1141     def get_maximum_segment_size():
1142         """Return a Deferred that fires with None or an integer. None
1143         indicates that the Uploadable doesn't care about segment size, and
1144         the IEncryptedUploadable wrapper will use a default of probably 1MB.
1145         If provided, the integer will be used as the maximum segment size.
1146         Larger values reduce hash overhead, smaller values reduce memory
1147         footprint and cause data to be delivered in smaller pieces (which may
1148         provide a smoother and more predictable download experience).
1149
1150         There are other constraints on the segment size (see
1151         IEncryptedUploadable.get_encoding_parameters), so the final segment
1152         size may be smaller than the one returned by this method.
1153         """
1154
1155     def get_encoding_parameters():
1156         """Return a Deferred that either fires with None or with a tuple of
1157         (k,happy,n). None indicates that the Uploadable doesn't care how it
1158         is encoded, causing the Uploader to use default k/happy/n (either
1159         hard-coded or provided by the Introducer).
1160
1161         This allows some IUploadables to request better redundancy than
1162         others.
1163         """
1164
1165     def get_encryption_key():
1166         """Return a Deferred that fires with a 16-byte AES key. This key will
1167         be used to encrypt the data. The key will also be hashed to derive
1168         the StorageIndex.
1169
1170         Uploadables which want to achieve convergence should hash their file
1171         contents and the serialized_encoding_parameters to form the key
1172         (which of course requires a full pass over the data). Uploadables can
1173         use the upload.ConvergentUploadMixin class to achieve this
1174         automatically.
1175
1176         Uploadables which do not care about convergence (or do not wish to
1177         make multiple passes over the data) can simply return a
1178         strongly-random 16 byte string.
1179
1180         get_encryption_key() may be called multiple times: the IUploadable is
1181         required to return the same value each time.
1182         """
1183
1184     def read(length):
1185         """Return a Deferred that fires with a list of strings (perhaps with
1186         only a single element) which, when concatenated together, contain the
1187         next 'length' bytes of data. If EOF is near, this may provide fewer
1188         than 'length' bytes. The total number of bytes provided by read()
1189         before it signals EOF must equal the size provided by get_size().
1190
1191         If the data must be acquired through multiple internal read
1192         operations, returning a list instead of a single string may help to
1193         reduce string copies.
1194
1195         'length' will typically be equal to (min(get_size(),1MB)/req_shares),
1196         so a 10kB file means length=3kB, 100kB file means length=30kB,
1197         and >=1MB file means length=300kB.
1198
1199         This method provides for a single full pass through the data. Later
1200         use cases may desire multiple passes or access to only parts of the
1201         data (such as a mutable file making small edits-in-place). This API
1202         will be expanded once those use cases are better understood.
1203         """
1204
1205     def close():
1206         """The upload is finished, and whatever filehandle was in use may be
1207         closed."""
1208
1209 class IUploader(Interface):
1210     def upload(uploadable):
1211         """Upload the file. 'uploadable' must impement IUploadable. This
1212         returns a Deferred which fires with the URI of the file."""
1213
1214     def upload_ssk(write_capability, new_version, uploadable):
1215         """TODO: how should this work?"""
1216
1217 class IChecker(Interface):
1218     def check(uri_to_check):
1219         """Accepts an IVerifierURI, and checks upon the health of its target.
1220
1221         For now, uri_to_check must be an IVerifierURI. In the future we
1222         expect to relax that to be anything that can be adapted to
1223         IVerifierURI (like read-only or read-write dirnode/filenode URIs).
1224
1225         This returns a Deferred. For dirnodes, this fires with either True or
1226         False (dirnodes are not distributed, so their health is a boolean).
1227
1228         For filenodes, this fires with a tuple of (needed_shares,
1229         total_shares, found_shares, sharemap). The first three are ints. The
1230         basic health of the file is found_shares / needed_shares: if less
1231         than 1.0, the file is unrecoverable.
1232
1233         The sharemap has a key for each sharenum. The value is a list of
1234         (binary) nodeids who hold that share. If two shares are kept on the
1235         same nodeid, they will fail as a pair, and overall reliability is
1236         decreased.
1237
1238         The IChecker instance remembers the results of the check. By default,
1239         these results are stashed in RAM (and are forgotten at shutdown). If
1240         a file named 'checker_results.db' exists in the node's basedir, it is
1241         used as a sqlite database of results, making them persistent across
1242         runs. To start using this feature, just 'touch checker_results.db',
1243         and the node will initialize it properly the next time it is started.
1244         """
1245
1246     def verify(uri_to_check):
1247         """Accepts an IVerifierURI, and verifies the crypttext of the target.
1248
1249         This is a more-intensive form of checking. For verification, the
1250         file's crypttext contents are retrieved, and the associated hash
1251         checks are performed. If a storage server is holding a corrupted
1252         share, verification will detect the problem, but checking will not.
1253         This returns a Deferred that fires with True if the crypttext hashes
1254         look good, and will probably raise an exception if anything goes
1255         wrong.
1256
1257         For dirnodes, 'verify' is the same as 'check', so the Deferred will
1258         fire with True or False.
1259
1260         Verification currently only uses a minimal subset of peers, so a lot
1261         of share corruption will not be caught by it. We expect to improve
1262         this in the future.
1263         """
1264
1265     def checker_results_for(uri_to_check):
1266         """Accepts an IVerifierURI, and returns a list of previously recorded
1267         checker results. This method performs no checking itself: it merely
1268         reports the results of checks that have taken place in the past.
1269
1270         Each element of the list is a two-entry tuple: (when, results).
1271         The 'when' values are timestamps (float seconds since epoch), and the
1272         results are as defined in the check() method.
1273
1274         Note: at the moment, this is specified to return synchronously. We
1275         might need to back away from this in the future.
1276         """
1277
1278 class IClient(Interface):
1279     def upload(uploadable):
1280         """Upload some data into a CHK, get back the URI string for it.
1281         @param uploadable: something that implements IUploadable
1282         @return: a Deferred that fires with the (string) URI for this file.
1283         """
1284
1285     def create_mutable_file(contents=""):
1286         """Create a new mutable file with contents, get back the URI string.
1287         @param contents: the initial contents to place in the file.
1288         @return: a Deferred that fires with tne (string) SSK URI for the new
1289                  file.
1290         """
1291
1292     def create_empty_dirnode():
1293         """Create a new dirnode, empty and unattached.
1294         @return: a Deferred that fires with the new IDirectoryNode instance.
1295         """
1296
1297     def create_node_from_uri(uri):
1298         """Create a new IFilesystemNode instance from the uri, synchronously.
1299         @param uri: a string or IURI-providing instance. This could be for a
1300                     LiteralFileNode, a CHK file node, a mutable file node, or
1301                     a directory node
1302         @return: an instance that provides IFilesystemNode (or more usefully one
1303                  of its subclasses). File-specifying URIs will result in
1304                  IFileNode or IMutableFileNode -providing instances, like
1305                  FileNode, LiteralFileNode, or MutableFileNode.
1306                  Directory-specifying URIs will result in
1307                  IDirectoryNode-providing instances, like NewDirectoryNode.
1308         """
1309
1310
1311 class NotCapableError(Exception):
1312     """You have tried to write to a read-only node."""
1313
1314 class BadWriteEnablerError(Exception):
1315     pass
1316
1317 class RIControlClient(RemoteInterface):
1318
1319     def wait_for_client_connections(num_clients=int):
1320         """Do not return until we have connections to at least NUM_CLIENTS
1321         storage servers.
1322         """
1323
1324     def upload_from_file_to_uri(filename=str):
1325         """Upload a file to the grid. This accepts a filename (which must be
1326         absolute) that points to a file on the node's local disk. The node
1327         will read the contents of this file, upload it to the grid, then
1328         return the URI at which it was uploaded.
1329         """
1330         return URI
1331
1332     def download_from_uri_to_file(uri=URI, filename=str):
1333         """Download a file from the grid, placing it on the node's local disk
1334         at the given filename (which must be absolute[?]). Returns the
1335         absolute filename where the file was written."""
1336         return str
1337
1338     # debug stuff
1339
1340     def get_memory_usage():
1341         """Return a dict describes the amount of memory currently in use. The
1342         keys are 'VmPeak', 'VmSize', and 'VmData'. The values are integers,
1343         measuring memory consupmtion in bytes."""
1344         return DictOf(str, int)
1345
1346     def speed_test(count=int, size=int, mutable=Any()):
1347         """Write 'count' tempfiles to disk, all of the given size. Measure
1348         how long (in seconds) it takes to upload them all to the servers.
1349         Then measure how long it takes to download all of them. If 'mutable'
1350         is 'create', time creation of mutable files. If 'mutable' is
1351         'upload', then time access to the same mutable file instead of
1352         creating one.
1353
1354         Returns a tuple of (upload_time, download_time).
1355         """
1356         return (float, float)
1357
1358     def measure_peer_response_time():
1359         """Send a short message to each connected peer, and measure the time
1360         it takes for them to respond to it. This is a rough measure of the
1361         application-level round trip time.
1362
1363         @return: a dictionary mapping peerid to a float (RTT time in seconds)
1364         """
1365
1366         return DictOf(Nodeid, float)
1367
1368 UploadResults = DictOf(str, str)
1369
1370 class RIEncryptedUploadable(RemoteInterface):
1371     __remote_name__ = "RIEncryptedUploadable.tahoe.allmydata.com"
1372
1373     def get_size():
1374         return int
1375
1376     def get_all_encoding_parameters():
1377         return (int, int, int, long)
1378
1379     def read_encrypted(offset=long, length=long):
1380         return ListOf(str)
1381
1382     def get_plaintext_hashtree_leaves(first=int, last=int, num_segments=int):
1383         return ListOf(Hash)
1384
1385     def get_plaintext_hash():
1386         return Hash
1387
1388     def close():
1389         return None
1390
1391
1392 class RICHKUploadHelper(RemoteInterface):
1393     __remote_name__ = "RIUploadHelper.tahoe.allmydata.com"
1394
1395     def upload(reader=RIEncryptedUploadable):
1396         return UploadResults
1397
1398
1399 class RIHelper(RemoteInterface):
1400     __remote_name__ = "RIHelper.tahoe.allmydata.com"
1401
1402     def upload_chk(si=StorageIndex):
1403         """See if a file with a given storage index needs uploading. The
1404         helper will ask the appropriate storage servers to see if the file
1405         has already been uploaded. If so, the helper will return a set of
1406         'upload results' that includes whatever hashes are needed to build
1407         the read-cap, and perhaps a truncated sharemap.
1408
1409         If the file has not yet been uploaded (or if it was only partially
1410         uploaded), the helper will return an empty upload-results dictionary
1411         and also an RICHKUploadHelper object that will take care of the
1412         upload process. The client should call upload() on this object and
1413         pass it a reference to an RIEncryptedUploadable object that will
1414         provide ciphertext. When the upload is finished, the upload() method
1415         will finish and return the upload results.
1416         """
1417         return (UploadResults, ChoiceOf(RICHKUploadHelper, None))
1418
1419
1420 class RIStatsProvider(RemoteInterface):
1421     __remote_name__ = "RIStatsProvider.tahoe.allmydata.com"
1422     """
1423     Provides access to statistics and monitoring information.
1424     """
1425
1426     def get_stats():
1427         """
1428         returns a dictionary containing 'counters' and 'stats', each a dictionary
1429         with string counter/stat name keys, and numeric values.  counters are
1430         monotonically increasing measures of work done, and stats are instantaneous
1431         measures (potentially time averaged internally)
1432         """
1433         return DictOf(str, DictOf(str, ChoiceOf(float, int, long)))
1434
1435 class RIStatsGatherer(RemoteInterface):
1436     __remote_name__ = "RIStatsGatherer.tahoe.allmydata.com"
1437     """
1438     Provides a monitoring service for centralised collection of stats
1439     """
1440
1441     def provide(provider=RIStatsProvider, nickname=str):
1442         """
1443         @param provider: a stats collector instance which should be polled
1444                          periodically by the gatherer to collect stats.
1445         @param nickname: a name useful to identify the provided client
1446         """
1447         return None
1448
1449
1450 class IStatsProducer(Interface):
1451     def get_stats():
1452         """
1453         returns a dictionary, with str keys representing the names of stats
1454         to be monitored, and numeric values.
1455         """
1456