private bool KeyMayMatch(Slice key, int filterStart, int filterLimit) { int len = filterLimit - filterStart; if (len < 2) return false; int bits = (len - 1)*8; var k = _accessor[filterLimit - 1]; if (k > 30) { // Reserved for potentially new encodings for short bloom filters. // Consider it a match. return true; } uint h = _bloomFilterPolicy.HashKey(key); uint delta = ((h >> 17) | (h << 15)); // rotate right 17 bits for (var i = 0; i < k; i++) { var bitpos = (int) (h%bits); byte b = _accessor[filterStart + bitpos/8]; if ((b & (1 << (bitpos%8))) == 0) return false; h += delta; } return true; }
public static bool TryFindFile(this IList<FileMetadata> files, Slice key, InternalKeyComparator internalKeyComparator, out int fileIndex) { var left = 0; var right = files.Count; while (left < right) { var mid = (left + right) / 2; var file = files[mid]; if (internalKeyComparator.Compare(file.LargestKey.TheInternalKey, key) < 0) { // Key at "mid.largest" is < "target". Therefore all // files at or before "mid" are uninteresting. left = mid + 1; } else { // Key at "mid.largest" is >= "target". Therefore all files // after "mid" are uninteresting. right = mid; } } fileIndex = right; return fileIndex < files.Count; }
public static uint Hash(Slice key, uint seed = 0xbc9f1d34) { var h = seed ^ ((uint)key.Count * m); int current = 0; for (; current + 4 <= key.Count; current += 4) { var w = BitConverter.ToUInt32(key.Array, key.Offset + current);// Pick up four bytes at a time h += w; h *= m; h ^= (h >> 16); } // Pick up remaining bytes switch (key.Count - current) { case 3: h += (uint)(key.Array[key.Offset + current+2] << 16); goto case 2; case 2: h += (uint)(key.Array[key.Offset + current + 1] << 8); goto case 1; case 1: h += key.Array[key.Offset + current]; h *= m; h ^= (h >> r); break; } return h; }
/// <summary> /// Intentional copying of the methods, this is a high perf portion of the codebase, /// and it is worth the code duplication to avoid virtual / delegate indirection /// </summary> public static uint HashCaseInsensitive(Slice key, uint seed = 0xbc9f1d34) { var h = (uint)(seed ^ (key.Count * m)); int current = 0; for (; current + 4 <= key.Count; current += 4) { // Pick up four bytes at a time var w = (uint) ( ToUpper(key.Array[key.Offset + current]) << 24 | ToUpper(key.Array[key.Offset + current + 1]) << 16 | ToUpper(key.Array[key.Offset + current + 2]) << 8 | ToUpper(key.Array[key.Offset + current + 3]) ); h += w; h *= m; h ^= (h >> 16); } // Pick up remaining bytes switch (key.Count - current) { case 3: h += (uint)(ToUpper(key.Array[key.Offset + current + 2]) << 16); goto case 2; case 2: h += (uint)(ToUpper(key.Array[key.Offset + current + 1]) << 8); goto case 1; case 1: h += ToUpper(key.Array[key.Offset + current]); h *= m; h ^= (h >> r); break; } return h; }
public InternalKey(Slice userKey, ulong seq, ItemType type) : this() { _userKey = userKey; _sequence= seq; _type = type; _ikey = Encode(); }
public void Seek(Slice target) { _indexIterator.Seek(target); InitDataIterator(); if(_dataIterator != null) _dataIterator.Seek(target); SkipEmptyDataBlocksForward(); }
public void Delete(Slice key) { _operations.Add(new Operation { Key = key, Op = Operations.Delete }); }
public int CompareTo(Slice other, IComparator comparator = null) { if (comparator == null) { comparator = ByteWiseComparator.Default; } return comparator.Compare(this, other); }
public async Task CompactAsync(int level, Slice begin, Slice end) { if (InProgress) throw new InvalidOperationException("Manual compaction is already in progess."); try { InProgress = true; Done = false; Level = level; Begin = new InternalKey(begin, Format.MaxSequenceNumber, ItemType.ValueForSeek); End = new InternalKey(end, Format.MaxSequenceNumber, ItemType.ValueForSeek); Task task = null; while (task == null) { state.CancellationToken.ThrowIfCancellationRequested(); if (state.BackgroundCompactionScheduled) { await Task.Delay(100).ConfigureAwait(false); continue; } using (AsyncLock.LockScope locker = await state.Lock.LockAsync().ConfigureAwait(false)) { while (Done == false) { state.BackgroundCompactionScheduled = true; await RunCompactionAsync(locker).ConfigureAwait(false); var manualEnd = new InternalKey(); if (compaction != null) { manualEnd = compaction.GetInput(0, compaction.GetNumberOfInputFiles(0) - 1).LargestKey; } if (Done == false) { // We only compacted part of the requested range. Update to the range that is left to be compacted. Begin = manualEnd; } } task = state.BackgroundTask; } } } finally { Done = true; InProgress = false; } }
public async Task CompactAsync(int level, Slice begin, Slice end) { Task compactAsync; using (await state.Lock.LockAsync().ConfigureAwait(false)) { compactAsync = state.Compactor.Manual.CompactAsync(level, begin, end); } await compactAsync.ConfigureAwait(false); // we do the wait _outside_ the lock }
public void Put(Slice key, Stream value) { _operations.Add(new Operation { Value = value, Key = key, Op = Operations.Put }); }
public int FindSharedPrefix(Slice a, Slice b) { int pos = 0; var minLen = Math.Min(a.Count, b.Count); while (pos < minLen && a.Array[a.Offset + pos] == b.Array[b.Offset + pos]) { pos++; } return pos; }
public unsafe int Compare(Slice a, Slice b) { var minLen = a.Count <= b.Count ? a.Count : b.Count; fixed (byte* aPtr = a.Array, bPtr = b.Array) { var result = memcmp(aPtr + a.Offset, bPtr + b.Offset, minLen); return result == 0 ? a.Count - b.Count : result; } }
public Slice(ref byte[] externalBuffer, Slice other, BufferPool bufferPool) { if (externalBuffer.Length < other.Count) { bufferPool.Return(externalBuffer); externalBuffer = bufferPool.Take(other.Count); } _array = externalBuffer; _count = other._count; _offset = 0; Buffer.BlockCopy(other.Array, other.Offset, externalBuffer, 0, other.Count); }
public bool KeyMayMatch(long position, Slice key) { int index = (int) (position >> _baseLg); if (index >= _num) return true; // errors are treated as potential matches var start = _accessor.ReadInt32(_offset + index*sizeof (int)); var limit = _accessor.ReadInt32(_offset + index * sizeof(int) + sizeof(int)); if (start > limit || limit > _accessor.Capacity) return false; // empty filters do no match any keys return KeyMayMatch(key, start, limit); }
public void FindShortestSeparator(ref Slice start, Slice limit) { var minLen = Math.Min(start.Count, limit.Count); var shared = FindSharedPrefix(start, limit); if (minLen == shared) // one is a prefix of other return; var diff = shared + 1; var diffByte = start.Array[start.Offset + diff]; if (diffByte < byte.MaxValue && diffByte < limit.Array[limit.Offset + diff]) { start.Array[diff] ++; start = new Slice(start.Array, start.Offset, diff + 1); Debug.Assert(Compare(start, limit) < 0); } }
public static bool TryParse(Slice input, out InternalKey internalKey) { internalKey = new InternalKey(); if (input.Count < 8) return false; var number = BitConverter.ToUInt64(input.Array, input.Offset + input.Count - 8); var sequence = number >> 8; var type = (ItemType)number; var key = new Slice(input.Array, input.Offset, input.Count - 8); internalKey = new InternalKey(key, sequence, type); return type <= ItemType.Value; }
public InternalKey(Slice key) : this() { _ikey = key; if (key.Count < 8) throw new ArgumentException("Key is too small"); var number = BitConverter.ToUInt64(key.Array, key.Offset + key.Count - 8); _sequence = number >> 8; _type = (ItemType)number; if (_type > ItemType.Value) throw new ArgumentException("Invalid key type"); _userKey = new Slice(key.Array, key.Offset, key.Count - 8); }
public Stream Read(Slice key, ReadOptions options = null) { if (options == null) { options = new ReadOptions(); } var mem = state.MemTable; var imm = state.ImmutableMemTable; var currentVersion = state.VersionSet.Current; var snapshot = options.Snapshot != null ? options.Snapshot.Sequence : state.VersionSet.LastSequence; var reference = new Reference<Slice> { Value = key }; state.PerfCounters.Read(); Stream stream; GetStats stats; if (mem.TryGet(reference.Value, snapshot, out stream)) { state.PerfCounters.BytesRead(stream.Length); return stream; } if (imm != null && imm.TryGet(reference.Value, snapshot, out stream)) { state.PerfCounters.BytesRead(stream.Length); return stream; } if (currentVersion.TryGet(reference.Value, snapshot, options, out stream, out stats)) { if (currentVersion.UpdateStats(stats)) { Background.Work(MaybeScheduleCompactionAsync()); } state.PerfCounters.BytesRead(stream.Length); return stream; } return null; }
public Slice FindShortestSuccessor(Slice key, ref byte[] scratch) { for (int i = 0; i < key.Count; i++) { var b = key.Array[key.Offset + i]; if (b != byte.MaxValue) { b++; scratch = i + 1 < scratch.Length ? scratch : new byte[i + 1]; if(i > 0) Buffer.BlockCopy(key.Array, key.Offset, scratch, 0, i - 1); scratch[i] = b; return new Slice(scratch, key.Offset, i+1); } } // if key is a run of 0xffs. Leave it alone. return key; }
public Aggregator(AggregationEngine aggregationEngine, string name, AbstractViewGenerator generator) { _aggregationEngine = aggregationEngine; _name = name; _generator = generator; _aggStat = "status/" + _name; using (var stream = aggregationEngine.Storage.Reader.Read(_aggStat)) { if (stream == null) { _lastAggregatedEtag = Etag.Empty; return; } var status = RavenJObject.Load(new JsonTextReader(new StreamReader(stream))); _lastAggregatedEtag = Etag.Parse(status.Value<string>("@etag")); } }
public void Seek(Slice target) { direction = Direction.Forward; savedKey = null; savedValueStream = null; storageContext.PerfCounters.Read(); savedKey = new InternalKey(target, sequence, ItemType.ValueForSeek).TheInternalKey; iterator.Seek(savedKey); if (iterator.IsValid) { FindNextUserEntry(false); return; } IsValid = false; }
public int Compare(Slice a, Slice b) { var minLen = a.Count <= b.Count ? a.Count : b.Count; unsafe { fixed (byte* ap = a.Array) { fixed (byte* bp = b.Array) { byte* aPtr = ap + a.Offset; byte* bPtr = bp + b.Offset; for (int i = 0; i < minLen; i++) { if (((*aPtr >= 'a' && *aPtr <= 'z') || (*aPtr >= 'A' && *aPtr <= 'Z')) && ((*bPtr >= 'a' && *bPtr <= 'z') || (*bPtr >= 'A' && *bPtr <= 'Z'))) { var diff = *aPtr - *bPtr; if (diff != 0 && diff != 32 && diff != -32) { return diff; } } else { var diff = *aPtr - *bPtr; if (diff != 0) return diff; } aPtr++; bPtr++; } } } } return a.Count - b.Count; }
public void Add(Slice key, Stream value) { if (_finished) throw new InvalidOperationException("Cannot add to a block after it has been finished"); if (_size > 0 && (_comparator.Compare(key, _lastKey) <= 0)) throw new InvalidOperationException("Add must be call on items in sorted order"); var valLen = value.Length - value.Position; if (valLen > int.MaxValue) throw new InvalidOperationException("Cannot store values that are greater than 2GB"); IsEmpty = false; int shared = 0; if (_counter < _blockRestartInterval) { // let us see how much we can share with the prev string // intentionally using the user key comparator and not the internal key comparator shared = _storageState.Options.Comparator.FindSharedPrefix(_lastKey, key); } else { // restart compression _restarts.Add(_size); _counter = 0; } int nonShared = key.Count - shared; // Add "<shared><non_shared><value_size>" _size += _stream.Write7BitEncodedInt(shared); _size += _stream.Write7BitEncodedInt(nonShared); _size += _stream.Write7BitEncodedInt((int)valLen); _stream.Write(key.Array, key.Offset + shared, key.Count - shared); _size += key.Count - shared; value.CopyTo(_stream); _size += (int)valLen; _lastKey = new Slice(ref _lastKeyBuffer, key, _storageState.Options.BufferPool); _counter++; }
public void Seek(Slice target) { files.TryFindFile(target, internalKeyComparator, out index); }
public void SetComparatorName(Slice name) { Comparator = name.ToString(); }
private static Etag ParseEtag(Slice key) { var str = Encoding.UTF8.GetString(key.Array, key.Offset + _eventsPrefix.Count, key.Count - _eventsPrefix.Count); return Etag.Parse(str); }
public Slice FindShortestSuccessor(Slice key, ref byte[] scratch) { return ByteWiseComparator.Default.FindShortestSuccessor(key, ref scratch); }
public void FindShortestSeparator(ref Slice start, Slice limit) { ByteWiseComparator.Default.FindShortestSeparator(ref start, limit); }
public int FindSharedPrefix(Slice a, Slice b) { return ByteWiseComparator.Default.FindSharedPrefix(a, b); }