4747
4848namespace redis {
4949
50+ namespace {
51+ template <bool Reverse, typename Container>
52+ inline decltype (auto ) GetCbeginIter(const Container& centroids) {
53+ if constexpr (Reverse) {
54+ return centroids.crbegin ();
55+ } else {
56+ return centroids.cbegin ();
57+ }
58+ }
59+
60+ template <bool Reverse, typename Container>
61+ inline decltype (auto ) GetCendIter(const Container& centroids) {
62+ if constexpr (Reverse) {
63+ return centroids.crend ();
64+ } else {
65+ return centroids.cend ();
66+ }
67+ }
68+ } // namespace
69+
5070// TODO: It should be replaced by a iteration of the rocksdb iterator
71+ template <bool Reverse>
5172class DummyCentroids {
5273 public:
53- class BaseIterator {
54- public:
55- virtual ~BaseIterator () = default ;
56- virtual bool Next () = 0;
57- virtual bool Prev () = 0;
58- virtual bool Valid () const = 0;
59- virtual std::unique_ptr<BaseIterator> Clone () const = 0;
60- virtual StatusOr<Centroid> GetCentroid () const = 0;
61- };
62-
6374 DummyCentroids (const TDigestMetadata& meta_data, const std::vector<Centroid>& centroids)
6475 : meta_data_(meta_data), centroids_(centroids) {}
65- class Iterator : public BaseIterator {
76+ class Iterator {
6677 public:
67- Iterator (std::vector<Centroid>::const_iterator&& iter, const std::vector<Centroid>& centroids)
68- : iter_(iter), centroids_(centroids) {}
69- std::unique_ptr<BaseIterator> Clone () const override {
70- if (iter_ != centroids_.cend ()) {
71- return std::make_unique<Iterator>(std::next (centroids_.cbegin (), std::distance (centroids_.cbegin (), iter_)),
72- centroids_);
78+ using IterType = std::conditional_t <Reverse, std::vector<Centroid>::const_reverse_iterator,
79+ std::vector<Centroid>::const_iterator>;
80+ Iterator (IterType iter, const std::vector<Centroid>& centroids) : iter_(iter), centroids_(centroids) {}
81+ std::unique_ptr<Iterator> Clone () const {
82+ if (iter_ != GetCendIter<Reverse>(centroids_)) {
83+ return std::make_unique<Iterator>(
84+ std::next (GetCbeginIter<Reverse>(centroids_), std::distance (GetCbeginIter<Reverse>(centroids_), iter_)),
85+ centroids_);
7386 }
74- return std::make_unique<Iterator>(centroids_. cend ( ), centroids_);
87+ return std::make_unique<Iterator>(GetCendIter<Reverse>(centroids_ ), centroids_);
7588 }
76- bool Next () override {
89+ bool Next () {
7790 if (Valid ()) {
7891 std::advance (iter_, 1 );
7992 }
80- return iter_ != centroids_. cend ( );
93+ return iter_ != GetCendIter<Reverse>(centroids_ );
8194 }
8295
8396 // The Prev function can only be called for item is not cend,
8497 // because we must guarantee the iterator to be inside the valid range before iteration.
85- bool Prev () override {
86- if (Valid () && iter_ != centroids_. cbegin ( )) {
98+ bool Prev () {
99+ if (Valid () && iter_ != GetCendIter<Reverse>(centroids_ )) {
87100 std::advance (iter_, -1 );
88101 }
89102 return Valid ();
90103 }
91- bool Valid () const override { return iter_ != centroids_. cend ( ); }
92- StatusOr<Centroid> GetCentroid () const override {
93- if (iter_ == centroids_. cend ( )) {
104+ bool Valid () const { return iter_ != GetCendIter<Reverse>(centroids_ ); }
105+ StatusOr<Centroid> GetCentroid () const {
106+ if (iter_ == GetCendIter<Reverse>(centroids_ )) {
94107 return {::Status::NotOK, " invalid iterator during decoding tdigest centroid" };
95108 }
96109 return *iter_;
97110 }
98111
99112 private:
100- std::vector<Centroid>::const_iterator iter_;
113+ IterType iter_;
101114 const std::vector<Centroid>& centroids_;
102115 };
103116
104- class ReverseIterator final : public BaseIterator {
105- public:
106- ReverseIterator (std::vector<Centroid>::const_reverse_iterator&& iter, const std::vector<Centroid>& centroids)
107- : iter_(iter), centroids_(centroids) {}
108- std::unique_ptr<BaseIterator> Clone () const override {
109- if (iter_ != centroids_.crend ()) {
110- return std::make_unique<ReverseIterator>(
111- std::next (centroids_.crbegin (), std::distance (centroids_.crbegin (), iter_)), centroids_);
112- }
113- return std::make_unique<ReverseIterator>(centroids_.crend (), centroids_);
114- }
115- bool Next () override {
116- if (Valid ()) {
117- std::advance (iter_, 1 );
118- }
119- return iter_ != centroids_.crend ();
120- }
121-
122- bool Prev () override {
123- if (Valid () && iter_ != centroids_.crbegin ()) {
124- std::advance (iter_, -1 );
125- }
126- return Valid ();
127- }
128- bool Valid () const override { return iter_ != centroids_.crend (); }
129- StatusOr<Centroid> GetCentroid () const override {
130- if (iter_ == centroids_.crend ()) {
131- return {::Status::NotOK, " invalid iterator during decoding tdigest centroid" };
132- }
133- return *iter_;
134- }
135-
136- private:
137- std::vector<Centroid>::const_reverse_iterator iter_;
138- const std::vector<Centroid>& centroids_;
139- };
140-
141- std::unique_ptr<BaseIterator> Begin (const bool reverse = false ) const {
142- if (reverse) {
143- return std::make_unique<ReverseIterator>(centroids_.crbegin (), centroids_);
144- }
145- return std::make_unique<Iterator>(centroids_.cbegin (), centroids_);
117+ std::unique_ptr<Iterator> Begin () const {
118+ return std::make_unique<Iterator>(GetCbeginIter<Reverse>(centroids_), centroids_);
146119 }
147- std::unique_ptr<BaseIterator > End (const bool reverse = false ) const {
120+ std::unique_ptr<Iterator > End () const {
148121 if (centroids_.empty ()) {
149- if (reverse) {
150- return std::make_unique<ReverseIterator>(centroids_.crend (), centroids_);
151- }
152- return std::make_unique<Iterator>(centroids_.cend (), centroids_);
153- }
154- if (reverse) {
155- return std::make_unique<ReverseIterator>(std::prev (centroids_.crend ()), centroids_);
122+ return std::make_unique<Iterator>(GetCendIter<Reverse>(centroids_), centroids_);
156123 }
157- return std::make_unique<Iterator>(std::prev (centroids_. cend ( )), centroids_);
124+ return std::make_unique<Iterator>(std::prev (GetCendIter<Reverse>(centroids_ )), centroids_);
158125 }
159126 double TotalWeight () const { return static_cast <double >(meta_data_.total_weight ); }
160127 double Min () const { return meta_data_.minimum ; }
@@ -273,10 +240,9 @@ rocksdb::Status TDigest::mergeNodes(engine::Context& ctx, const std::string& ns_
273240 return rocksdb::Status::OK ();
274241}
275242
276- rocksdb::Status TDigest::Rank (engine::Context& ctx, const Slice& digest_name, const std::vector< double >& inputs ,
277- bool reverse, std::vector<int >& result ) {
243+ rocksdb::Status TDigest::prepareRankData (engine::Context& ctx, const Slice& digest_name, TDigestMetadata& metadata ,
244+ std::vector<Centroid >& centroids ) {
278245 auto ns_key = AppendNamespacePrefix (digest_name);
279- TDigestMetadata metadata;
280246 {
281247 LockGuard guard (storage_->GetLockManager (), ns_key);
282248
@@ -285,23 +251,51 @@ rocksdb::Status TDigest::Rank(engine::Context& ctx, const Slice& digest_name, co
285251 }
286252
287253 if (metadata.total_observations == 0 ) {
288- result.resize (inputs.size (), -2 );
289254 return rocksdb::Status::OK ();
290255 }
291256
292257 if (auto status = mergeNodes (ctx, ns_key, &metadata); !status.ok ()) {
293258 return status;
294259 }
295260 }
261+ return dumpCentroids (ctx, ns_key, metadata, ¢roids);
262+ }
296263
264+ rocksdb::Status TDigest::Rank (engine::Context& ctx, const Slice& digest_name, const std::vector<double >& inputs,
265+ std::vector<int >& result) {
266+ TDigestMetadata metadata;
297267 std::vector<Centroid> centroids;
298- if (auto status = dumpCentroids (ctx, ns_key, metadata, ¢roids); !status.ok ()) {
268+ if (auto status = prepareRankData (ctx, digest_name, metadata, centroids); !status.ok ()) {
269+ return status;
270+ }
271+
272+ if (metadata.total_observations == 0 ) {
273+ result.resize (inputs.size (), -2 );
274+ return rocksdb::Status::OK ();
275+ }
276+
277+ auto dump_centroids = DummyCentroids<false >(metadata, centroids);
278+ if (auto status = TDigestRank<false >(dump_centroids, inputs, result); !status) {
279+ return rocksdb::Status::InvalidArgument (status.Msg ());
280+ }
281+ return rocksdb::Status::OK ();
282+ }
283+
284+ rocksdb::Status TDigest::RevRank (engine::Context& ctx, const Slice& digest_name, const std::vector<double >& inputs,
285+ std::vector<int >& result) {
286+ TDigestMetadata metadata;
287+ std::vector<Centroid> centroids;
288+ if (auto status = prepareRankData (ctx, digest_name, metadata, centroids); !status.ok ()) {
299289 return status;
300290 }
301291
302- auto dump_centroids = DummyCentroids (metadata, centroids);
303- auto status = TDigestRank (dump_centroids, inputs, reverse, result);
304- if (!status) {
292+ if (metadata.total_observations == 0 ) {
293+ result.resize (inputs.size (), -2 );
294+ return rocksdb::Status::OK ();
295+ }
296+
297+ auto dump_centroids = DummyCentroids<true >(metadata, centroids);
298+ if (auto status = TDigestRank<true >(dump_centroids, inputs, result); !status) {
305299 return rocksdb::Status::InvalidArgument (status.Msg ());
306300 }
307301 return rocksdb::Status::OK ();
@@ -332,7 +326,7 @@ rocksdb::Status TDigest::Quantile(engine::Context& ctx, const Slice& digest_name
332326 return status;
333327 }
334328
335- auto dump_centroids = DummyCentroids (metadata, centroids);
329+ auto dump_centroids = DummyCentroids< false > (metadata, centroids);
336330
337331 auto quantile_results = std::vector<double >();
338332 quantile_results.reserve (qs.size ());
0 commit comments