X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fos%2Ffilestore%2FDBObjectMap.h;fp=src%2Fceph%2Fsrc%2Fos%2Ffilestore%2FDBObjectMap.h;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=fb1653e489d0e4070a98f2c20a744873b1c1ab77;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/os/filestore/DBObjectMap.h b/src/ceph/src/os/filestore/DBObjectMap.h deleted file mode 100644 index fb1653e..0000000 --- a/src/ceph/src/os/filestore/DBObjectMap.h +++ /dev/null @@ -1,581 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -#ifndef DBOBJECTMAP_DB_H -#define DBOBJECTMAP_DB_H - -#include "include/buffer_fwd.h" -#include -#include -#include - -#include -#include "include/memory.h" -#include - -#include "os/ObjectMap.h" -#include "kv/KeyValueDB.h" -#include "osd/osd_types.h" -#include "common/Mutex.h" -#include "common/Cond.h" -#include "common/simple_cache.hpp" -#include - -#include "SequencerPosition.h" - -/** - * DBObjectMap: Implements ObjectMap in terms of KeyValueDB - * - * Prefix space structure: - * - * @see complete_prefix - * @see user_prefix - * @see sys_prefix - * - * - HOBJECT_TO_SEQ: Contains leaf mapping from ghobject_t->header.seq and - * corresponding omap header - * - SYS_PREFIX: GLOBAL_STATE_KEY - contains next seq number - * @see State - * @see write_state - * @see init - * @see generate_new_header - * - USER_PREFIX + header_key(header->seq) + USER_PREFIX - * : key->value for header->seq - * - USER_PREFIX + header_key(header->seq) + COMPLETE_PREFIX: see below - * - USER_PREFIX + header_key(header->seq) + XATTR_PREFIX: xattrs - * - USER_PREFIX + header_key(header->seq) + SYS_PREFIX - * : USER_HEADER_KEY - omap header for header->seq - * : HEADER_KEY - encoding of header for header->seq - * - * For each node (represented by a header), we - * store three mappings: the key mapping, the complete mapping, and the parent. - * The complete mapping (COMPLETE_PREFIX space) is key->key. Each x->y entry in - * this mapping indicates that the key mapping contains all entries on [x,y). - * Note, max string is represented by "", so ""->"" indicates that the parent - * is unnecessary (@see rm_keys). When looking up a key not contained in the - * the complete set, we have to check the parent if we don't find it in the - * key set. During rm_keys, we copy keys from the parent and update the - * complete set to reflect the change @see rm_keys. - */ -class DBObjectMap : public ObjectMap { -public: - boost::scoped_ptr db; - - /** - * Serializes access to next_seq as well as the in_use set - */ - Mutex header_lock; - Cond header_cond; - Cond map_header_cond; - - /** - * Set of headers currently in use - */ - set in_use; - set map_header_in_use; - - /** - * Takes the map_header_in_use entry in constructor, releases in - * destructor - */ - class MapHeaderLock { - DBObjectMap *db; - boost::optional locked; - - MapHeaderLock(const MapHeaderLock &); - MapHeaderLock &operator=(const MapHeaderLock &); - public: - explicit MapHeaderLock(DBObjectMap *db) : db(db) {} - MapHeaderLock(DBObjectMap *db, const ghobject_t &oid) : db(db), locked(oid) { - Mutex::Locker l(db->header_lock); - while (db->map_header_in_use.count(*locked)) - db->map_header_cond.Wait(db->header_lock); - db->map_header_in_use.insert(*locked); - } - - const ghobject_t &get_locked() const { - assert(locked); - return *locked; - } - - void swap(MapHeaderLock &o) { - assert(db == o.db); - - // centos6's boost optional doesn't seem to have swap :( - boost::optional _locked = o.locked; - o.locked = locked; - locked = _locked; - } - - ~MapHeaderLock() { - if (locked) { - Mutex::Locker l(db->header_lock); - assert(db->map_header_in_use.count(*locked)); - db->map_header_cond.Signal(); - db->map_header_in_use.erase(*locked); - } - } - }; - - DBObjectMap(CephContext* cct, KeyValueDB *db) - : ObjectMap(cct), db(db), header_lock("DBOBjectMap"), - cache_lock("DBObjectMap::CacheLock"), - caches(cct->_conf->filestore_omap_header_cache_size) - {} - - int set_keys( - const ghobject_t &oid, - const map &set, - const SequencerPosition *spos=0 - ) override; - - int set_header( - const ghobject_t &oid, - const bufferlist &bl, - const SequencerPosition *spos=0 - ) override; - - int get_header( - const ghobject_t &oid, - bufferlist *bl - ) override; - - int clear( - const ghobject_t &oid, - const SequencerPosition *spos=0 - ) override; - - int clear_keys_header( - const ghobject_t &oid, - const SequencerPosition *spos=0 - ) override; - - int rm_keys( - const ghobject_t &oid, - const set &to_clear, - const SequencerPosition *spos=0 - ) override; - - int get( - const ghobject_t &oid, - bufferlist *header, - map *out - ) override; - - int get_keys( - const ghobject_t &oid, - set *keys - ) override; - - int get_values( - const ghobject_t &oid, - const set &keys, - map *out - ) override; - - int check_keys( - const ghobject_t &oid, - const set &keys, - set *out - ) override; - - int get_xattrs( - const ghobject_t &oid, - const set &to_get, - map *out - ) override; - - int get_all_xattrs( - const ghobject_t &oid, - set *out - ) override; - - int set_xattrs( - const ghobject_t &oid, - const map &to_set, - const SequencerPosition *spos=0 - ) override; - - int remove_xattrs( - const ghobject_t &oid, - const set &to_remove, - const SequencerPosition *spos=0 - ) override; - - int clone( - const ghobject_t &oid, - const ghobject_t &target, - const SequencerPosition *spos=0 - ) override; - - int rename( - const ghobject_t &from, - const ghobject_t &to, - const SequencerPosition *spos=0 - ); - - int legacy_clone( - const ghobject_t &oid, - const ghobject_t &target, - const SequencerPosition *spos=0 - ); - - /// Read initial state from backing store - int get_state(); - /// Write current state settings to DB - void set_state(); - /// Read initial state and upgrade or initialize state - int init(bool upgrade = false); - - /// Upgrade store to current version - int upgrade_to_v2(); - - /// Consistency check, debug, there must be no parallel writes - int check(std::ostream &out, bool repair = false, bool force = false) override; - - /// Ensure that all previous operations are durable - int sync(const ghobject_t *oid=0, const SequencerPosition *spos=0) override; - - void compact() override { - assert(db); - db->compact(); - } - - /// Util, get all objects, there must be no other concurrent access - int list_objects(vector *objs ///< [out] objects - ); - - struct _Header; - // Util, get all object headers, there must be no other concurrent access - int list_object_headers(vector<_Header> *out ///< [out] headers - ); - - ObjectMapIterator get_iterator(const ghobject_t &oid) override; - - static const string USER_PREFIX; - static const string XATTR_PREFIX; - static const string SYS_PREFIX; - static const string COMPLETE_PREFIX; - static const string HEADER_KEY; - static const string USER_HEADER_KEY; - static const string GLOBAL_STATE_KEY; - static const string HOBJECT_TO_SEQ; - - /// Legacy - static const string LEAF_PREFIX; - static const string REVERSE_LEAF_PREFIX; - - /// persistent state for store @see generate_header - struct State { - static const __u8 CUR_VERSION = 3; - __u8 v; - uint64_t seq; - // legacy is false when complete regions never used - bool legacy; - State() : v(0), seq(1), legacy(false) {} - explicit State(uint64_t seq) : v(0), seq(seq), legacy(false) {} - - void encode(bufferlist &bl) const { - ENCODE_START(3, 1, bl); - ::encode(v, bl); - ::encode(seq, bl); - ::encode(legacy, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::iterator &bl) { - DECODE_START(3, bl); - if (struct_v >= 2) - ::decode(v, bl); - else - v = 0; - ::decode(seq, bl); - if (struct_v >= 3) - ::decode(legacy, bl); - else - legacy = false; - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const { - f->dump_unsigned("v", v); - f->dump_unsigned("seq", seq); - f->dump_bool("legacy", legacy); - } - - static void generate_test_instances(list &o) { - o.push_back(new State(0)); - o.push_back(new State(20)); - } - } state; - - struct _Header { - uint64_t seq; - uint64_t parent; - uint64_t num_children; - - ghobject_t oid; - - SequencerPosition spos; - - void encode(bufferlist &bl) const { - coll_t unused; - ENCODE_START(2, 1, bl); - ::encode(seq, bl); - ::encode(parent, bl); - ::encode(num_children, bl); - ::encode(unused, bl); - ::encode(oid, bl); - ::encode(spos, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::iterator &bl) { - coll_t unused; - DECODE_START(2, bl); - ::decode(seq, bl); - ::decode(parent, bl); - ::decode(num_children, bl); - ::decode(unused, bl); - ::decode(oid, bl); - if (struct_v >= 2) - ::decode(spos, bl); - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const { - f->dump_unsigned("seq", seq); - f->dump_unsigned("parent", parent); - f->dump_unsigned("num_children", num_children); - f->dump_stream("oid") << oid; - } - - static void generate_test_instances(list<_Header*> &o) { - o.push_back(new _Header); - o.push_back(new _Header); - o.back()->parent = 20; - o.back()->seq = 30; - } - - _Header() : seq(0), parent(0), num_children(1) {} - }; - - /// String munging (public for testing) - static string ghobject_key(const ghobject_t &oid); - static string ghobject_key_v0(coll_t c, const ghobject_t &oid); - static int is_buggy_ghobject_key_v1(CephContext* cct, - const string &in); -private: - /// Implicit lock on Header->seq - typedef ceph::shared_ptr<_Header> Header; - Mutex cache_lock; - SimpleLRU caches; - - string map_header_key(const ghobject_t &oid); - string header_key(uint64_t seq); - string complete_prefix(Header header); - string user_prefix(Header header); - string sys_prefix(Header header); - string xattr_prefix(Header header); - string sys_parent_prefix(_Header header); - string sys_parent_prefix(Header header) { - return sys_parent_prefix(*header); - } - - class EmptyIteratorImpl : public ObjectMapIteratorImpl { - public: - int seek_to_first() override { return 0; } - int seek_to_last() { return 0; } - int upper_bound(const string &after) override { return 0; } - int lower_bound(const string &to) override { return 0; } - bool valid() override { return false; } - int next(bool validate=true) override { ceph_abort(); return 0; } - string key() override { ceph_abort(); return ""; } - bufferlist value() override { ceph_abort(); return bufferlist(); } - int status() override { return 0; } - }; - - - /// Iterator - class DBObjectMapIteratorImpl : public ObjectMapIteratorImpl { - public: - DBObjectMap *map; - - /// NOTE: implicit lock hlock->get_locked() when returned out of the class - MapHeaderLock hlock; - /// NOTE: implicit lock on header->seq AND for all ancestors - Header header; - - /// parent_iter == NULL iff no parent - ceph::shared_ptr parent_iter; - KeyValueDB::Iterator key_iter; - KeyValueDB::Iterator complete_iter; - - /// cur_iter points to currently valid iterator - ceph::shared_ptr cur_iter; - int r; - - /// init() called, key_iter, complete_iter, parent_iter filled in - bool ready; - /// past end - bool invalid; - - DBObjectMapIteratorImpl(DBObjectMap *map, Header header) : - map(map), hlock(map), header(header), r(0), ready(false), invalid(true) {} - int seek_to_first() override; - int seek_to_last(); - int upper_bound(const string &after) override; - int lower_bound(const string &to) override; - bool valid() override; - int next(bool validate=true) override; - string key() override; - bufferlist value() override; - int status() override; - - bool on_parent() { - return cur_iter == parent_iter; - } - - /// skips to next valid parent entry - int next_parent(); - - /// first parent() >= to - int lower_bound_parent(const string &to); - - /** - * Tests whether to_test is in complete region - * - * postcondition: complete_iter will be max s.t. complete_iter->value > to_test - */ - int in_complete_region(const string &to_test, ///< [in] key to test - string *begin, ///< [out] beginning of region - string *end ///< [out] end of region - ); ///< @returns true if to_test is in the complete region, else false - - private: - int init(); - bool valid_parent(); - int adjust(); - }; - - typedef ceph::shared_ptr DBObjectMapIterator; - DBObjectMapIterator _get_iterator(Header header) { - return std::make_shared(this, header); - } - - /// sys - - /// Removes node corresponding to header - void clear_header(Header header, KeyValueDB::Transaction t); - - /// Set node containing input to new contents - void set_header(Header input, KeyValueDB::Transaction t); - - /// Remove leaf node corresponding to oid in c - void remove_map_header( - const MapHeaderLock &l, - const ghobject_t &oid, - Header header, - KeyValueDB::Transaction t); - - /// Set leaf node for c and oid to the value of header - void set_map_header( - const MapHeaderLock &l, - const ghobject_t &oid, _Header header, - KeyValueDB::Transaction t); - - /// Set leaf node for c and oid to the value of header - bool check_spos(const ghobject_t &oid, - Header header, - const SequencerPosition *spos); - - /// Lookup or create header for c oid - Header lookup_create_map_header( - const MapHeaderLock &l, - const ghobject_t &oid, - KeyValueDB::Transaction t); - - /** - * Generate new header for c oid with new seq number - * - * Has the side effect of syncronously saving the new DBObjectMap state - */ - Header _generate_new_header(const ghobject_t &oid, Header parent); - Header generate_new_header(const ghobject_t &oid, Header parent) { - Mutex::Locker l(header_lock); - return _generate_new_header(oid, parent); - } - - /// Lookup leaf header for c oid - Header _lookup_map_header( - const MapHeaderLock &l, - const ghobject_t &oid); - Header lookup_map_header( - const MapHeaderLock &l2, - const ghobject_t &oid) { - Mutex::Locker l(header_lock); - return _lookup_map_header(l2, oid); - } - - /// Lookup header node for input - Header lookup_parent(Header input); - - - /// Helpers - int _get_header(Header header, bufferlist *bl); - - /// Scan keys in header into out_keys and out_values (if nonnull) - int scan(Header header, - const set &in_keys, - set *out_keys, - map *out_values); - - /// Remove header and all related prefixes - int _clear(Header header, - KeyValueDB::Transaction t); - - /* Scan complete region bumping *begin to the beginning of any - * containing region and adding all complete region keys between - * the updated begin and end to the complete_keys_to_remove set */ - int merge_new_complete(DBObjectMapIterator &iter, - string *begin, - const string &end, - set *complete_keys_to_remove); - - /// Writes out State (mainly next_seq) - int write_state(KeyValueDB::Transaction _t = - KeyValueDB::Transaction()); - - /// Copies header entry from parent @see rm_keys - int copy_up_header(Header header, - KeyValueDB::Transaction t); - - /// Sets header @see set_header - void _set_header(Header header, const bufferlist &bl, - KeyValueDB::Transaction t); - - /** - * Removes header seq lock and possibly object lock - * once Header is out of scope - * @see lookup_parent - * @see generate_new_header - */ - class RemoveOnDelete { - public: - DBObjectMap *db; - explicit RemoveOnDelete(DBObjectMap *db) : - db(db) {} - void operator() (_Header *header) { - Mutex::Locker l(db->header_lock); - assert(db->in_use.count(header->seq)); - db->in_use.erase(header->seq); - db->header_cond.Signal(); - delete header; - } - }; - friend class RemoveOnDelete; -}; -WRITE_CLASS_ENCODER(DBObjectMap::_Header) -WRITE_CLASS_ENCODER(DBObjectMap::State) - -ostream& operator<<(ostream& out, const DBObjectMap::_Header& h); - -#endif