예제 #1
0
        private IEnumerator <KeyValuePair <Key, Value> > GetEnumerator()
        {
            if (NextPageIndex < 0)
            {
                StopEnumerating = true;
                yield break;
            }

            PageRecord page = ActiveManifest.FindPageForIndex(Level, NextPageIndex++);

            if (page == null)
            {
                StopEnumerating = true;
                yield break;
            }

            var sbt = new SortedBlockTable(Cache, BaseFileName, page.Level, page.Version);

            try {
                foreach (var pair in sbt.EnumerateFromKey(Cache, StartKey))
                {
                    yield return(pair);
                }
            } finally {
                sbt.Close();
            }
        }
예제 #2
0
        private Value InternalGet(Key lookupKey)
        {
            Value output = Value.Empty;
            // Capture copy of the rotated table if there is one
            var rotatedMemTable = _rotatedJournaledMemTable;

            // somtimes on shutdown this is null
            if (_currentJournaledMemTable == null || _manifest == null)
            {
                return(Value.Empty);
            }

            // First check the current memtable
            if (_currentJournaledMemTable.Lookup(lookupKey, out output))
            {
                return(output);
            }

            // Check the table in rotation
            if (rotatedMemTable != null)
            {
                if (rotatedMemTable.Lookup(lookupKey, out output))
                {
                    return(output);
                }
            }


            // Now check the files on disk
            using (var manifest = _manifest.GetLatestManifest()) {
                // Must check all pages on level 0
                var zeroPages = manifest.GetPagesAtLevel(0).OrderByDescending((page) => page.Version);
                foreach (var page in zeroPages)
                {
                    if (SortedBlockTable.Lookup(_manifest.BaseFileName, page.Level, page.Version, _cache, lookupKey, out output, _exceptionHandling, _manifest.Logger))
                    {
                        return(output);
                    }
                }
                // If not found, must check pages on the higher levels, but we can use the page index to make the search quicker
                for (int level = 1; level < manifest.NumLevels; level++)
                {
                    var page = manifest.FindPageForKey(level, lookupKey);
                    if (page != null && SortedBlockTable.Lookup(_manifest.BaseFileName, page.Level, page.Version, _cache, lookupKey, out output, _exceptionHandling, _manifest.Logger))
                    {
                        return(output);
                    }
                }
            }
            // OK, not found anywhere, return null
            return(Value.Empty);
        }
예제 #3
0
        public static bool Lookup(string baseFileName, int level, int version, RazorCache cache, Key key, out Value value, ExceptionHandling exceptionHandling, Action <string> logger)
        {
            PerformanceCounters.SBTLookup.Increment();
            SortedBlockTable sbt = new SortedBlockTable(cache, baseFileName, level, version);

            try {
                byte[] lastScanKey;
                int    dataBlockNum = FindBlockForKey(baseFileName, level, version, cache, key, out lastScanKey);
                if (dataBlockNum >= 0 && dataBlockNum < sbt._dataBlocks)
                {
                    byte[] block = sbt.ReadBlock(LocalThreadAllocatedBlock(), dataBlockNum, lastScanKey);
                    return(sbt.ScanBlockForKey(block, key, out value));
                }
            } finally {
                sbt.Close();
            }
            value = Value.Empty;
            return(false);
        }
예제 #4
0
파일: Cache.cs 프로젝트: lanicon/razordb
        public Key[] GetBlockTableIndex(string baseName, int level, int version)
        {
            string fileName = Config.SortedBlockTableFile(baseName, level, version);

            Key[] index;

            if (_blockIndexCache.TryGetValue(fileName, out index))
            {
                return(index);
            }

            PerformanceCounters.SBTGetBlockTableIndex.Increment();
            var sbt = new SortedBlockTable(null, baseName, level, version);

            try {
                index = sbt.GetIndex();
                _blockIndexCache.Set(fileName, index);
                return(index);
            } finally {
                sbt.Close();
            }
        }
예제 #5
0
        public static void RunTableMergePass(KeyValueStore kvStore)
        {
            try {
                Interlocked.Increment(ref kvStore.mergeCount);

                lock (kvStore.mergeLock) {
                    RazorCache cache    = kvStore.Cache;
                    Manifest   manifest = kvStore.Manifest;

                    while (true)
                    {
                        bool mergedDuringLastPass = false;
                        using (var manifestInst = kvStore.Manifest.GetLatestManifest()) {
                            // Handle level 0 (merge all pages)
                            if (manifestInst.GetNumPagesAtLevel(0) >= Config.MaxPagesOnLevel(0))
                            {
                                mergedDuringLastPass = true;
                                var inputPageRecords = manifestInst.GetPagesAtLevel(0).OrderBy(p => p.Version).ToList();
                                var startKey         = inputPageRecords.Min(p => p.FirstKey);
                                var endKey           = inputPageRecords.Max(p => p.LastKey);
                                var mergePages       = manifestInst.FindPagesForKeyRange(1, startKey, endKey).AsPageRefs().ToList();
                                var allInputPages    = inputPageRecords.AsPageRefs().Concat(mergePages).ToList();

                                var outputPages = SortedBlockTable.MergeTables(cache, manifest, 1, allInputPages, ExceptionHandling.ThrowAll, null).ToList();
                                manifest.ModifyPages(outputPages, allInputPages);

                                manifest.LogMessage("Merge Level 0 => InputPages: {0} OutputPages:{1}",
                                                    string.Join(",", allInputPages.Select(p => string.Format("{0}-{1}", p.Level, p.Version)).ToArray()),
                                                    string.Join(",", outputPages.Select(p => string.Format("{0}-{1}", p.Level, p.Version)).ToArray())
                                                    );
                            }
                            // handle the rest of the levels (merge only one page upwards)
                            for (int level = 1; level < manifestInst.NumLevels - 1; level++)
                            {
                                if (manifestInst.GetNumPagesAtLevel(level) >= Config.MaxPagesOnLevel(level))
                                {
                                    mergedDuringLastPass = true;
                                    var inputPage        = manifest.NextMergePage(level);
                                    var mergePages       = manifestInst.FindPagesForKeyRange(level + 1, inputPage.FirstKey, inputPage.LastKey).ToList();
                                    var inputPageRecords = mergePages.Concat(new PageRecord[] { inputPage });
                                    var allInputPages    = inputPageRecords.AsPageRefs().ToList();
                                    var outputPages      = SortedBlockTable.MergeTables(cache, manifest, level + 1, allInputPages, ExceptionHandling.ThrowAll, null);

                                    // Notify if a merge happened, implemented for testing primarily
                                    if (kvStore.MergeCallback != null)
                                    {
                                        kvStore.MergeCallback(level, inputPageRecords, outputPages);
                                    }
                                    manifest.ModifyPages(outputPages, allInputPages);

                                    manifest.LogMessage("Merge Level >0 => InputPages: {0} OutputPages:{1}",
                                                        string.Join(",", allInputPages.Select(p => string.Format("{0}-{1}", p.Level, p.Version)).ToArray()),
                                                        string.Join(",", outputPages.Select(p => string.Format("{0}-{1}", p.Level, p.Version)).ToArray())
                                                        );
                                }
                            }
                        }

                        // No more merging is needed, we are finished with this pass
                        if (!mergedDuringLastPass)
                        {
                            return;
                        }
                    }
                }
            } finally {
                Interlocked.Decrement(ref kvStore.mergeCount);
            }
        }