1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
8 //
9 // Class for specifying user-defined functions which perform a
10 // transformation on a slice.  It is not required that every slice
11 // belong to the domain and/or range of a function.  Subclasses should
12 // define InDomain and InRange to determine which slices are in either
13 // of these sets respectively.
14 
15 #pragma once
16 
17 #include <string>
18 
19 #include "rocksdb/rocksdb_namespace.h"
20 
21 namespace ROCKSDB_NAMESPACE {
22 
23 class Slice;
24 
25 /*
26  * A SliceTransform is a generic pluggable way of transforming one string
27  * to another. Its primary use-case is in configuring rocksdb
28  * to store prefix blooms by setting prefix_extractor in
29  * ColumnFamilyOptions.
30  */
31 class SliceTransform {
32  public:
~SliceTransform()33   virtual ~SliceTransform(){};
34 
35   // Return the name of this transformation.
36   virtual const char* Name() const = 0;
37 
38   // Extract a prefix from a specified key. This method is called when
39   // a key is inserted into the db, and the returned slice is used to
40   // create a bloom filter.
41   virtual Slice Transform(const Slice& key) const = 0;
42 
43   // Determine whether the specified key is compatible with the logic
44   // specified in the Transform method. This method is invoked for every
45   // key that is inserted into the db. If this method returns true,
46   // then Transform is called to translate the key to its prefix and
47   // that returned prefix is inserted into the bloom filter. If this
48   // method returns false, then the call to Transform is skipped and
49   // no prefix is inserted into the bloom filters.
50   //
51   // For example, if the Transform method operates on a fixed length
52   // prefix of size 4, then an invocation to InDomain("abc") returns
53   // false because the specified key length(3) is shorter than the
54   // prefix size of 4.
55   //
56   // Wiki documentation here:
57   // https://github.com/facebook/rocksdb/wiki/Prefix-Seek-API-Changes
58   //
59   virtual bool InDomain(const Slice& key) const = 0;
60 
61   // This is currently not used and remains here for backward compatibility.
InRange(const Slice &)62   virtual bool InRange(const Slice& /*dst*/) const { return false; }
63 
64   // Some SliceTransform will have a full length which can be used to
65   // determine if two keys are consecuitive. Can be disabled by always
66   // returning 0
FullLengthEnabled(size_t *)67   virtual bool FullLengthEnabled(size_t* /*len*/) const { return false; }
68 
69   // Transform(s)=Transform(`prefix`) for any s with `prefix` as a prefix.
70   //
71   // This function is not used by RocksDB, but for users. If users pass
72   // Options by string to RocksDB, they might not know what prefix extractor
73   // they are using. This function is to help users can determine:
74   //   if they want to iterate all keys prefixing `prefix`, whether it is
75   //   safe to use prefix bloom filter and seek to key `prefix`.
76   // If this function returns true, this means a user can Seek() to a prefix
77   // using the bloom filter. Otherwise, user needs to skip the bloom filter
78   // by setting ReadOptions.total_order_seek = true.
79   //
80   // Here is an example: Suppose we implement a slice transform that returns
81   // the first part of the string after splitting it using delimiter ",":
82   // 1. SameResultWhenAppended("abc,") should return true. If applying prefix
83   //    bloom filter using it, all slices matching "abc:.*" will be extracted
84   //    to "abc,", so any SST file or memtable containing any of those key
85   //    will not be filtered out.
86   // 2. SameResultWhenAppended("abc") should return false. A user will not
87   //    guaranteed to see all the keys matching "abc.*" if a user seek to "abc"
88   //    against a DB with the same setting. If one SST file only contains
89   //    "abcd,e", the file can be filtered out and the key will be invisible.
90   //
91   // i.e., an implementation always returning false is safe.
SameResultWhenAppended(const Slice &)92   virtual bool SameResultWhenAppended(const Slice& /*prefix*/) const {
93     return false;
94   }
95 };
96 
97 extern const SliceTransform* NewFixedPrefixTransform(size_t prefix_len);
98 
99 extern const SliceTransform* NewCappedPrefixTransform(size_t cap_len);
100 
101 extern const SliceTransform* NewNoopTransform();
102 
103 }  // namespace ROCKSDB_NAMESPACE
104