]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/immutable/literal.py
16effaa4d40a3e08a7e708bfa8c143e66de8d530
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / immutable / literal.py
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
8
9 class _ImmutableFileNodeBase(object):
10     implements(IImmutableFileNode, ICheckable)
11
12     def get_write_uri(self):
13         return None
14
15     def get_readonly_uri(self):
16         return self.get_uri()
17
18     def is_mutable(self):
19         return False
20
21     def is_readonly(self):
22         return True
23
24     def is_unknown(self):
25         return False
26
27     def is_allowed_in_immutable_directory(self):
28         return True
29
30     def raise_error(self):
31         pass
32
33     def __hash__(self):
34         return self.u.__hash__()
35     def __eq__(self, other):
36         if isinstance(other, _ImmutableFileNodeBase):
37             return self.u.__eq__(other.u)
38         else:
39             return False
40     def __ne__(self, other):
41         if isinstance(other, _ImmutableFileNodeBase):
42             return self.u.__eq__(other.u)
43         else:
44             return True
45
46
47 class LiteralProducer:
48     implements(IPushProducer)
49     def resumeProducing(self):
50         pass
51     def stopProducing(self):
52         pass
53
54
55 class LiteralFileNode(_ImmutableFileNodeBase):
56
57     def __init__(self, filecap):
58         assert isinstance(filecap, LiteralFileURI)
59         self.u = filecap
60
61     def get_size(self):
62         return len(self.u.data)
63     def get_current_size(self):
64         return defer.succeed(self.get_size())
65
66     def get_cap(self):
67         return self.u
68     def get_readcap(self):
69         return self.u
70     def get_verify_cap(self):
71         return None
72     def get_repair_cap(self):
73         return None
74
75     def get_uri(self):
76         return self.u.to_string()
77
78     def get_storage_index(self):
79         return None
80
81     def check(self, monitor, verify=False, add_lease=False):
82         return defer.succeed(None)
83
84     def check_and_repair(self, monitor, verify=False, add_lease=False):
85         return defer.succeed(None)
86
87     def read(self, consumer, offset=0, size=None):
88         if size is None:
89             data = self.u.data[offset:]
90         else:
91             data = self.u.data[offset:offset+size]
92
93         # We use twisted.protocols.basic.FileSender, which only does
94         # non-streaming, i.e. PullProducer, where the receiver/consumer must
95         # ask explicitly for each chunk of data. There are only two places in
96         # the Twisted codebase that can't handle streaming=False, both of
97         # which are in the upload path for an FTP/SFTP server
98         # (protocols.ftp.FileConsumer and
99         # vfs.adapters.ftp._FileToConsumerAdapter), neither of which is
100         # likely to be used as the target for a Tahoe download.
101
102         d = basic.FileSender().beginFileTransfer(StringIO(data), consumer)
103         d.addCallback(lambda lastSent: consumer)
104         return d
105
106     # IReadable, IFileNode, IFilesystemNode
107     def get_best_readable_version(self):
108         return defer.succeed(self)
109
110
111     def download_best_version(self):
112         return defer.succeed(self.u.data)
113
114
115     download_to_data = download_best_version
116     get_size_of_best_version = get_current_size