提交 c9aef3c4 编写于 作者: S Satnam Singh

Add RocksDb/GeoDb Iterator interface

Summary:
This diff is a first step towards an iterator based interface for the
SearchRadial method which replaces a vector of GeoObjects with an
iterator for GeoObjects. This diff works by just wrapping the iterator
for the encapsulated vector of GeoObjects. A future diff could extend
this approach by defining an interator in terms of the underlying
iteration in SearchRadial which would then remove the need to have
an in-memory representation for all the matching GeoObjects.
Fixes T8421387

Test Plan:
The existing tests have been modified to work with the new
interface.

Reviewers: IslamAbdelRahman, kradhakrishnan, dhruba, igor

Reviewed By: igor

Subscribers: igor, dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D50031
上级 db68a2c0
......@@ -59,6 +59,16 @@ class GeoObject {
}
};
class GeoIterator {
public:
GeoIterator() = default;
virtual ~GeoIterator() {}
virtual void Next() = 0;
virtual bool Valid() const = 0;
virtual const GeoObject& geo_object() = 0;
virtual Status status() const = 0;
};
//
// Stack your DB with GeoDB to be able to get geo-spatial support
//
......@@ -91,14 +101,13 @@ class GeoDB : public StackableDB {
// Delete the specified object
virtual Status Remove(const Slice& id) = 0;
// Returns a list of all items within a circular radius from the
// Returns an iterator for the items within a circular radius from the
// specified gps location. If 'number_of_values' is specified,
// then this call returns at most that many number of objects.
// then the iterator is capped to that number of objects.
// The radius is specified in 'meters'.
virtual Status SearchRadial(const GeoPosition& pos,
double radius,
std::vector<GeoObject>* values,
int number_of_values = INT_MAX) = 0;
virtual GeoIterator* SearchRadial(const GeoPosition& pos,
double radius,
int number_of_values = INT_MAX) = 0;
};
} // namespace rocksdb
......
......@@ -159,15 +159,63 @@ Status GeoDBImpl::Remove(const Slice& id) {
return db_->Write(woptions_, &batch);
}
Status GeoDBImpl::SearchRadial(const GeoPosition& pos,
class GeoIteratorImpl : public GeoIterator {
private:
std::vector<GeoObject> values_;
std::vector<GeoObject>::iterator iter_;
public:
explicit GeoIteratorImpl(std::vector<GeoObject> values)
: values_(std::move(values)) {
iter_ = values_.begin();
}
virtual void Next() override;
virtual bool Valid() const override;
virtual const GeoObject& geo_object() override;
virtual Status status() const override;
};
class GeoErrorIterator : public GeoIterator {
private:
Status status_;
public:
explicit GeoErrorIterator(Status s) : status_(s) {}
virtual void Next() override {};
virtual bool Valid() const override { return false; }
virtual const GeoObject& geo_object() override {
GeoObject* g = new GeoObject();
return *g;
}
virtual Status status() const override { return status_; }
};
void GeoIteratorImpl::Next() {
assert(Valid());
iter_++;
}
bool GeoIteratorImpl::Valid() const {
return iter_ != values_.end();
}
const GeoObject& GeoIteratorImpl::geo_object() {
assert(Valid());
return *iter_;
}
Status GeoIteratorImpl::status() const {
return Status::OK();
}
GeoIterator* GeoDBImpl::SearchRadial(const GeoPosition& pos,
double radius,
std::vector<GeoObject>* values,
int number_of_values) {
std::vector<GeoObject> values;
// Gather all bounding quadkeys
std::vector<std::string> qids;
Status s = searchQuadIds(pos, radius, &qids);
if (!s.ok()) {
return s;
return new GeoErrorIterator(s);
}
// create an iterator
......@@ -200,7 +248,7 @@ Status GeoDBImpl::SearchRadial(const GeoPosition& pos,
if (res.first == qid.end()) {
GeoPosition obj_pos(atof(parts[3].c_str()), atof(parts[4].c_str()));
GeoObject obj(obj_pos, parts[4], iter->value().ToString());
values->push_back(obj);
values.push_back(obj);
number_of_values--;
} else {
break;
......@@ -208,7 +256,7 @@ Status GeoDBImpl::SearchRadial(const GeoPosition& pos,
}
}
delete iter;
return Status::OK();
return new GeoIteratorImpl(std::move(values));
}
std::string GeoDBImpl::MakeKey1(const GeoPosition& pos, Slice id,
......
......@@ -46,9 +46,8 @@ class GeoDBImpl : public GeoDB {
// Returns a list of all items within a circular radius from the
// specified gps location
virtual Status SearchRadial(const GeoPosition& pos, double radius,
std::vector<GeoObject>* values,
int number_of_values) override;
virtual GeoIterator* SearchRadial(const GeoPosition& pos, double radius,
int number_of_values) override;
private:
DB* db_;
......
......@@ -103,17 +103,21 @@ TEST_F(GeoDBTest, Search) {
// search all objects centered at 46 degree latitude with
// a radius of 200 kilometers. We should find the one object that
// we inserted earlier.
std::vector<GeoObject> values;
status = getdb()->SearchRadial(GeoPosition(46, 46), 200000, &values);
GeoIterator* iter = getdb()->SearchRadial(GeoPosition(46, 46), 200000);
ASSERT_TRUE(status.ok());
ASSERT_EQ(values.size(), 1U);
ASSERT_EQ(iter->geo_object().value, "midvalue1");
uint size = 0;
while (iter->Valid()) {
size++;
iter->Next();
}
ASSERT_EQ(size, 1U);
// search all objects centered at 46 degree latitude with
// a radius of 2 kilometers. There should be none.
values.clear();
status = getdb()->SearchRadial(GeoPosition(46, 46), 2, &values);
iter = getdb()->SearchRadial(GeoPosition(46, 46), 2);
ASSERT_TRUE(status.ok());
ASSERT_EQ(values.size(), 0U);
ASSERT_FALSE(iter->Valid());
}
} // namespace rocksdb
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册