public void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service) { // 1) We read previous object placement and change it. ObjectInfo info = childrenTree.Find(service, (uint)prevName.GetHashCode()); BlockStream stream = BlockStream.FromBase(info.Address, service); ChildTag childTag = Common.DeserializeFromArray(stream.Read(info.Size)) as ChildTag; childTag.Remove(prevName); // Remove it if empty. if (childTag.IsEmpty) { childrenTree.Remove(service, (uint)prevName.GetHashCode(), 1, false); } else { // Update the entry (now without this child). byte[] childTagData = Common.SerializeToArray(childTag); stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength); stream.Write(childTagData); childrenTree.Replace(service, new ObjectInfo((uint)prevName.GetHashCode(), (ulong)childTagData.LongLength, stream.BaseAddress)); } // 3) We create new and insert it into tree. ObjectInfo info2 = childrenTree.Find(service, (uint)newName.GetHashCode()); if (info2 == null) { // We create new tag. childTag = new ChildTag(); childTag.Add(newName, info.Address); byte[] childTagData = Common.SerializeToArray(childTag); stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength); stream.Write(childTagData); // And we add child. childrenTree.Add(service, new ObjectInfo((uint)newName.GetHashCode(), (ulong)childTagData.LongLength, stream.BaseAddress)); } else { // We append it and release previous tag. stream = BlockStream.FromBase(info2.Address, service); childTag = Common.DeserializeFromArray(stream.Read(info2.Size)) as ChildTag; stream.Deallocate(); // We modify and rewrite it. childTag.Add(newName, info.Address); byte[] childTagData = Common.SerializeToArray(childTag); stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength); stream.Write(childTagData); // We insert into children tree. childrenTree.Replace(service, new ObjectInfo((uint)newName.GetHashCode(), (ulong)childTagData.LongLength, info.Address)); } }
public void ToByteArray() { BlockStream s = new BlockStream(); s.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 10); Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s.ToArray()); }
public void SetLength_Modify() { BlockStream s; byte[] r = new byte[10]; byte[] w = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] c = new byte[10]; s = new BlockStream(); s.SetLength(100000, true); Assert.Equal(100000, s.Length); Assert.Equal(0, s.Position); s.Position = 50000; s.Write(w, 0, 10); Assert.Equal(50010, s.Position); s.SetLength(50005, true); Assert.Equal(50005, s.Length); Assert.Equal(50005, s.Position); s.Position = 50000; Zero(r); Assert.Equal(5, s.Read(r, 0, 10)); Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 }, r); s.SetLength(0, true); Assert.Equal(0, s.Length); Assert.Equal(0, s.Position); }
public void ValidateParameters() { using (var ms = new MemoryStream()) { using (var blockStream = new BlockStream(Zstd, ms, CompressionMode.Compress)) { var buffer = new byte[10]; // ReSharper disable once AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>(delegate { blockStream.Write(null, 10, 10); }); Assert.Throws <ArgumentOutOfRangeException>(delegate { blockStream.Write(buffer, -1, 10); }); Assert.Throws <ArgumentOutOfRangeException>(delegate { blockStream.Write(buffer, 10, -1); }); Assert.Throws <ArgumentException>(delegate { blockStream.Write(buffer, 5, 10); }); } } }
public void EndOfFile() { using (var ms = new MemoryStream()) { var writeBuffer = GetRandomBytes(100); var readBuffer = new byte[60]; using (var blockStream = new BlockStream(Zstd, ms, CompressionMode.Compress, true)) { blockStream.Write(writeBuffer, 0, writeBuffer.Length); } ms.Position = 0; using (var blockStream = new BlockStream(Zstd, ms, CompressionMode.Decompress)) { int numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length); Assert.Equal(readBuffer.Length, numBytesRead); numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length); Assert.Equal(writeBuffer.Length - readBuffer.Length, numBytesRead); numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length); Assert.Equal(0, numBytesRead); } } }
public unsafe void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service) { Debug.Assert(stage == 0); // 1) We first write object to stream. BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)objectData.LongLength); stream.Write(objectData); // 2) We may need to delete object from B+ stream. Block block = service.Read(BlockType.TypedStreamHeader, typedStreamHeader); fixed(byte *p = block.Data) { TypedStreamHeader *header = (TypedStreamHeader *)p; // We may need to delete link. if (header->ObjectsAddress != 0) { BlockStream objToDelete = BlockStream.FromBase(header->ObjectsAddress, service); objToDelete.Deallocate(); } // 3) We must relink it to out block. header->ObjectsAddress = stream.BaseAddress; header->ObjectSize = (ulong)objectData.LongLength; } service.Write(BlockType.TypedStreamHeader, typedStreamHeader, block); }
public void BlockStream_ToByteArray() { BlockStream s = new BlockStream(); s.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 10); CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s.ToArray()); }
public void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service) { Debug.Assert(stage == 0); // 1) We first write to allocated block stream. BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)objectData.LongLength); stream.Write(objectData); // 2) We may need to delete object at index. ObjectInfo data = tree.Find(service, index); if (data != null) { // Deallocate link. BlockStream stream2 = BlockStream.FromBase(data.Address, service); stream2.Deallocate(); // We replace the entry (cheaper than delete and rewrite). tree.Replace(service, new ObjectInfo(index, (ulong)objectData.LongLength, stream.BaseAddress)); } else { // 3) We execute insert operation. tree.Add(service, new ObjectInfo(index, (ulong)objectData.LongLength, stream.BaseAddress)); } }
public void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service) { // 1) We create the object. BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)objectData.LongLength); stream.Write(objectData); // 2) We insert to B+ tree. tree.Insert(service, before, new ObjectInfo(index, (ulong)objectData.LongLength, stream.BaseAddress)); }
private static void CheckWriteException(BlockStream reader) { var exception = Record.Exception(() => { var buffer = new byte[10]; // ReSharper disable once AccessToDisposedClosure reader.Write(buffer, 0, 1); }); Assert.NotNull(exception); Assert.IsType <CompressionException>(exception); }
public void Append() { BlockStream s; byte[] b1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] b2 = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; byte[] c; //------------------------- s = new BlockStream(); s.Append(new Block(b1)); Assert.Equal(10, s.Length); Assert.Equal(10, s.Position); c = new byte[10]; s.Position = 0; Assert.Equal(10, s.Read(c, 0, 10)); Assert.Equal(b1, c); //------------------------- s = new BlockStream(); s.Write(b1, 0, 10); s.Append(new Block(b2)); Assert.Equal(20, s.Length); Assert.Equal(20, s.Position); c = new byte[20]; s.Position = 0; Assert.Equal(20, s.Read(c, 0, 20)); Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, c); //------------------------- s = new BlockStream(); s.Append(new Block[] { new Block(b1), new Block(b2) }); Assert.Equal(20, s.Length); Assert.Equal(20, s.Position); c = new byte[20]; s.Position = 0; Assert.Equal(20, s.Read(c, 0, 20)); Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, c); }
public void ReadWriteBlocks() { var bs = new BlockStream(); var maxSize = 16 * 1024; for (int i = 0; i < maxSize; i++) { var data = new byte[i]; for (int j = 0; j < i; j++) { data[j] = (byte)j; } bs.Write(data, 0, data.Length); } bs.Seek(0, SeekOrigin.Begin); var buffer = new byte[maxSize]; for (int i = 0; i < maxSize; i++) { for (var j = 0; j < i; j++) { buffer[i] = (byte)(j + 1); } bs.Read(buffer, 0, i); for (int j = 0; j < i; j++) { Assert.Equal((byte)j, buffer[j]); } } }
public void Seek() { BlockStream s = new BlockStream(); byte[] r = new byte[10]; byte[] w = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] c = new byte[] { 0, 0, 0, 0, 4, 5, 6, 7, 8, 9 }; for (int i = 0; i < 100000; i++) { w[0] = (byte)(i << 24); w[1] = (byte)(i << 16); w[2] = (byte)(i << 8); w[3] = (byte)(i); s.Write(w, 0, 10); } for (int i = 0; i < 100000; i++) { int pos = i; c[0] = (byte)(pos << 24); c[1] = (byte)(pos << 16); c[2] = (byte)(pos << 8); c[3] = (byte)(pos); s.Seek(pos * 10, SeekOrigin.Begin); Assert.Equal((long)(pos * 10), s.Position); Assert.Equal(10, s.Read(r, 0, 10)); Assert.Equal(c, r); } for (int i = 0; i < 100000; i++) { int pos = i; c[0] = (byte)(pos << 24); c[1] = (byte)(pos << 16); c[2] = (byte)(pos << 8); c[3] = (byte)(pos); s.Position = 50000 * 10; s.Seek(pos * 10 - 50000 * 10, SeekOrigin.Current); Assert.Equal((long)(pos * 10), s.Position); Assert.Equal(10, s.Read(r, 0, 10)); Assert.Equal(c, r); } for (int i = 0; i < 100000; i++) { int pos = i; c[0] = (byte)(pos << 24); c[1] = (byte)(pos << 16); c[2] = (byte)(pos << 8); c[3] = (byte)(pos); s.Seek(-(100000 * 10 - pos * 10), SeekOrigin.End); Assert.Equal((long)(pos * 10), s.Position); Assert.Equal(10, s.Read(r, 0, 10)); Assert.Equal(c, r); } }
public void ReadWriteBuffer() { BlockStream s; byte[] r; byte[] w; byte[] c; s = new BlockStream(); r = new byte[10]; w = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Assert.Equal(0, s.Read(r, 0, 10)); Assert.Equal(0, s.Length); Assert.Equal(0, s.Position); s.Write(w, 0, 10); Assert.Equal(10, s.Length); Assert.Equal(10, s.Position); s.Position = 0; Zero(r); s.Read(r, 0, 10); Assert.Equal(10, s.Length); Assert.Equal(10, s.Position); Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, r); s.Position = 5; Zero(r); Assert.Equal(5, s.Read(r, 0, 10)); Assert.Equal(new byte[] { 5, 6, 7, 8, 9, 0, 0, 0, 0, 0 }, r); s.Position = 5; Zero(r); Assert.Equal(5, s.Read(r, 5, 5)); Assert.Equal(new byte[] { 0, 0, 0, 0, 0, 5, 6, 7, 8, 9 }, r); s = new BlockStream(); s.Write(w, 5, 5); Assert.Equal(5, s.Length); Assert.Equal(5, s.Position); s.Position = 0; Zero(r); Assert.Equal(5, s.Read(r, 5, 5)); Assert.Equal(new byte[] { 0, 0, 0, 0, 0, 5, 6, 7, 8, 9 }, r); s = new BlockStream(); w = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; for (int i = 0; i < 100000; i++) { w[0] = (byte)(i << 24); w[1] = (byte)(i << 16); w[2] = (byte)(i << 8); w[3] = (byte)(i); s.Write(w, 0, 10); } Assert.Equal(10 * 100000, s.Position); Assert.Equal(10 * 100000, s.Length); s.Position = 0; c = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; for (int i = 0; i < 100000; i++) { Assert.Equal(10, s.Read(r, 0, 10)); c[0] = (byte)(i << 24); c[1] = (byte)(i << 16); c[2] = (byte)(i << 8); c[3] = (byte)(i); Assert.Equal(c, r); } }
public unsafe void Execute(uint stage, IService service) { // 1) We create the node common block. versionAddress = service.AllocationContext.AllocateBlock(); commonAddress = service.AllocationContext.AllocateBlock(); BPlusTree versionTS = new BPlusTree(service.AllocationContext.CreateEmptyBTree()); // Fill common block and write. Block commonBlock = new Block(service.BlockSize); fixed(byte *p = commonBlock.Data) { NodeCommonHeader *header = (NodeCommonHeader *)p; header->ChildrenBTree = service.AllocationContext.CreateEmptyBTree(); header->CurrentVersionAddress = versionAddress; header->CurrentVersionNumber = 0; header->HeaderMagic = NodeCommonHeader.Magic; header->ParentAddress = parentAddress; header->VersionsBTree = versionTS.RootAddress; } service.Write(BlockType.NodeHeaderBlock, commonAddress, commonBlock); // 2) We create the node default typed stream. Block tsblock = new Block(service.BlockSize); ulong tsBlock = service.AllocationContext.AllocateBlock(); fixed(byte *p = tsblock.Data) { TypedStreamHeader *header = (TypedStreamHeader *)p; header->ObjectsAddress = (defaultTSOptions & StreamOptions.SingleObject) == 0 ? service.AllocationContext.CreateEmptyBTree() : 0; header->Options = defaultTSOptions; header->ObjectSize = 0; int i; for (i = 0; i < defaultTSType.Length; i++) { header->Type[i] = defaultTSType[i]; } // Null terminate it. header->Type[i] = '\0'; } service.Write(BlockType.TypedStreamHeader, tsBlock, tsblock); // 3) We create the node version block. // Fill version block and write. Block versionBlock = new Block(service.BlockSize); fixed(byte *pp = versionBlock.Data) { NodeVersionHeader *header = (NodeVersionHeader *)pp; header->CreationTime = DateTime.Now; header->DefaultTypedStream = 0; header->HeaderMagic = NodeVersionHeader.Magic; header->ModifiedTime = DateTime.Now; header->NodeCommonAddress = commonAddress; header->StreamCount = 0; //< Is actually one but NodeHelper changes this. header->VersionNumber = 0; } // We must add default typed stream to block. NodeVersionHelper.AddTypedStream(tsBlock, defaultTSType, versionBlock); service.Write(BlockType.NodeHeaderBlock, versionAddress, versionBlock); // 4) We add to children tree. ObjectInfo info = childrenTree.Find(service, (uint)childName.GetHashCode()); if (info == null) { // We simply create a new object at address. ChildTag childTag = new ChildTag(); childTag.HashCode = childName.GetHashCode(); childTag.Add(childName, commonAddress); byte[] childData = Common.SerializeToArray(childTag); // We write it to block stream. BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)childData.LongLength); stream.Write(childData); // We now add it to B+ tree. childrenTree.Add(service, new ObjectInfo((uint)childName.GetHashCode(), (ulong)childData.LongLength, stream.BaseAddress)); } else { // The index at hash already exists, we must add it, first read it. BlockStream stream = BlockStream.FromBase(info.Address, service); ChildTag childTag = Common.DeserializeFromArray(stream.Read(info.Size)) as ChildTag; // Steam not used anymore. stream.Deallocate(); // We modify child tag. childTag.Add(childName, commonAddress); byte[] childData = Common.SerializeToArray(childTag); // We must write it to new address. stream = service.AllocationContext.CreateBlockStream((ulong)childData.LongLength); stream.Write(childData); // Now we replace the data in tree. childrenTree.Replace(service, new ObjectInfo((uint)childName.GetHashCode(), (ulong)childData.LongLength, stream.BaseAddress)); } // 5) Add version to typed stream. VersionTag versionTag = new VersionTag((0).GetHashCode()); versionTag.Add(0, versionAddress); byte[] versionTagData = Common.SerializeToArray(versionTag); // Write to stream. BlockStream versionTagStream = service.AllocationContext.CreateBlockStream((ulong)versionTagData.LongLength); versionTagStream.Write(versionTagData); versionTS.Add(service, new ObjectInfo((uint)(0).GetHashCode(), (ulong)versionTagData.LongLength, versionTagStream.BaseAddress)); }
public unsafe void Execute(uint stage, IService service) { string defaultTSType = typeof(object).FullName; // 1) We create the node common block. ulong versionAddress = service.AllocationContext.AllocateBlock(); ulong commonAddress = service.AllocationContext.AllocateBlock(); BPlusTree versionTS = new BPlusTree(service.AllocationContext.CreateEmptyBTree()); // Fill common block and write. Block commonBlock = new Block(service.BlockSize); fixed(byte *p = commonBlock.Data) { NodeCommonHeader *header = (NodeCommonHeader *)p; header->ChildrenBTree = service.AllocationContext.CreateEmptyBTree(); header->CurrentVersionAddress = versionAddress; header->CurrentVersionNumber = 0; header->HeaderMagic = NodeCommonHeader.Magic; header->ParentAddress = 0; header->VersionsBTree = versionTS.RootAddress; } service.Write(BlockType.NodeHeaderBlock, commonAddress, commonBlock); // 2) We create the node default typed stream. Block tsblock = new Block(service.BlockSize); fixed(byte *p = tsblock.Data) { TypedStreamHeader *header = (TypedStreamHeader *)p; header->ObjectsAddress = service.AllocationContext.AllocateBlock(); header->Options = StreamOptions.None; header->ObjectSize = 0; int i; for (i = 0; i < defaultTSType.Length; i++) { header->Type[i] = defaultTSType[i]; } // Null terminate it. header->Type[i] = '\0'; } ulong tsBlock = service.AllocationContext.AllocateBlock(); service.Write(BlockType.TypedStreamHeader, tsBlock, tsblock); // 3) We create the node version block. // Fill version block and write. Block versionBlock = new Block(service.BlockSize); fixed(byte *pp = versionBlock.Data) { NodeVersionHeader *header = (NodeVersionHeader *)pp; header->CreationTime = DateTime.Now; header->DefaultTypedStream = 0; header->HeaderMagic = NodeVersionHeader.Magic; header->ModifiedTime = DateTime.Now; header->NodeCommonAddress = commonAddress; header->StreamCount = 0; //< Is actually one but NodeHelper changes this. header->VersionNumber = 0; } // We must add default typed stream to block. NodeVersionHelper.AddTypedStream(tsBlock, defaultTSType, versionBlock); service.Write(BlockType.NodeHeaderBlock, versionAddress, versionBlock); // 4) We must create versions VersionTag versionTag = new VersionTag((0).GetHashCode()); versionTag.Add(0, versionAddress); byte[] versionTagData = Common.SerializeToArray(versionTag); // Write to stream. BlockStream versionTagStream = service.AllocationContext.CreateBlockStream((ulong)versionTagData.LongLength); versionTagStream.Write(versionTagData); versionTS.Add(service, new ObjectInfo((uint)(0).GetHashCode(), (ulong)versionTagData.LongLength, versionTagStream.BaseAddress)); // 5) We must write to database header. Block block = service.Read(BlockType.NoCache, 0); fixed(byte *ppp = block.Data) { DatabaseHeader *header = (DatabaseHeader *)ppp; header->RootObjectAddress = commonAddress; } // Write the header. service.Write(BlockType.NoCache, 0, block); }
/// <summary> /// Executes the operation. /// </summary> /// <param name="service">Service for operation.</param> unsafe void ExecuteInternal(IService service) { ulong childrenTS; ulong versionTS; // 1) We extract child TS and version TS Block block = service.Read(BlockType.NodeHeaderBlock, commonAddress); fixed(byte *p = block.Data) { NodeCommonHeader *header = (NodeCommonHeader *)p; childrenTS = header->ChildrenBTree; versionTS = header->VersionsBTree; } // 2) Can get rid of node. service.DeAllocate(commonAddress); // 3) We delete children TS, it should be empty (since deletes were already called on nodes). service.DeAllocate(childrenTS); // 4) We go through versions. BPlusTree versionsTree = new BPlusTree(versionTS); List <ObjectInfo> versions = versionsTree.ListAll(service); // 5) We delete each version. foreach (ObjectInfo info in versions) { // a) Read version tag. BlockStream versionTagStream = BlockStream.FromBase(info.Address, service); VersionTag versionTag = Common.DeserializeFromArray(versionTagStream.Read(info.Size)) as VersionTag; versionTagStream.Deallocate(); foreach (KeyValuePair <ulong, ulong> versionToNode in versionTag.VersionAddress) { block = service.Read(BlockType.NodeHeaderBlock, versionToNode.Value); List <ulong> typedStreams = NodeVersionHelper.ListAllTypedStreamsAsAddresses(block, service); // b) Delete all typed streams. for (int i = 0; i < typedStreams.Count; i++) { // 1) We delete the typed stream object. block = service.Read(BlockType.TypedStreamHeader, typedStreams[i]); fixed(byte *p = block.Data) { TypedStreamHeader *header = (TypedStreamHeader *)p; // We delete single object. if ((header->Options & StreamOptions.SingleObject) != 0) { if (header->ObjectsAddress != 0) { BlockStream stream = BlockStream.FromBase(header->ObjectsAddress, service); stream.Deallocate(); } } else { // We delete all children. BPlusTree tree = new BPlusTree(header->ObjectsAddress); foreach (ObjectInfo info2 in tree.ListAll(service)) { BlockStream stream = BlockStream.FromBase(info2.Address, service); stream.Deallocate(); } } } // 2) We also delete the header itself. service.DeAllocate(typedStreams[i]); } // c) We deallocate version block. service.DeAllocate(versionToNode.Value); } } // 6) We delete the tree. versionsTree.DeallocateTree(service); // 7) We must erase the node from root. ObjectInfo childInfo = parentChildTree.Find(service, (uint)childName.GetHashCode()); BlockStream childTagStream = BlockStream.FromBase(childInfo.Address, service); byte[] childTagData = childTagStream.Read(childInfo.Size); ChildTag childTag = Common.DeserializeFromArray(childTagData) as ChildTag; childTagStream.Deallocate(); if (childTag.Children.Count == 1) { // Simply delete it. parentChildTree.Remove(service, (uint)childName.GetHashCode(), 1, false); } else { // We have to replace it. childTag.Remove(childName); childTagData = Common.SerializeToArray(childTag); childTagStream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength); childTagStream.Write(childTagData); parentChildTree.Replace(service, new ObjectInfo((uint)childName.GetHashCode(), (ulong)childTagData.LongLength, childTagStream.BaseAddress)); } }
public unsafe void Execute(uint stage, IService service) { ulong versionAddress = service.AllocationContext.AllocateBlock(); // 1) We first create new version node. Block versionBlock = new Block(service.BlockSize); fixed(byte *p = versionBlock.Data) { NodeVersionHeader *header = (NodeVersionHeader *)p; header->CreationTime = DateTime.Now; header->DefaultTypedStream = 0; header->HeaderMagic = NodeVersionHeader.Magic; header->ModifiedTime = DateTime.Now; header->NodeCommonAddress = commonAddress; header->StreamCount = 0; //< For now 0. header->VersionNumber = version; } // 2) We create default TS. ulong defaultTSAddress = service.AllocationContext.AllocateBlock(); Block block = new Block(service.BlockSize); fixed(byte *p = block.Data) { TypedStreamHeader *header = (TypedStreamHeader *)p; header->ObjectsAddress = (defaultTSOptions & StreamOptions.SingleObject) != 0 ? 0 : service.AllocationContext.CreateEmptyBTree(); header->ObjectSize = 0; header->Options = defaultTSOptions; // Copy the name. int i; for (i = 0; i < defaultTSType.Length; i++) { header->Type[i] = defaultTSType[i]; } header->Type[i] = '\0'; } service.Write(BlockType.TypedStreamHeader, defaultTSAddress, block); // 3) We add the default typed stream and write it. NodeVersionHelper.AddTypedStream(defaultTSAddress, defaultTSType, versionBlock); service.Write(BlockType.NodeHeaderBlock, versionAddress, versionBlock); // 4) And finnaly add to versions. ObjectInfo info = versionTree.Find(service, (uint)version.GetHashCode()); if (info == null) { // Create block stream. VersionTag versionTag = new VersionTag(version.GetHashCode()); versionTag.Add(version, versionAddress); byte[] versionTagData = Common.SerializeToArray(versionTag); BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)versionTagData.LongLength); // Write the stream. stream.Write(versionTagData); // And to B+ tree. versionTree.Add(service, new ObjectInfo((uint)version.GetHashCode(), (ulong)versionTagData.LongLength, stream.BaseAddress));; } else { // We first create appropriate VersionTag and kill the stream. BlockStream stream = BlockStream.FromBase(info.Address, service); VersionTag versionTag = Common.DeserializeFromArray(stream.Read(info.Size)) as VersionTag; versionTag.Add(version, versionAddress); stream.Deallocate(); // We write a new version tag. byte[] versionTagData = Common.SerializeToArray(versionTag); stream = service.AllocationContext.CreateBlockStream((ulong)versionTagData.LongLength); stream.Write(versionTagData); // We replace in B+ tree. versionTree.Replace(service, new ObjectInfo((uint)version.GetHashCode(), (ulong)versionTagData.LongLength, versionAddress)); } // 5) The new version is replaced in common. block = service.Read(BlockType.NodeHeaderBlock, commonAddress); fixed(byte *p = block.Data) { NodeCommonHeader *header = (NodeCommonHeader *)p; header->CurrentVersionNumber = version; header->CurrentVersionAddress = versionAddress; } service.Write(BlockType.NodeHeaderBlock, commonAddress, block); }