1 from cStringIO import StringIO
2 from zope.interface import implements
3 from twisted.internet import defer
4 from twisted.internet.interfaces import IPushProducer
5 from twisted.protocols import basic
6 from allmydata.interfaces import IImmutableFileNode, ICheckable
7 from allmydata.uri import LiteralFileURI
9 class _ImmutableFileNodeBase(object):
10 implements(IImmutableFileNode, ICheckable)
12 def get_write_uri(self):
15 def get_readonly_uri(self):
21 def is_readonly(self):
27 def is_allowed_in_immutable_directory(self):
30 def raise_error(self):
34 return self.u.__hash__()
35 def __eq__(self, other):
36 if isinstance(other, _ImmutableFileNodeBase):
37 return self.u.__eq__(other.u)
40 def __ne__(self, other):
41 if isinstance(other, _ImmutableFileNodeBase):
42 return self.u.__eq__(other.u)
47 class LiteralProducer:
48 implements(IPushProducer)
50 def pauseProducing(self):
53 def resumeProducing(self):
56 def stopProducing(self):
60 class LiteralFileNode(_ImmutableFileNodeBase):
62 def __init__(self, filecap):
63 assert isinstance(filecap, LiteralFileURI)
67 return len(self.u.data)
68 def get_current_size(self):
69 return defer.succeed(self.get_size())
73 def get_readcap(self):
75 def get_verify_cap(self):
77 def get_repair_cap(self):
81 return self.u.to_string()
83 def get_storage_index(self):
86 def check(self, monitor, verify=False, add_lease=False):
87 return defer.succeed(None)
89 def check_and_repair(self, monitor, verify=False, add_lease=False):
90 return defer.succeed(None)
92 def read(self, consumer, offset=0, size=None):
94 data = self.u.data[offset:]
96 data = self.u.data[offset:offset+size]
98 # We use twisted.protocols.basic.FileSender, which only does
99 # non-streaming, i.e. PullProducer, where the receiver/consumer must
100 # ask explicitly for each chunk of data. There are only two places in
101 # the Twisted codebase that can't handle streaming=False, both of
102 # which are in the upload path for an FTP/SFTP server
103 # (protocols.ftp.FileConsumer and
104 # vfs.adapters.ftp._FileToConsumerAdapter), neither of which is
105 # likely to be used as the target for a Tahoe download.
107 d = basic.FileSender().beginFileTransfer(StringIO(data), consumer)
108 d.addCallback(lambda lastSent: consumer)
111 # IReadable, IFileNode, IFilesystemNode
112 def get_best_readable_version(self):
113 return defer.succeed(self)
116 def download_best_version(self, progress=None):
117 if progress is not None:
118 progress.set_progress_total(len(self.u.data))
119 progress.set_progress(len(self.u.data))
120 return defer.succeed(self.u.data)
123 download_to_data = download_best_version
124 get_size_of_best_version = get_current_size