old_header->cid = cid;
old_header->oid = target;
set_header(cid, target, *old_header, t);
-
- // "in_use" still hold the "seq"
}
int GenericObjectMap::init(bool do_upgrade)
to_get.insert(header_key(cid, oid));
_Header header;
- while (1) {
- map<string, bufferlist> out;
- bool try_again = false;
-
- int r = db->get(GHOBJECT_TO_SEQ_PREFIX, to_get, &out);
- if (r < 0)
- return Header();
- if (out.empty())
- return Header();
-
- bufferlist::iterator iter = out.begin()->second.begin();
- header.decode(iter);
-
- while (in_use.count(header.seq)) {
- header_cond.Wait(header_lock);
+ map<string, bufferlist> out;
- // Another thread is hold this header, wait for it.
- // Because the seq of this object may change, such as clone
- // and rename operation, here need to look up "seq" again
- try_again = true;
- }
+ int r = db->get(GHOBJECT_TO_SEQ_PREFIX, to_get, &out);
+ if (r < 0)
+ return Header();
+ if (out.empty())
+ return Header();
- if (!try_again) {
- break;
- }
- }
+ bufferlist::iterator iter = out.begin()->second.begin();
+ header.decode(iter);
- Header ret = Header(new _Header(header), RemoveOnDelete(this));
- in_use.insert(ret->seq);
+ Header ret = Header(new _Header(header));
return ret;
}
const coll_t &cid, const ghobject_t &oid, Header parent,
KeyValueDB::Transaction t)
{
- Header header = Header(new _Header(), RemoveOnDelete(this));
+ Header header = Header(new _Header());
header->seq = state.seq++;
if (parent) {
header->parent = parent->seq;
header->num_children = 1;
header->oid = oid;
header->cid = cid;
- assert(!in_use.count(header->seq));
- in_use.insert(header->seq);
write_state(t);
return header;
GenericObjectMap::Header GenericObjectMap::lookup_parent(Header input)
{
Mutex::Locker l(header_lock);
- while (in_use.count(input->parent))
- header_cond.Wait(header_lock);
map<string, bufferlist> out;
set<string> keys;
keys.insert(PARENT_KEY);
return Header();
}
- Header header = Header(new _Header(), RemoveOnDelete(this));
+ Header header = Header(new _Header());
header->seq = input->parent;
bufferlist::iterator iter = out.begin()->second.begin();
header->decode(iter);
dout(20) << "lookup_parent: parent seq is " << header->seq << " with parent "
<< header->parent << dendl;
- in_use.insert(header->seq);
return header;
}
* Serializes access to next_seq as well as the in_use set
*/
Mutex header_lock;
- Cond header_cond;
-
- /**
- * Set of headers currently in use
- */
- set<uint64_t> in_use;
GenericObjectMap(KeyValueDB *db) : db(db), header_lock("GenericObjectMap") {}
// Sets header @see set_header
void _set_header(Header header, const bufferlist &bl,
KeyValueDB::Transaction t);
-
- /**
- * Removes header seq lock once Header is out of scope
- * @see _lookup_header
- * @see lookup_parent
- * @see generate_new_header
- */
- class RemoveOnDelete {
- public:
- GenericObjectMap *db;
- RemoveOnDelete(GenericObjectMap *db) :
- db(db) {}
- void operator() (_Header *header) {
- Mutex::Locker l(db->header_lock);
- db->in_use.erase(header->seq);
- db->header_cond.Signal();
- delete header;
- }
- };
- friend class RemoveOnDelete;
};
WRITE_CLASS_ENCODER(GenericObjectMap::_Header)
WRITE_CLASS_ENCODER(GenericObjectMap::State)