示例#1
0
        public Handle GetGenerationHandle(Handle handle, out int generation)
        {
            if (handle.IsVirtual)
            {
                // TODO: if a virtual handle is connected to real handle then translate the rid,
                // otherwise return vhandle and base.
                throw new NotSupportedException();
            }

            if (handle.IsHeapHandle)
            {
                int heapOffset = handle.Offset;

                HeapIndex heapIndex;
                MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex);

                var sizes = _heapSizes[(int)heapIndex];

                generation = sizes.BinarySearch(heapOffset);
                if (generation >= 0)
                {
                    Debug.Assert(sizes[generation] == heapOffset);

                    // the index points to the start of the next generation that added data to the heap:
                    do
                    {
                        generation++;
                    }while (generation < sizes.Length && sizes[generation] == heapOffset);
                }
                else
                {
                    generation = ~generation;
                }

                if (generation >= sizes.Length)
                {
                    throw new ArgumentException(SR.HandleBelongsToFutureGeneration, "handle");
                }

                // GUID heap accumulates - previous heap is copied to the next generation
                int relativeHeapOffset = (handle.Type == HandleType.Guid || generation == 0) ? heapOffset : heapOffset - sizes[generation - 1];

                return(new Handle((byte)handle.Type, relativeHeapOffset));
            }
            else
            {
                int rowId = handle.RowId;

                var sizes = _rowCounts[(int)handle.Type];

                generation = sizes.BinarySearch(new RowCounts {
                    AggregateInserts = rowId
                });
                if (generation >= 0)
                {
                    Debug.Assert(sizes[generation].AggregateInserts == rowId);

                    // the row is in a generation that inserted exactly one row -- the one that we are looking for;
                    // or it's in a preceding generation if the current one didn't insert any rows of the kind:
                    while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId)
                    {
                        generation--;
                    }
                }
                else
                {
                    // the row is in a generation that inserted multiple new rows:
                    generation = ~generation;

                    if (generation >= sizes.Length)
                    {
                        throw new ArgumentException(SR.HandleBelongsToFutureGeneration, "handle");
                    }
                }

                // In each delta table updates always precede inserts.
                int relativeRowId = (generation == 0) ? rowId :
                                    rowId -
                                    sizes[generation - 1].AggregateInserts +
                                    sizes[generation].Updates;

                return(new Handle((byte)handle.Type, relativeRowId));
            }
        }
示例#2
0
        public Handle GetGenerationHandle(Handle handle, out int generation)
        {
            if (handle.IsVirtual)
            {
                // TODO: if a virtual handle is connected to real handle then translate the rid,
                // otherwise return vhandle and base.
                throw new NotSupportedException();
            }

            int  rowId  = (int)handle.RowId;
            uint typeId = handle.TokenType;
            int  relativeRowId;

            if (handle.IsHeapHandle)
            {
                HeapIndex heapIndex;
                MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex);

                var sizes = heapSizes[(int)heapIndex];

                generation = sizes.BinarySearch(rowId);
                if (generation >= 0)
                {
                    DebugCorlib.Assert(sizes[generation] == rowId);

                    // the index points to the start of the next generation that added data to the heap:
                    do
                    {
                        generation++;
                    }while (generation < sizes.Length && sizes[generation] == rowId);
                }
                else
                {
                    generation = ~generation;
                }

                if (generation >= sizes.Length)
                {
                    throw new ArgumentException("Handle belongs to a future generation", "handle");
                }

                // GUID heap accumulates - previous heap is copied to the next generation
                relativeRowId = (typeId == TokenTypeIds.Guid || generation == 0) ? rowId : rowId - sizes[generation - 1];
            }
            else
            {
                var sizes = rowCounts[(int)handle.value >> TokenTypeIds.RowIdBitCount];

                generation = sizes.BinarySearch(new RowCounts {
                    AggregateInserts = rowId
                });
                if (generation >= 0)
                {
                    DebugCorlib.Assert(sizes[generation].AggregateInserts == rowId);

                    // the row is in a generation that inserted exactly one row -- the one that we are looking for;
                    // or it's in a preceeding generation if the current one didn't insert any rows of the kind:
                    while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId)
                    {
                        generation--;
                    }
                }
                else
                {
                    // the row is in a generation that inserted multiple new rows:
                    generation = ~generation;

                    if (generation >= sizes.Length)
                    {
                        throw new ArgumentException("Handle belongs to a future generation", "handle");
                    }
                }

                // In each delta table updates always precede inserts.
                relativeRowId = (generation == 0) ? rowId :
                                rowId -
                                sizes[generation - 1].AggregateInserts +
                                sizes[generation].Updates;
            }

            return(new Handle(typeId | (uint)relativeRowId));
        }