internal bool IsDataBlock([NotNullWhen(returnValue: true)] out DataBlock?dataBlock,
                                  [NotNullWhen(returnValue: false)] out DataBlockSource <TKey>?dataSource)
        {
            var d = Data;

            // They are mutually exclusive so save one isinst call,
            // and we could later replace isinst with bool field (there is padding space so it's free, need to benchmark)
            if (d is DataBlock db)
            {
                dataBlock  = db;
                dataSource = null;
                return(true);
            }

            dataBlock  = null;
            dataSource = Unsafe.As <DataBlockSource <TKey> >(d);
            return(false);
        }
Example #2
0
        private DataBlock GrowCapacity(TKey key, DataBlock block)
        {
            try
            {
                // TODO review: do we want buffers in LOH or not? <= vs <
                // next increment will be 64kb, avoid buffer in LOH
                if (block.RowIndex.Length < MaxBufferLength)
                {
                    if (block.IncreaseSeriesCapacity <TKey, TValue>() < 0)
                    {
                        return(null);
                    }
                }
                else
                {
                    // refactor switching to source logic to reuse in MutableSeries
                    if (DataSource == null)
                    {
                        DataSource = new DataBlockSource <TKey>();
                        DataSource.AddLast(block.RowIndex.DangerousGetRef <TKey>(0), block);
                        DataBlock = null;
                    }

                    var minCapacity = block.RowIndex.Length;
                    var newBlock    = DataBlock.Create();
                    if (newBlock.IncreaseSeriesCapacity <TKey, TValue>(minCapacity) < 0)
                    {
                        return(null);
                    }
                    DataSource.AddLast(key, newBlock);
                    block = newBlock;
                }

                return(block);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                return(null);
            }
        }
        internal bool TryFindBlockAtFromSource([NotNullWhen(true)] out DataBlock?db,
                                               DataBlockSource <TKey> ds,
                                               TKey key,
                                               Lookup sourceDirection)
        {
            if (!ds.TryFindAt(key, sourceDirection, out var kvp))
            {
                db = null;
                return(false);
            }

            if (AdditionalCorrectnessChecks.Enabled)
            {
                if (kvp.Value.RowCount <= 0 ||
                    _comparer.Compare(kvp.Key, kvp.Value.DangerousRowKey <TKey>(index: 0)) != 0)
                {
                    ThrowBadBlockFromSource();
                }
            }

            db = kvp.Value;
            return(true);
        }
 private bool TryGetBlockFromSource([NotNullWhen(true)] out DataBlock?db,
                                    DataBlockSource <TKey> ds,
                                    in TKey key)
Example #5
0
        private bool TryAppendGrowCapacity(TKey key, TValue value, [NotNullWhen(true)] ref DataBlock?block, out object?data)
        {
            ThrowHelper.DebugAssert(block != null);
            data = null;
            try
            {
                if (block == DataBlock.Empty)
                {
                    block = DataBlock.SeriesCreate(rowLength: 0);
                    data  = block;
                }

                // TODO review: do we want buffers in LOH or not? <= vs <
                // next increment will be 64kb, avoid buffer in LOH

                // ReSharper disable once PossibleNullReferenceException
                if (block.RowCapacity < MaxBlockRowCount)
                {
                    if (block.SeriesIncreaseCapacity <TKey, TValue>() < 0)
                    {
                        block = null;
                        return(false);
                    }
                    // WindowOptions?.OnBeforeAppend();
                    block.SeriesAppend(key, value);
                }
                else
                {
                    // refactor switching to source logic to reuse in MutableSeries
                    if (IsDataBlock(out var db, out var ds))
                    {
                        Debug.Assert(ReferenceEquals(block, db));

                        ds = new DataBlockSource <TKey>();
                        ds.AddLast(block.DangerousRowKey <TKey>(0), block);
                        data = ds;
                    }

                    // before creating a new block try to remove first blocks that
                    // are not used and satisfy MovingWindowOptions
                    //if (!IsDataBlock(out _, out _))
                    //    WindowOptions?.OnBeforeNewBlock();

                    var minCapacity = block.RowCapacity;
                    var newBlock    = DataBlock.SeriesCreate(rowLength: 0);
                    if (newBlock.SeriesIncreaseCapacity <TKey, TValue>(minCapacity) < 0)
                    {
                        block = null;
                        return(false);
                    }

                    // WindowOptions?.OnBeforeAppend();
                    newBlock.SeriesAppend(key, value);

                    ds.AddLast(key, newBlock);
                    block = newBlock;
                    ThrowHelper.DebugAssert(Data == ds || data == ds);
                }

                return(true);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                block = null;
                return(false);
            }
        }