]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/include/rocksdb/utilities/spatial_db.h
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).
12 #include "rocksdb/db.h"
13 #include "rocksdb/slice.h"
14 #include "rocksdb/utilities/stackable_db.h"
19 // NOTE: SpatialDB is experimental and we might change its API without warning.
20 // Please talk to us before developing against SpatialDB API.
22 // SpatialDB is a support for spatial indexes built on top of RocksDB.
23 // When creating a new SpatialDB, clients specifies a list of spatial indexes to
24 // build on their data. Each spatial index is defined by the area and
25 // granularity. If you're storing map data, different spatial index
26 // granularities can be used for different zoom levels.
28 // Each element inserted into SpatialDB has:
29 // * a bounding box, which determines how will the element be indexed
30 // * string blob, which will usually be WKB representation of the polygon
31 // (http://en.wikipedia.org/wiki/Well-known_text)
32 // * feature set, which is a map of key-value pairs, where value can be null,
33 // int, double, bool, string
34 // * a list of indexes to insert the element in
36 // Each query is executed on a single spatial index. Query guarantees that it
37 // will return all elements intersecting the specified bounding box, but it
38 // might also return some extra non-intersecting elements.
40 // Variant is a class that can be many things: null, bool, int, double or string
41 // It is used to store different value types in FeatureSet (see below)
43 // Don't change the values here, they are persisted on disk
52 Variant() : type_(kNull
) {}
53 /* implicit */ Variant(bool b
) : type_(kBool
) { data_
.b
= b
; }
54 /* implicit */ Variant(uint64_t i
) : type_(kInt
) { data_
.i
= i
; }
55 /* implicit */ Variant(double d
) : type_(kDouble
) { data_
.d
= d
; }
56 /* implicit */ Variant(const std::string
& s
) : type_(kString
) {
57 new (&data_
.s
) std::string(s
);
60 Variant(const Variant
& v
) : type_(v
.type_
) { Init(v
, data_
); }
62 Variant
& operator=(const Variant
& v
);
64 Variant(Variant
&& rhs
) : type_(kNull
) { *this = std::move(rhs
); }
66 Variant
& operator=(Variant
&& v
);
68 ~Variant() { Destroy(type_
, data_
); }
70 Type
type() const { return type_
; }
71 bool get_bool() const { return data_
.b
; }
72 uint64_t get_int() const { return data_
.i
; }
73 double get_double() const { return data_
.d
; }
74 const std::string
& get_string() const { return *GetStringPtr(data_
); }
76 bool operator==(const Variant
& other
) const;
77 bool operator!=(const Variant
& other
) const { return !(*this == other
); }
86 // Current version of MS compiler not C++11 compliant so can not put
88 // however, even then we still need the rest of the maintenance.
89 char s
[sizeof(std::string
)];
92 // Avoid type_punned aliasing problem
93 static std::string
* GetStringPtr(Data
& d
) {
95 return reinterpret_cast<std::string
*>(p
);
98 static const std::string
* GetStringPtr(const Data
& d
) {
100 return reinterpret_cast<const std::string
*>(p
);
103 static void Init(const Variant
&, Data
&);
105 static void Destroy(Type t
, Data
& d
) {
108 GetStringPtr(d
)->~string();
113 // FeatureSet is a map of key-value pairs. One feature set is associated with
114 // each element in SpatialDB. It can be used to add rich data about the element.
117 typedef std::unordered_map
<std::string
, Variant
> map
;
122 /* implicit */ iterator(const map::const_iterator itr
) : itr_(itr
) {}
123 iterator
& operator++() {
127 bool operator!=(const iterator
& other
) { return itr_
!= other
.itr_
; }
128 bool operator==(const iterator
& other
) { return itr_
== other
.itr_
; }
129 map::value_type
operator*() { return *itr_
; }
132 map::const_iterator itr_
;
134 FeatureSet() = default;
136 FeatureSet
* Set(const std::string
& key
, const Variant
& value
);
137 bool Contains(const std::string
& key
) const;
138 // REQUIRES: Contains(key)
139 const Variant
& Get(const std::string
& key
) const;
140 iterator
Find(const std::string
& key
) const;
142 iterator
begin() const { return map_
.begin(); }
143 iterator
end() const { return map_
.end(); }
146 size_t Size() const { return map_
.size(); }
148 void Serialize(std::string
* output
) const;
149 // REQUIRED: empty FeatureSet
150 bool Deserialize(const Slice
& input
);
152 std::string
DebugString() const;
158 // BoundingBox is a helper structure for defining rectangles representing
159 // bounding boxes of spatial elements.
160 template <typename T
>
162 T min_x
, min_y
, max_x
, max_y
;
163 BoundingBox() = default;
164 BoundingBox(T _min_x
, T _min_y
, T _max_x
, T _max_y
)
165 : min_x(_min_x
), min_y(_min_y
), max_x(_max_x
), max_y(_max_y
) {}
167 bool Intersects(const BoundingBox
<T
>& a
) const {
168 return !(min_x
> a
.max_x
|| min_y
> a
.max_y
|| a
.min_x
> max_x
||
173 struct SpatialDBOptions
{
174 uint64_t cache_size
= 1 * 1024 * 1024 * 1024LL; // 1GB
175 int num_threads
= 16;
176 bool bulk_load
= true;
179 // Cursor is used to return data from the query to the client. To get all the
180 // data from the query, just call Next() while Valid() is true
186 virtual bool Valid() const = 0;
188 virtual void Next() = 0;
190 // Lifetime of the underlying storage until the next call to Next()
192 virtual const Slice
blob() = 0;
193 // Lifetime of the underlying storage until the next call to Next()
195 virtual const FeatureSet
& feature_set() = 0;
197 virtual Status
status() const = 0;
200 // No copying allowed
201 Cursor(const Cursor
&);
202 void operator=(const Cursor
&);
205 // SpatialIndexOptions defines a spatial index that will be built on the data
206 struct SpatialIndexOptions
{
207 // Spatial indexes are referenced by names
209 // An area that is indexed. If the element is not intersecting with spatial
210 // index's bbox, it will not be inserted into the index
211 BoundingBox
<double> bbox
;
212 // tile_bits control the granularity of the spatial index. Each dimension of
213 // the bbox will be split into (1 << tile_bits) tiles, so there will be a
214 // total of (1 << tile_bits)^2 tiles. It is recommended to configure a size of
215 // each tile to be approximately the size of the query on that spatial index
217 SpatialIndexOptions() {}
218 SpatialIndexOptions(const std::string
& _name
,
219 const BoundingBox
<double>& _bbox
, uint32_t _tile_bits
)
220 : name(_name
), bbox(_bbox
), tile_bits(_tile_bits
) {}
223 class SpatialDB
: public StackableDB
{
225 // Creates the SpatialDB with specified list of indexes.
226 // REQUIRED: db doesn't exist
227 static Status
Create(const SpatialDBOptions
& options
, const std::string
& name
,
228 const std::vector
<SpatialIndexOptions
>& spatial_indexes
);
230 // Open the existing SpatialDB. The resulting db object will be returned
231 // through db parameter.
232 // REQUIRED: db was created using SpatialDB::Create
233 static Status
Open(const SpatialDBOptions
& options
, const std::string
& name
,
234 SpatialDB
** db
, bool read_only
= false);
236 explicit SpatialDB(DB
* db
) : StackableDB(db
) {}
238 // Insert the element into the DB. Element will be inserted into specified
239 // spatial_indexes, based on specified bbox.
240 // REQUIRES: spatial_indexes.size() > 0
241 virtual Status
Insert(const WriteOptions
& write_options
,
242 const BoundingBox
<double>& bbox
, const Slice
& blob
,
243 const FeatureSet
& feature_set
,
244 const std::vector
<std::string
>& spatial_indexes
) = 0;
246 // Calling Compact() after inserting a bunch of elements should speed up
247 // reading. This is especially useful if you use SpatialDBOptions::bulk_load
248 // Num threads determines how many threads we'll use for compactions. Setting
249 // this to bigger number will use more IO and CPU, but finish faster
250 virtual Status
Compact(int num_threads
= 1) = 0;
252 // Query the specified spatial_index. Query will return all elements that
253 // intersect bbox, but it may also return some extra elements.
254 virtual Cursor
* Query(const ReadOptions
& read_options
,
255 const BoundingBox
<double>& bbox
,
256 const std::string
& spatial_index
) = 0;
259 } // namespace spatial
260 } // namespace rocksdb
261 #endif // ROCKSDB_LITE