source file: /home/buildslave/tahoe/edgy/build/src/allmydata/introducer/interfaces.py
file stats: 35 lines, 35 executed: 100.0% covered
1. 2. from zope.interface import Interface 3. from foolscap.schema import StringConstraint, TupleOf, SetOf 4. from foolscap import RemoteInterface 5. FURL = StringConstraint(1000) 6. 7. # Announcements are (FURL, service_name, remoteinterface_name, 8. # nickname, my_version, oldest_supported) 9. # the (FURL, service_name, remoteinterface_name) refer to the service being 10. # announced. The (nickname, my_version, oldest_supported) refer to the 11. # client as a whole. The my_version/oldest_supported strings can be parsed 12. # by an allmydata.util.version.Version instance, and then compared. The 13. # first goal is to make sure that nodes are not confused by speaking to an 14. # incompatible peer. The second goal is to enable the development of 15. # backwards-compatibility code. 16. 17. Announcement = TupleOf(FURL, str, str, 18. str, str, str) 19. 20. class RIIntroducerSubscriberClient(RemoteInterface): 21. __remote_name__ = "RIIntroducerSubscriberClient.tahoe.allmydata.com" 22. 23. def announce(announcements=SetOf(Announcement)): 24. """I accept announcements from the publisher.""" 25. return None 26. 27. def set_encoding_parameters(parameters=(int, int, int)): 28. """Advise the client of the recommended k-of-n encoding parameters 29. for this grid. 'parameters' is a tuple of (k, desired, n), where 'n' 30. is the total number of shares that will be created for any given 31. file, while 'k' is the number of shares that must be retrieved to 32. recover that file, and 'desired' is the minimum number of shares that 33. must be placed before the uploader will consider its job a success. 34. n/k is the expansion ratio, while k determines the robustness. 35. 36. Introducers should specify 'n' according to the expected size of the 37. grid (there is no point to producing more shares than there are 38. peers), and k according to the desired reliability-vs-overhead goals. 39. 40. Note that setting k=1 is equivalent to simple replication. 41. """ 42. return None 43. 44. # When Foolscap can handle multiple interfaces (Foolscap#17), the 45. # full-powered introducer will implement both RIIntroducerPublisher and 46. # RIIntroducerSubscriberService. Until then, we define 47. # RIIntroducerPublisherAndSubscriberService as a combination of the two, and 48. # make everybody use that. 49. 50. class RIIntroducerPublisher(RemoteInterface): 51. """To publish a service to the world, connect to me and give me your 52. announcement message. I will deliver a copy to all connected subscribers.""" 53. __remote_name__ = "RIIntroducerPublisher.tahoe.allmydata.com" 54. 55. def publish(announcement=Announcement): 56. # canary? 57. return None 58. 59. class RIIntroducerSubscriberService(RemoteInterface): 60. __remote_name__ = "RIIntroducerSubscriberService.tahoe.allmydata.com" 61. 62. def subscribe(subscriber=RIIntroducerSubscriberClient, service_name=str): 63. """Give me a subscriber reference, and I will call its new_peers() 64. method will any announcements that match the desired service name. I 65. will ignore duplicate subscriptions. 66. """ 67. return None 68. 69. class RIIntroducerPublisherAndSubscriberService(RemoteInterface): 70. __remote_name__ = "RIIntroducerPublisherAndSubscriberService.tahoe.allmydata.com" 71. def publish(announcement=Announcement): 72. return None 73. def subscribe(subscriber=RIIntroducerSubscriberClient, service_name=str): 74. return None 75. 76. class IIntroducerClient(Interface): 77. """I provide service introduction facilities for a node. I help nodes 78. publish their services to the rest of the world, and I help them learn 79. about services available on other nodes.""" 80. 81. def publish(furl, service_name, remoteinterface_name): 82. """Once you call this, I will tell the world that the Referenceable 83. available at FURL is available to provide a service named 84. SERVICE_NAME. The precise definition of the service being provided is 85. identified by the Foolscap 'remote interface name' in the last 86. parameter: this is supposed to be a globally-unique string that 87. identifies the RemoteInterface that is implemented.""" 88. 89. def subscribe_to(service_name): 90. """Call this if you will eventually want to use services with the 91. given SERVICE_NAME. This will prompt me to subscribe to announcements 92. of those services. You can pick up the announcements later by calling 93. get_all_connections_for() or get_permuted_peers(). 94. """ 95. 96. def get_all_connections(): 97. """Return a frozenset of (nodeid, service_name, rref) tuples, one for 98. each active connection we've established to a remote service. This is 99. mostly useful for unit tests that need to wait until a certain number 100. of connections have been made.""" 101. 102. def get_all_connectors(): 103. """Return a dict that maps from (nodeid, service_name) to a 104. RemoteServiceConnector instance for all services that we are actively 105. trying to connect to. Each RemoteServiceConnector has the following 106. public attributes:: 107. 108. service_name: the type of service provided, like 'storage' 109. announcement_time: when we first heard about this service 110. last_connect_time: when we last established a connection 111. last_loss_time: when we last lost a connection 112. 113. version: the peer's version, from the most recent connection 114. oldest_supported: the peer's oldest supported version, same 115. 116. rref: the RemoteReference, if connected, otherwise None 117. remote_host: the IAddress, if connected, otherwise None 118. 119. This method is intended for monitoring interfaces, such as a web page 120. which describes connecting and connected peers. 121. """ 122. 123. def get_all_peerids(): 124. """Return a frozenset of all peerids to whom we have a connection (to 125. one or more services) established. Mostly useful for unit tests.""" 126. 127. def get_all_connections_for(service_name): 128. """Return a frozenset of (nodeid, service_name, rref) tuples, one 129. for each active connection that provides the given SERVICE_NAME.""" 130. 131. def get_permuted_peers(service_name, key): 132. """Returns an ordered list of (peerid, rref) tuples, selecting from 133. the connections that provide SERVICE_NAME, using a hash-based 134. permutation keyed by KEY. This randomizes the service list in a 135. repeatable way, to distribute load over many peers. 136. """ 137. 138. def connected_to_introducer(): 139. """Returns a boolean, True if we are currently connected to the 140. introducer, False if not.""" 141.