]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - allmydata/vdrive.py
allmydata.Crypto: fix all internal imports
[tahoe-lafs/tahoe-lafs.git] / allmydata / vdrive.py
1
2 """This is the client-side facility to manipulate virtual drives."""
3
4 from twisted.application import service
5 from twisted.internet import defer
6 from twisted.python import log
7 from allmydata import upload, download
8
9 class VDrive(service.MultiService):
10     name = "vdrive"
11
12     def set_root(self, root):
13         self.gvd_root = root
14
15     def dirpath(self, dir_or_path):
16         if isinstance(dir_or_path, str):
17             return self.get_dir(dir_or_path)
18         return defer.succeed(dir_or_path)
19
20     def get_dir(self, path):
21         """Return a Deferred that fires with a RemoteReference to a
22         MutableDirectoryNode at the given /-delimited path."""
23         d = defer.succeed(self.gvd_root)
24         if path.startswith("/"):
25             path = path[1:]
26         if path == "":
27             return d
28         for piece in path.split("/"):
29             d.addCallback(lambda parent: parent.callRemote("list"))
30             def _find(table, subdir):
31                 for name,target in table:
32                     if name == subdir:
33                         return target
34                 else:
35                     raise KeyError("no such directory '%s' in '%s'" %
36                                    (subdir, [t[0] for t in table]))
37             d.addCallback(_find, piece)
38         def _check(subdir):
39             assert not isinstance(subdir, str), "Hey, %s shouldn't be a string" % subdir
40             return subdir
41         d.addCallback(_check)
42         return d
43
44     def get_verifierid_from_parent(self, parent, filename):
45         assert not isinstance(parent, str), "'%s' isn't a directory node" % (parent,)
46         d = parent.callRemote("list")
47         def _find(table):
48             for name,target in table:
49                 if name == filename:
50                     assert isinstance(target, str), "Hey, %s isn't a file" % filename
51                     return target
52             else:
53                 raise KeyError("no such file '%s' in '%s'" %
54                                (filename, [t[0] for t in table]))
55         d.addCallback(_find)
56         return d
57
58     def get_root(self):
59         return self.gvd_root
60
61     def listdir(self, dir_or_path):
62         d = self.dirpath(dir_or_path)
63         d.addCallback(lambda parent: parent.callRemote("list"))
64         def _list(table):
65             return [t[0] for t in table]
66         d.addCallback(_list)
67         return d
68
69     def put_file(self, dir_or_path, name, uploadable):
70         """Upload an IUploadable and add it to the virtual drive (as an entry
71         called 'name', in 'dir_or_path') 'dir_or_path' must either be a
72         string like 'root/subdir1/subdir2', or a directory node (either the
73         root directory node returned by get_root(), or a subdirectory
74         returned by list() ).
75
76         The uploadable can be an instance of allmydata.upload.Data,
77         FileHandle, or FileName.
78
79         I return a deferred that will fire when the operation is complete.
80         """
81
82         log.msg("putting file to '%s'" % name)
83         ul = self.parent.getServiceNamed("uploader")
84         d = self.dirpath(dir_or_path)
85         def _got_dir(dirnode):
86             d1 = ul.upload(uploadable)
87             d1.addCallback(lambda vid:
88                            dirnode.callRemote("add_file", name, vid))
89             return d1
90         d.addCallback(_got_dir)
91         def _done(res):
92             log.msg("finished putting file to '%s'" % name)
93             return res
94         d.addCallback(_done)
95         return d
96
97     def put_file_by_filename(self, dir_or_path, name, filename):
98         return self.put_file(dir_or_path, name, upload.FileName(filename))
99     def put_file_by_data(self, dir_or_path, name, data):
100         return self.put_file(dir_or_path, name, upload.Data(data))
101     def put_file_by_filehandle(self, dir_or_path, name, filehandle):
102         return self.put_file(dir_or_path, name, upload.FileHandle(filehandle))
103
104     def make_directory(self, dir_or_path, name):
105         d = self.dirpath(dir_or_path)
106         d.addCallback(lambda parent: parent.callRemote("add_directory", name))
107         return d
108
109     def remove(self, parent, name):
110         assert not isinstance(parent, str)
111         log.msg("vdrive removing %s" % name)
112         # first find the verifierid
113         d = self.get_verifierid_from_parent(parent, name)
114         def _got_verifierid(vid):
115             # TODO: delete the file's shares using this
116             pass
117         d.addCallback(_got_verifierid)
118         def _delete_from_parent(res):
119             return parent.callRemote("remove", name)
120         d.addCallback(_delete_from_parent)
121         def _done(res):
122             log.msg("vdrive done removing %s" % name)
123         d.addCallback(_done)
124         return d
125
126
127     def get_file(self, dir_and_name_or_path, download_target):
128         """Retrieve a file from the virtual drive and put it somewhere.
129
130         The file to be retrieved may either be specified as a (dir, name)
131         tuple or as a full /-delimited pathname. In the former case, 'dir'
132         can be either a DirectoryNode or a pathname.
133
134         The download target must be an IDownloadTarget instance like
135         allmydata.download.Data, .FileName, or .FileHandle .
136         """
137
138         log.msg("getting file from %s" % (dir_and_name_or_path,))
139         dl = self.parent.getServiceNamed("downloader")
140
141         if isinstance(dir_and_name_or_path, tuple):
142             dir_or_path, name = dir_and_name_or_path
143             d = self.dirpath(dir_or_path)
144             def _got_dir(dirnode):
145                 return self.get_verifierid_from_parent(dirnode, name)
146             d.addCallback(_got_dir)
147         else:
148             rslash = dir_and_name_or_path.rfind("/")
149             if rslash == -1:
150                 # we're looking for a file in the root directory
151                 dir = self.gvd_root
152                 name = dir_and_name_or_path
153                 d = self.get_verifierid_from_parent(dir, name)
154             else:
155                 dirpath = dir_and_name_or_path[:rslash]
156                 name = dir_and_name_or_path[rslash+1:]
157                 d = self.dirpath(dirpath)
158                 d.addCallback(lambda dir:
159                               self.get_verifierid_from_parent(dir, name))
160
161         def _got_verifierid(verifierid):
162             return dl.download(verifierid, download_target)
163         d.addCallback(_got_verifierid)
164         def _done(res):
165             log.msg("finished getting file")
166             return res
167         d.addCallback(_done)
168         return d
169
170     def get_file_to_filename(self, from_where, filename):
171         return self.get_file(from_where, download.FileName(filename))
172     def get_file_to_data(self, from_where):
173         return self.get_file(from_where, download.Data())
174     def get_file_to_filehandle(self, from_where, filehandle):
175         return self.get_file(from_where, download.FileHandle(filehandle))
176