return 0;
}
+int D4NFilterObject::load_obj_state(const DoutPrefixProvider *dpp, optional_yield y,
+ bool follow_olh)
+{
+ if (load_from_store) {
+ return next->load_obj_state(dpp, y, follow_olh);
+ }
+ bool has_instance = false;
+ if (!this->get_instance().empty()) {
+ has_instance = true;
+ }
+ int ret = get_obj_attrs_from_cache(dpp, y);
+ if (ret) {
+ /* clearing instance if not present in object before
+ calling get_obj_attrs_from_cache as it incorrectly
+ causes delete obj to be invoked for an instance
+ even though a simple delete request has been issued
+ (after load_obj_state is invoked) */
+ if (!has_instance) {
+ this->clear_instance();
+ }
+ return 0;
+ }
+ return next->load_obj_state(dpp, y, follow_olh);
+}
+
int D4NFilterObject::set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs,
Attrs* delattrs, optional_yield y, uint32_t flags)
{
}
}//end-if
}//end-for
- this->set_instance(instance); //set this only after setting object state else it won't take effect
+ if (!instance.empty()) {
+ this->set_instance(instance); //set this only after setting object state else it won't take effect
+ }
attrs.erase(RGW_CACHE_ATTR_MTIME);
attrs.erase(RGW_CACHE_ATTR_OBJECT_SIZE);
attrs.erase(RGW_CACHE_ATTR_ACCOUNTED_SIZE);
}
std::string key = head_oid_in_cache;
this->driver->get_policy_driver()->get_cache_policy()->update(dpp, key, 0, 0, version, block.cacheObj.dirty, rgw::d4n::RefCount::DECR, y);
+ this->exists_in_cache = true;
} else {
found_in_cache = false;
}
ldpp_dout(dpp, 0) << "D4NFilterWriter::" << __func__ << "(): writing to backend store failed, ret=" << ret << dendl;
return ret;
}
+ /* we want to always load latest object state from store
+ to avoid reading stale state in case of object overwrites. */
+ object->set_load_obj_from_store(true);
object->load_obj_state(dpp, y);
attrs = object->get_attrs();
object->set_attrs_from_obj_state(dpp, y, attrs, dirty);
//Cache only the head object for multipart objects
D4NFilterObject* d4n_target_obj = dynamic_cast<D4NFilterObject*>(target_obj);
+ /* we want to always load latest object state from store
+ to avoid reading stale state in case of object overwrites. */
+ d4n_target_obj->set_load_obj_from_store(true);
d4n_target_obj->load_obj_state(dpp, y);
rgw::sal::Attrs attrs = d4n_target_obj->get_attrs();
d4n_target_obj->set_attrs_from_obj_state(dpp, y, attrs);
rgw::sal::Bucket* dest_bucket{nullptr}; //for copy-object
bool multipart{false};
bool delete_marker{false};
+ bool exists_in_cache{false};
+ bool load_from_store{false};
public:
struct D4NFilterReadOp : FilterReadOp {
optional_yield y) override;
virtual const std::string &get_name() const override { return next->get_name(); }
+ virtual int load_obj_state(const DoutPrefixProvider *dpp, optional_yield y,
+ bool follow_olh = true) override;
virtual int set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs,
Attrs* delattrs, optional_yield y, uint32_t flags) override;
virtual int get_obj_attrs(optional_yield y, const DoutPrefixProvider* dpp,
int set_attr_crypt_parts(const DoutPrefixProvider* dpp, optional_yield y, rgw::sal::Attrs& attrs);
int create_delete_marker(const DoutPrefixProvider* dpp, optional_yield y);
bool is_delete_marker() { return delete_marker; }
+ bool exists(void) override { if (exists_in_cache) { return true;} return next->exists(); };
+ bool load_obj_from_store() { return load_from_store; }
+ void set_load_obj_from_store(bool load_from_store) { this->load_from_store = load_from_store; }
};
class D4NFilterWriter : public FilterWriter {