/// <summary> /// protected virtual dispose. /// Closes this Collection on disk, its deleted blocks and Mru Segments. /// Sets the data block driver to null. /// </summary> protected internal virtual void InternalDispose() { if (FileStream != null) { Close(); } if (deletedBlocks != null) { deletedBlocks.Dispose(); deletedBlocks = null; } Parent = null; if (DataBlockDriver != null) { if (!IsCloned) { DataBlockDriver.Dispose(); } DataBlockDriver = null; } if (OnDiskBinaryReader != null) { OnDiskBinaryReader.Close(); OnDiskBinaryReader = null; } if (OnDiskBinaryWriter != null) { OnDiskBinaryWriter.Close(); OnDiskBinaryWriter = null; } _instanceTransaction = null; _parentTransactionLogger = null; File = null; }
/// <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> /// Shallow copy the Collection into a new instance and return it. /// </summary> public virtual object Clone() { var lid = new LinkedListOnDisk { File = File, DataBlockSize = DataBlockSize, HintSizeOnDisk = HintSizeOnDisk, currentEntry = currentEntry, DataAddress = DataAddress, MruManager = MruManager, MruMinCapacity = MruMinCapacity, MruMaxCapacity = MruMaxCapacity, SyncRoot = SyncRoot, DataBlockDriver = (DataBlock.DataBlockDriver)DataBlockDriver.Clone(), FirstItem = new LinkedItemOnDisk(File.DataBlockSize) }; lid.CurrentItem = lid.FirstItem; lid.LastItem = new LinkedItemOnDisk(File.DataBlockSize); int systemDetectedBlockSize; lid.FileStream = File.UnbufferedOpen(out systemDetectedBlockSize); lid.isOpen = true; lid.IsCloned = true; lid.Name = Name; // string.Format("{0} Clone", Name); lid.OnDiskBinaryWriter = new OnDiskBinaryWriter(File.Server.Encoding); lid.OnDiskBinaryReader = new OnDiskBinaryReader(File.Server.Encoding); return(lid); }
/// <summary> /// Returns flag that tells whether this Collection had been modified or not /// </summary> /// <param name="block"></param> /// <returns></returns> public bool GetIsDirty(Sop.DataBlock block) { if (DataBlockDriver == null) { return(block.IsDirty); } return(DataBlockDriver.GetIsDirty(block)); }
/// <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> /// Clear contents of this Collection. /// Changes will be saved right after clearing the contents. /// </summary> public virtual void Clear() { if (HeaderData.OccupiedBlocksHead != null && HeaderData.OccupiedBlocksTail != null) { HeaderData.DiskBuffer.IsDirty = true; HeaderData.OccupiedBlocksTail.DataAddress = HeaderData.NextAllocatableAddress = HeaderData.StartAllocatableAddress = HeaderData.OccupiedBlocksHead.DataAddress; int segmentSize = File.GetSegmentSize(); if (HeaderData.OccupiedBlocksHead.DataAddress + segmentSize != HeaderData.EndAllocatableAddress) { //**** add to File.DeletedCollections the next _region for reuse... //** read next segment of deleted collection var dbi = new DeletedBlockInfo(); Sop.DataBlock db; db = DataBlockDriver.ReadBlockFromDisk(this, HeaderData.OccupiedBlocksHead.DataAddress + segmentSize - (int)File.DataBlockSize, true); if (db.InternalNextBlockAddress >= 0) { dbi.StartBlockAddress = db.InternalNextBlockAddress; dbi.EndBlockAddress = db.InternalNextBlockAddress + segmentSize; if (File.DeletedCollections != null) { bool oc = ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry; ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry = ChangeRegistry; File.DeletedCollections.Add(dbi); ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry = oc; } HeaderData.EndAllocatableAddress = HeaderData.OccupiedBlocksHead.DataAddress + segmentSize; } } } HeaderData.Count = 0; if (HeaderData.diskBuffer != null) { HeaderData.diskBuffer.ClearData(); } if (deletedBlocks != null) { deletedBlocks.Clear(); } //if (MruManager != null) // MruManager.Clear(); //if (this.DataBlockDriver != null) // this.DataBlockDriver.MruManager.Clear(); //Blocks.Clear(); currentDataBlock = null; currentEntry = null; _currentEntryDataAddress = -1; RegisterChange(); Flush(); }
/// <summary> /// Mark this Collection as modified or not /// </summary> /// <param name="block"></param> /// <param name="newValue"></param> public void SetIsDirty(Sop.DataBlock block, bool newValue) { if (DataBlockDriver == null) { block.IsDirty = newValue; } else { DataBlockDriver.SetIsDirty(block, newValue); } }
/// <summary> /// Remove ObjectToRemove from the Collection if found, else throws an exception /// </summary> public void Remove(object item) { if (!Contains(item)) { return; } Sop.DataBlock currBlock = this.GetCurrentDataBlock(true); if (GetId(currBlock) >= 0) { MruManager.Remove(GetId(currBlock), true); } DataBlockDriver.Remove(this, currBlock); }
/// <summary> /// Add 'Value' to the Collection /// </summary> public long Add(object value) { var o = new LinkedItemOnDisk(this.DataBlockSize) { Data = value }; WriteToDisk(o, false); UpdateCount(UpdateCountType.Increment); //*** update Current, Last & First if (LastItem.DiskBuffer.DataAddress != -1) { o.PreviousItemAddress = LastItem.DiskBuffer.DataAddress; WriteToDisk(o, false); LinkedItemOnDisk biod = CurrentItem; biod.NextItemAddress = o.DiskBuffer.DataAddress; Sop.DataBlock db = DataBlockDriver.ReadBlockFromDisk(this, LastItem.DiskBuffer.DataAddress, true); if (CurrentItem.DiskBuffer.DataAddress != LastItem.DiskBuffer.DataAddress) { biod = (LinkedItemOnDisk)ReadFromBlock(db); biod.NextItemAddress = o.DiskBuffer.DataAddress; } else { PurifyMeta(biod, db); if (db.SizeOccupied > 0) { biod.DiskBuffer = db; } } WriteToDisk(biod, false); } else { FirstItem.DiskBuffer.DataAddress = o.DiskBuffer.DataAddress; } currentEntry = null; CurrentItem = o; CurrentEntryDataAddress = o.DiskBuffer.DataAddress; currentDataBlock = o.DiskBuffer; LastItem.DiskBuffer.DataAddress = o.DiskBuffer.DataAddress; MruManager.Add(CurrentEntryDataAddress, o); //** update the header RegisterChange(true); //IsDirty = true; return(o.DiskBuffer.DataAddress); }
/// <summary> /// protected virtual dispose. /// Closes this Collection on disk, its deleted blocks and Mru Segments. /// Sets the data block driver to null. /// </summary> protected internal virtual void InternalDispose() { // note: SOP's Dispose pattern is created to provide way to do early // garbage collection of the "graph" objects, simply. Not for freeing up unmanaged // resources, thus, no finalizer/SafeHandle "patterns". All members are "virtualized" // objects and they have custom Dispose for the same. if (isDisposed) { return; } isDisposed = true; // FileStream is a wrapper, not the .Net FileStream. if (FileStream != null) { Close(); } if (deletedBlocks != null) { deletedBlocks.Dispose(); deletedBlocks = null; } Parent = null; if (DataBlockDriver != null) { //if (!IsCloned) DataBlockDriver.Dispose(); DataBlockDriver = null; } if (OnDiskBinaryReader != null) { OnDiskBinaryReader.Close(); OnDiskBinaryReader = null; } if (OnDiskBinaryWriter != null) { OnDiskBinaryWriter.Close(); OnDiskBinaryWriter = null; } _instanceTransaction = null; _parentTransactionLogger = null; File = null; Blocks = null; var locker = _syncRoot as IDisposable; if (locker != null) { locker.Dispose(); } }
/// <summary> /// Delete & Dispose this collection. /// Send all allocated segments:blocks to recycle bin /// </summary> public virtual void Delete() { if (DataBlockDriver != null) { DataBlockDriver.Delete(this); CollectionOnDisk codParent = GetTopParent(); if (codParent.deletedBlocks != null && codParent.deletedBlocks.DataAddress >= 0) { IDataBlockRecycler dc = codParent.deletedBlocks; codParent.deletedBlocks = null; dc.Delete(); } } Dispose(); }
/// <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> /// MoveFirst makes the first entry in the Collection the current one /// </summary> public override bool MoveFirst() { if (Count > 0 && CurrentItem != null) { if (FirstItem.DiskBuffer.DataAddress != CurrentEntryDataAddress || FirstItem.DiskBuffer.DataAddress != CurrentItem.DiskBuffer.DataAddress) { CurrentEntryDataAddress = -1; this.DataBlockDriver.MoveTo(this, FirstItem.DiskBuffer.DataAddress); Sop.DataBlock db = DataBlockDriver.ReadBlockFromDisk(this, FirstItem.DiskBuffer.DataAddress, false); this.currentDataBlock = db; CurrentItem = (LinkedItemOnDisk)ReadFromBlock(db); } return(true); } return(false); }
/// <summary> /// When maximum capacity of Collection's Objects' MRU Manager is reached, /// it calls this version of "OnMaxCapacity" in order to /// reduce the number of objects kept in-memory /// </summary> /// <param name="nodes">List of Collection Objects or "Nodes" that were removed /// from memory and should be saved to disk</param> public virtual int OnMaxCapacity(IEnumerable nodes) { foreach (IInternalPersistent node in nodes) { if (!node.IsDirty) { continue; } //** save Items' Data var block = WriteToBlock(node); DataBlockDriver.SetDiskBlock(this, block, false); AddToBlocks(block, Blocks); node.IsDirty = false; } int r = Blocks.Count; SaveBlocks(false); return(r); }
/// <summary> /// DeSerialize this Collection's Meta Info /// </summary> /// <param name="parent"></param> /// <param name="reader"></param> public virtual void Unpack(IInternalPersistent parent, System.IO.BinaryReader reader) { long da = reader.ReadInt64(); if (da >= 0) { DataAddress = da; } DataBlockSize = (DataBlockSize)reader.ReadInt32(); Name = reader.ReadString(); HintSizeOnDisk = reader.ReadInt32(); long l = reader.ReadInt64(); if (l >= 0) { DataBlockDriver.SetId(this.DiskBuffer, l); } bool hasHeader = reader.ReadBoolean(); if (hasHeader) { if (HeaderData == null) { HeaderData = new HeaderData(); } HeaderData.Unpack(parent, reader); } MruMinCapacity = ((CollectionOnDisk)parent).File.Profile.MruMinCapacity; MruMaxCapacity = ((CollectionOnDisk)parent).File.Profile.MruMaxCapacity; bool hasDeletedBlocks = reader.ReadBoolean(); if (hasDeletedBlocks) { _deletedBlocksAddress = reader.ReadInt64(); } else if (deletedBlocks != null) { deletedBlocks = null; } }
/// <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; } } }
protected virtual void WriteBlocksToDisk(ICollectionOnDisk parent, IDictionary <long, Sop.DataBlock> blocks, bool clear) { DataBlockDriver.WriteBlocksToDisk(parent, blocks, clear); }
/// <summary> /// Initialize. NOTE: this function doesn't open the file. /// </summary> /// <param name="file"></param> /// <param name="parameters"> </param> protected internal virtual void Initialize(File.IFile file, params KeyValuePair <string, object>[] parameters) { if (file == null) { throw new ArgumentNullException("file"); } if (transaction == null || (transaction is Transaction.Transaction && ((Transaction.Transaction)transaction).Server != file.Server)) { Transaction.ITransactionLogger trans = file.Transaction; if (trans != null) { trans = ((Transaction.TransactionBase)trans).GetLeafChild(); } if (trans == null || trans is Transaction.Transaction) { transaction = trans; } } if (string.IsNullOrEmpty(this.Name)) { var f = new FileInfo(file.Filename); Name = string.Format("{0} Collection {1}", f.Name, ((Sop.OnDisk.File.File)file).GetNewStoreId()); } if (MruMinCapacity == 0) { MruMinCapacity = file.Profile.MruMinCapacity; } if (MruMaxCapacity == 0) { MruMaxCapacity = file.Profile.MruMaxCapacity; } if (File == null) { File = file; } if (DataBlockSize == DataBlockSize.Unknown) { DataBlockSize = file.DataBlockSize; } HeaderData hd = null; if (parameters != null && parameters.Length > 0) { foreach (KeyValuePair <string, object> o in parameters) { switch (o.Key) { case "HasMruSegments": break; case "HeaderData": hd = (HeaderData)o.Value; break; default: if (o.Key == "DataBlockDriver" && o.Value != null) { DataBlockDriver = (IDataBlockDriver)o.Value; } break; } } } if (DataBlockDriver == null) { DataBlockDriver = new DataBlockDriver(this, hd); } else { if (DataBlockDriver.HeaderData == null) { DataBlockDriver.HeaderData = hd ?? new HeaderData(DataBlockSize); } } if (MruManager == null) { int min = MruMinCapacity; int max = MruMaxCapacity; //MruManager = new ConcurrentMruManager(min, max); MruManager = new MruManager(min, max); MruManager.SetDataStores(this, DataBlockDriver); } if (_diskBuffer == null) { _diskBuffer = CreateBlock(); //new Sop.DataBlock(DataBlockSize); } }
/// <summary> /// OnRead gets called to read Object from Disk /// </summary> /// <param name="address">Address of Object on disk</param> /// <returns></returns> protected internal virtual object OnRead(long address) { //** read Node including Keys Sop.DataBlock d = DataBlockDriver.ReadBlockFromDisk(this, address, false); return(ReadFromBlock(d)); }
/// <summary> /// Serialize object and write its byte array to disk /// </summary> /// <param name="value"></param> /// <param name="isCollectionBlock"> </param> protected void WriteToDisk(IInternalPersistent value, bool isCollectionBlock) { Sop.DataBlock block = WriteToBlock(value, value.DiskBuffer); DataBlockDriver.SetDiskBlock(this, block, isCollectionBlock); }
/// <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> /// Set Block ID to a given Address /// </summary> /// <param name="block"></param> /// <param name="address"></param> public void SetId(Sop.DataBlock block, long address) { DataBlockDriver.SetId(block, address); }
/// <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)); }
//internal override bool RemoveInMemory(long DataAddress, Transaction.ITransactionLogger Transaction) //{ // if (LastItem != null) // LastItem.Clear(); // if (FirstItem != null) // FirstItem.Clear(); // CurrentItem = null; // base.RemoveInMemory(DataAddress, Transaction); // return true; //} private void RemoveAt(long dataAddress, bool willMove) { if (willMove && !MoveTo(dataAddress)) { return; } if (IsDeletedBlocksList && Count == 1) { return; } Sop.DataBlock currBlock = this.GetCurrentDataBlock(true); if (FirstItem.DiskBuffer.DataAddress == dataAddress) { MoveFirst(); if (MoveNext()) { FirstItem.DiskBuffer.DataAddress = CurrentItem.DiskBuffer.DataAddress; CurrentItem.PreviousItemAddress = -1; Sop.DataBlock db = WriteToBlock(CurrentItem, CurrentItem.DiskBuffer); DataBlockDriver.SetDiskBlock(this, db, false); } else { long address = FirstItem.DiskBuffer.DataAddress; FirstItem.DiskBuffer.DataAddress = LastItem.DiskBuffer.DataAddress = -1; CurrentItem = FirstItem; Sop.DataBlock db = WriteToBlock(CurrentItem, CurrentItem.DiskBuffer); db.DataAddress = address; DataBlockDriver.SetDiskBlock(this, db, false); db.DataAddress = -1; } } else if (LastItem.DiskBuffer.DataAddress == dataAddress) { if (MovePrevious() || FirstItem.DiskBuffer.DataAddress == CurrentItem.DiskBuffer.DataAddress) { LastItem.DiskBuffer.DataAddress = CurrentItem.DiskBuffer.DataAddress; CurrentItem.NextItemAddress = -1; Sop.DataBlock db = WriteToBlock(CurrentItem, CurrentItem.DiskBuffer); DataBlockDriver.SetDiskBlock(this, db, false); } else { throw new InvalidOperationException("Can't go previous but First is not the only item."); } } else { LinkedItemOnDisk curr = CurrentItem; LinkedItemOnDisk prev = null, next = null; if (MoveTo(curr.PreviousItemAddress)) { prev = CurrentItem; } if (MoveTo(curr.NextItemAddress)) { next = CurrentItem; } if (prev != null && next != null) { prev.NextItemAddress = curr.NextItemAddress; next.PreviousItemAddress = curr.PreviousItemAddress; Sop.DataBlock db = WriteToBlock(prev, prev.DiskBuffer); DataBlockDriver.SetDiskBlock(this, db, false); db = WriteToBlock(next, next.DiskBuffer); DataBlockDriver.SetDiskBlock(this, db, false); } } if (MruManager.Count > 0) { MruManager.Remove(dataAddress, true); } DataBlockDriver.Remove(this, currBlock); }
//private const int ObjectBlockCountThreshold = 64; /// <summary> /// If in AutoFlush mode and data Value is not saved in Key segment, /// this method will Add/Update Big Data Value to disk and at end of the process, /// set the Value to null to conserve memory. /// </summary> /// <param name="item"></param> /// <returns></returns> private bool SetBigDataValue(BTreeItemOnDisk item) { if (!IsDataInKeySegment) { // load meta data so Blocks layout in-memory can get recreated... long da = GetId(item.Value.DiskBuffer); if (da >= 0) { if (!item.Value.DiskBuffer.IsFolded) { if (item.Value.DiskBuffer.IsFoldedInfoOnDisk) { // read the block chain info so these blocks will not be replaced during update! var metaBlocks = DataBlockDriver.ReadBlockInfoFromDisk(this, da); // assign read block chain info to a DataBlock simulating a "Folded" scenario. item.Value.diskBuffer.foldedDataAddresses = metaBlocks.ToArray(); item.Value.diskBuffer.contiguousBlockCount = metaBlocks[0].BlockCount; } } // delete the blocks on disk if they are big and data being set is null if (item.Value.Data == null && item.Value.DiskBuffer.IsFolded && item.Value.DiskBuffer.CountMembers() >= 1024) { DataSet.DataBlockDriver.Remove(DataSet, item.Value.DiskBuffer); item.Value.DiskBuffer = CreateBlock(); } } // save big data to disk if (item.Value.diskBuffer != null) { item.Value.diskBuffer.Unfold(this); } Sop.DataBlock b = WriteToBlock(item.Value); DataSet.DataBlockDriver.SetDiskBlock(DataSet, b, false, false); var cnt = b.ProcessHeadSets(); // store blocks to the pool if block count < 500, otherwise direct write to disk! if (cnt < File.Profile.BigDataBlockCount) { AddToBlocks(b, Blocks); item.ValueLoaded = true; item.Value.IsDirty = false; item.IsDirty = false; item.Value.diskBuffer.Fold(); } else { if (cnt <= 500) { AddToBlocks(b, Blocks); } else { // direct write to disk var blocks = new Collections.Generic.SortedDictionary <long, Sop.DataBlock>(); AddToBlocks(b, blocks); WriteBlocksToDisk(DataSet, blocks, false); } item.IsDirty = false; item.Value.IsDirty = false; item.ValueLoaded = false; item.Value.diskBuffer.Fold(); // nullify big data to conserve memory item.Value.Data = null; } return(true); } return(false); }
internal Sop.DataBlock CreateBlock(DataBlockSize size) { return(DataBlockDriver.CreateBlock(size)); }