예제 #1
0
        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;
        }
예제 #2
0
 // 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;
 }
예제 #3
0
 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);
        }
예제 #8
0
 public void Persist(IIndexNode node)
 {
     _blockManipulator.WriteBlock(node.BlockNumber, _blockParser.NodeToBytes(node));
 }
예제 #9
0
 private IBlockList GetBlockList(IIndexNode parentFolder)
 {
     return new BlockList(parentFolder, _blockAllocation, _options, _blockParser, _blockManipulator, _persistence);
 }
예제 #10
0
 private void AppendBlockReference(IIndexNode parentFolder, long reference)
 {
     GetBlockList(parentFolder).AddReference(reference);
 }
예제 #11
0
        /// <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;
        }
예제 #12
0
        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());
        }
예제 #13
0
        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;
        }
예제 #14
0
        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());
        }
예제 #15
0
        public void Delete(IIndexNode node)
        {
            CheckDisposed();
            CheckVersion();

            if (node.Parent == null) throw new VFSException("Cannot delete root node");
            ArchiveAndReplaceRoot(node.Parent, node, null);

            SetBlocksUsed();
        }