/// <summary> /// Create stream table /// </summary> /// <param name="storage">Owner storage</param> public StreamTable(StorageStream stream) { this.stream = stream; writer = new BinaryWriter(stream); LoadStreamTable(); }
internal void StreamChanged(StorageStreamChangeType changeType, StorageStream stream) { if (!SystemStreamId.IsSystemStreamId(stream.StreamId) || stream.StreamId == SystemStreamId.EmptySpace) { switch (changeType) { case StorageStreamChangeType.SegmentsAndMetadata: if (!streamsChangedDuringTransaction.Contains(stream)) { streamsChangedDuringTransaction.Add(stream); } break; case StorageStreamChangeType.Closing: if (streamsChangedDuringTransaction.Contains(stream)) { streamsChangedDuringTransaction.Remove(stream); } openedStreams.Remove(stream.StreamId); //e.Stream.Changed -= StorageStream_Changed; break; } } }
/// <summary> /// Creates a storage /// </summary> private void CreateStorage(Stream stream) { this.MasterStream = new MasterStream(stream, false); // Initialize storage metadata Segment metadataStreamSegment = Segment.Create(0, blockSize, null); metadataStreamSegment.Save(stream); StorageStream metadataStream = new StorageStream(new StorageStreamMetadata(null) { FirstSegmentPosition = 0, InitializedLength = blockSize - Segment.StructureSize, Length = blockSize - Segment.StructureSize, StreamId = SystemStreamId.StorageMetadata, StreamTableIndex = -1 }, this); StorageMetadata storageMetadata = new StorageMetadata("[TmStorage 1.0]"); // Set metadata again because above, stream was not specified storageMetadata.Save(metadataStream); metadataStream.Close(); // Initialize stream table long streamTableSegmentSize = 1000 / ((int)blockSize / StorageStreamMetadata.StructureSize) * blockSize; Segment streamTableSegment = Segment.Create(blockSize, streamTableSegmentSize, null); stream.Position = metadataStreamSegment.DataAreaEnd; streamTableSegment.Save(stream); StorageStream streamTableStream = new StorageStream(new StorageStreamMetadata(null) { FirstSegmentPosition = blockSize, InitializedLength = streamTableSegmentSize - Segment.StructureSize, Length = streamTableSegmentSize - Segment.StructureSize, StreamId = SystemStreamId.StreamTable, StreamTableIndex = -1 }, this); // Initialize empty space stream Segment emptyStreamSegment = Segment.Create(streamTableSegment.DataAreaEnd, long.MaxValue - streamTableSegment.DataAreaEnd, null); stream.Position = streamTableSegment.DataAreaEnd; emptyStreamSegment.Save(stream); // Write empty space stream metadata to stream table StorageStreamMetadata emptySpaceStreamMetadata = new StorageStreamMetadata(streamTableStream) { FirstSegmentPosition = emptyStreamSegment.Location, InitializedLength = emptyStreamSegment.DataAreaSize, Length = emptyStreamSegment.DataAreaSize, StreamId = SystemStreamId.EmptySpace, StreamTableIndex = 0 }; emptySpaceStreamMetadata.Save(); this.MasterStream = null; }
/// <summary> /// Opens a stream /// </summary> /// <param name="streamId">Stream Id</param> public StorageStream OpenStream(Guid streamId) { CheckClosed(); if (SystemStreamId.IsSystemStreamId(streamId)) { throw new InvalidStreamIdException(); } StartTransaction(); try { StorageStream tmpStream = null; WeakReference <StorageStream> streamRef; // Check if stream is already opened if (openedStreams.TryGetValue(streamId, out streamRef)) { if (!streamRef.TryGetTarget(out tmpStream)) { tmpStream = null; openedStreams.Remove(streamId); } } // Open stream if (tmpStream == null) { var streamMetadata = streamTable.Get(streamId); if (streamMetadata == null) { throw new StreamNotFoundException(); } tmpStream = new StorageStream(streamMetadata, this); //tmpStream.Changed += StorageStream_Changed; openedStreams.Add(streamId, new WeakReference <StorageStream>(tmpStream)); } tmpStream.Position = 0; CommitTransaction(); return(tmpStream); } catch { RollbackTransaction(); throw; } }
/// <summary> /// Gets areas where specified stream segments are located /// </summary> public List <SegmentExtent> GetStreamExtents(Guid streamId) { CheckClosed(); if (SystemStreamId.IsSystemStreamId(streamId)) { throw new InvalidStreamIdException(); } StorageStream stream = OpenStream(streamId); return(stream.GetStreamExtents()); }
/// <summary> /// Deletes a stream /// </summary> /// <param name="streamId">Stream Id</param> public void DeleteStream(Guid streamId) { CheckClosed(); if (SystemStreamId.IsSystemStreamId(streamId)) { throw new InvalidStreamIdException(); } StartTransaction(); try { // Before deleting, set stream size to zero to deallocate all of the space it occupies StorageStream tmpStream = OpenStream(streamId); tmpStream.SetLength(0); tmpStream.Close(); openedStreams.Remove(streamId); streamTable.Remove(streamId); // Remove stream from list of changed streams tmpStream = streamsChangedDuringTransaction.SingleOrDefault(x => x.StreamId == streamId); if (tmpStream != null) { streamsChangedDuringTransaction.Remove(tmpStream); } // Remove stream from list of created streams if (streamsCreatedDuringTransaction.Contains(streamId)) { streamsCreatedDuringTransaction.Remove(streamId); } CommitTransaction(); } catch { RollbackTransaction(); throw; } }
/// <summary> /// Opens the storage /// </summary> private void OpenStorage() { StartTransaction(); try { // For metadata assume block size of 512 because blockSize is unknown at this point. // 512 is the smallest block size so it will work as long as storage metadata is not // longer than 512 bytes storageMetadataStream = new StorageStream(new StorageStreamMetadata(null) { FirstSegmentPosition = 0, InitializedLength = 512 - Segment.StructureSize, Length = 512 - Segment.StructureSize, StreamId = SystemStreamId.StorageMetadata, StreamTableIndex = -1 }, this); StorageMetadata = StorageMetadata.Load(storageMetadataStream); streamTableStreamMetadata = new StorageStreamMetadata(storageMetadataStream) { FirstSegmentPosition = blockSize, StreamId = SystemStreamId.StreamTable, StreamTableIndex = -1 }; streamTableStream = new StorageStream(streamTableStreamMetadata, this); streamTable = new StreamTable(streamTableStream); var freeSpaceStreamMetadata = streamTable.Get(SystemStreamId.EmptySpace); FreeSpaceStream = new StorageStream(freeSpaceStreamMetadata, this); CommitTransaction(); } catch { RollbackTransaction(); throw; } }
internal void StreamChanged(StorageStreamChangeType changeType, StorageStream stream) { if (!SystemStreamId.IsSystemStreamId(stream.StreamId) || stream.StreamId == SystemStreamId.EmptySpace) { switch (changeType) { case StorageStreamChangeType.SegmentsAndMetadata: if (!streamsChangedDuringTransaction.Contains(stream)) streamsChangedDuringTransaction.Add(stream); break; case StorageStreamChangeType.Closing: if (streamsChangedDuringTransaction.Contains(stream)) streamsChangedDuringTransaction.Remove(stream); openedStreams.Remove(stream.StreamId); //e.Stream.Changed -= StorageStream_Changed; break; } } }
/// <summary> /// Opens a stream /// </summary> /// <param name="streamId">Stream Id</param> public StorageStream OpenStream(Guid streamId) { CheckClosed(); if (SystemStreamId.IsSystemStreamId(streamId)) throw new InvalidStreamIdException(); StartTransaction(); try { StorageStream tmpStream = null; WeakReference<StorageStream> streamRef; // Check if stream is already opened if (openedStreams.TryGetValue(streamId, out streamRef)) { if (!streamRef.TryGetTarget(out tmpStream)) { tmpStream = null; openedStreams.Remove(streamId); } } // Open stream if (tmpStream == null) { var streamMetadata = streamTable.Get(streamId); if (streamMetadata == null) throw new StreamNotFoundException(); tmpStream = new StorageStream(streamMetadata, this); //tmpStream.Changed += StorageStream_Changed; openedStreams.Add(streamId, new WeakReference<StorageStream>(tmpStream)); } tmpStream.Position = 0; CommitTransaction(); return tmpStream; } catch { RollbackTransaction(); throw; } }