All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.apple.foundationdb.directory.DirectorySubspace Maven / Gradle / Ivy

/*
 * DirectorySubspace.java
 *
 * This source file is part of the FoundationDB open source project
 *
 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.apple.foundationdb.directory;

import static com.apple.foundationdb.directory.DirectoryLayer.EMPTY_BYTES;
import static com.apple.foundationdb.directory.DirectoryLayer.EMPTY_PATH;
import static com.apple.foundationdb.tuple.ByteArrayUtil.printable;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import com.apple.foundationdb.ReadTransactionContext;
import com.apple.foundationdb.TransactionContext;
import com.apple.foundationdb.subspace.Subspace;

/**
 *  A DirectorySubspace represents the contents of a directory, but it
 *  also remembers the path with which it was opened and offers convenience
 *  methods to operate on the directory at that path.
 *
 * 

* An instance of DirectorySubspace can be used for all the usual subspace * operations. It can also be used to operate on the directory with which * it was opened. *

*/ public class DirectorySubspace extends Subspace implements Directory { private final List path; private final byte[] layer; private final DirectoryLayer directoryLayer; DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer) { this(path, prefix, directoryLayer, EMPTY_BYTES); } DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer, byte[] layer) { super(prefix); this.path = path; this.layer = layer; this.directoryLayer = directoryLayer; } /** * @return a printable representation of this {@code DirectorySubspace} */ @Override public String toString() { return getClass().getSimpleName() + '(' + DirectoryUtil.pathStr(path) + ", " + printable(getKey()) + ')'; } /** * Returns whether this {@code DirectorySubspace} is equal to {@code rhs}. * Two {@code DirectorySubspace}s are equal if they were created by the same * {@link DirectoryLayer} and have the same path, layer, and subspace prefix. * * @param rhs the {@code} Object to test for equality * @return true if this is equal to {@code rhs} */ @Override public boolean equals(Object rhs) { if(this == rhs) { return true; } if(rhs == null || getClass() != rhs.getClass()) { return false; } DirectorySubspace other = (DirectorySubspace)rhs; return (path == other.path || path.equals(other.path)) && Arrays.equals(layer, other.layer) && directoryLayer.equals(other.directoryLayer) && super.equals(rhs); } /** * Computes a hash code compatible with the {@link #equals(Object) equals()} method of * this class. In particular, it will produce a hash code that is based off of the hashes * of its path, its layer, and its subspace prefix. * * @return a hash compatible with this class's {@code equals()} method */ @Override public int hashCode() { return path.hashCode() ^ (Arrays.hashCode(layer) * 1153) ^ (directoryLayer.hashCode() * 929) ^ (super.hashCode() * 419); } @Override public List getPath() { return Collections.unmodifiableList(path); } @Override public byte[] getLayer() { return Arrays.copyOf(layer, layer.length); } @Override public DirectoryLayer getDirectoryLayer() { return directoryLayer; } @Override public CompletableFuture createOrOpen(TransactionContext tcx, List subpath, byte[] otherLayer) { return directoryLayer.createOrOpen(tcx, getPartitionSubpath(subpath), otherLayer); } @Override public CompletableFuture open(ReadTransactionContext tcx, List subpath, byte[] otherLayer) { return directoryLayer.open(tcx, getPartitionSubpath(subpath), otherLayer); } @Override public CompletableFuture create(TransactionContext tcx, List subpath, byte[] otherLayer, byte[] prefix) { return directoryLayer.create(tcx, getPartitionSubpath(subpath), otherLayer, prefix); } @Override public CompletableFuture> list(ReadTransactionContext tcx, List subpath) { return directoryLayer.list(tcx, getPartitionSubpath(subpath)); } @Override public CompletableFuture move(TransactionContext tcx, List oldSubpath, List newSubpath) { return directoryLayer.move(tcx, getPartitionSubpath(oldSubpath), getPartitionSubpath(newSubpath)); } @Override public CompletableFuture moveTo(TransactionContext tcx, List newAbsolutePath) { DirectoryLayer dir = getLayerForPath(EMPTY_PATH); int partitionLen = dir.getPath().size(); List partitionPath = newAbsolutePath.subList(0, Math.min(newAbsolutePath.size(), partitionLen)); if(!partitionPath.equals(dir.getPath())) throw new DirectoryMoveException("Cannot move between partitions", path, newAbsolutePath); return dir.move(tcx, getPartitionSubpath(EMPTY_PATH, dir), newAbsolutePath.subList(partitionLen, newAbsolutePath.size())); } @Override public CompletableFuture remove(TransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); return dir.remove(tcx, getPartitionSubpath(subpath, dir)); } @Override public CompletableFuture removeIfExists(TransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); return dir.removeIfExists(tcx, getPartitionSubpath(subpath, dir)); } @Override public CompletableFuture exists(ReadTransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); return dir.exists(tcx, getPartitionSubpath(subpath, dir)); } private List getPartitionSubpath(List path) { return getPartitionSubpath(path, directoryLayer); } private List getPartitionSubpath(List path, DirectoryLayer directoryLayer) { return PathUtil.join(this.path.subList(directoryLayer.getPath().size(), this.path.size()), path); } /** * Called by all functions that could operate on this subspace directly (moveTo, remove, removeIfExists, exists). * Subclasses can chooose to return a different directory layer to use for the operation if path is in fact empty. */ DirectoryLayer getLayerForPath(List path) { return directoryLayer; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy