1 /*
2  * DirectorySubspace.cpp
3  *
4  * This source file is part of the FoundationDB open source project
5  *
6  * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #include "DirectorySubspace.h"
22 
23 namespace FDB {
DirectorySubspace(Path const & path,StringRef const & prefix,Reference<DirectoryLayer> directoryLayer,Standalone<StringRef> const & layer)24 	DirectorySubspace::DirectorySubspace(Path const& path, StringRef const& prefix, Reference<DirectoryLayer> directoryLayer, Standalone<StringRef> const& layer)
25 		: Subspace(prefix), directoryLayer(directoryLayer), path(path), layer(layer) { }
26 
27 
create(Reference<Transaction> const & tr,Path const & path,Standalone<StringRef> const & layer,Optional<Standalone<StringRef>> const & prefix)28 	Future<Reference<DirectorySubspace>> DirectorySubspace::create(Reference<Transaction> const& tr, Path const& path, Standalone<StringRef> const& layer,
29 																	Optional<Standalone<StringRef>> const& prefix)
30 	{
31 		return directoryLayer->create(tr, getPartitionSubpath(path), layer, prefix);
32 	}
33 
open(Reference<Transaction> const & tr,Path const & path,Standalone<StringRef> const & layer)34 	Future<Reference<DirectorySubspace>> DirectorySubspace::open(Reference<Transaction> const& tr, Path const& path, Standalone<StringRef> const& layer) {
35 		return directoryLayer->open(tr, getPartitionSubpath(path), layer);
36 	}
37 
createOrOpen(Reference<Transaction> const & tr,Path const & path,Standalone<StringRef> const & layer)38 	Future<Reference<DirectorySubspace>> DirectorySubspace::createOrOpen(Reference<Transaction> const& tr, Path const& path, Standalone<StringRef> const& layer) {
39 		return directoryLayer->createOrOpen(tr, getPartitionSubpath(path), layer);
40 	}
41 
exists(Reference<Transaction> const & tr,Path const & path)42 	Future<bool> DirectorySubspace::exists(Reference<Transaction> const& tr, Path const& path) {
43 		Reference<DirectoryLayer> directoryLayer = getDirectoryLayerForPath(path);
44 		return directoryLayer->exists(tr, getPartitionSubpath(path, directoryLayer));
45 	}
46 
list(Reference<Transaction> const & tr,Path const & path)47 	Future<Standalone<VectorRef<StringRef>>> DirectorySubspace::list(Reference<Transaction> const& tr, Path const& path) {
48 		return directoryLayer->list(tr, getPartitionSubpath(path));
49 	}
50 
move(Reference<Transaction> const & tr,Path const & oldPath,Path const & newPath)51 	Future<Reference<DirectorySubspace>> DirectorySubspace::move(Reference<Transaction> const& tr, Path const& oldPath, Path const& newPath) {
52 		return directoryLayer->move(tr, getPartitionSubpath(oldPath), getPartitionSubpath(newPath));
53 	}
54 
moveTo(Reference<Transaction> const & tr,Path const & newAbsolutePath)55 	Future<Reference<DirectorySubspace>> DirectorySubspace::moveTo(Reference<Transaction> const& tr, Path const& newAbsolutePath) {
56 		Reference<DirectoryLayer> directoryLayer = getDirectoryLayerForPath(Path());
57 		Path directoryLayerPath = directoryLayer->getPath();
58 
59 		if(directoryLayerPath.size() > newAbsolutePath.size()) {
60 			return cannot_move_directory_between_partitions();
61 		}
62 
63 		for(int i = 0; i < directoryLayerPath.size(); ++i) {
64 			if(directoryLayerPath[i] != newAbsolutePath[i]) {
65 				return cannot_move_directory_between_partitions();
66 			}
67 		}
68 
69 		Path newRelativePath(newAbsolutePath.begin() + directoryLayerPath.size(), newAbsolutePath.end());
70 		return directoryLayer->move(tr, getPartitionSubpath(Path(), directoryLayer), newRelativePath);
71 	}
72 
remove(Reference<Transaction> const & tr,Path const & path)73 	Future<Void> DirectorySubspace::remove(Reference<Transaction> const& tr, Path const& path) {
74 		Reference<DirectoryLayer> directoryLayer = getDirectoryLayerForPath(path);
75 		return directoryLayer->remove(tr, getPartitionSubpath(path, directoryLayer));
76 	}
77 
removeIfExists(Reference<Transaction> const & tr,Path const & path)78 	Future<bool> DirectorySubspace::removeIfExists(Reference<Transaction> const& tr, Path const& path) {
79 		Reference<DirectoryLayer> directoryLayer = getDirectoryLayerForPath(path);
80 		return directoryLayer->removeIfExists(tr, getPartitionSubpath(path, directoryLayer));
81 	}
82 
getDirectoryLayer()83 	Reference<DirectoryLayer> DirectorySubspace::getDirectoryLayer() {
84 		return directoryLayer;
85 	}
86 
getLayer() const87 	const Standalone<StringRef> DirectorySubspace::getLayer() const {
88 		return layer;
89 	}
90 
getPath() const91 	const IDirectory::Path DirectorySubspace::getPath() const {
92 		return path;
93 	}
94 
getPartitionSubpath(Path const & path,Reference<DirectoryLayer> directoryLayer) const95 	IDirectory::Path DirectorySubspace::getPartitionSubpath(Path const& path, Reference<DirectoryLayer> directoryLayer) const {
96 		if(!directoryLayer) {
97 			directoryLayer = this->directoryLayer;
98 		}
99 
100 		Path newPath(this->path.begin() + directoryLayer->getPath().size(), this->path.end());
101 		newPath.insert(newPath.end(), path.begin(), path.end());
102 
103 		return newPath;
104 	}
105 
getDirectoryLayerForPath(Path const & path) const106 	Reference<DirectoryLayer> DirectorySubspace::getDirectoryLayerForPath(Path const& path) const {
107 		return directoryLayer;
108 	}
109 }
110