mirror of
https://github.com/ceph/ceph
synced 2024-12-24 12:24:19 +00:00
20204b642a
ECBackend is going to need a transaction representation which reduces the operational representation from the OSDOp to a descriptive one which makes questions like "what is the largest offest written" and "does this transaction delete the object?" simple to answer. At the same time, we're going to eliminate the PGBackend::PGTransaction interface since I don't think writing directly to an ObjectStore::Transaction is buying us enough to offset the irritation of having to update both implemenations. A happy consequence of this design will be that we can fill in the pg_log_entry_t::mod_desc member after submission in the backend rather than inline in do_osd_ops. We can also dispense with having to maintain OpContext::pending_attrs separately from the ongoing PGTransaction. Signed-off-by: Samuel Just <sjust@redhat.com>
130 lines
3.2 KiB
C++
130 lines
3.2 KiB
C++
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
|
// vim: ts=8 sw=2 smarttab
|
|
/*
|
|
* Ceph - scalable distributed file system
|
|
*
|
|
* Copyright (C) 2016 Red Hat
|
|
*
|
|
* This is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software
|
|
* Foundation. See file COPYING.
|
|
*
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "osd/PGTransaction.h"
|
|
|
|
TEST(pgtransaction, simple)
|
|
{
|
|
hobject_t h;
|
|
PGTransaction t;
|
|
ASSERT_TRUE(t.empty());
|
|
t.nop(h);
|
|
ASSERT_FALSE(t.empty());
|
|
unsigned num = 0;
|
|
t.safe_create_traverse(
|
|
[&](const pair<const hobject_t, PGTransaction::ObjectOperation> &p) {
|
|
ASSERT_EQ(p.first, h);
|
|
using T = PGTransaction::ObjectOperation::Init;
|
|
ASSERT_TRUE(boost::get<T::None>(&p.second.init_type));
|
|
++num;
|
|
});
|
|
ASSERT_EQ(num, 1u);
|
|
}
|
|
|
|
TEST(pgtransaction, clone_safe_create_traverse)
|
|
{
|
|
hobject_t h, h2;
|
|
h2.snap = 1;
|
|
PGTransaction t;
|
|
ASSERT_TRUE(t.empty());
|
|
t.nop(h2);
|
|
ASSERT_FALSE(t.empty());
|
|
t.clone(h, h2);
|
|
unsigned num = 0;
|
|
t.safe_create_traverse(
|
|
[&](const pair<const hobject_t, PGTransaction::ObjectOperation> &p) {
|
|
using T = PGTransaction::ObjectOperation::Init;
|
|
if (num == 0) {
|
|
ASSERT_EQ(p.first, h);
|
|
ASSERT_TRUE(boost::get<T::Clone>(&p.second.init_type));
|
|
ASSERT_EQ(
|
|
boost::get<T::Clone>(&p.second.init_type)->source,
|
|
h2);
|
|
} else if (num == 1) {
|
|
ASSERT_EQ(p.first, h2);
|
|
ASSERT_TRUE(boost::get<T::None>(&p.second.init_type));
|
|
} else {
|
|
ASSERT_LT(num, 2u);
|
|
}
|
|
++num;
|
|
});
|
|
}
|
|
|
|
TEST(pgtransaction, clone_safe_create_traverse2)
|
|
{
|
|
hobject_t h, h2, h3;
|
|
h.snap = 10;
|
|
h2.snap = 5;
|
|
h3.snap = 3;
|
|
PGTransaction t;
|
|
ASSERT_TRUE(t.empty());
|
|
t.nop(h3);
|
|
ASSERT_FALSE(t.empty());
|
|
t.clone(h, h2);
|
|
t.remove(h2);
|
|
t.clone(h2, h3);
|
|
unsigned num = 0;
|
|
t.safe_create_traverse(
|
|
[&](const pair<const hobject_t, PGTransaction::ObjectOperation> &p) {
|
|
using T = PGTransaction::ObjectOperation::Init;
|
|
if (num == 0) {
|
|
ASSERT_EQ(p.first, h);
|
|
ASSERT_TRUE(boost::get<T::Clone>(&p.second.init_type));
|
|
ASSERT_EQ(
|
|
boost::get<T::Clone>(&p.second.init_type)->source,
|
|
h2);
|
|
} else if (num == 1) {
|
|
ASSERT_EQ(p.first, h2);
|
|
ASSERT_TRUE(boost::get<T::Clone>(&p.second.init_type));
|
|
ASSERT_EQ(
|
|
boost::get<T::Clone>(&p.second.init_type)->source,
|
|
h3);
|
|
} else if (num == 2) {
|
|
ASSERT_EQ(p.first, h3);
|
|
ASSERT_TRUE(boost::get<T::None>(&p.second.init_type));
|
|
} else {
|
|
ASSERT_LT(num, 3u);
|
|
}
|
|
++num;
|
|
});
|
|
}
|
|
|
|
TEST(pgtransaction, clone_safe_create_traverse3)
|
|
{
|
|
hobject_t h, h2, h3;
|
|
h.snap = 10;
|
|
h2.snap = 5;
|
|
h3.snap = 3;
|
|
PGTransaction t;
|
|
t.remove(h);
|
|
t.remove(h2);
|
|
t.clone(h2, h3);
|
|
unsigned num = 0;
|
|
t.safe_create_traverse(
|
|
[&](const pair<const hobject_t, PGTransaction::ObjectOperation> &p) {
|
|
using T = PGTransaction::ObjectOperation::Init;
|
|
if (p.first == h) {
|
|
ASSERT_TRUE(p.second.is_delete());
|
|
} else if (p.first == h2) {
|
|
ASSERT_TRUE(boost::get<T::Clone>(&p.second.init_type));
|
|
ASSERT_EQ(
|
|
boost::get<T::Clone>(&p.second.init_type)->source,
|
|
h3);
|
|
}
|
|
ASSERT_LT(num, 2u);
|
|
++num;
|
|
});
|
|
}
|