internal void ExpandStorage(int newCount)
        {
            // There is no need to take additional locks (assuming that a read lock is already being held),
            // because of the way how every expandable array takes care of its expansion (e.g. grow-only, block-oriented).
            // Compaction might break this logic, but it will have to be executed while holding StructureLock in writable mode.
            // The only important global state is our capacity, which is a volatile variable.
            var currentCapacity = m_capacity;

            if (currentCapacity < newCount)
            {
                if (!StructureLock.IsReadLockHeld && !StructureLock.IsWriteLockHeld && !StructureLock.IsUpgradeableReadLockHeld)
                {
                    throw new InvalidOperationException("StructureLock must be held in any mode in order to start expansion");
                }

                var newCapacity = newCount - (newCount % GrowthIncrement) + GrowthIncrement;

                // first, expand field storage
                int goodCount;
                do
                {
                    goodCount = 0;

                    foreach (var store in ColumnStores)
                    {
                        if (m_capacity >= newCapacity)
                        {
                            // some other thread has completed the expansion
                            // stop whatever we are doing here
                            return;
                        }

                        // use "Try" variation here to allow multi-threaded allocation for blocks
                        if (store.TryEnsureCapacity(newCapacity))
                        {
                            goodCount++;
                        }
                    }

                    if (goodCount <= ColumnStores.Length / 2)
                    {
                        // seems like other threads are making progress on expansion too,
                        // let them do something
                        Thread.Yield();
                    }
                } while (goodCount != ColumnStores.Length && m_capacity < newCapacity);

                // also expand backbone structures
                DocumentKeys.EnsureCapacity(newCapacity);
                ValidDocumentsBitmap.EnsureCapacity(newCapacity);

                // have to be careful here, multiple threads compete to set this value
                // some of those had new value for capacity larger or smaller than ours
                currentCapacity = m_capacity;
                while (currentCapacity < newCapacity)
                {
                    currentCapacity = Interlocked.CompareExchange(ref m_capacity, newCapacity, currentCapacity);
                }
            }
        }
        unsafe ExpandableArrayOfKeys GenerateKeys(ulong count)
        {
            var result = new ExpandableArrayOfKeys(_pool);
            result.EnsureCapacity(count);

            var key = new byte[10];

            for (ulong i = 1; i <= count; i++)
            {
                var val = i;
                byte pos = 1;
                while (val != 0)
                {
                    key[pos++] = (byte)val;
                    val >>= 8;
                }

                key[0] = (byte)(pos-1);

                //result[i-1] = key;
                if (!result.TrySetAt((int)i - 1, key))
                {
                    throw new Exception("Failed to set a key element at " + (i-1));
                }
            }

            for (ulong i = 1; i <= count; i++)
            {
                var storedKey = result.GetAt(i-1);

                var val = i;
                byte pos = 1;
                while (val != 0)
                {
                    key[pos++] = (byte)val;
                    val >>= 8;
                }

                key[0] = (byte)(pos-1);

                if (storedKey[0] != key[0])
                {
                    throw new Exception("Length prefix broken at " + (i - 1));
                }

                for (var j = 0; j <= key[0]; j++)
                {
                    //Console.Write(storedKey[j]);
                    //Console.Write(',');

                    if (storedKey[j] != key[j])
                    {
                        throw new Exception("Data broken at " + (i - 1) + ", offset " + j);
                    }
                }

                //Console.WriteLine();
            }

            return result;
        }
Beispiel #3
0
        unsafe ExpandableArrayOfKeys GenerateKeys(ulong count)
        {
            var result = new ExpandableArrayOfKeys(_pool);

            result.EnsureCapacity(count);

            var key = new byte[10];

            for (ulong i = 1; i <= count; i++)
            {
                var  val = i;
                byte pos = 1;
                while (val != 0)
                {
                    key[pos++] = (byte)val;
                    val      >>= 8;
                }

                key[0] = (byte)(pos - 1);

                //result[i-1] = key;
                if (!result.TrySetAt((int)i - 1, key))
                {
                    throw new Exception("Failed to set a key element at " + (i - 1));
                }
            }

            for (ulong i = 1; i <= count; i++)
            {
                var storedKey = result.GetAt(i - 1);

                var  val = i;
                byte pos = 1;
                while (val != 0)
                {
                    key[pos++] = (byte)val;
                    val      >>= 8;
                }

                key[0] = (byte)(pos - 1);

                if (storedKey[0] != key[0])
                {
                    throw new Exception("Length prefix broken at " + (i - 1));
                }

                for (var j = 0; j <= key[0]; j++)
                {
                    //Console.Write(storedKey[j]);
                    //Console.Write(',');

                    if (storedKey[j] != key[j])
                    {
                        throw new Exception("Data broken at " + (i - 1) + ", offset " + j);
                    }
                }

                //Console.WriteLine();
            }


            return(result);
        }