]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/immutable/literal.py
Flesh out "tahoe magic-folder status" command
[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
50     def pauseProducing(self):
51         pass
52
53     def resumeProducing(self):
54         pass
55
56     def stopProducing(self):
57         pass
58
59
60 class LiteralFileNode(_ImmutableFileNodeBase):
61
62     def __init__(self, filecap):
63         assert isinstance(filecap, LiteralFileURI)
64         self.u = filecap
65
66     def get_size(self):
67         return len(self.u.data)
68     def get_current_size(self):
69         return defer.succeed(self.get_size())
70
71     def get_cap(self):
72         return self.u
73     def get_readcap(self):
74         return self.u
75     def get_verify_cap(self):
76         return None
77     def get_repair_cap(self):
78         return None
79
80     def get_uri(self):
81         return self.u.to_string()
82
83     def get_storage_index(self):
84         return None
85
86     def check(self, monitor, verify=False, add_lease=False):
87         return defer.succeed(None)
88
89     def check_and_repair(self, monitor, verify=False, add_lease=False):
90         return defer.succeed(None)
91
92     def read(self, consumer, offset=0, size=None):
93         if size is None:
94             data = self.u.data[offset:]
95         else:
96             data = self.u.data[offset:offset+size]
97
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.
106
107         d = basic.FileSender().beginFileTransfer(StringIO(data), consumer)
108         d.addCallback(lambda lastSent: consumer)
109         return d
110
111     # IReadable, IFileNode, IFilesystemNode
112     def get_best_readable_version(self):
113         return defer.succeed(self)
114
115
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)
121
122
123     download_to_data = download_best_version
124     get_size_of_best_version = get_current_size