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;
		 }
Example #3
0
		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;
		}
Example #4
0
		/// <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
				});
		}
Example #8
0
		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;
			}
		}
Example #14
0
		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);
		}