internal async Task<FdbDirectorySubspace> MoveInternalAsync(IFdbTransaction trans, IFdbTuple oldPath, IFdbTuple newPath, bool throwOnError) { Contract.Requires(trans != null && oldPath != null && newPath != null); if (oldPath.Count == 0) { throw new InvalidOperationException("The root directory may not be moved."); } if (newPath.Count == 0) { throw new InvalidOperationException("The root directory cannot be overwritten."); } if (newPath.StartsWith(oldPath)) { throw new InvalidOperationException(string.Format("The destination directory({0}) cannot be a subdirectory of the source directory({1}).", newPath, oldPath)); } await CheckWriteVersionAsync(trans).ConfigureAwait(false); var oldNode = await FindAsync(trans, oldPath).ConfigureAwait(false); if (!oldNode.Exists) { if (throwOnError) throw new InvalidOperationException(string.Format("The source directory '{0}' does not exist.", oldPath)); return null; } var newNode = await FindAsync(trans, newPath).ConfigureAwait(false); // we have already checked that old and new are under this partition path, but one of them (or both?) could be under a sub-partition.. if (oldNode.IsInPartition(false) || newNode.IsInPartition(false)) { if (!oldNode.IsInPartition(false) || !newNode.IsInPartition(false) || !FdbTuple.Equals(oldNode.Path, newNode.Path)) { throw new InvalidOperationException("Cannot move between partitions."); } // both nodes are in the same sub-partition, delegate to it return await GetPartitionForNode(newNode).DirectoryLayer.MoveInternalAsync(trans, oldNode.PartitionSubPath, newNode.PartitionSubPath, throwOnError).ConfigureAwait(false); } if (newNode.Exists) { if (throwOnError) throw new InvalidOperationException(string.Format("The destination directory '{0}' already exists. Remove it first.", newPath)); return null; } var parentNode = await FindAsync(trans, newPath.Substring(0, newPath.Count - 1)).ConfigureAwait(false); if (!parentNode.Exists) { if (throwOnError) throw new InvalidOperationException(string.Format("The parent of the destination directory '{0}' does not exist. Create it first.", newPath)); return null; } trans.Set(GetSubDirKey(parentNode.Subspace, newPath.Get<string>(-1)), this.NodeSubspace.UnpackSingle<Slice>(oldNode.Subspace.Key)); await RemoveFromParent(trans, oldPath).ConfigureAwait(false); return ContentsOfNode(oldNode.Subspace, newPath, oldNode.Layer); }
/// <summary>Maps an absolute path to a relative path within this directory layer</summary> internal IFdbTuple ToRelativePath(IFdbTuple path) { if (path == null) throw new ArgumentNullException("path"); if (!path.StartsWith(this.Location)) throw new InvalidOperationException("The path cannot be outside of this partition"); return path.Substring(this.Location.Count); }