int IoCtx::exec(const std::string& oid, const char *cls, const char *method,
bufferlist& inbl, bufferlist& outbl) {
TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
- return ctx->exec(oid, *get_class_handler(), cls, method, inbl, &outbl);
+ return ctx->exec(oid, *get_class_handler(), cls, method, inbl, &outbl,
+ ctx->get_snap_context());
}
void IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io) {
int IoCtx::write(const std::string& oid, bufferlist& bl, size_t len,
uint64_t off) {
TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
- return ctx->write(oid, bl, len, off);
+ return ctx->write(oid, bl, len, off, ctx->get_snap_context());
}
int IoCtx::write_full(const std::string& oid, bufferlist& bl) {
TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
- return ctx->write_full(oid, bl);
+ return ctx->write_full(oid, bl, ctx->get_snap_context());
}
static int save_operation_result(int result, int *pval) {
TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
o->ops.push_back(boost::bind(&TestIoCtxImpl::exec, _1, _2,
boost::ref(*get_class_handler()),
- cls, method, inbl, _3));
+ cls, method, inbl, _3, _4));
}
void ObjectOperation::set_op_flags2(int flags) {
out_snaps);
if (prval != NULL) {
op = boost::bind(save_operation_result,
- boost::bind(op, _1, _2, _3), prval);
+ boost::bind(op, _1, _2, _3, _4), prval);
}
o->ops.push_back(op);
}
if (prval != NULL) {
op = boost::bind(save_operation_result,
- boost::bind(op, _1, _2, _3), prval);
+ boost::bind(op, _1, _2, _3, _4), prval);
}
o->ops.push_back(op);
}
if (prval != NULL) {
op = boost::bind(save_operation_result,
- boost::bind(op, _1, _2, _3), prval);
+ boost::bind(op, _1, _2, _3, _4), prval);
}
o->ops.push_back(op);
}
void ObjectWriteOperation::write(uint64_t off, const bufferlist& bl) {
TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
o->ops.push_back(boost::bind(&TestIoCtxImpl::write, _1, _2, bl, bl.length(),
- off));
+ off, _4));
}
void ObjectWriteOperation::write_full(const bufferlist& bl) {
TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
- o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl));
+ o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl, _4));
}
void ObjectWriteOperation::zero(uint64_t off, uint64_t len) {
bufferlist *inbl) {
librados::TestClassHandler::MethodContext *ctx =
reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
- return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs);
+ return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc);
}
int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) {
librados::TestClassHandler::MethodContext *ctx =
reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
- return ctx->io_ctx_impl->write_full(ctx->oid, *inbl);
+ return ctx->io_ctx_impl->write_full(ctx->oid, *inbl, ctx->snapc);
}
int cls_log(int level, const char *format, ...) {
}
TestClassHandler::SharedMethodContext TestClassHandler::get_method_context(
- TestIoCtxImpl *io_ctx_impl, const std::string &oid) {
+ TestIoCtxImpl *io_ctx_impl, const std::string &oid,
+ const SnapContext &snapc) {
SharedMethodContext ctx(new MethodContext());
ctx->io_ctx_impl = io_ctx_impl;
ctx->oid = oid;
+ ctx->snapc = snapc;
return ctx;
}
#define CEPH_TEST_CLASS_HANDLER_H
#include "objclass/objclass.h"
+#include "common/snap_types.h"
#include <boost/shared_ptr.hpp>
#include <list>
#include <map>
struct MethodContext {
TestIoCtxImpl *io_ctx_impl;
std::string oid;
+ SnapContext snapc;
};
typedef boost::shared_ptr<MethodContext> SharedMethodContext;
cls_method_cxx_call_t get_method(const std::string &cls,
const std::string &method);
SharedMethodContext get_method_context(TestIoCtxImpl *io_ctx_impl,
- const std::string &oid);
+ const std::string &oid,
+ const SnapContext &snapc);
private:
int TestIoCtxImpl::aio_operate(const std::string& oid, TestObjectOperationImpl &ops,
AioCompletionImpl *c, SnapContext *snap_context,
int flags) {
- // TODO ignoring snap_context and flags for now
+ // TODO flags for now
ops.get();
m_client->add_aio_operation(oid, true, boost::bind(
&TestIoCtxImpl::execute_aio_operations, this, oid, &ops,
- reinterpret_cast<bufferlist*>(NULL)), c);
+ reinterpret_cast<bufferlist*>(NULL),
+ snap_context != NULL ? *snap_context : m_snapc), c);
return 0;
}
// TODO ignoring flags for now
ops.get();
m_client->add_aio_operation(oid, true, boost::bind(
- &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl), c);
+ &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl, m_snapc), c);
return 0;
}
int TestIoCtxImpl::exec(const std::string& oid, TestClassHandler &handler,
const char *cls, const char *method,
- bufferlist& inbl, bufferlist* outbl) {
+ bufferlist& inbl, bufferlist* outbl,
+ const SnapContext &snapc) {
cls_method_cxx_call_t call = handler.get_method(cls, method);
if (call == NULL) {
return -ENOSYS;
}
return (*call)(reinterpret_cast<cls_method_context_t>(
- handler.get_method_context(this, oid).get()), &inbl, outbl);
+ handler.get_method_context(this, oid, snapc).get()), &inbl, outbl);
}
int TestIoCtxImpl::list_watchers(const std::string& o,
ops.get();
m_client->add_aio_operation(oid, false, boost::bind(
&TestIoCtxImpl::execute_aio_operations, this, oid, &ops,
- reinterpret_cast<bufferlist*>(NULL)), comp);
+ reinterpret_cast<bufferlist*>(NULL), m_snapc), comp);
comp->wait_for_safe();
int ret = comp->get_return_value();
ops.get();
m_client->add_aio_operation(oid, false, boost::bind(
- &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl), comp);
+ &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl,
+ m_snapc), comp);
comp->wait_for_complete();
int ret = comp->get_return_value();
bufferlist out;
::encode(tmap_header, out);
::encode(tmap, out);
- r = write_full(oid, out);
+ r = write_full(oid, out, m_snapc);
return r;
}
int TestIoCtxImpl::execute_aio_operations(const std::string& oid,
TestObjectOperationImpl *ops,
- bufferlist *pbl) {
+ bufferlist *pbl,
+ const SnapContext &snapc) {
int ret = 0;
- for (ObjectOperations::iterator it = ops->ops.begin(); it != ops->ops.end(); ++it) {
- ret = (*it)(this, oid, pbl);
+ for (ObjectOperations::iterator it = ops->ops.begin();
+ it != ops->ops.end(); ++it) {
+ ret = (*it)(this, oid, pbl, snapc);
if (ret < 0) {
break;
}
typedef boost::function<int(TestIoCtxImpl*,
const std::string&,
- bufferlist *)> ObjectOperationTestImpl;
+ bufferlist *,
+ const SnapContext &)> ObjectOperationTestImpl;
typedef std::list<ObjectOperationTestImpl> ObjectOperations;
struct TestObjectOperationImpl {
virtual int create(const std::string& oid, bool exclusive) = 0;
virtual int exec(const std::string& oid, TestClassHandler &handler,
const char *cls, const char *method,
- bufferlist& inbl, bufferlist* outbl);
+ bufferlist& inbl, bufferlist* outbl,
+ const SnapContext &snapc);
virtual int list_snaps(const std::string& o, snap_set_t *out_snaps) = 0;
virtual int list_watchers(const std::string& o,
std::list<obj_watch_t> *out_watchers);
virtual int watch(const std::string& o, uint64_t *handle,
librados::WatchCtx *ctx, librados::WatchCtx2 *ctx2);
virtual int write(const std::string& oid, bufferlist& bl, size_t len,
- uint64_t off) = 0;
- virtual int write_full(const std::string& oid, bufferlist& bl) = 0;
+ uint64_t off, const SnapContext &snapc) = 0;
+ virtual int write_full(const std::string& oid, bufferlist& bl,
+ const SnapContext &snapc) = 0;
virtual int xattr_get(const std::string& oid,
std::map<std::string, bufferlist>* attrset) = 0;
virtual int xattr_set(const std::string& oid, const std::string &name,
TestIoCtxImpl(const TestIoCtxImpl& rhs);
virtual ~TestIoCtxImpl();
- int execute_aio_operations(const std::string& oid, TestObjectOperationImpl *ops,
- bufferlist *pbl);
+ int execute_aio_operations(const std::string& oid,
+ TestObjectOperationImpl *ops,
+ bufferlist *pbl, const SnapContext &snapc);
private:
int TestMemIoCtxImpl::assert_exists(const std::string &oid) {
RWLock::RLocker l(m_pool->file_lock);
- TestMemRadosClient::SharedFile file = get_file(oid, false);
+ TestMemRadosClient::SharedFile file = get_file(oid, false,
+ get_snap_context());
if (file == NULL) {
return -ENOENT;
}
}
RWLock::WLocker l(m_pool->file_lock);
- get_file(oid, true);
+ get_file(oid, true, get_snap_context());
return 0;
}
TestMemRadosClient::SharedFile file;
{
RWLock::RLocker l(m_pool->file_lock);
- file = get_file(oid, false);
+ file = get_file(oid, false, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, true);
+ file = get_file(oid, true, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, true);
+ file = get_file(oid, true, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::RLocker l(m_pool->file_lock);
- file = get_file(oid, false);
+ file = get_file(oid, false, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
}
RWLock::WLocker l(m_pool->file_lock);
- TestMemRadosClient::SharedFile file = get_file(oid, false);
+ TestMemRadosClient::SharedFile file = get_file(oid, false,
+ get_snap_context());
if (file == NULL) {
return -ENOENT;
}
- file = get_file(oid, true);
+ file = get_file(oid, true, get_snap_context());
RWLock::WLocker l2(file->lock);
file->exists = false;
TestMemRadosClient::SharedFile file;
{
RWLock::RLocker l(m_pool->file_lock);
- file = get_file(oid, false);
+ file = get_file(oid, false, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::RLocker l(m_pool->file_lock);
- file = get_file(oid, false);
+ file = get_file(oid, false, get_snap_context());
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, true);
+ file = get_file(oid, true, get_snap_context());
}
RWLock::WLocker l(file->lock);
}
int TestMemIoCtxImpl::write(const std::string& oid, bufferlist& bl, size_t len,
- uint64_t off) {
+ uint64_t off, const SnapContext &snapc) {
if (get_snap_read() != CEPH_NOSNAP) {
return -EROFS;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, true);
+ file = get_file(oid, true, snapc);
}
RWLock::WLocker l(file->lock);
return 0;
}
-int TestMemIoCtxImpl::write_full(const std::string& oid, bufferlist& bl) {
+int TestMemIoCtxImpl::write_full(const std::string& oid, bufferlist& bl,
+ const SnapContext &snapc) {
if (get_snap_read() != CEPH_NOSNAP) {
return -EROFS;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, true);
+ file = get_file(oid, true, snapc);
if (file == NULL) {
return -ENOENT;
}
TestMemRadosClient::SharedFile file;
{
RWLock::WLocker l(m_pool->file_lock);
- file = get_file(oid, false);
+ file = get_file(oid, false, get_snap_context());
if (!file) {
return 0;
}
- file = get_file(oid, true);
+ file = get_file(oid, true, get_snap_context());
RWLock::RLocker l2(file->lock);
if (len > 0 && off + len >= file->data.length()) {
bufferlist bl;
bl.append_zero(len);
- return write(oid, bl, len, off);
+ return write(oid, bl, len, off, get_snap_context());
}
void TestMemIoCtxImpl::append_clone(bufferlist& src, bufferlist* dest) {
}
TestMemRadosClient::SharedFile TestMemIoCtxImpl::get_file(
- const std::string &oid, bool write) {
+ const std::string &oid, bool write, const SnapContext &snapc) {
assert(m_pool->file_lock.is_locked() || m_pool->file_lock.is_wlocked());
assert(!write || m_pool->file_lock.is_wlocked());
}
if (write) {
- const SnapContext &snapc = get_snap_context();
bool new_version = false;
if (!file || !file->exists) {
file = TestMemRadosClient::SharedFile(new TestMemRadosClient::File());
}
}
- uint64_t prev_size = file->data.length();
+ bufferlist prev_data = file->data;
file = TestMemRadosClient::SharedFile(
new TestMemRadosClient::File(*file));
- if (prev_size > 0) {
- file->snap_overlap.insert(0, prev_size);
+ file->data.clear();
+ append_clone(prev_data, &file->data);
+ if (prev_data.length() > 0) {
+ file->snap_overlap.insert(0, prev_data.length());
}
new_version = true;
}
virtual int stat(const std::string& oid, uint64_t *psize, time_t *pmtime);
virtual int truncate(const std::string& oid, uint64_t size);
virtual int write(const std::string& oid, bufferlist& bl, size_t len,
- uint64_t off);
- virtual int write_full(const std::string& oid, bufferlist& bl);
+ uint64_t off, const SnapContext &snapc);
+ virtual int write_full(const std::string& oid, bufferlist& bl,
+ const SnapContext &snapc);
virtual int xattr_get(const std::string& oid,
std::map<std::string, bufferlist>* attrset);
virtual int xattr_set(const std::string& oid, const std::string &name,
size_t clip_io(size_t off, size_t len, size_t bl_len);
void ensure_minimum_length(size_t len, bufferlist *bl);
- TestMemRadosClient::SharedFile get_file(const std::string &oid, bool write);
+ TestMemRadosClient::SharedFile get_file(const std::string &oid, bool write,
+ const SnapContext &snapc);
};