ceph/ceph — pull request #402 by dachary (2013-07-07 13:13:23+00:00)
Title: replace ObjectContext pointers with shared_ptr

The ObjectContext pointers are shared using a ref data member that
needs to be updated by the caller. This is tedious and error
prone. All pointers are replaced with shared_ptr for
automatic reference counting and the ref data member is removed.

The ReplicatedPG::object_contexts registry does not claim ownership of
the ObjectContext pointers it contains. It uses weak_ptr instead of
shared_ptr. If ReplicatedPG::object_contexts contains an expired()
ObjectContext weak_ptr, it is considered non existent.

The shared_ptr do not delete the ObjectContext or update the
ReplicatedPG::object_contexts at exactly the same point as
ReplicatedPG::put_object_context. It happens when the last object
holding a shared_ptr goes out of scopen, which is always later than
the call to ReplicatedPG::put_object_context.

The ObjectContext::get method is removed: its only purpose is to
increment the ref.

The ReplicatedPG::_lookup_object_context method is removed because it
is used once to retrieve an ObjectContext without incrementing ref, in
order to save a call to ReplicatedPG::put_object_context. Since the ref
data member is no longer used, the method is redundant.

The ReplicatedPG::put_object_context has three different purposes: a)
check mode.wake b) decrement the ref of the associated ObjectContext
given in argument c) if the ref drops to zero delete the object,
delete its entry in the ReplicatedPG::object_contexts registry and
call PG::kick. The decrementing part is no longer necessary because
shared_ptr takes care of it. The mode.wake check is moved to the
check_wake method. The cleanup that happens on deletion is moved to
the ObjectContext destructor, using a Context object as a callback to
invoque the ReplicatedPG::object_context_destructor_callback method.

struct C_PG_ObjectContext : public Context is a callback added to the
ObjecContext and called by the destructor. It is set by the
ReplicatedPG::register_object_context method which is called
immediately after new ObjectContext.

ReplicatedPG::put_object_contexts calls put_object_context on a list
of ObjectContexts and clears the list. It is replaced by a call to
list::clear. It also ( indirectly ) checks mode.wake because
put_object_context does. However, it is always called before or a
after a call to ReplicatedPG::put_object_context ( no s at the end )
which is replaced with check_wake, therefore the expected side effect
happens anyway.

ReplicatedPG::context_registry_on_change is a call to the
Watch::discard method of all the watchers found in
ReplicatedPG::object_contexts. It also calls
ReplicatedPG::put_object_contexts on all of them and it is replaced
with a single call to check_wake()

ReplicatedPG::_finish_mark_all_unfound_lost explicitely calls
ReplicatedPG::put_object_contexts in a loop to clear the list. It is
taken care of by shared_ptr and the list can be cleared without
iterating over all its elements. A single call to check_wake is added.

Watch::get_obc is inlined and does not rely on the ObjectContext::get
method.

http://tracker.ceph.com/issues/5510 refs #5510

Signed-off-by: Loic Dachary