void LoadStream(StorageStreamMetadata metadata) { // Load segments this.metadata = metadata; long?segmentPosition = metadata.FirstSegmentPosition; segments.Clear(); while (segmentPosition.HasValue) { Segment segment = Segment.Load(_storage.MasterStream, segmentPosition.Value); segments.AddLast(segment); segmentPosition = segment.NextLocation; } // Manually adjust stream length and initializedSized for stream table stream if (metadata.StreamId == SystemStreamId.StreamTable) { //metadata.Length = segments.Sum(x => x.DataAreaSize); long length = 0; foreach (var segment in segments) { length += segment.DataAreaSize; } metadata.Length = length; metadata.InitializedLength = metadata.Length; } }
/// <summary> /// Loads metadata /// </summary> public static StorageStreamMetadata Load(Stream streamTableStream, int streamTableIndex) { streamTableStream.Position = streamTableIndex * StorageStreamMetadata.StructureSize; streamTableStream.Read(Tools.Buffer, 0, StorageStreamMetadata.StructureSize); Tools.BufferReader.BaseStream.Position = 0; StorageStreamMetadata metadata = new StorageStreamMetadata(streamTableStream); metadata.StreamTableIndex = streamTableIndex; metadata.StreamId = new Guid(Tools.BufferReader.ReadBytes(16)); metadata.Length = Tools.BufferReader.ReadInt64(); metadata.InitializedLength = Tools.BufferReader.ReadInt64(); long firstSegmentPos = Tools.BufferReader.ReadInt64(); metadata.FirstSegmentPosition = firstSegmentPos != 0 ? firstSegmentPos : (long?)null; metadata.Tag = Tools.BufferReader.ReadInt32(); int hash = Tools.BufferReader.ReadInt32(); int calculatedHash = Tools.CalculateHash(metadata.StreamId, metadata.Length, metadata.InitializedLength, firstSegmentPos); if (hash != calculatedHash) { throw new StorageException("Error loading stream metadata"); } return(metadata); }
void LoadStreamTable() { StorageStreamMetadata streamMetadata; stream.Position = 0; int index = 0; map.Clear(); items.Clear(); int cnt = (int)stream.Length / StorageStreamMetadata.StructureSize; for (int i = 0; i < cnt; i++) { streamMetadata = StorageStreamMetadata.Load(stream, i); if (streamMetadata.StreamId != Guid.Empty) { map.Set(index, true); items.Add(streamMetadata.StreamId, index); } index++; } }
// Reloads segments from storage internal void ReloadSegmentsOnRollback(StorageStreamMetadata metadata) { CheckClosed(); changeNotified = false; // Reaload metadata and segments LoadStream(metadata); }
/// <summary> /// Constructor that loads the segments from master stream /// </summary> internal StorageStream(StorageStreamMetadata metadata, Storage _storage) { if (_storage == null) { throw new ArgumentNullException("_storage"); } this._storage = _storage; LoadStream(metadata); }
/// <summary> /// Returns table entries /// </summary> public IEnumerable <StorageStreamMetadata> Get() { StorageStreamMetadata streamMetadata; foreach (StorageStreamMetadata entry in entriesAddedInTransaction.Values) { yield return(entry); } for (int i = 0; i < stream.Length / StorageStreamMetadata.StructureSize; i++) { streamMetadata = StorageStreamMetadata.Load(stream, i); if (streamMetadata.StreamId != Guid.Empty) { yield return(streamMetadata); } } }
/// <summary> /// Gets first segment location for specified streamId or nulll if not found. /// </summary> public StorageStreamMetadata Get(Guid streamId) { StorageStreamMetadata result = null; int index; // Search through entries in memory if (!entriesAddedInTransaction.TryGetValue(streamId, out result)) { // Load it from stream table stream if (items.TryGetValue(streamId, out index)) { result = StorageStreamMetadata.Load(stream, index); } } return(result); }
/// <summary> /// Adds new entry /// </summary> public StorageStreamMetadata Add(Guid streamId, int tag = 0) { // Get the position of first empty entry int index = map.FindFirstEmptyEntry(); long streamPosition = index * StorageStreamMetadata.StructureSize; // Resize stream is needed if ((streamPosition + StorageStreamMetadata.StructureSize) > stream.Length) { int count = (int)stream.Length / StorageStreamMetadata.StructureSize; count += Math.Min(Math.Max((int)(count * 1.5), 512), 50000); long oldLength = stream.Length; stream.SetLength(count * StorageStreamMetadata.StructureSize); // Write zeros to newly allocated space long bytesToWrite = stream.Length - oldLength; stream.Position = oldLength; while (bytesToWrite > 0) { int amount = (int)Math.Min(bytesToWrite, Tools.EmptyBuffer.Length); stream.Write(Tools.EmptyBuffer, 0, amount); bytesToWrite -= amount; } stream.Save(); } StorageStreamMetadata streamMetadata = new StorageStreamMetadata(stream) { FirstSegmentPosition = null, StreamId = streamId, Tag = tag, StreamTableIndex = index }; entriesAddedInTransaction.Add(streamId, streamMetadata); //streamMetadata.Save(); map.Set(index, true); items.Add(streamId, index); return(streamMetadata); }