/// <summary> /// Serialize this Collection meta info /// </summary> /// <param name="parent"></param> /// <param name="writer"></param> public virtual void Pack(IInternalPersistent parent, System.IO.BinaryWriter writer) { writer.Write(DataAddress); writer.Write((int)DataBlockSize); writer.Write(Name); writer.Write(HintSizeOnDisk); if (DataBlockDriver == null) { writer.Write(DiskBuffer.DataAddress); } else { writer.Write(DataBlockDriver.GetId(this.DiskBuffer)); } bool hasHeader = HeaderData != null; writer.Write(hasHeader); if (hasHeader) { HeaderData.Pack(parent, writer); } bool hasDeletedBlocks = deletedBlocks != null; writer.Write(hasDeletedBlocks); if (hasDeletedBlocks) { writer.Write(deletedBlocks.DiskBuffer.DataAddress); } }
/// <summary> /// Returns the Current Sop.DataBlock with option not to put it on cache /// </summary> /// <param name="getForRemoval"></param> /// <returns></returns> protected internal Sop.DataBlock GetCurrentDataBlock(bool getForRemoval) { if (currentDataBlock == null || DataBlockDriver.GetId(currentDataBlock) == -1) { currentDataBlock = DataBlockDriver.ReadBlockFromDisk(this, getForRemoval); } return(currentDataBlock); }
/// <summary> /// Reads into memory the Collection On Disk's Header Block which contains /// state information of the collection /// </summary> public virtual void Load() { if (DiskBuffer == null) { throw new InvalidOperationException("'DiskBuffer' is null."); } if (DataBlockDriver.GetId(DiskBuffer) < 0) { throw new InvalidOperationException("'DiskBuffer.DataAddress' is < 0."); } //Blocks.Clear(); //if (DataBlockDriver.MruManager != null) // DataBlockDriver.MruManager.Clear(); //if (MruManager != null) // MruManager.Clear(); currentDataBlock = null; DataBlockDriver.MoveTo(this, DataBlockDriver.GetId(DiskBuffer)); Sop.DataBlock block = GetCurrentDataBlock(); if (block.SizeOccupied > 0) { if (block.DataAddress == DiskBuffer.DataAddress && DiskBuffer.Data == null) { DiskBuffer = block; } ReadFromBlock(block, this); DiskBuffer = block; } if (IsDirty) { IsDirty = false; } //** allow deleted blocks to be loaded its Header and clear its MRU cache... if (File.Server.HasTrashBin && _deletedBlocksAddress >= 0) // && deletedBlocks.DataAddress >= 0) { // ensure Deleted Blocks collection is loaded & initialized. var o = DeletedBlocks; //if (DeletedBlocksAddress != DeletedBlocks.DataAddress) // DeletedBlocks.DataAddress = DeletedBlocksAddress; deletedBlocks.Load(); } }
/// <summary> /// Register current collection's state /// </summary> public virtual void RegisterChange(bool partialRegister = false) { IsDirty = true; _registerCallCount++; if (_registerCallCount == 1) { if (DiskBuffer == null) { throw new InvalidOperationException("'DiskBuffer' is null."); } bool stateSerialized = false; if (!partialRegister || DiskBuffer.SizeOccupied == 0) { stateSerialized = true; DiskBuffer.ClearData(); OnDiskBinaryWriter.WriteObject(File, this, DiskBuffer); } if (!ChangeRegistry) { _registerCallCount = 0; if (!partialRegister || stateSerialized) { Blocks.Add(DataBlockDriver.GetId(DiskBuffer), DiskBuffer); //90; } //DataBlockDriver.MruManager.Add(DataBlockDriver.GetId(DiskBuffer), DiskBuffer); } else { DataBlockDriver.SetDiskBlock(this, DiskBuffer, true); if (_registerCallCount > 1) { _registerCallCount = 0; //IsDirty = true; RegisterChange(partialRegister); } _registerCallCount = 0; } } }
/// <summary> /// Open the Collection /// </summary> public virtual void Open() { SetupCachePool(); if (DataBlockDriver == null) { throw new InvalidOperationException( "DataBlockDriver is null. Make sure you have assigned valid File 'Parent'" ); } if (OnDiskBinaryWriter == null && File.Server != null) { OnDiskBinaryWriter = new OnDiskBinaryWriter(File.Server.Encoding); OnDiskBinaryReader = new OnDiskBinaryReader(File.Server.Encoding); } if (isOpen) { return; } long fileSize = 0; if (FileStream == null) { int systemDetectedBlockSize; FileStream = File.UnbufferedOpen(out systemDetectedBlockSize); if (FileStream != null && File.Size < (fileSize = FileStream.Length)) { short ss = (short)DataBlockSize; long segmentSize = File.CollectionGrowthSizeInNob * ss; long segmentCount = fileSize / segmentSize; if (fileSize % segmentSize != 0 || segmentCount == 0) { segmentCount++; } File.Size = segmentCount * segmentSize; } } isOpen = true; //** read the header if there is one... if (DiskBuffer == null) { return; } if (fileSize == 0) { fileSize = FileStream.Length; } if (DataBlockDriver.GetId(DiskBuffer) >= 0 && fileSize > 0) { if (deletedBlocks != null) { deletedBlocks.Open(); } Load(); ReuseCacheFromPool(); IsDirty = false; } else { //** write header into 1st block if (fileSize == 0 && File.Store.IsItMe(this)) { bool shouldGenerateZeroAddress = false; if (File.Server != null) { if (DiskBuffer.DataAddress == File.DiskBuffer.DataAddress) { DiskBuffer.DataAddress = -1; shouldGenerateZeroAddress = true; } Flush(); IsDirty = DataAddress == -1; } if (shouldGenerateZeroAddress && DiskBuffer.DataAddress != 0) { throw new InvalidOperationException( "Didn't allocate the 1st block(DataAddress=0) on collection's DiskBuffer."); } } } }
/// <summary> /// Returns the ID(DataAddress if block is not virtualized block) of a given block /// </summary> /// <param name="block"></param> /// <returns></returns> public long GetId(Sop.DataBlock block) { return(DataBlockDriver.GetId(block)); }