mirror of
https://github.com/ceph/ceph
synced 2025-01-02 17:12:31 +00:00
acec741706
Signed-off-by: liuchang0812 <liuchang0812@gmail.com>
237 lines
6.9 KiB
C++
237 lines
6.9 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 Storage, Inc.
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#ifndef SNAPMAPPER_H
|
|
#define SNAPMAPPER_H
|
|
|
|
#include <string>
|
|
#include <set>
|
|
#include <utility>
|
|
#include <string.h>
|
|
|
|
#include "common/map_cacher.hpp"
|
|
#include "common/hobject.h"
|
|
#include "include/buffer.h"
|
|
#include "include/encoding.h"
|
|
#include "include/object.h"
|
|
#include "os/ObjectStore.h"
|
|
|
|
class OSDriver : public MapCacher::StoreDriver<std::string, bufferlist> {
|
|
ObjectStore *os;
|
|
coll_t cid;
|
|
ghobject_t hoid;
|
|
|
|
public:
|
|
class OSTransaction : public MapCacher::Transaction<std::string, bufferlist> {
|
|
friend class OSDriver;
|
|
coll_t cid;
|
|
ghobject_t hoid;
|
|
ObjectStore::Transaction *t;
|
|
OSTransaction(
|
|
coll_t cid,
|
|
const ghobject_t &hoid,
|
|
ObjectStore::Transaction *t)
|
|
: cid(cid), hoid(hoid), t(t) {}
|
|
public:
|
|
void set_keys(
|
|
const std::map<std::string, bufferlist> &to_set) override {
|
|
t->omap_setkeys(cid, hoid, to_set);
|
|
}
|
|
void remove_keys(
|
|
const std::set<std::string> &to_remove) override {
|
|
t->omap_rmkeys(cid, hoid, to_remove);
|
|
}
|
|
void add_callback(
|
|
Context *c) override {
|
|
t->register_on_applied(c);
|
|
}
|
|
};
|
|
|
|
OSTransaction get_transaction(
|
|
ObjectStore::Transaction *t) {
|
|
return OSTransaction(cid, hoid, t);
|
|
}
|
|
|
|
OSDriver(ObjectStore *os, coll_t cid, const ghobject_t &hoid) :
|
|
os(os), cid(cid), hoid(hoid) {}
|
|
int get_keys(
|
|
const std::set<std::string> &keys,
|
|
std::map<std::string, bufferlist> *out) override;
|
|
int get_next(
|
|
const std::string &key,
|
|
pair<std::string, bufferlist> *next) override;
|
|
};
|
|
|
|
/**
|
|
* SnapMapper
|
|
*
|
|
* Manages two mappings:
|
|
* 1) hobject_t -> {snapid}
|
|
* 2) snapid -> {hobject_t}
|
|
*
|
|
* We accomplish this using two sets of keys:
|
|
* 1) OBJECT_PREFIX + obj.str() -> encoding of object_snaps
|
|
* 2) MAPPING_PREFIX + snapid_t + obj.str() -> encoding of pair<snapid_t, obj>
|
|
*
|
|
* The on disk strings and encodings are implemented in to_raw, to_raw_key,
|
|
* from_raw, to_object_key.
|
|
*
|
|
* The object -> {snapid} mapping is primarily included so that the
|
|
* SnapMapper state can be verified against the external PG state during
|
|
* scrub etc.
|
|
*
|
|
* The 2) mapping is arranged such that all objects in a particular
|
|
* snap will sort together, and so that all objects in a pg for a
|
|
* particular snap will group under up to 8 prefixes.
|
|
*/
|
|
class SnapMapper {
|
|
public:
|
|
CephContext* cct;
|
|
struct object_snaps {
|
|
hobject_t oid;
|
|
std::set<snapid_t> snaps;
|
|
object_snaps(hobject_t oid, const std::set<snapid_t> &snaps)
|
|
: oid(oid), snaps(snaps) {}
|
|
object_snaps() {}
|
|
void encode(bufferlist &bl) const;
|
|
void decode(bufferlist::iterator &bp);
|
|
};
|
|
|
|
private:
|
|
MapCacher::MapCacher<std::string, bufferlist> backend;
|
|
|
|
static const std::string MAPPING_PREFIX;
|
|
static const std::string OBJECT_PREFIX;
|
|
|
|
static std::string get_prefix(snapid_t snap);
|
|
|
|
std::string to_raw_key(
|
|
const std::pair<snapid_t, hobject_t> &to_map);
|
|
|
|
std::pair<std::string, bufferlist> to_raw(
|
|
const std::pair<snapid_t, hobject_t> &to_map);
|
|
|
|
static bool is_mapping(const std::string &to_test);
|
|
|
|
std::pair<snapid_t, hobject_t> from_raw(
|
|
const std::pair<std::string, bufferlist> &image);
|
|
|
|
std::string to_object_key(const hobject_t &hoid);
|
|
|
|
int get_snaps(const hobject_t &oid, object_snaps *out);
|
|
|
|
void set_snaps(
|
|
const hobject_t &oid,
|
|
const object_snaps &out,
|
|
MapCacher::Transaction<std::string, bufferlist> *t);
|
|
|
|
void clear_snaps(
|
|
const hobject_t &oid,
|
|
MapCacher::Transaction<std::string, bufferlist> *t);
|
|
|
|
// True if hoid belongs in this mapping based on mask_bits and match
|
|
bool check(const hobject_t &hoid) const {
|
|
return hoid.match(mask_bits, match);
|
|
}
|
|
|
|
int _remove_oid(
|
|
const hobject_t &oid, ///< [in] oid to remove
|
|
MapCacher::Transaction<std::string, bufferlist> *t ///< [out] transaction
|
|
);
|
|
|
|
public:
|
|
static string make_shard_prefix(shard_id_t shard) {
|
|
if (shard == shard_id_t::NO_SHARD)
|
|
return string();
|
|
char buf[20];
|
|
int r = snprintf(buf, sizeof(buf), ".%x", (int)shard);
|
|
assert(r < (int)sizeof(buf));
|
|
return string(buf, r) + '_';
|
|
}
|
|
uint32_t mask_bits;
|
|
const uint32_t match;
|
|
string last_key_checked;
|
|
const int64_t pool;
|
|
const shard_id_t shard;
|
|
const string shard_prefix;
|
|
SnapMapper(
|
|
CephContext* cct,
|
|
MapCacher::StoreDriver<std::string, bufferlist> *driver,
|
|
uint32_t match, ///< [in] pgid
|
|
uint32_t bits, ///< [in] current split bits
|
|
int64_t pool, ///< [in] pool
|
|
shard_id_t shard ///< [in] shard
|
|
)
|
|
: cct(cct), backend(driver), mask_bits(bits), match(match), pool(pool),
|
|
shard(shard), shard_prefix(make_shard_prefix(shard)) {
|
|
update_bits(mask_bits);
|
|
}
|
|
|
|
set<string> prefixes;
|
|
/// Update bits in case of pg split
|
|
void update_bits(
|
|
uint32_t new_bits ///< [in] new split bits
|
|
) {
|
|
assert(new_bits >= mask_bits);
|
|
mask_bits = new_bits;
|
|
set<string> _prefixes = hobject_t::get_prefixes(
|
|
mask_bits,
|
|
match,
|
|
pool);
|
|
prefixes.clear();
|
|
for (set<string>::iterator i = _prefixes.begin();
|
|
i != _prefixes.end();
|
|
++i) {
|
|
prefixes.insert(shard_prefix + *i);
|
|
}
|
|
}
|
|
|
|
/// Update snaps for oid, empty new_snaps removes the mapping
|
|
int update_snaps(
|
|
const hobject_t &oid, ///< [in] oid to update
|
|
const std::set<snapid_t> &new_snaps, ///< [in] new snap set
|
|
const std::set<snapid_t> *old_snaps, ///< [in] old snaps (for debugging)
|
|
MapCacher::Transaction<std::string, bufferlist> *t ///< [out] transaction
|
|
); ///@ return error, 0 on success
|
|
|
|
/// Add mapping for oid, must not already be mapped
|
|
void add_oid(
|
|
const hobject_t &oid, ///< [in] oid to add
|
|
const std::set<snapid_t>& new_snaps, ///< [in] snaps
|
|
MapCacher::Transaction<std::string, bufferlist> *t ///< [out] transaction
|
|
);
|
|
|
|
/// Returns first object with snap as a snap
|
|
int get_next_objects_to_trim(
|
|
snapid_t snap, ///< [in] snap to check
|
|
unsigned max, ///< [in] max to get
|
|
vector<hobject_t> *out ///< [out] next objects to trim (must be empty)
|
|
); ///< @return error, -ENOENT if no more objects
|
|
|
|
/// Remove mapping for oid
|
|
int remove_oid(
|
|
const hobject_t &oid, ///< [in] oid to remove
|
|
MapCacher::Transaction<std::string, bufferlist> *t ///< [out] transaction
|
|
); ///< @return error, -ENOENT if the object is not mapped
|
|
|
|
/// Get snaps for oid
|
|
int get_snaps(
|
|
const hobject_t &oid, ///< [in] oid to get snaps for
|
|
std::set<snapid_t> *snaps ///< [out] snaps
|
|
); ///< @return error, -ENOENT if oid is not recorded
|
|
};
|
|
WRITE_CLASS_ENCODER(SnapMapper::object_snaps)
|
|
|
|
#endif
|