Exemple #1
0
 public static void EncodeFixed32(ByteArrayPointer buf, UInt32 value)
 {
     buf[0] = (byte)(value & 0xff);
     buf[1] = (byte)((value >> 8) & 0xff);
     buf[2] = (byte)((value >> 16) & 0xff);
     buf[3] = (byte)((value >> 24) & 0xff);
 }
Exemple #2
0
        // Add an entry into memtable that maps key to value at the
        // specified sequence number and with the specified type.
        // Typically value will be empty if type==kTypeDeletion.
        public void Add(UInt64 seq, int type,
						 Slice key,
						 Slice value)
        {
            // Format of an entry is concatenation of:
            //  key_size     : varint32 of internal_key.size()
            //  key bytes    : char[internal_key.size()]
            //  value_size   : varint32 of value.size()
            //  value bytes  : char[value.size()]
            int key_size = key.Size;
            int val_size = value.Size;
            int internal_key_size = key_size + 8;
            int encoded_len =
                    Coding.VarintLength(internal_key_size) + internal_key_size +
                    Coding.VarintLength(val_size) + val_size;
            ByteArrayPointer buf = new ByteArrayPointer(encoded_len);
            ByteArrayPointer p = Coding.EncodeVarint32(buf, (uint)internal_key_size);

            key.Data.CopyTo(p, key_size);

            p += key_size;
            Coding.EncodeFixed64(p, (seq << 8) | (UInt64)type);

            p += 8;
            p = Coding.EncodeVarint32(p, (uint)val_size);

            value.Data.CopyTo(p, val_size);

            Debug.Assert((p + val_size) - buf == encoded_len);
            m_table.Insert(buf);
        }
Exemple #3
0
        // Helper routine: decode the next block entry starting at "p",
        // storing the number of shared key bytes, non_shared key bytes,
        // and the length of the value in "*shared", "*non_shared", and
        // "*value_length", respectively.  Will not derefence past "limit".
        //
        // If any errors are detected, returns NULL.  Otherwise, returns a
        // pointer to the key delta (just past the three decoded values).
        private static ByteArrayPointer DecodeEntry(ByteArrayPointer p, ByteArrayPointer limit,
																				 out UInt32 shared,
																				 out UInt32 non_shared,
																				 out UInt32 value_length)
        {
            if (limit - p < 3)
            {
                shared = non_shared = value_length = 0;
                return ByteArrayPointer.Null;
            }
            shared = p[0];
            non_shared = p[1];
            value_length = p[3];
            if ((shared | non_shared | value_length) < 128)
            {
                // Fast path: all three values are encoded in one byte each
                p += 3;
            }
            else
            {
                if ((p = Coding.GetVarint32Ptr(p, limit, out shared)) == ByteArrayPointer.Null) return ByteArrayPointer.Null;
                if ((p = Coding.GetVarint32Ptr(p, limit, out non_shared)) == ByteArrayPointer.Null) return ByteArrayPointer.Null;
                if ((p = Coding.GetVarint32Ptr(p, limit, out value_length)) == ByteArrayPointer.Null) return ByteArrayPointer.Null;
            }

            if ((limit - p) < (non_shared + value_length))
            {
                return ByteArrayPointer.Null;
            }
            return p;
        }
Exemple #4
0
 public int Compare(ByteArrayPointer aptr, ByteArrayPointer bptr)
 {
     // Internal keys are encoded as length-prefixed strings.
     Slice a = MemTable.GetLengthPrefixedSlice(aptr);
     Slice b = MemTable.GetLengthPrefixedSlice(bptr);
     return Comparator.Compare(a, b);
 }
Exemple #5
0
 public static UInt32 DecodeFixed32(ByteArrayPointer ptr)
 {
     return ((UInt32)ptr[0])
             | (((UInt32)ptr[1]) << 8)
             | (((UInt32)ptr[2]) << 16)
             | (((UInt32)ptr[3]) << 24);
 }
Exemple #6
0
        // Initialize *this for looking up user_key at a snapshot with
        // the specified sequence number.
        public LookupKey(Slice user_key, UInt64 sequence)
        {
            int usize = user_key.Size;
            int needed = usize + 13;  // A conservative estimate
            ByteArrayPointer dst;

            if (needed <= space_.Length)
            {
                dst = new ByteArrayPointer(space_);
            }
            else
            {
                dst = new ByteArrayPointer(needed);
            }

            start_ = dst;
            dst = Coding.EncodeVarint32(dst, (uint)(usize + 8));
            kstart_ = dst;

            user_key.Data.CopyTo(dst, usize);

            dst += usize;

            Coding.EncodeFixed64(dst, Global.PackSequenceAndType(sequence ,Global.kValueTypeForSeek));
            end_ = dst + 8;
        }
Exemple #7
0
 public static void EncodeFixed64(ByteArrayPointer buf, UInt64 value)
 {
     buf[0] = (byte)(value & 0xff);
     buf[1] = (byte)((value >> 8) & 0xff);
     buf[2] = (byte)((value >> 16) & 0xff);
     buf[3] = (byte)((value >> 24) & 0xff);
     buf[4] = (byte)((value >> 32) & 0xff);
     buf[5] = (byte)((value >> 40) & 0xff);
     buf[6] = (byte)((value >> 48) & 0xff);
     buf[7] = (byte)((value >> 56) & 0xff);
 }
Exemple #8
0
        /// <summary>				
        /// Attempt to open the table that is stored in bytes [0..file_size)
        /// of "file", and read the metadata entries necessary to allow
        /// retrieving data from the table.
        ///
        /// If successful, returns ok and sets "*table" to the newly opened
        /// table.  The client should delete "*table" when no longer needed.
        /// If there was an error while initializing the table, sets "*table"
        /// to NULL and returns a non-ok status.  Does not take ownership of
        /// "*source", but the client must ensure that "source" remains live
        /// for the duration of the returned table's lifetime.
        ///
        /// *file must remain live while this Table is in use.				
        /// </summary>
        public static Status Open(Options options, RandomAccessFile file, UInt64 size, out Table table)
        {
            table = null;
            if (size < Footer.kEncodedLength)
            {
                return Status.InvalidArgument("file is too short to be an sstable");
            }

            ByteArrayPointer footerSpace = new ByteArrayPointer(Footer.kEncodedLength);

            Slice footerInput;
            Status s = file.Read(size - Footer.kEncodedLength, Footer.kEncodedLength, out footerInput, footerSpace);
            if (!s.IsOk) return s;

            Footer footer = new Footer();
            s = footer.DecodeFrom(ref footerInput);
            if (!s.IsOk) return s;

            // Read the index block
            BlockContents contents;
            Block indexBlock = null;
            if (s.IsOk)
            {
                s = FormatHelper.ReadBlock(file, ReadOptions.Default, footer.IndexHandle, out contents);
                if (s.IsOk)
                {
                    indexBlock = new Block(contents);
                }
            }

            if (s.IsOk)
            {
                // We've successfully read the footer and the index block: we're
                // ready to serve requests.

                Rep rep = new Rep();
                rep.Options = options;
                rep.File = file;
                rep.MetaindexHandle = footer.MetaindexHandle;
                rep.IndexBlock = indexBlock;
                rep.CacheId = (options.BlockCache != null ? options.BlockCache.NewId() : 0);
                rep.FilterData = ByteArrayPointer.Null;
                rep.Filter = null;
                table = new Table(rep);
                table.ReadMeta(footer);
            }

            return s;
        }
        // REQUIRES: "contents" and *policy must stay live while *this is live.
        public FilterBlockReader(FilterPolicy policy, Slice contents)
        {
            policy_ = policy;
              data_ = ByteArrayPointer.Null;
              offset_ = ByteArrayPointer.Null;
              num_ = 0;
              base_lg_ = 0;

              int n = contents.Size;
              if (n < 5) return;  // 1 byte for base_lg_ and 4 for start of offset array
              base_lg_ = contents[n - 1];
              UInt32 last_word = Coding.DecodeFixed32(contents.Data + n - 5);
              if (last_word > n - 5) return;
              data_ = contents.Data;
              offset_ = data_ + (int)last_word;
              num_ = (int)((n - 5 - last_word) / 4);
        }
Exemple #10
0
        public static ByteArrayPointer EncodeVarint32(ByteArrayPointer dst, UInt32 v)
        {
            // Operate on characters as unsigneds
            ByteArrayPointer ptr = dst;
            int B = 128;
            if (v < (1 << 7))
            {
                ptr[0] = (byte)v;
                ptr += 1;
            }
            else if (v < (1 << 14))
            {
                ptr[0] = (byte)(v | B);
                ptr[1] = (byte)(v >> 7);
                ptr += 2;
            }
            else if (v < (1 << 21))
            {
                ptr[0] = (byte)(v | B);
                ptr[1] = (byte)((v >> 7) | B);
                ptr[2] = (byte)(v >> 14);
                ptr += 3;
            }
            else if (v < (1 << 28))
            {
                ptr[0] = (byte)(v | B);
                ptr[1] = (byte)((v >> 7) | B);
                ptr[2] = (byte)((v >> 14) | B);
                ptr[3] = (byte)(v >> 21);
                ptr += 4;
            }
            else
            {
                ptr[0] = (byte)(v | B);
                ptr[1] = (byte)((v >> 7) | B);
                ptr[2] = (byte)((v >> 14) | B);
                ptr[3] = (byte)((v >> 21) | B);
                ptr[4] = (byte)(v >> 28);
                ptr += 5;
            }

            return ptr;
        }
Exemple #11
0
        // Initialize the block with the specified contents.
        public Block(BlockContents contents)
        {
            data_ = contents.Data.Data;
            size_ = contents.Data.Size;
            owned_ = contents.HeapAllocated;

            if (size_ < sizeof(UInt32))
            {
                size_ = 0;  // Error marker
            }
            else
            {
                restart_offset_ = (uint)(size_ - (1 + NumRestarts()) * sizeof(UInt32));
                if (restart_offset_ > size_ - sizeof(UInt32))
                {
                    // The size is too small for NumRestarts() and therefore
                    // restart_offset_ wrapped around.
                    size_ = 0;
                }
            }
        }
Exemple #12
0
 public static ByteArrayPointer EncodeVarint64(ByteArrayPointer dst, UInt64 v)
 {
     const int B = 128;
     ByteArrayPointer ptr = dst;
     while (v >= B)
     {
         ptr[0] = (byte)((v & (B - 1)) | B);
         ptr += 1;
         v >>= 7;
     }
     ptr[0] = (byte)v;
     ptr += 1;
     return ptr;
 }
Exemple #13
0
 // Return the earliest node that comes at or after key.
 // Return NULL if there is no such node.
 //
 // If prev is non-NULL, fills prev[level] with pointer to previous
 // node at "level" for every level in [0..max_height_-1].
 private Node FindGreaterOrEqual(ByteArrayPointer key, Node[] prev)
 {
     Node x = head_;
     int level = MaxHeight - 1;
     while (true)
     {
         Node next = x.Next(level);
         if (KeyIsAfterNode(key, next))
         {
             // Keep searching in this list
             x = next;
         }
         else
         {
             if (prev != null) prev[level] = x;
             if (level == 0)
             {
                 return next;
             }
             else
             {
                 // Switch to next list
                 level--;
             }
         }
     }
 }
Exemple #14
0
 // Return the latest node with a key < key.
 // Return head_ if there is no such node.
 private Node FindLessThan(ByteArrayPointer key)
 {
     Node x = head_;
     int level = MaxHeight - 1;
     while (true)
     {
         Debug.Assert(x == head_ || compare_.Compare(x.Key, key) < 0);
         Node next = x.Next(level);
         if (next == null || compare_.Compare(next.Key, key) >= 0)
         {
             if (level == 0)
             {
                 return x;
             }
             else
             {
                 // Switch to next list
                 level--;
             }
         }
         else
         {
             x = next;
         }
     }
 }
Exemple #15
0
 // Advance to the first entry with a key >= target
 public void Seek(ByteArrayPointer target)
 {
     node_ = list_.FindGreaterOrEqual(target, null);
 }
Exemple #16
0
        // Insert key into the list.
        // REQUIRES: nothing that compares equal to key is currently in the list.
        public void Insert(ByteArrayPointer key)
        {
            // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
            // here since Insert() is externally synchronized.
            Node[] prev = new Node[kMaxHeight];
            Node x = FindGreaterOrEqual(key, prev);

            // Our data structure does not allow duplicate insertion
            Debug.Assert(x == null || !Equal(key, x.Key));

            int height = RandomHeight();
            if (height > MaxHeight)
            {
                for (int i = MaxHeight; i < height; i++)
                {
                    prev[i] = head_;
                }
                //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);

                // It is ok to mutate max_height_ without any synchronization
                // with concurrent readers.  A concurrent reader that observes
                // the new value of max_height_ will see either the old value of
                // new level pointers from head_ (NULL), or a new value set in
                // the loop below.  In the former case the reader will
                // immediately drop to the next level since NULL sorts after all
                // keys.  In the latter case the reader will use the new node.
                max_height_.NoBarrierStore(height);
            }

            x = NewNode(key, height);

            for (int i = 0; i < height; i++)
            {
                // NoBarrier_SetNext() suffices since we will add a barrier when
                // we publish a pointer to "x" in prev[i].
                x.NoBarrier_SetNext(i, prev[i].NoBarrierNext(i));
                prev[i].SetNext(i, x);
            }
        }
Exemple #17
0
            public Iter(Comparator comparator,
					 ByteArrayPointer data,
					 UInt32 restarts,
					 UInt32 num_restarts)
            {
                comparator_ = comparator;
                data_ = data;
                restarts_ = restarts;
                num_restarts_ = num_restarts;
                current_ = restarts_;
                restart_index_ = num_restarts_;
                Debug.Assert(num_restarts_ > 0);
            }
Exemple #18
0
 public static UInt64 DecodeFixed64(ByteArrayPointer ptr)
 {
     UInt64 lo = DecodeFixed32(ptr);
     UInt64 hi = DecodeFixed32(ptr + 4);
     return (hi << 32) | lo;
 }
Exemple #19
0
        private static Iterator BlockReader(object arg, ReadOptions options, Slice indexValue)
        {
            Table table = (Table)arg;
            Cache blockCache = table.rep_.Options.BlockCache;
            Block block = null;
            Cache.Handle cacheHandle = null;

            BlockHandle handle = new BlockHandle();
            Slice input = indexValue;
            Status s = handle.DecodeFrom(ref input);
            // We intentionally allow extra stuff in index_value so that we
            // can add more features in the future.

            if (s.IsOk)
            {
                BlockContents contents;
                if (blockCache != null)
                {
                    ByteArrayPointer cacheKeyBuffer = new ByteArrayPointer(16);

                    Coding.EncodeFixed64(cacheKeyBuffer, table.rep_.CacheId);
                    Coding.EncodeFixed64(cacheKeyBuffer + 8, handle.Offset);

                    Slice key = new Slice(cacheKeyBuffer, cacheKeyBuffer.Length);

                    cacheHandle = blockCache.Lookup(key);
                    if (cacheHandle != null)
                    {
                        block = (Block)(blockCache.Value(cacheHandle));
                    }
                    else
                    {
                        s = FormatHelper.ReadBlock(table.rep_.File, options, handle, out contents);
                        if (s.IsOk)
                        {
                            block = new Block(contents);
                            if (contents.Cachable && options.FillCache)
                            {
                                cacheHandle = blockCache.Insert(key, block, block.Size);
                            }
                        }
                    }
                }
                else
                {
                    s = FormatHelper.ReadBlock(table.rep_.File, options, handle, out contents);
                    if (s.IsOk)
                    {
                        block = new Block(contents);
                    }
                }
            }

            Iterator iter;

            if (block != null)
            {
                iter = block.NewIterator(table.rep_.Options.Comparator);
                if (cacheHandle != null)
                {
                    iter.RegisterCleanup(ReleaseBlock, blockCache, cacheHandle);
                }
            }
            else
            {
                iter = Iterator.NewErrorIterator(s);
            }
            return iter;
        }
Exemple #20
0
 // Return true if key is greater than the data stored in "n"
 private bool KeyIsAfterNode(ByteArrayPointer key, Node n)
 {
     // NULL n is considered infinite
     //return (n != null) && (compare_(n->key, key) < 0);
     return (n != null) && (compare_.Compare(n.Key, key) < 0);
 }
Exemple #21
0
        public static ByteArrayPointer GetLengthPrefixedSlice(ByteArrayPointer p, ByteArrayPointer limit,
																			 out Slice result)
        {
            result = null;
            UInt32 len;
            p = GetVarint32Ptr(p, limit, out len);
            if (p.IsNull) return p;
            if (p + (int)len > limit) return ByteArrayPointer.Null;
            result = new Slice(p, (int)len);

            return p + (int)len;
        }
Exemple #22
0
 // Returns true iff an entry that compares equal to key is in the list.
 public bool Contains(ByteArrayPointer key)
 {
     Node x = FindGreaterOrEqual(key, null);
     if (x != null && Equal(key, x.Key))
     {
         return true;
     }
     else
     {
         return false;
     }
 }
Exemple #23
0
 public Node(ByteArrayPointer k, int height)
 {
     Key = k;
     next_ = new AtomicPointer<Node>[height];
 }
Exemple #24
0
 internal static Slice GetLengthPrefixedSlice(ByteArrayPointer data)
 {
     UInt32 len;
     ByteArrayPointer p = data;
     p = Coding.GetVarint32Ptr(p, p + 5, out len);  // +5: we assume "p" is not corrupted
     return new Slice(p, (int)len);
 }
Exemple #25
0
 private bool Equal(ByteArrayPointer a, ByteArrayPointer b)
 {
     return (compare_.Compare(a, b) == 0);
 }
Exemple #26
0
        public static ByteArrayPointer GetVarint64Ptr(ByteArrayPointer p, ByteArrayPointer limit, out UInt64 value)
        {
            UInt64 result = 0;
            for (int shift = 0; shift <= 63 && p < limit; shift += 7)
            {
                UInt64 b = p[0];
                p += 1;

                if ((b & 128) != 0)
                {
                    // More bytes are present
                    result |= ((b & 127) << shift);
                }
                else
                {
                    result |= (b << shift);
                    value = result;
                    return p;
                }
            }

            value = 0;
            return ByteArrayPointer.Null;
        }
Exemple #27
0
        public static void PutFixed64(ref string dst, UInt64 value)
        {
            ByteArrayPointer buf = new ByteArrayPointer(sizeof(UInt64));
            EncodeFixed64(buf, value);

            dst += buf.GetString(buf.Length);
        }
Exemple #28
0
 public static void PutVarint64(ref string dst, UInt64 v)
 {
     ByteArrayPointer buf = new ByteArrayPointer(10);
     ByteArrayPointer ptr = EncodeVarint64(buf, v);
     dst += buf.GetString(ptr - buf);
 }
Exemple #29
0
        public static ByteArrayPointer GetVarint32Ptr(ByteArrayPointer p,
																									ByteArrayPointer limit,
																									out UInt32 value)
        {
            if (p < limit)
            {
                UInt32 result = p[0];
                if ((result & 128) == 0)
                {
                    value = result;
                    return new ByteArrayPointer(p, 1);
                }
            }
            return GetVarint32PtrFallback(p, limit, out value);
        }
Exemple #30
0
        private Node NewNode(ByteArrayPointer key, int height)
        {
            var node  = new Node(key, height);

            return node;
        }