mirror of
https://github.com/ceph/ceph
synced 2025-04-11 04:02:04 +00:00
257 lines
6.3 KiB
C++
257 lines
6.3 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) 2013 Inktank <info@inktank.com>
|
|
*
|
|
* 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 "HitSet.h"
|
|
#include "common/Formatter.h"
|
|
|
|
using std::ostream;
|
|
using std::list;
|
|
using ceph::Formatter;
|
|
|
|
// -- HitSet --
|
|
|
|
HitSet::HitSet(const HitSet::Params& params)
|
|
: sealed(false)
|
|
{
|
|
switch (params.get_type()) {
|
|
case TYPE_BLOOM:
|
|
{
|
|
BloomHitSet::Params *p =
|
|
static_cast<BloomHitSet::Params*>(params.impl.get());
|
|
impl.reset(new BloomHitSet(p));
|
|
}
|
|
break;
|
|
|
|
case TYPE_EXPLICIT_HASH:
|
|
impl.reset(new ExplicitHashHitSet(static_cast<ExplicitHashHitSet::Params*>(params.impl.get())));
|
|
break;
|
|
|
|
case TYPE_EXPLICIT_OBJECT:
|
|
impl.reset(new ExplicitObjectHitSet(static_cast<ExplicitObjectHitSet::Params*>(params.impl.get())));
|
|
break;
|
|
|
|
default:
|
|
assert (0 == "unknown HitSet type");
|
|
}
|
|
}
|
|
|
|
void HitSet::encode(ceph::buffer::list &bl) const
|
|
{
|
|
ENCODE_START(1, 1, bl);
|
|
encode(sealed, bl);
|
|
if (impl) {
|
|
encode((__u8)impl->get_type(), bl);
|
|
impl->encode(bl);
|
|
} else {
|
|
encode((__u8)TYPE_NONE, bl);
|
|
}
|
|
ENCODE_FINISH(bl);
|
|
}
|
|
|
|
void HitSet::decode(ceph::buffer::list::const_iterator& bl)
|
|
{
|
|
DECODE_START(1, bl);
|
|
decode(sealed, bl);
|
|
__u8 type;
|
|
decode(type, bl);
|
|
switch ((impl_type_t)type) {
|
|
case TYPE_EXPLICIT_HASH:
|
|
impl.reset(new ExplicitHashHitSet);
|
|
break;
|
|
case TYPE_EXPLICIT_OBJECT:
|
|
impl.reset(new ExplicitObjectHitSet);
|
|
break;
|
|
case TYPE_BLOOM:
|
|
impl.reset(new BloomHitSet);
|
|
break;
|
|
case TYPE_NONE:
|
|
impl.reset(NULL);
|
|
break;
|
|
default:
|
|
throw ceph::buffer::malformed_input("unrecognized HitMap type");
|
|
}
|
|
if (impl)
|
|
impl->decode(bl);
|
|
DECODE_FINISH(bl);
|
|
}
|
|
|
|
void HitSet::dump(Formatter *f) const
|
|
{
|
|
f->dump_string("type", get_type_name());
|
|
f->dump_string("sealed", sealed ? "yes" : "no");
|
|
if (impl)
|
|
impl->dump(f);
|
|
}
|
|
|
|
void HitSet::generate_test_instances(list<HitSet*>& o)
|
|
{
|
|
o.push_back(new HitSet);
|
|
o.push_back(new HitSet(new BloomHitSet(10, .1, 1)));
|
|
o.back()->insert(hobject_t());
|
|
o.back()->insert(hobject_t("asdf", "", CEPH_NOSNAP, 123, 1, ""));
|
|
o.back()->insert(hobject_t("qwer", "", CEPH_NOSNAP, 456, 1, ""));
|
|
o.push_back(new HitSet(new ExplicitHashHitSet));
|
|
o.back()->insert(hobject_t());
|
|
o.back()->insert(hobject_t("asdf", "", CEPH_NOSNAP, 123, 1, ""));
|
|
o.back()->insert(hobject_t("qwer", "", CEPH_NOSNAP, 456, 1, ""));
|
|
o.push_back(new HitSet(new ExplicitObjectHitSet));
|
|
o.back()->insert(hobject_t());
|
|
o.back()->insert(hobject_t("asdf", "", CEPH_NOSNAP, 123, 1, ""));
|
|
o.back()->insert(hobject_t("qwer", "", CEPH_NOSNAP, 456, 1, ""));
|
|
}
|
|
|
|
HitSet::Params::Params(const Params& o) noexcept
|
|
{
|
|
if (o.get_type() != TYPE_NONE) {
|
|
create_impl(o.get_type());
|
|
// it's annoying to write virtual operator= methods; use encode/decode
|
|
// instead.
|
|
ceph::buffer::list bl;
|
|
o.impl->encode(bl);
|
|
auto p = bl.cbegin();
|
|
impl->decode(p);
|
|
} // else we don't need to do anything
|
|
}
|
|
|
|
const HitSet::Params& HitSet::Params::operator=(const Params& o)
|
|
{
|
|
create_impl(o.get_type());
|
|
if (o.impl) {
|
|
// it's annoying to write virtual operator= methods; use encode/decode
|
|
// instead.
|
|
ceph::buffer::list bl;
|
|
o.impl->encode(bl);
|
|
auto p = bl.cbegin();
|
|
impl->decode(p);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void HitSet::Params::encode(ceph::buffer::list &bl) const
|
|
{
|
|
ENCODE_START(1, 1, bl);
|
|
if (impl) {
|
|
encode((__u8)impl->get_type(), bl);
|
|
impl->encode(bl);
|
|
} else {
|
|
encode((__u8)TYPE_NONE, bl);
|
|
}
|
|
ENCODE_FINISH(bl);
|
|
}
|
|
|
|
bool HitSet::Params::create_impl(impl_type_t type)
|
|
{
|
|
switch ((impl_type_t)type) {
|
|
case TYPE_EXPLICIT_HASH:
|
|
impl.reset(new ExplicitHashHitSet::Params);
|
|
break;
|
|
case TYPE_EXPLICIT_OBJECT:
|
|
impl.reset(new ExplicitObjectHitSet::Params);
|
|
break;
|
|
case TYPE_BLOOM:
|
|
impl.reset(new BloomHitSet::Params);
|
|
break;
|
|
case TYPE_NONE:
|
|
impl.reset(NULL);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void HitSet::Params::decode(ceph::buffer::list::const_iterator& bl)
|
|
{
|
|
DECODE_START(1, bl);
|
|
__u8 type;
|
|
decode(type, bl);
|
|
if (!create_impl((impl_type_t)type))
|
|
throw ceph::buffer::malformed_input("unrecognized HitMap type");
|
|
if (impl)
|
|
impl->decode(bl);
|
|
DECODE_FINISH(bl);
|
|
}
|
|
|
|
void HitSet::Params::dump(Formatter *f) const
|
|
{
|
|
f->dump_string("type", HitSet::get_type_name(get_type()));
|
|
if (impl)
|
|
impl->dump(f);
|
|
}
|
|
|
|
void HitSet::Params::generate_test_instances(list<HitSet::Params*>& o)
|
|
{
|
|
#define loop_hitset_params(kind) \
|
|
{ \
|
|
list<kind::Params*> params; \
|
|
kind::Params::generate_test_instances(params); \
|
|
for (list<kind::Params*>::iterator i = params.begin(); \
|
|
i != params.end(); ++i) \
|
|
o.push_back(new Params(*i)); \
|
|
}
|
|
o.push_back(new Params);
|
|
o.push_back(new Params(new BloomHitSet::Params));
|
|
loop_hitset_params(BloomHitSet);
|
|
o.push_back(new Params(new ExplicitHashHitSet::Params));
|
|
loop_hitset_params(ExplicitHashHitSet);
|
|
o.push_back(new Params(new ExplicitObjectHitSet::Params));
|
|
loop_hitset_params(ExplicitObjectHitSet);
|
|
}
|
|
|
|
ostream& operator<<(ostream& out, const HitSet::Params& p) {
|
|
out << HitSet::get_type_name(p.get_type());
|
|
if (p.impl) {
|
|
out << "{";
|
|
p.impl->dump_stream(out);
|
|
}
|
|
out << "}";
|
|
return out;
|
|
}
|
|
|
|
|
|
void ExplicitHashHitSet::dump(Formatter *f) const {
|
|
f->dump_unsigned("insert_count", count);
|
|
f->open_array_section("hash_set");
|
|
for (ceph::unordered_set<uint32_t>::const_iterator p = hits.begin();
|
|
p != hits.end();
|
|
++p)
|
|
f->dump_unsigned("hash", *p);
|
|
f->close_section();
|
|
}
|
|
|
|
void ExplicitObjectHitSet::dump(Formatter *f) const {
|
|
f->dump_unsigned("insert_count", count);
|
|
f->open_array_section("set");
|
|
for (ceph::unordered_set<hobject_t>::const_iterator p = hits.begin();
|
|
p != hits.end();
|
|
++p) {
|
|
f->open_object_section("object");
|
|
p->dump(f);
|
|
f->close_section();
|
|
}
|
|
f->close_section();
|
|
}
|
|
|
|
void BloomHitSet::Params::dump(Formatter *f) const {
|
|
f->dump_float("false_positive_probability", get_fpp());
|
|
f->dump_int("target_size", target_size);
|
|
f->dump_int("seed", seed);
|
|
}
|
|
|
|
void BloomHitSet::dump(Formatter *f) const {
|
|
f->open_object_section("bloom_filter");
|
|
bloom.dump(f);
|
|
f->close_section();
|
|
}
|