/// <summary> /// Inserts the entry into list. /// Tries to resurrect deleted entry if possible. /// Adds new entry if not possible. Updates data in storage. /// Tries to do optimization on every 100 items added. /// </summary> private void InsertEntryIntoList([NotNull] string name, bool directory, [NotNull] Address nodeAddress) { uint currentBlockIndex = 0; uint currentBlockSpace = Constants.BlockSizeBytes; foreach (var currentEntry in _list) { if (currentEntry.IsDeleted && currentEntry.Name.Length >= name.Length) { currentEntry.Resurrect(name, directory, nodeAddress); currentEntry.Save(DiskAccess); return; } if (currentEntry.EntrySizeBytes > currentBlockSpace) { currentBlockIndex++; currentBlockSpace = Constants.BlockSizeBytes; } currentBlockSpace -= currentEntry.EntrySizeBytes; } var newEntry = new DirectoryEntry { Name = name, IsDirectory = directory, NodeAddress = nodeAddress }; if (currentBlockSpace < newEntry.EntrySizeBytes) { currentBlockIndex++; currentBlockSpace = Constants.BlockSizeBytes; } if (currentBlockIndex >= Storage.NumBlocksAllocated) { // should never need to allocate more than 1 block Storage.AddBlocks(1); } var offset = Constants.BlockSizeBytes - currentBlockSpace; var addr = Storage.GetBlockStartAddress(currentBlockIndex); newEntry.EntrySelfAddress = new Address(addr.Value + offset); newEntry.Save(DiskAccess); var lastItem = _list.LastOrDefault(); if (lastItem != null) { lastItem.Next = newEntry.EntrySelfAddress; lastItem.Save(DiskAccess); } _list.Add(newEntry); UpdateSize((ulong)_list.Count); // size holds total number of entries, including deleted ones. if (_list.Count % 100 == 0) { // do space optimization on every 100 files, // to prevent attack like adding files with increasing name length. Save(); } }
/// <summary> /// Overload of base load, used to load directory entries from storage. /// </summary> /// <exception cref="Exception">Directory entry list corrupted.</exception> public override void Load() { base.Load(); // now load directory list, after loading base node info. _list.Clear(); var address = Storage.GetBlockStartAddress(0); var dataOffset = address.Value; for (int i = 0; i < NumberOfEntries; ++i) { var entry = new DirectoryEntry(); entry.Load(dataOffset, DiskAccess); _list.Add(entry); dataOffset = entry.Next == null ? 0 : entry.Next.Value; } if (NumberOfEntries > 0 && dataOffset != 0) { throw new Exception("Directory entry list corrupted."); } }