Esempio n. 1
0
        public IEnumerable <IndexEntry> GetRange(ulong stream, long startNumber, long endNumber, int?limit = null)
        {
            Ensure.Nonnegative(startNumber, "startNumber");
            Ensure.Nonnegative(endNumber, "endNumber");

            ulong hash = GetHash(stream);

            var result   = new List <IndexEntry>();
            var startKey = BuildKey(hash, startNumber);
            var endKey   = BuildKey(hash, endNumber);

            if (startKey.GreaterThan(_maxEntry) || endKey.SmallerThan(_minEntry))
            {
                return(result);
            }

            var workItem = GetWorkItem();

            try {
                IndexEntryKey lowBoundsCheck, highBoundsCheck;
                var           recordRange = LocateRecordRange(endKey, out lowBoundsCheck, out highBoundsCheck);
                long          low         = recordRange.Lower;
                long          high        = recordRange.Upper;
                while (low < high)
                {
                    var        mid         = low + (high - low) / 2;
                    IndexEntry midpoint    = ReadEntry(_indexEntrySize, mid, workItem, _version);
                    var        midpointKey = new IndexEntryKey(midpoint.Stream, midpoint.Version);

                    if (midpointKey.GreaterThan(lowBoundsCheck))
                    {
                        throw new MaybeCorruptIndexException(String.Format(
                                                                 "Midpoint key (stream: {0}, version: {1}) > low bounds check key (stream: {2}, version: {3})",
                                                                 midpointKey.Stream, midpointKey.Version, lowBoundsCheck.Stream, lowBoundsCheck.Version));
                    }
                    else if (!midpointKey.GreaterEqualsThan(highBoundsCheck))
                    {
                        throw new MaybeCorruptIndexException(String.Format(
                                                                 "Midpoint key (stream: {0}, version: {1}) < high bounds check key (stream: {2}, version: {3})",
                                                                 midpointKey.Stream, midpointKey.Version, highBoundsCheck.Stream, highBoundsCheck.Version));
                    }

                    if (midpointKey.SmallerEqualsThan(endKey))
                    {
                        high            = mid;
                        highBoundsCheck = midpointKey;
                    }
                    else
                    {
                        low            = mid + 1;
                        lowBoundsCheck = midpointKey;
                    }
                }

                PositionAtEntry(_indexEntrySize, high, workItem);
                for (long i = high, n = Count; i < n; ++i)
                {
                    IndexEntry entry        = ReadNextNoSeek(workItem, _version);
                    var        candidateKey = new IndexEntryKey(entry.Stream, entry.Version);
                    if (candidateKey.GreaterThan(endKey))
                    {
                        throw new MaybeCorruptIndexException(string.Format(
                                                                 "entry ({0}@{1}) > endKey {2}, stream {3}, startNum {4}, endNum {5}, PTable: {6}.",
                                                                 entry.Stream, entry.Version, startKey, stream, startNumber, endNumber, Filename));
                    }
                    if (candidateKey.SmallerThan(startKey))
                    {
                        return(result);
                    }
                    result.Add(entry);
                    if (result.Count == limit)
                    {
                        break;
                    }
                }

                return(result);
            } finally {
                ReturnWorkItem(workItem);
            }
        }
Esempio n. 2
0
        private bool TryGetSmallestEntry(ulong stream, long startNumber, long endNumber, out IndexEntry entry)
        {
            Ensure.Nonnegative(startNumber, "startNumber");
            Ensure.Nonnegative(endNumber, "endNumber");

            entry = TableIndex.InvalidIndexEntry;

            var startKey = BuildKey(stream, startNumber);
            var endKey   = BuildKey(stream, endNumber);

            if (startKey.GreaterThan(_maxEntry) || endKey.SmallerThan(_minEntry))
            {
                return(false);
            }

            var workItem = GetWorkItem();

            try {
                IndexEntryKey lowBoundsCheck, highBoundsCheck;
                var           recordRange = LocateRecordRange(startKey, out lowBoundsCheck, out highBoundsCheck);

                long low  = recordRange.Lower;
                long high = recordRange.Upper;
                while (low < high)
                {
                    var mid         = low + (high - low + 1) / 2;
                    var midpoint    = ReadEntry(_indexEntrySize, mid, workItem, _version);
                    var midpointKey = new IndexEntryKey(midpoint.Stream, midpoint.Version);

                    if (midpointKey.GreaterThan(lowBoundsCheck))
                    {
                        throw new MaybeCorruptIndexException(String.Format(
                                                                 "Midpoint key (stream: {0}, version: {1}) > low bounds check key (stream: {2}, version: {3})",
                                                                 midpointKey.Stream, midpointKey.Version, lowBoundsCheck.Stream, lowBoundsCheck.Version));
                    }
                    else if (!midpointKey.GreaterEqualsThan(highBoundsCheck))
                    {
                        throw new MaybeCorruptIndexException(String.Format(
                                                                 "Midpoint key (stream: {0}, version: {1}) < high bounds check key (stream: {2}, version: {3})",
                                                                 midpointKey.Stream, midpointKey.Version, highBoundsCheck.Stream, highBoundsCheck.Version));
                    }

                    if (midpointKey.SmallerThan(startKey))
                    {
                        high            = mid - 1;
                        highBoundsCheck = midpointKey;
                    }
                    else
                    {
                        low            = mid;
                        lowBoundsCheck = midpointKey;
                    }
                }

                var candEntry    = ReadEntry(_indexEntrySize, high, workItem, _version);
                var candidateKey = new IndexEntryKey(candEntry.Stream, candEntry.Version);
                if (candidateKey.SmallerThan(startKey))
                {
                    throw new MaybeCorruptIndexException(string.Format(
                                                             "candEntry ({0}@{1}) < startKey {2}, stream {3}, startNum {4}, endNum {5}, PTable: {6}.",
                                                             candEntry.Stream, candEntry.Version, startKey, stream, startNumber, endNumber, Filename));
                }
                if (candidateKey.GreaterThan(endKey))
                {
                    return(false);
                }
                entry = candEntry;
                return(true);
            } finally {
                ReturnWorkItem(workItem);
            }
        }