public override void GenerateLandscape(Chunk chunk, BlockOffset blockOffset) { Vector3 coord = chunk.GetAbsPosition(blockOffset); float height = _landScapeHeight - _noiseLandscape.GetSimplexFractal(coord.X, coord.Z) * (_heightGain.GetSimplexFractal(coord.X, coord.Z) * 50); IBlock block = new BlockAir(); if (coord.Y <= height) { block = new BlockGrass(); } if ((coord.Y <= height - 1) && (coord.Y > height - 5)) { block = new BlockDirt(); } if (coord.Y <= height - 5) { block = new BlockStone(); } chunk.SetBlock(blockOffset, block); }
public BlockOffset[] Remove(int count) { var offsets = this.ToArray(); if (offsets.Length < count) { throw new ArgumentOutOfRangeException("count",count,"Not enough offsets in the block to satisfy the remove request."); } // Move offsets to result, setting them to 0 in the offset-array var result = new BlockOffset[count]; for (var i = 0; i < result.Length; i++) { var revIdx = offsets.Length - 1 - i; result[i] = offsets[revIdx]; offsets[revIdx] = (BlockOffset) 0; } // Write back the modified offsets ReplaceOffsets(offsets); // Also update the free block count TotalFreeBlockCount -= count; return result; }
public unsafe void ReplaceOffsets(BlockOffset[] offsets) { if (offsets == null) throw new ArgumentNullException("offsets"); if (offsets.Length > ListCapacity) { throw new ArgumentOutOfRangeException("offsets",offsets.Length,"Not all block offsets fit into this block."); } // Replace all offsets in the block with the supplied offsets, // padding with 0 if the array is too short. // var ptr = ((uint*) ThisPointer)+MetaDataPrefixUInt32Count; for (var i = 0; i < ListCapacity; i++) { if (i < offsets.Length) { ptr[i] = offsets[i].Offset; } else { ptr[i] = 0u; } } OnBlockChanged(); }
public RowBlockBuilder <TPointer> SetField(int index, IBlockBuilder block) { BlockOffset field = Table.Layout.GetField(index); using (MemoryStream stream = new MemoryStream(_data, (int)field.Start, (int)field.Length, true, false)) block.WriteTo(stream); return(this); }
public void SetBlock(BlockOffset blockOffset, IBlock block) { if (blockOffset.X >= 0 && blockOffset.X < SizeX && blockOffset.Y >= 0 && blockOffset.Y < SizeY && blockOffset.Z >= 0 && blockOffset.Z < SizeZ) { _blocks[blockOffset.X, blockOffset.Y, blockOffset.Z] = block; _needRebuild = true; } }
public override void GenerateWater(Chunk chunk, BlockOffset blockOffset) { Vector3 coord = chunk.GetAbsPosition(blockOffset); IBlock block = chunk.GetBlock(blockOffset); if (block is BlockAir && coord.Y == 79995) { chunk.SetBlock(blockOffset, new BlockWater()); } }
public override void GenerateCave(Chunk chunk, BlockOffset blockOffset) { Vector3 coord = chunk.GetAbsPosition(blockOffset); float n = _noiseCave.GetPerlin(coord.X, coord.Y, coord.Z); if (n < _shearCaveMax && n > _shearCaveMin) { chunk.SetBlock(blockOffset, new BlockAir()); } }
public IBlock GetBlock(BlockOffset blockOffset) { if (blockOffset.X >= 0 && blockOffset.X < SizeX && blockOffset.Y >= 0 && blockOffset.Y < SizeY && blockOffset.Z >= 0 && blockOffset.Z < SizeZ) { return(_blocks[blockOffset.X, blockOffset.Y, blockOffset.Z]); } return(new BlockAir()); }
public void Append(BlockOffset[] freeBlockOffsets) { if (freeBlockOffsets == null) throw new ArgumentNullException("freeBlockOffsets"); ThrowIfDeallocated(); if (_offsets.Count + freeBlockOffsets.Length > ListCapacity) { throw new ArgumentOutOfRangeException("freeBlockOffsets", "Not enough free space in offset list."); } _offsets.AddRange(freeBlockOffsets); }
public override void GenerateDiamond(Chunk chunk, BlockOffset blockOffset) { Vector3 coord = chunk.GetAbsPosition(blockOffset); float height = _landScapeHeight - _noiseLandscape.GetSimplexFractal(coord.X, coord.Z) * (_heightGain.GetSimplexFractal(coord.X, coord.Z) * 50); float n = _noiseDiamond.GetPerlin(coord.X, coord.Y, coord.Z); if (coord.Y <= height - _minHeightDiamond - 5 && coord.Y > height - _maxHeightDiamond && n < _shearDiamondMax && n > _shearDiamondMin) { chunk.SetBlock(blockOffset, new BlockDiamond()); } }
BlockOffset[] UpdateBlockData(Vector3 cubeSize) { var blockOffsets = new BlockOffset[this.blockDatas.Length]; for (var i = 0; i < this.blockDatas.Length; ++i) { var blockData = this.blockDatas[i]; var blockOffset = new BlockOffset { name = blockData.GetType().Name, cellOffsets = this.GetCubeOffsets(blockData) }; blockOffsets[i] = blockOffset; } return(blockOffsets); }
public void Append(BlockOffset[] freeBlockOffsets) { if (freeBlockOffsets == null) throw new ArgumentNullException("freeBlockOffsets"); // This is a very simplistic implementation of append: // reading the entire blocklist, appending the new offsets in memory and // then writing the entire list back. // A more sophisticated implementation would just write the modified entries. var offsets = this.ToList(); offsets.AddRange(freeBlockOffsets); if(offsets.Count > ListCapacity) throw new ArgumentOutOfRangeException("freeBlockOffsets",freeBlockOffsets.Length,"Not all offsets fit into this block."); ReplaceOffsets(offsets.ToArray()); TotalFreeBlockCount += freeBlockOffsets.Length; }
public override void Generate(Chunk chunk) { for (int x = 0; x < Chunk.SizeX; x++) { for (int y = 0; y < Chunk.SizeY; y++) { for (int z = 0; z < Chunk.SizeZ; z++) { BlockOffset blockOffset = new BlockOffset(x, y, z); GenerateLandscape(chunk, blockOffset); GenerateCoal(chunk, blockOffset); GenerateIron(chunk, blockOffset); GenerateGold(chunk, blockOffset); GenerateDiamond(chunk, blockOffset); GenerateCave(chunk, blockOffset); GenerateWater(chunk, blockOffset); } } } }
public virtual IDirectoryBlock GetDirectoryBlock(BlockOffset blockOffset) { return new RawDirectoryBlock(this,blockOffset,(uint)BlockSize); }
public virtual void FreeBlock(BlockOffset blockOffset) { if (blockOffset.Offset + 1 == Break.Offset) { // The block to be free lies next to break, // reduce break instead Break = (BlockOffset) (Break.Offset - 1u); if(Space.CanShrink) Space.Resize(Break.Offset*BlockSize); // We treat a freed block as a changed block since that // allows us to retrieve the original version in case of // a rollback OnBlockChanged(blockOffset); } else { // The block lies within our allocated space // We need to track it in our empty space list. var head = GetEmptyListBlock(EmptyListOffset); // If we don't have enough space to add a new offset // then prepend a new empty list block. if (head.Count >= head.ListCapacity) { var newHead = AllocateEmptyListBlock(); newHead.ContinuationBlockOffset = head.Offset; EmptyListOffset = newHead.Offset; head = newHead; } head.Append(new[] { blockOffset }); // Here we don't need to record the block as changed since // it is being left as it is by free block // Should it be repurposed, that operation will generate // a journal entry. // This enables a relatively cheap restoration of deleted // files if their blocks have not been reused yet. } }
public MemDirectoryBlock(BlockOffset offset, int capacity) : base(offset,capacity) { }
public virtual void DirectRead(BlockOffset blockOffset, byte[] destination, int index) { var raw = BlockManager as RawBlockManager; if (raw == null) throw new NotSupportedException( "The block manager underlying this virtual disk does not support synchronization."); raw.ReadDataBlock(blockOffset, destination, index,0,null); }
internal static unsafe void Initialize( [NotNull] IRawPersistenceSpace space, uint blockCount, uint blockSize = VirtualFileSystem.DefaultBlockSize, BlockOffset? rootDirectoryOffset = null, BlockOffset? emptyListOffset = null) { if (blockSize < MinimumBlockSize) throw new ArgumentOutOfRangeException("blockSize", blockSize, "Block size must be at least " + MinimumBlockSize + "."); if (space == null) throw new ArgumentNullException("space"); var actualRootDirectoryOffset = rootDirectoryOffset ?? (BlockOffset)1; var actualEmptyListOffset = emptyListOffset ?? (BlockOffset)2; if (actualRootDirectoryOffset.Offset >= blockCount) throw new ArgumentOutOfRangeException("rootDirectoryOffset", rootDirectoryOffset, "Root directory offset is beyond the end of the disk."); if (actualEmptyListOffset.Offset >= blockCount) throw new ArgumentOutOfRangeException("emptyListOffset", emptyListOffset, "Empty list offset is beyond the end of the disk."); var uintPtr = (uint*)space.Pointer; uintPtr[BlockCountFieldOffset] = blockCount; uintPtr[BlockSizeFieldOffset] = blockSize; uintPtr[RootDirectoryFieldOffset] = actualRootDirectoryOffset.Offset; uintPtr[EmptyListFieldOffset] = actualEmptyListOffset.Offset; uintPtr[BreakFieldOffset] = Math.Max(actualRootDirectoryOffset.Offset, actualEmptyListOffset.Offset) + 1; uintPtr[JournalFieldOffset] = 0; var end = ((byte*)space.Pointer) + blockSize; for (var bytePtr = (byte*)&uintPtr[BreakFieldOffset + 1]; bytePtr < end; bytePtr++) *bytePtr = 0; _initZero(space, blockSize, actualRootDirectoryOffset); _initZero(space, blockSize, actualEmptyListOffset); }
public unsafe virtual void WriteBlockDirect(BlockOffset blockOffset, byte[] data) { if (data == null) throw new ArgumentNullException("data"); var dataBlockSize = BlockSize; if (data.Length > dataBlockSize) throw new ArgumentException( string.Format("Data array is longer than block size. (block size = {0}, data length = {1})", dataBlockSize, data.Length), "data"); // Copy the provided data var blockAddress = _blockAt(blockOffset); Marshal.Copy(data, 0, (IntPtr)blockAddress, data.Length); // Padd rest with 0 // (this is not really necessary, but it will help us debug) var start = (byte*)blockAddress; var end = start + dataBlockSize; for (var ptr = start + data.Length; ptr < end; ptr++) *ptr = 0; }
public virtual IFileContinuationBlock GetFileContinuationBlock(BlockOffset blockOffset) { return new RawOffsetListBlock(this,blockOffset,(uint) BlockSize); }
public void SetBlock(ChunkOffset chunkOffset, BlockOffset blockOffset, IBlock block) { Chunk chunk = FindChunk(chunkOffset); chunk?.SetBlock(blockOffset, block); }
private unsafe void* _blockAt(BlockOffset offset) { var bytePtr = (byte*)_space.Pointer; return bytePtr + BlockSize * offset.Offset; }
protected IJournalBlock GetJournalBlock(BlockOffset blockOffset) { if (blockOffset.Offset >= Break.Offset) throw new ArgumentOutOfRangeException("blockOffset", blockOffset, "Block offset points to location beyond allocation allocated space."); return new RawJournalBlock(this,blockOffset, (uint) BlockSize); }
public IBlock GetBlock(ChunkOffset chunkOffset, BlockOffset blockOffset) { Chunk chunk = FindChunk(chunkOffset); return(chunk?.GetBlock(blockOffset)); }
public Vector3 GetAbsPosition(BlockOffset blockOffset) => CoordinateConverter.ToAbsPosition(Offset, blockOffset);
public virtual void ReceiveChanges(BlockOffset blockOffset, byte[] data) { var raw = BlockManager as RawBlockManager; if (raw == null) throw new NotSupportedException( "The block manager underlying this virtual disk does not support synchronization."); raw.WriteBlockDirect(blockOffset, data); }
public virtual IDirectoryContinuationBlock GetDirectoryContinuationBlock(BlockOffset blockOffset) { return new RawDirectoryEntryListBlock(this,blockOffset,(uint) BlockSize); }
public virtual IFileBlock GetFileBlock(BlockOffset blockOffset) { return new RawFileBlock(this, blockOffset, (uint)BlockSize); }
private async Task _mergeRemoteBlockAsync(DiskViewModel diskModel, BlockOffset blockOffset, byte[] buffer) { using (var blockResp = await _serviceClient.GetAsync(new GetBlock() { DiskName = diskModel.Name, BlockOffset = blockOffset.Offset })) { // incorporate into the local disk blockResp.Read(buffer, 0, buffer.Length); diskModel.SynchronizingDisk.ReceiveChanges(blockOffset, buffer); } }
public unsafe virtual void ReadDataBlock(BlockOffset blockOffset, byte[] destination, int destinationIndex, int blockIndex, int? count) { if (destination == null) throw new ArgumentNullException("destination"); if (destinationIndex < 0) throw new ArgumentOutOfRangeException("destinationIndex", destinationIndex, "Destination index cannot be negative."); if (blockIndex < 0) throw new ArgumentOutOfRangeException("blockIndex", blockIndex, "Block index cannot be negative."); // Check block index var blockRemainingLength = BlockSize - blockIndex; if (blockRemainingLength < 0) throw new ArgumentOutOfRangeException("blockIndex", blockIndex, string.Format( "Index into data block is beyond block boundary. (block size = {0})", BlockSize)); // Check destination index var destinationRemainingLength = destination.Length - destinationIndex; if (destinationRemainingLength < 0) throw new ArgumentOutOfRangeException("destinationIndex", destinationIndex, string.Format( "Index into destination is beyond block boundary. (destination length = {0})", destination.Length)); // Check count var actualCount = count ?? Math.Min(destinationRemainingLength, blockRemainingLength); if (actualCount > destinationRemainingLength || actualCount > blockRemainingLength) throw new ArgumentOutOfRangeException("count", count, "Read count is larger than either the remaining block or the remaining destination array."); if (actualCount < 0) throw new ArgumentOutOfRangeException("count", count, "Count cannot be negative."); // Perform copy var ptr = (IntPtr)_blockAt(blockOffset); Marshal.Copy(IntPtr.Add(ptr, blockIndex), destination, destinationIndex, actualCount); }
public MemOffsetList(BlockOffset offset, int listCapacity) : base(offset) { _listCapacity = listCapacity; }
public unsafe virtual void WriteDataBlock(BlockOffset blockOffset, byte[] data) { WriteBlockDirect(blockOffset, data); OnBlockChanged(blockOffset); }
public RawJournalBlock([NotNull] RawBlockManager manager, BlockOffset offset, uint blockSize) : base(manager, offset, blockSize) { }
/// <summary> /// Called whenever a block has been changed. Used to write the journal. /// </summary> /// <param name="blockOffset">Offset of the block that has changed.</param> protected internal void OnBlockChanged(BlockOffset blockOffset) { Contract.Ensures(!IsJournaling || _journalJobQueue.Count == 0); // Check if journaling is even enabled if(!IsJournaling) return; // Between two synchronization operations don't add the same block // more than once. // This "optimization" is crucial as the journal pages // are being changed constantly and we only want them to appear once // in the journal itself. if(_modifiedBlocks.Contains(blockOffset)) return; var alreadyRunning = _journalJobQueue.Count > 0; _journalJobQueue.Enqueue(blockOffset); _modifiedBlocks.Add(blockOffset); // If OnBlockChanges is already running and this is a recursive/nested call, putting // the block offset in the queue was enough. The activation higher up in the call stack // will make sure it is stored. if(alreadyRunning) return; // Get the latest journal block (or allocate a new journal if this // disk hasn't kept a journal before) var nextJournalOffset = JournalOffset; IJournalBlock journalBlock; if (nextJournalOffset == null) { journalBlock = AllocateJournalBlock(); JournalOffset = journalBlock.Offset; } else { journalBlock = GetJournalBlock(nextJournalOffset.Value); } while (_journalJobQueue.Count > 0) { var jobOffset = _journalJobQueue.Dequeue(); var success = journalBlock.TryAppendEntry(new JournalEntry(DateTime.Now, jobOffset)); if (!success) { // there was not enough room for the entry in the current journal block // save the entry for later and allocate more space _journalJobQueue.Enqueue(jobOffset); var nextBlock = AllocateJournalBlock(); // link new block to old list and move the journal head pointer to the new block nextBlock.ContinuationBlockOffset = journalBlock.Offset; JournalOffset = nextBlock.Offset; // start inserting into the new journal block journalBlock = nextBlock; } } }
public MemDirectoryBase(BlockOffset offset, int capacity) : base(offset) { _capacity = capacity; }
private static unsafe void _initZero([NotNull] IRawPersistenceSpace space, uint blockSize, BlockOffset blockOffset) { var ptr = (byte*)space.Pointer; ptr = ptr + blockSize * blockOffset.Offset; var end = ptr + blockSize; // Use platform-specific pointer size when possible if (_isAligned(ptr) && blockSize % sizeof(void*) == 0) { var ptrEnd = (void*)end; for (var ptrAligned = (void**)ptr; ptrAligned < ptrEnd; ptrAligned++) { *ptrAligned = null; } } else { // Fall back to byte-by-byte, slower but works regardless of alignment and processor word size for (; ptr < end; ptr++) { *ptr = 0; } } }
public MemFileBlock(BlockOffset offset, int listCapacity) : base(offset, listCapacity) { }
public abstract void GenerateLandscape(Chunk chunk, BlockOffset blockOffset);
public abstract void GenerateGold(Chunk chunk, BlockOffset blockOffset);
public MemDirectoryContinuationBlock(BlockOffset offset, int capacity) : base(offset, capacity) { }
public abstract void GenerateDiamond(Chunk chunk, BlockOffset blockOffset);
public RawFileBlock([NotNull] RawBlockManager manager, BlockOffset offset, uint size) : base(manager, offset, size) { }
public RawBlock([NotNull] RawBlockManager manager, BlockOffset offset, uint blockSize) { _manager = manager; _offset = offset; _blockSize = blockSize; }
public RawContinuedBlock(RawBlockManager manager, BlockOffset offset, uint blockSize) : base(manager, offset, blockSize) { }
public void ReplaceOffsets(BlockOffset[] offsets) { ThrowIfDeallocated(); _offsets.Clear(); Append(offsets); }