Skip to content

Commit c740754

Browse files
committed
os, osd: introduce a lightweight OMAP iteration
Signed-off-by: Radoslaw Zarzynski <[email protected]>
1 parent d3aa715 commit c740754

File tree

2 files changed

+73
-21
lines changed

2 files changed

+73
-21
lines changed

src/os/ObjectStore.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include <errno.h>
3131
#include <sys/stat.h>
32+
#include <functional>
3233
#include <map>
3334
#include <memory>
3435
#include <vector>
@@ -766,6 +767,50 @@ class ObjectStore {
766767
const ghobject_t &oid ///< [in] object
767768
) = 0;
768769

770+
struct omap_iter_seek_t {
771+
std::string seek_position;
772+
enum {
773+
// start with provided key (seek_position), if it exists
774+
LOWER_BOUND,
775+
// skip provided key (seek_position) even if it exists
776+
UPPER_BOUND
777+
} seek_type = LOWER_BOUND;
778+
static omap_iter_seek_t min_lower_bound() { return {}; }
779+
};
780+
enum class omap_iter_ret_t {
781+
STOP,
782+
NEXT
783+
};
784+
/**
785+
* Iterate over object map with user-provided callable
786+
*
787+
* Warning! The callable is executed under lock on bluestore
788+
* operations in c. Do not use bluestore methods on c while
789+
* iterating. (Filling in a transaction is no problem).
790+
*
791+
* @param c collection
792+
* @param oid object
793+
* @param start_from where the iterator should point to at
794+
* the beginning
795+
* @param visitor callable that takes OMAP key and corresponding
796+
* value as string_views and controls iteration
797+
* by the return. It is executed for every object's
798+
* OMAP entry from `start_from` till end of the
799+
* object's OMAP or till the iteration is stopped
800+
* by `STOP`. Please note that if there is no such
801+
* entry, `visitor` will be called 0 times.
802+
* @return error code, zero on success
803+
*/
804+
virtual int omap_iterate(
805+
CollectionHandle &c,
806+
const ghobject_t &oid,
807+
omap_iter_seek_t start_from,
808+
std::function<omap_iter_ret_t(std::string_view,
809+
std::string_view)> visitor
810+
) {
811+
return -EOPNOTSUPP;
812+
}
813+
769814
virtual int flush_journal() { return -EOPNOTSUPP; }
770815

771816
virtual int dump_journal(std::ostream& out) { return -EOPNOTSUPP; }

src/osd/PrimaryLogPG.cc

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7755,27 +7755,34 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
77557755
bool truncated = false;
77567756
bufferlist bl;
77577757
if (oi.is_omap()) {
7758-
ObjectMap::ObjectMapIterator iter = osd->store->get_omap_iterator(
7759-
ch, ghobject_t(soid)
7760-
);
7761-
if (!iter) {
7762-
result = -ENOENT;
7763-
goto fail;
7764-
}
7765-
iter->upper_bound(start_after);
7766-
if (filter_prefix > start_after) iter->lower_bound(filter_prefix);
7767-
for (num = 0;
7768-
iter->valid() &&
7769-
iter->key().substr(0, filter_prefix.size()) == filter_prefix;
7770-
++num, iter->next()) {
7771-
dout(20) << "Found key " << iter->key() << dendl;
7772-
if (num >= max_return ||
7773-
bl.length() >= cct->_conf->osd_max_omap_bytes_per_request) {
7774-
truncated = true;
7775-
break;
7776-
}
7777-
encode(iter->key(), bl);
7778-
encode(iter->value(), bl);
7758+
using omap_iter_seek_t = ObjectStore::omap_iter_seek_t;
7759+
result = osd->store->omap_iterate(
7760+
ch, ghobject_t(soid),
7761+
// try to seek as many keys-at-once as possible for the sake of performance.
7762+
// note complexity should be logarithmic, so seek(n/2) + seek(n/2) is worse
7763+
// than just seek(n).
7764+
ObjectStore::omap_iter_seek_t{
7765+
.seek_position = std::max(start_after, filter_prefix),
7766+
.seek_type = filter_prefix > start_after ? omap_iter_seek_t::LOWER_BOUND
7767+
: omap_iter_seek_t::UPPER_BOUND
7768+
},
7769+
[&bl, &truncated, &filter_prefix, &num, max_return,
7770+
max_bytes=cct->_conf->osd_max_omap_bytes_per_request]
7771+
(std::string_view key, std::string_view value) mutable {
7772+
if (key.substr(0, filter_prefix.size()) != filter_prefix) {
7773+
return ObjectStore::omap_iter_ret_t::STOP;
7774+
}
7775+
if (num >= max_return || bl.length() >= max_bytes) {
7776+
truncated = true;
7777+
return ObjectStore::omap_iter_ret_t::STOP;
7778+
}
7779+
encode(key, bl);
7780+
encode(value, bl);
7781+
++num;
7782+
return ObjectStore::omap_iter_ret_t::NEXT;
7783+
});
7784+
if (result < 0) {
7785+
goto fail;
77797786
}
77807787
} // else return empty out_set
77817788
encode(num, osd_op.outdata);

0 commit comments

Comments
 (0)