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 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)); }