Introduced wrappers around omap read operations in PGBackend to include updates from the journal in EC pools with optimisations enabled.
Introduced a function for encoding an EC_OMAP operation in the ObjectModDesc::Visitor class and a function for committing an operation in the Trimmer struct.
Signed-off-by: Matty Williams <Matty.Williams@ibm.com>
o.omap_digest_present = true;
return 0;
}
+
+bool ECBackend::remove_ec_omap_journal_entry(const hobject_t &hoid, const ECOmapJournalEntry &entry) {
+ return ec_omap_journal.remove_entry(hoid, entry);
+}
+
+std::pair<gen_t, bool> ECBackend::omap_get_generation(const hobject_t& hoid)
+{
+ return ec_omap_journal.get_generation(hoid);
+}
+
+void ECBackend::omap_trim_delete_from_journal(const hobject_t &hoid, const version_t version)
+{
+ return ec_omap_journal.trim_delete(hoid, version);
+}
+
+int ECBackend::omap_iterate (
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from,
+ ///^ [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f, ///< [in] function to call for each key/value pair
+ ObjectStore *store
+) {
+ // Updates in update_map take priority over removed_ranges
+ auto [update_map, removed_ranges] = ec_omap_journal.get_value_updates(oid.hobj);
+
+ auto journal_it = update_map.begin();
+ if (!start_from.seek_position.empty()) {
+ journal_it = update_map.lower_bound(start_from.seek_position);
+ }
+
+ auto wrapper = [&](const std::string_view store_key, const std::string_view store_value) {
+ bool found_store_key_in_journal = false;
+
+ while (journal_it != update_map.end() && journal_it->first <= store_key) {
+ if (journal_it->first == store_key) {
+ found_store_key_in_journal = true;
+ }
+ if (journal_it->second.value.has_value()) {
+ ObjectStore::omap_iter_ret_t r = f(
+ journal_it->first,
+ std::string_view(
+ journal_it->second.value->c_str(),
+ journal_it->second.value->length()
+ )
+ );
+ if (r == ObjectStore::omap_iter_ret_t::STOP) {
+ return r;
+ }
+ }
+ ++journal_it;
+ }
+
+ if (found_store_key_in_journal) {
+ return ObjectStore::omap_iter_ret_t::NEXT;
+ }
+
+ if (should_be_removed(removed_ranges, store_key)) {
+ return ObjectStore::omap_iter_ret_t::NEXT;
+ }
+
+ return f(store_key, store_value);
+ };
+
+ if (const auto result = store->omap_iterate(c_, oid, start_from, wrapper);
+ result < 0) {
+ return result;
+ } else if (result > 0) {
+ return 1;
+ }
+
+ auto ret = ObjectStore::omap_iter_ret_t::NEXT;
+ while (journal_it != update_map.end()) {
+ if (journal_it->second.value.has_value()) {
+ ret = f(journal_it->first, std::string_view(journal_it->second.value->c_str(), journal_it->second.value->length()));
+ if (ret == ObjectStore::omap_iter_ret_t::STOP) {
+ break;
+ }
+ }
+ ++journal_it;
+ }
+
+ return ret == ObjectStore::omap_iter_ret_t::STOP ? 1 : 0;
+}
+
+int ECBackend::omap_get_values(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out, ///< [out] returned key/values
+ ObjectStore *store
+) {
+ auto [update_map, removed_ranges] = ec_omap_journal.get_value_updates(oid.hobj);
+
+ set<string> keys_still_to_get;
+ for (auto &key : keys) {
+ if (auto it = update_map.find(key);
+ it != update_map.end()) {
+ if (!it->second.value.has_value()) {
+ continue;
+ }
+ (*out)[key] = *(it->second.value);
+ } else if (should_be_removed(removed_ranges, key)) {
+ continue;
+ } else {
+ keys_still_to_get.insert(key);
+ }
+ }
+ store->omap_get_values(c_, oid, keys_still_to_get, out);
+
+ return 0;
+}
+
+int ECBackend::omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ const bool allow_eio, ///< [in] don't assert on eio
+ ObjectStore *store
+) {
+ std::optional<ceph::buffer::list> header_from_journal = ec_omap_journal.get_updated_header(oid.hobj);
+ if (header_from_journal) {
+ *header = *header_from_journal;
+ } else {
+ store->omap_get_header(c_, oid, header, allow_eio);
+ }
+ return 0;
+}
+
+int ECBackend::omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out, /// < [out] Key to value map
+ ObjectStore *store
+) {
+ // Update map takes priority over removed_ranges
+ auto [update_map, removed_ranges] = ec_omap_journal.get_value_updates(oid.hobj);
+ const auto updated_header = ec_omap_journal.get_updated_header(oid.hobj);
+
+ if (const int r = store->omap_get(c_, oid, header, out);
+ r < 0) {
+ return r;
+ }
+
+ // Update header if present
+ if (updated_header) {
+ *header = *updated_header;
+ }
+
+ // Remove keys in removed_ranges
+ for (auto out_it = out->begin(); out_it != out->end(); ++out_it) {
+ if (should_be_removed(removed_ranges, out_it->first)) {
+ out->erase(out_it->first);
+ }
+ }
+
+ // Apply updates in update_map
+ for (const auto &[key, val_opt] : update_map) {
+ if (val_opt.value.has_value()) {
+ (*out)[key] = *(val_opt.value);
+ } else {
+ out->erase(key);
+ }
+ }
+
+ return 0;
+}
+
+int ECBackend::omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out, ///< [out] Subset of keys defined on oid
+ ObjectStore *store
+) {
+ // Update map takes priority over removed_ranges
+ auto [update_map, removed_ranges] = ec_omap_journal.get_value_updates(oid.hobj);
+ auto updated_header = ec_omap_journal.get_updated_header(oid.hobj);
+
+ // First check keys in update_map and removed_ranges
+ set<string> keys_to_check_on_disk;
+ for (const auto &key : keys) {
+ if (auto it = update_map.find(key);
+ it != update_map.end()) {
+ if (it->second.value.has_value()) {
+ out->insert(key);
+ }
+ } else if (should_be_removed(removed_ranges, key)) {
+ continue;
+ } else {
+ keys_to_check_on_disk.insert(key);
+ }
+ }
+
+ const int r = store->omap_check_keys(c_, oid, keys_to_check_on_disk, out);
+
+ return r;
+}
+
+bool ECBackend::should_be_removed(
+ const std::map<std::string, std::optional<std::string>>& removed_ranges,
+ std::string_view key)
+{
+ if (removed_ranges.empty()) {
+ return false;
+ }
+
+ // Find range that comes after this key
+ auto it = removed_ranges.upper_bound(std::string(key));
+
+ // If all ranges start after the key, it can't be in any range
+ if (it == removed_ranges.begin()) {
+ return false;
+ }
+
+ // Go back to the previous range
+ --it;
+ // If this range contains the key, return true
+ const auto& end_opt = it->second;
+ if (!end_opt || key < *end_opt) {
+ return true;
+ }
+
+ // No ranges contain the key, return false
+ return false;
+}
}
return object_size_to_shard_size(logical_size, shard_id);
}
+
+ bool remove_ec_omap_journal_entry(const hobject_t &hoid, const ECOmapJournalEntry &entry);
+ std::pair<gen_t, bool> omap_get_generation(const hobject_t &hoid);
+ void omap_trim_delete_from_journal(const hobject_t &hoid, const version_t version);
+
+ using OmapIterFunction = std::function<ObjectStore::omap_iter_ret_t(std::string_view, std::string_view)>;
+ int omap_iterate (
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from, ///< [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f, ///< [in] function to call for each key/value pair
+ ObjectStore *store
+ );
+
+ int omap_get_values(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out, ///< [out] returned key/values
+ ObjectStore *store
+ );
+
+ int omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ bool allow_eio, ///< [in] don't assert on eio
+ ObjectStore *store
+ );
+
+ int omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out, /// < [out] Key to value map
+ ObjectStore *store
+ );
+
+ int omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out, ///< [out] Subset of keys defined on oid
+ ObjectStore *store
+ );
+
+ bool should_be_removed(
+ const std::map<std::string, std::optional<std::string>>& removed_ranges,
+ std::string_view key
+ );
};
#include "ECTypes.h"
#include "messages/MOSDPGPushReply.h"
#include "msg/MessageRef.h"
+#include "osd/ECOmapJournal.h"
#if WITH_CRIMSON
#include "crimson/osd/object_context.h"
#include "os/Transaction.h"
struct RecoveryMessages;
struct ECCommon {
+ ECOmapJournal ec_omap_journal;
+
struct ec_extent_t {
int err;
extent_map emap;
bool get_is_ec_optimized() const final {
return is_optimized();
}
+ bool remove_ec_omap_journal_entry(const hobject_t &hoid, const ECOmapJournalEntry &entry) override {
+ ceph_assert(is_optimized());
+ return optimized.remove_ec_omap_journal_entry(hoid, entry);
+ }
+
+ std::pair<gen_t, bool> omap_get_generation(const hobject_t &hoid) override
+ {
+ ceph_assert(is_optimized());
+ return optimized.omap_get_generation(hoid);
+ }
+
+ void omap_trim_delete_from_journal(const hobject_t &hoid, const version_t version) override
+ {
+ ceph_assert(is_optimized());
+ optimized.omap_trim_delete_from_journal(hoid, version);
+ }
+
+ int omap_iterate (
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from,
+ ///^ [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f ///< [in] function to call for each key/value pair
+ ) override {
+ if (!is_optimized()) {
+ return store->omap_iterate(c_, oid, start_from, f);
+ }
+ return optimized.omap_iterate(c_, oid, start_from, f, store);
+ }
+
+ int omap_get_values(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out ///< [out] returned key/values
+ ) override {
+ if (!is_optimized()) {
+ return store->omap_get_values(c_, oid, keys, out);
+ }
+ return optimized.omap_get_values(c_, oid, keys, out, store);
+ }
+
+ int omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ bool allow_eio ///< [in] don't assert on eio
+ ) override {
+ if (!is_optimized()) {
+ return store->omap_get_header(c_, oid, header, allow_eio);
+ }
+ return optimized.omap_get_header(c_, oid, header, allow_eio, store);
+ }
+
+ int omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out /// < [out] Key to value map
+ ) override {
+ if (!is_optimized()) {
+ return store->omap_get(c_, oid, header, out);
+ }
+ return optimized.omap_get(c_, oid, header, out, store);
+ }
+
+ int omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out ///< [out] Subset of keys defined on oid
+ ) override {
+ if (!is_optimized()) {
+ return store->omap_check_keys(c_, oid, keys, out);
+ }
+ return optimized.omap_check_keys(c_, oid, keys, out, store);
+ }
};
const hobject_t &soid;
PGBackend *pg;
ObjectStore::Transaction *t;
+ const pg_log_entry_t &entry;
Trimmer(
- const hobject_t &soid,
PGBackend *pg,
- ObjectStore::Transaction *t)
- : soid(soid), pg(pg), t(t) {}
+ ObjectStore::Transaction *t,
+ const pg_log_entry_t &entry)
+ : soid(entry.soid), pg(pg), t(t), entry(entry) {}
void rmobject(version_t old_version) override {
pg->trim_rollback_object(
soid,
}
}
}
+
+ void ec_omap(bool clear_omap, std::optional<ceph::buffer::list> omap_header,
+ std::vector<std::pair<OmapUpdateType, ceph::buffer::list>> &omap_updates) override {
+
+ auto shard = pg->get_parent()->whoami_shard().shard;
+ spg_t spg = pg->get_parent()->whoami_spg_t();
+ auto sinfo = pg->ec_get_sinfo();
+ const auto [gen, lost_delete] = pg->omap_get_generation(soid);
+
+ if (!sinfo.is_nonprimary_shard(shard)) {
+ // If lost_delete is true, check if the object exists before performing updates
+ bool should_update = true;
+ if (lost_delete) {
+ struct stat st;
+ int r = pg->store->stat(
+ pg->ch,
+ ghobject_t(soid, gen, shard),
+ &st,
+ true);
+ if (r != 0) {
+ // Object doesn't exist on this shard, skip the update
+ should_update = false;
+ }
+ }
+
+ if (should_update) {
+ if (omap_header) {
+ t->omap_setheader(
+ coll_t(spg),
+ ghobject_t(soid, gen, shard),
+ *(omap_header));
+ }
+
+ if (clear_omap) {
+ t->omap_clear(
+ coll_t(spg),
+ ghobject_t(soid, gen, shard));
+ }
+
+ for (auto &&up: omap_updates) {
+ switch (up.first) {
+ case OmapUpdateType::Remove:
+ t->omap_rmkeys(
+ coll_t(spg),
+ ghobject_t(soid, gen, shard),
+ up.second);
+ break;
+ case OmapUpdateType::Insert:
+ t->omap_setkeys(
+ coll_t(spg),
+ ghobject_t(soid, gen, shard),
+ up.second);
+ break;
+ case OmapUpdateType::RemoveRange:
+ t->omap_rmkeyrange(
+ coll_t(spg),
+ ghobject_t(soid, gen, shard),
+ up.second);
+ break;
+ }
+ }
+ }
+ }
+
+ // Only remove journal entry if generation is NO_GEN (object not deleted)
+ // If gen != NO_GEN, the object has been deleted and journal was already cleared
+ if (gen == ghobject_t::NO_GEN && pg->get_parent()->pgb_is_primary()) {
+ const ECOmapJournalEntry to_remove(
+ entry.version, clear_omap,
+ omap_header, omap_updates
+ );
+ pg->remove_ec_omap_journal_entry(soid, to_remove);
+ }
+ }
};
void PGBackend::rollforward(
ldpp_dout(dpp, 20) << __func__ << ": entry=" << entry << dendl;
if (!entry.can_rollback())
return;
- Trimmer trimmer(entry.soid, this, t);
+ Trimmer trimmer(this, t, entry);
entry.mod_desc.visit(&trimmer);
}
{
if (!entry.can_rollback())
return;
- Trimmer trimmer(entry.soid, this, t);
+ Trimmer trimmer(this, t, entry);
entry.mod_desc.visit(&trimmer);
}
#ifndef PGBACKEND_H
#define PGBACKEND_H
-#include "ECListener.h"
-#include "ECTypes.h"
-#include "ECExtentCache.h"
-#include "osd_types.h"
-#include "pg_features.h"
-#include "common/intrusive_timer.h"
+#include <string>
+
+#include "common/LogClient.h"
#include "common/WorkQueue.h"
+#include "common/intrusive_timer.h"
+#include "common/ostream_temp.h"
#include "include/Context.h"
#include "os/ObjectStore.h"
#include "osd/scrubber_common.h"
-#include "common/LogClient.h"
-#include <string>
+
+#include "ECExtentCache.h"
+#include "ECListener.h"
+#include "ECTypes.h"
#include "PGTransaction.h"
-#include "common/ostream_temp.h"
+#include "osd_types.h"
+#include "pg_features.h"
+
+
+class ECOmapJournalEntry;
namespace Scrub {
class Store;
virtual shard_id_map<bufferlist> ec_decode_acting_set(
const shard_id_map<bufferlist> &shard_map, int chunk_size) const = 0;
virtual ECUtil::stripe_info_t ec_get_sinfo() const = 0;
-
+ virtual bool remove_ec_omap_journal_entry(const hobject_t &hoid, const ECOmapJournalEntry &entry) {
+ return false; // Only EC uses ec_omap_journal
+ };
+ virtual std::pair<gen_t, bool> omap_get_generation(const hobject_t &hoid) {
+ return {0, false}; // Only EC uses ec_omap_journal
+ };
+ virtual void omap_trim_delete_from_journal(const hobject_t &hoid, const version_t version) {};
+ using OmapIterFunction = std::function<ObjectStore::omap_iter_ret_t(std::string_view, std::string_view)>;
+ virtual int omap_iterate(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from,
+ ///^ [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f ///< [in] function to call for each key/value pair
+ ) = 0;
+ virtual int omap_get_values(
+ ObjectStore::ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out ///< [out] returned key/values
+ ) = 0;
+ virtual int omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ bool allow_eio ///< [in] don't assert on eio
+ ) = 0;
+ virtual int omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out /// < [out] Key to value map
+ ) = 0;
+ virtual int omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out ///< [out] Subset of keys defined on oid
+ ) = 0;
private:
std::set<hobject_t> temp_contents;
public:
}
}
+ int omap_iterate(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from,
+ ///^ [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f ///< [in] function to call for each key/value pair
+ ) override
+ {
+ return store->omap_iterate(c_, oid, start_from, f);
+ }
+ int omap_get_values(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out ///< [out] returned key/values
+ ) override
+ {
+ return store->omap_get_values(c_, oid, keys, out);
+ }
+ int omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ bool allow_eio ///< [in] don't assert on eio
+ ) override
+ {
+ return store->omap_get_header(c_, oid, header, allow_eio);
+ }
+ int omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out /// < [out] Key to value map
+ ) override
+ {
+ return store->omap_get(c_, oid, header, out);
+ }
+ int omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out ///< [out] Subset of keys defined on oid
+ ) override
+ {
+ return store->omap_check_keys(c_, oid, keys, out);
+ }
+
int objects_read_sync(
const hobject_t &hoid,
uint64_t off,
using shard_id_set = bitset_set<128, shard_id_t>;
WRITE_CLASS_DENC(shard_id_set)
-enum class OmapUpdateType {Remove, Insert, RemoveRange};
+enum class OmapUpdateType : uint8_t {Remove, Insert, RemoveRange};
/**
* osd request identifier
public:
virtual void append(uint64_t old_offset) {}
virtual void setattrs(std::map<std::string, std::optional<ceph::buffer::list>> &attrs) {}
+ virtual void ec_omap(bool clear_omap, std::optional<ceph::buffer::list> omap_header,
+ std::vector<std::pair<OmapUpdateType, ceph::buffer::list>> &omap_updates) {}
virtual void rmobject(version_t old_version) {}
/**
* Used to support the unfound_lost_delete log event: if the stashed
CREATE = 4,
UPDATE_SNAPS = 5,
TRY_DELETE = 6,
- ROLLBACK_EXTENTS = 7
+ ROLLBACK_EXTENTS = 7,
+ EC_OMAP = 8
};
ObjectModDesc() : can_local_rollback(true), rollback_info_completed(false) {
bl.reassign_to_mempool(mempool::mempool_osd_pglog);
encode(old_attrs, bl);
ENCODE_FINISH(bl);
}
+ void ec_omap(bool clear_omap, std::optional<ceph::buffer::list> omap_header,
+ std::vector<std::pair<OmapUpdateType, ceph::buffer::list>> &omap_updates) {
+ if(!can_local_rollback) {
+ return;
+ }
+ ENCODE_START(1, 1, bl);
+ append_id(EC_OMAP);
+ encode(clear_omap, bl);
+ encode(omap_header, bl);
+ encode(omap_updates, bl);
+ ENCODE_FINISH(bl);
+ }
bool rmobject(version_t deletion_version) {
if (!can_local_rollback || rollback_info_completed) {
return false;
cb();
}
+ int omap_iterate(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const ObjectStore::omap_iter_seek_t &start_from,
+ ///^ [in] where the iterator should point to at the beginning
+ const OmapIterFunction &f ///< [in] function to call for each key/value pair
+ ) override {
+ return 0;
+ }
+ int omap_get_values(
+ ObjectStore::CollectionHandle &c_, ///< [in] collection
+ const ghobject_t &oid, ///< [in] object
+ const std::set<std::string> &keys, ///< [in] keys to get
+ std::map<std::string, ceph::buffer::list> *out ///< [out] returned key/values
+ ) override {
+ return 0;
+ }
+ int omap_get_header(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ bool allow_eio ///< [in] don't assert on eio
+ ) override {
+ return 0;
+ }
+ int omap_get(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ ceph::buffer::list *header, ///< [out] omap header
+ std::map<std::string, ceph::buffer::list> *out /// < [out] Key to value map
+ ) override {
+ return 0;
+ }
+ int omap_check_keys(
+ ObjectStore::CollectionHandle &c_, ///< [in] Collection containing oid
+ const ghobject_t &oid, ///< [in] Object containing omap
+ const std::set<std::string> &keys, ///< [in] Keys to check
+ std::set<std::string> *out ///< [out] Subset of keys defined on oid
+ ) override {
+ return 0;
+ }
+
// Object operations
int objects_read_sync(
const hobject_t &hoid,