diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h index c4384e34057..a93f53be414 100644 --- a/src/osd/ReplicatedPG.h +++ b/src/osd/ReplicatedPG.h @@ -93,6 +93,7 @@ public: * state associated with a copy operation */ struct OpContext; + class CopyCallback; struct CopyOp { OpContext *ctx; @@ -126,6 +127,62 @@ public: }; typedef boost::shared_ptr CopyOpRef; + /** + * The CopyCallback class defines an interface for completions to the + * copy_start code. Users of the copy infrastructure must implement + * one and give an instance of the class to start_copy. + * In particular, + * 1) Once the copy code has placed data in the temp object, it calls + * the data_in_temp_obj() function. + * 2) if everything has succeeded, it may call copy_complete_ops() and + * pass in a Transaction which contains the ops that must be executed + * in order to complete the copy. The implementer must make sure these ops + * are executed if they are provide (at present, they are). + * 3) If everything has succeeded, it will call data_size() with the + * size of copied object + * 4) It will call finish(). + * + * The implementer is responsible for making sure that the CopyCallback + * can associate itself with the correct copy operation. The presence + * of copy_complete_ops ensures that write operations can be performed + * atomically with the copy being completed (which doing them in separate + * transactions would not allow); if you are doing the copy for a read + * op you will have to generate a separate op to finish the copy with. + */ + class CopyCallback : public Context { + protected: + bool data_in_temp; + uint64_t data_size; + int result_code; + + CopyCallback() : data_in_temp(false), data_size((uint64_t)-1), + result_code(0) {} + virtual void finish(int r) { result_code = r; } + public: + /// Give the CopyCallback ops to perform to complete the copy + virtual void copy_complete_ops(ObjectStore::Transaction& t) = 0; + /// Tell the CopyCallback that there is now data in the temp object + virtual void data_in_temp_obj() { data_in_temp = true; }; + bool is_temp_obj_used() { return data_in_temp; } + /// Provide the final size of the copied object to the CopyCallback + virtual void set_data_size(uint64_t size) { data_size = size; } + uint64_t get_data_size() { return data_size; } + int get_result() { return result_code; } + virtual ~CopyCallback() {}; + }; + + class CopyFromCallback: public CopyCallback { + protected: + virtual void finish(int r) {} + public: + OpContext *ctx; + hobject_t temp_obj; + CopyFromCallback(OpContext *ctx_, const hobject_t& temp_obj_) : + ctx(ctx_), temp_obj(temp_obj_) {} + void copy_complete_ops(ObjectStore::Transaction& t); + ~CopyFromCallback() {} + }; + boost::scoped_ptr pgbackend; /// Listener methods