const std::string &prefix ///< [in] Prefix by which to remove keys
) = 0;
+ virtual void rm_range_keys(
+ const string &prefix, ///< [in] Prefix by which to remove keys
+ const string &start, ///< [in] The start bound of remove keys
+ const string &end ///< [in] The start bound of remove keys
+ ) = 0;
+
/// Merge value into key
virtual void merge(
const std::string &prefix, ///< [in] Prefix ==> MUST match some established merge operator
}
}
+void KineticStore::KineticTransactionImpl::rm_range_keys(const string &prefix, const string &start, const string &end)
+{
+ KeyValueDB::Iterator it = db->get_iterator(prefix);
+ it->lower_bound(start);
+ while (it->valid()) {
+ if (it->key() >= end) {
+ break;
+ }
+ ops.push_back(
+ KineticOp(KINETIC_OP_DELETE, combine_strings(prefix, it->key())));
+ it->next();
+ }
+}
+
int KineticStore::get(
const string &prefix,
const std::set<string> &keys,
void rmkeys_by_prefix(
const string &prefix
);
+ void rm_range_keys(
+ const string &prefix,
+ const string &start,
+ const string &end);
};
KeyValueDB::Transaction get_transaction() {
for (it->seek_to_first();
it->valid();
it->next()) {
- string key = combine_strings(prefix, it->key());
- bat.Delete(key);
+ bat.Delete(leveldb::Slice(combine_strings(prefix, it->key())));
+ }
+}
+
+void LevelDBStore::LevelDBTransactionImpl::rm_range_keys(const string &prefix, const string &start, const string &end)
+{
+ KeyValueDB::Iterator it = db->get_iterator(prefix);
+ it->lower_bound(start);
+ while (it->valid()) {
+ if (it->key() >= end) {
+ break;
+ }
+ bat.Delete(combine_strings(prefix, it->key()));
+ it->next();
}
}
void rmkeys_by_prefix(
const string &prefix
) override;
+ virtual void rm_range_keys(
+ const string &prefix,
+ const string &start,
+ const string &end) override;
+
using KeyValueDB::TransactionImpl::rmkey;
};
}
}
+void MemDB::MDBTransactionImpl::rm_range_keys(const string &prefix, const string &start, const string &end)
+{
+ KeyValueDB::Iterator it = m_db->get_iterator(prefix);
+ it->lower_bound(start);
+ while (it->valid()) {
+ if (it->key() >= end) {
+ break;
+ }
+ rmkey(prefix, it->key());
+ it->next();
+ }
+}
+
void MemDB::MDBTransactionImpl::merge(
const std::string &prefix, const std::string &key, const bufferlist &value)
{
void rmkey(const std::string &prefix, const std::string &k) override;
using KeyValueDB::TransactionImpl::rmkey;
void rmkeys_by_prefix(const std::string &prefix) override;
+ void rm_range_keys(
+ const string &prefix,
+ const string &start,
+ const string &end) override;
void merge(const std::string &prefix, const std::string &key, const bufferlist &value) override;
void clear() {
}
}
+void RocksDBStore::RocksDBTransactionImpl::rm_range_keys(const string &prefix,
+ const string &start,
+ const string &end)
+{
+ bat.DeleteRange(combine_strings(prefix, start), combine_strings(prefix, end));
+}
+
void RocksDBStore::RocksDBTransactionImpl::merge(
const string &prefix,
const string &k,
void rmkeys_by_prefix(
const string &prefix
) override;
+ void rm_range_keys(
+ const string &prefix,
+ const string &start,
+ const string &end) override;
void merge(
const string& prefix,
const string& k,
return 0;
}
+int KeyValueDBMemory::rm_range_keys(const string &prefix, const string &start, const string &end) {
+ map<std::pair<string,string>,bufferlist>::iterator i;
+ i = db.lower_bound(make_pair(prefix, start));
+ if (i == db.end())
+ return 0;
+
+ while (i != db.end()) {
+ std::pair<string,string> key = (*i).first;
+ if (key.first != prefix)
+ break;
+ if (key.second >= end)
+ break;
+ ++i;
+ rmkey(key.first, key.second);
+ }
+ return 0;
+}
+
KeyValueDB::WholeSpaceIterator KeyValueDBMemory::_get_iterator() {
return ceph::shared_ptr<KeyValueDB::WholeSpaceIteratorImpl>(
new WholeSpaceMemIterator(this)
const string &prefix
);
+ int rm_range_keys(
+ const string &prefix,
+ const string &start,
+ const string &end
+ );
+
class TransactionImpl_ : public TransactionImpl {
public:
list<Context *> on_commit;
on_commit.push_back(new RmKeysByPrefixOp(db, prefix));
}
+ struct RmRangeKeys: public Context {
+ KeyValueDBMemory *db;
+ string prefix, start, end;
+ RmRangeKeys(KeyValueDBMemory *db, const string &prefix, const string &s, const string &e)
+ : db(db), prefix(prefix), start(s), end(e) {}
+ void finish(int r) {
+ db->rm_range_keys(prefix, start, end);
+ }
+ };
+
+ void rm_range_keys(const string &prefix, const string &start, const string &end) {
+ on_commit.push_back(new RmRangeKeys(db, prefix, start, end));
+ }
+
int complete() {
for (list<Context *>::iterator i = on_commit.begin();
i != on_commit.end();
fini();
}
+TEST_P(KVTest, RMRange) {
+ ASSERT_EQ(0, db->create_and_open(cout));
+ bufferlist value;
+ value.append("value");
+ {
+ KeyValueDB::Transaction t = db->get_transaction();
+ t->set("prefix", "key1", value);
+ t->set("prefix", "key2", value);
+ t->set("prefix", "key3", value);
+ t->set("prefix", "key4", value);
+ t->set("prefix", "key45", value);
+ t->set("prefix", "key5", value);
+ t->set("prefix", "key6", value);
+ db->submit_transaction_sync(t);
+ }
+
+ {
+ KeyValueDB::Transaction t = db->get_transaction();
+ t->set("prefix", "key7", value);
+ t->set("prefix", "key8", value);
+ t->rm_range_keys("prefix", "key2", "key7");
+ db->submit_transaction_sync(t);
+ bufferlist v1, v2;
+ ASSERT_EQ(0, db->get("prefix", "key1", &v1));
+ v1.clear();
+ ASSERT_EQ(-ENOENT, db->get("prefix", "key45", &v1));
+ ASSERT_EQ(0, db->get("prefix", "key8", &v1));
+ v1.clear();
+ ASSERT_EQ(-ENOENT, db->get("prefix", "key2", &v1));
+ ASSERT_EQ(0, db->get("prefix", "key7", &v2));
+ }
+
+ {
+ KeyValueDB::Transaction t = db->get_transaction();
+ t->rm_range_keys("prefix", "key", "key");
+ db->submit_transaction_sync(t);
+ bufferlist v1, v2;
+ ASSERT_EQ(0, db->get("prefix", "key1", &v1));
+ ASSERT_EQ(0, db->get("prefix", "key8", &v2));
+ }
+
+ {
+ KeyValueDB::Transaction t = db->get_transaction();
+ t->rm_range_keys("prefix", "key-", "key~");
+ db->submit_transaction_sync(t);
+ bufferlist v1, v2;
+ ASSERT_EQ(-ENOENT, db->get("prefix", "key1", &v1));
+ ASSERT_EQ(-ENOENT, db->get("prefix", "key8", &v2));
+ }
+
+ fini();
+}
+
INSTANTIATE_TEST_CASE_P(
KeyValueDB,