public byte[] NodeToBytes(IIndexNode node) { var bb = new byte[_options.BlockSize]; bb[0] = TypeBit(node); WriteNameToBuffer(ref bb, node.Name); var offset = _options.NameLength + 1; BitConverter.GetBytes(node.BlocksCount).CopyTo(bb, offset); offset += sizeof(long); BitConverter.GetBytes(node.IndirectNodeNumber).CopyTo(bb, offset); offset += sizeof(long); BitConverter.GetBytes(node.Version).CopyTo(bb, offset); offset += sizeof(long); BitConverter.GetBytes(node.PredecessorBlockNr).CopyTo(bb, offset); offset += sizeof(long); var file = node as VFSFile; if (file != null) BitConverter.GetBytes(file.LastBlockSize).CopyTo(bb, offset); var folder = node as Folder; if (folder != null) BitConverter.GetBytes(folder.BlocksUsed).CopyTo(bb, offset); return bb; }
// NOTE: long parameter smell. Are they all needed? If yes: refactoring "introduce parameter object". public BlockList(IIndexNode node, BlockAllocation blockAllocation, FileSystemOptions options, BlockParser blockParser, BlockManipulator blockManipulator, Persistence persistence) { _node = node; _blockAllocation = blockAllocation; _options = options; _blockParser = blockParser; _blockManipulator = blockManipulator; _persistence = persistence; }
private static byte TypeBit(IIndexNode node) { if (node is Folder) return FolderType; if (node is VFSFile) return FileType; throw new ArgumentException("is not a folder or file", "node"); }
public void Export(IIndexNode source, string destination, CallbacksBase exportCallbacks) { _lock.EnterWriteLock(); try { _fileSystem.Export(source, destination, exportCallbacks); } finally { _lock.ExitWriteLock(); } }
public void Delete(IIndexNode node) { _lock.EnterWriteLock(); try { _fileSystem.Delete(node); } finally { _lock.ExitWriteLock(); } }
public void Copy(IIndexNode nodeToCopy, Folder destination, string nameOfCopiedElement, CallbacksBase copyCallbacks) { _lock.EnterWriteLock(); try { _fileSystem.Copy(nodeToCopy, destination, nameOfCopiedElement, copyCallbacks); } finally { _lock.ExitWriteLock(); } }
private IIndexNode FindNode(Queue<string> folders, IIndexNode node) { if (!folders.Any()) return node; var folder = node as Folder; if (folder == null) return null; var folderName = folders.Dequeue(); var subFolder = _fileSystem.Find(folder, folderName); return subFolder == null ? null : FindNode(folders, subFolder); }
public void Persist(IIndexNode node) { _blockManipulator.WriteBlock(node.BlockNumber, _blockParser.NodeToBytes(node)); }
private IBlockList GetBlockList(IIndexNode parentFolder) { return new BlockList(parentFolder, _blockAllocation, _options, _blockParser, _blockManipulator, _persistence); }
private void AppendBlockReference(IIndexNode parentFolder, long reference) { GetBlockList(parentFolder).AddReference(reference); }
/// <summary> /// Copies the toCopy index node, and replaces the toReplace node with the replacement /// </summary> /// <param name="toCopy">To index node to copy.</param> /// <param name="toReplace">To node to be replaced. Can be set to null if only a node should be appended and no one should be replaced.</param> /// <param name="replacement">The node to replace the node toReplace. Can be set to null for the delete action.</param> /// <param name="newVersion"></param> /// <returns></returns> public Folder CopyReplacingReference(Folder toCopy, IIndexNode toReplace, IIndexNode replacement, long newVersion) { var toReplaceNr = toReplace == null ? 0 : toReplace.BlockNumber; var replacementNr = replacement == null ? 0 : replacement.BlockNumber; var newFolder = new Folder(toCopy.Name) { //BlocksCount = newBlocksCount, PredecessorBlockNr = toCopy.BlockNumber, //toReplaceNr, BlockNumber = _blockAllocation.Allocate(), Version = newVersion }; _persistence.Persist(newFolder); var b = new BlockList(newFolder, _blockAllocation, _options, _blockParser, _blockManipulator, _persistence); // This algorithm section can be improved. We don't have to copy all references, we only have to copy the references that are different. foreach (var reference in AsEnumerable()) { var blockNumber = reference.BlockNumber == toReplaceNr ? replacementNr : reference.BlockNumber; if (blockNumber != 0) b.AddReference(blockNumber); } if (toReplace == null && replacement != null) b.AddReference(replacementNr); if (replacement != null) replacement.Parent = newFolder; return newFolder; }
public void Copy(IIndexNode nodeToCopy, Folder destination, string name, CallbacksBase copyCallbacks) { CheckDisposed(); CheckName(name); CheckVersion(); // Gather totals (copy in ~O(1) :D) copyCallbacks.TotalToProcess++; // Do the real copy if (nodeToCopy is Folder) CopyFolder(nodeToCopy as Folder, destination, name, copyCallbacks); else if (nodeToCopy is VFSFile) CopyFile(nodeToCopy as VFSFile, destination, name, copyCallbacks); else throw new ArgumentException("nodeToCopy must be of type Folder or VFSFile", "nodeToCopy"); SetBlocksUsed(); copyCallbacks.OperationCompleted(!copyCallbacks.ShouldAbort()); }
private Folder ArchiveAndReplaceRoot(Folder folderToCopy, IIndexNode nodeToReplace, IIndexNode nodeReplacement) { if (folderToCopy == null) throw new VFSException("Node cannot be null"); var toCopy = folderToCopy; var toReplace = nodeToReplace; var replacement = nodeReplacement; Folder copyOfFolderToCopy = null; Folder previous = null; while (toCopy != null) { var newFolder = GetBlockList(toCopy).CopyReplacingReference(toCopy, toReplace, replacement, NextVersion); if (copyOfFolderToCopy == null) copyOfFolderToCopy = newFolder; if (previous != null) { previous.Parent = newFolder; _persistence.Persist(previous); } toReplace = toCopy; toCopy = toCopy.Parent; replacement = newFolder; previous = newFolder; } Debug.Assert(previous != null, "previous != null"); Debug.Assert(string.IsNullOrEmpty(previous.Name), "previous.Name == \"\""); // previous is now the new root node! previous.IsRoot = true; _persistence.Persist(previous); ResetRoot(previous); return copyOfFolderToCopy; }
public void Export(IIndexNode source, string destination, CallbacksBase exportCallbacks) { var absoluteDestination = Path.GetFullPath(destination); EnsureParentDirectoryExists(absoluteDestination); CheckDisposed(); if (source == null) throw new NotFoundException(); if (File.Exists(absoluteDestination) || Directory.Exists(absoluteDestination)) throw new VFSException("Destination already exists!"); // Gather totals if (source is Folder) CollectExportDirectoryTotals(source as Folder, exportCallbacks); else if (source is VFSFile) exportCallbacks.TotalToProcess++; else throw new ArgumentException("Source must be of type Folder or VFSFile", "source"); // Do the real export if (source is Folder) ExportFolder(source as Folder, absoluteDestination, exportCallbacks); else ExportFile(source as VFSFile, absoluteDestination, exportCallbacks); exportCallbacks.OperationCompleted(!exportCallbacks.ShouldAbort()); }
public void Delete(IIndexNode node) { CheckDisposed(); CheckVersion(); if (node.Parent == null) throw new VFSException("Cannot delete root node"); ArchiveAndReplaceRoot(node.Parent, node, null); SetBlocksUsed(); }