Merge pull request #7269 from liewegas/wip-bluestore-btree

bluestore: use btree_map for allocator

Reviewed-by: Igor Fedotov <ifedotov@mirantis.com>
Reviewed-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
Sage Weil 2016-01-27 13:21:26 -05:00
commit 9c30be93e3
17 changed files with 4202 additions and 85 deletions

View File

@ -52,6 +52,7 @@ noinst_HEADERS += \
include/atomic.h \
include/bitmapper.h \
include/blobhash.h \
include/btree_interval_set.h \
include/buffer.h \
include/buffer_fwd.h \
include/byteorder.h \
@ -63,9 +64,13 @@ noinst_HEADERS += \
include/cmp.h \
include/color.h \
include/compat.h \
include/cpp-btree/btree.h \
include/cpp-btree/btree_container.h \
include/cpp-btree/btree_map.h \
include/sock_compat.h \
include/crc32c.h \
include/encoding.h \
include/encoding_btree.h \
include/err.h \
include/error.h \
include/filepath.h \

View File

@ -0,0 +1,584 @@
// -*- 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) 2004-2006 Sage Weil <sage@newdream.net>
*
* 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 CEPH_BTREE_INTERVAL_SET_H
#define CEPH_BTREE_INTERVAL_SET_H
#include <iterator>
#include <map>
#include <ostream>
#include "encoding.h"
#ifndef MIN
# define MIN(a,b) ((a)<=(b) ? (a):(b))
#endif
#ifndef MAX
# define MAX(a,b) ((a)>=(b) ? (a):(b))
#endif
#include "cpp-btree/btree_map.h"
#include "assert.h"
#include "encoding_btree.h"
template<typename T>
class btree_interval_set {
public:
typedef btree::btree_map<T,T> map_t;
class const_iterator;
class iterator : public std::iterator <std::forward_iterator_tag, T>
{
public:
explicit iterator(typename map_t::iterator iter)
: _iter(iter)
{ }
// For the copy constructor and assignment operator, the compiler-generated functions, which
// perform simple bitwise copying, should be fine.
bool operator==(const iterator& rhs) const {
return (_iter == rhs._iter);
}
bool operator!=(const iterator& rhs) const {
return (_iter != rhs._iter);
}
// Dereference this iterator to get a pair.
std::pair < T, T > &operator*() {
return *_iter;
}
// Return the interval start.
T get_start() const {
return _iter->first;
}
// Return the interval length.
T get_len() const {
return _iter->second;
}
// Set the interval length.
void set_len(T len) {
_iter->second = len;
}
// Preincrement
iterator &operator++()
{
++_iter;
return *this;
}
// Postincrement
iterator operator++(int)
{
iterator prev(_iter);
++_iter;
return prev;
}
friend class btree_interval_set<T>::const_iterator;
protected:
typename map_t::iterator _iter;
friend class btree_interval_set<T>;
};
class const_iterator : public std::iterator <std::forward_iterator_tag, T>
{
public:
explicit const_iterator(typename map_t::const_iterator iter)
: _iter(iter)
{ }
const_iterator(const iterator &i)
: _iter(i._iter)
{ }
// For the copy constructor and assignment operator, the compiler-generated functions, which
// perform simple bitwise copying, should be fine.
bool operator==(const const_iterator& rhs) const {
return (_iter == rhs._iter);
}
bool operator!=(const const_iterator& rhs) const {
return (_iter != rhs._iter);
}
// Dereference this iterator to get a pair.
std::pair < T, T > operator*() const {
return *_iter;
}
// Return the interval start.
T get_start() const {
return _iter->first;
}
// Return the interval length.
T get_len() const {
return _iter->second;
}
// Preincrement
const_iterator &operator++()
{
++_iter;
return *this;
}
// Postincrement
const_iterator operator++(int)
{
const_iterator prev(_iter);
++_iter;
return prev;
}
protected:
typename map_t::const_iterator _iter;
};
btree_interval_set() : _size(0) {}
int num_intervals() const
{
return m.size();
}
typename btree_interval_set<T>::iterator begin() {
return typename btree_interval_set<T>::iterator(m.begin());
}
typename btree_interval_set<T>::iterator lower_bound(T start) {
return typename btree_interval_set<T>::iterator(find_inc_m(start));
}
typename btree_interval_set<T>::iterator end() {
return typename btree_interval_set<T>::iterator(m.end());
}
typename btree_interval_set<T>::const_iterator begin() const {
return typename btree_interval_set<T>::const_iterator(m.begin());
}
typename btree_interval_set<T>::const_iterator lower_bound(T start) const {
return typename btree_interval_set<T>::const_iterator(find_inc(start));
}
typename btree_interval_set<T>::const_iterator end() const {
return typename btree_interval_set<T>::const_iterator(m.end());
}
// helpers
private:
typename map_t::const_iterator find_inc(T start) const {
typename map_t::const_iterator p = m.lower_bound(start); // p->first >= start
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
if (p->first + p->second <= start)
p++; // it doesn't.
}
return p;
}
typename map_t::iterator find_inc_m(T start) {
typename map_t::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
if (p->first + p->second <= start)
p++; // it doesn't.
}
return p;
}
typename map_t::const_iterator find_adj(T start) const {
typename map_t::const_iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
if (p->first + p->second < start)
p++; // it doesn't.
}
return p;
}
typename map_t::iterator find_adj_m(T start) {
typename map_t::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
if (p->first + p->second < start)
p++; // it doesn't.
}
return p;
}
public:
bool operator==(const btree_interval_set& other) const {
return _size == other._size && m == other.m;
}
int size() const {
return _size;
}
void encode(bufferlist& bl) const {
::encode(m, bl);
}
void encode_nohead(bufferlist& bl) const {
::encode_nohead(m, bl);
}
void decode(bufferlist::iterator& bl) {
::decode(m, bl);
_size = 0;
for (typename map_t::const_iterator p = m.begin();
p != m.end();
p++)
_size += p->second;
}
void decode_nohead(int n, bufferlist::iterator& bl) {
::decode_nohead(n, m, bl);
_size = 0;
for (typename map_t::const_iterator p = m.begin();
p != m.end();
p++)
_size += p->second;
}
void clear() {
m.clear();
_size = 0;
}
bool contains(T i, T *pstart=0, T *plen=0) const {
typename map_t::const_iterator p = find_inc(i);
if (p == m.end()) return false;
if (p->first > i) return false;
if (p->first+p->second <= i) return false;
assert(p->first <= i && p->first+p->second > i);
if (pstart)
*pstart = p->first;
if (plen)
*plen = p->second;
return true;
}
bool contains(T start, T len) const {
typename map_t::const_iterator p = find_inc(start);
if (p == m.end()) return false;
if (p->first > start) return false;
if (p->first+p->second <= start) return false;
assert(p->first <= start && p->first+p->second > start);
if (p->first+p->second < start+len) return false;
return true;
}
bool intersects(T start, T len) const {
btree_interval_set a;
a.insert(start, len);
btree_interval_set i;
i.intersection_of( *this, a );
if (i.empty()) return false;
return true;
}
// outer range of set
bool empty() const {
return m.empty();
}
T range_start() const {
assert(!empty());
typename map_t::const_iterator p = m.begin();
return p->first;
}
T range_end() const {
assert(!empty());
typename map_t::const_iterator p = m.end();
p--;
return p->first+p->second;
}
// interval start after p (where p not in set)
bool starts_after(T i) const {
assert(!contains(i));
typename map_t::const_iterator p = find_inc(i);
if (p == m.end()) return false;
return true;
}
T start_after(T i) const {
assert(!contains(i));
typename map_t::const_iterator p = find_inc(i);
return p->first;
}
// interval end that contains start
T end_after(T start) const {
assert(contains(start));
typename map_t::const_iterator p = find_inc(start);
return p->first+p->second;
}
void insert(T val) {
insert(val, 1);
}
void insert(T start, T len, T *pstart=0, T *plen=0) {
//cout << "insert " << start << "~" << len << endl;
assert(len > 0);
_size += len;
typename map_t::iterator p = find_adj_m(start);
if (p == m.end()) {
m[start] = len; // new interval
if (pstart)
*pstart = start;
if (plen)
*plen = len;
} else {
if (p->first < start) {
if (p->first + p->second != start) {
//cout << "p is " << p->first << "~" << p->second << ", start is " << start << ", len is " << len << endl;
assert(0);
}
p->second += len; // append to end
typename map_t::iterator n = p;
n++;
if (pstart)
*pstart = p->first;
if (n != m.end() &&
start+len == n->first) { // combine with next, too!
p->second += n->second;
if (plen)
*plen = p->second;
m.erase(n);
} else {
if (plen)
*plen = p->second;
}
} else {
if (start+len == p->first) {
if (pstart)
*pstart = start;
if (plen)
*plen = len + p->second;
T plen = p->second;
m.erase(p);
m[start] = len + plen; // append to front
} else {
assert(p->first > start+len);
if (pstart)
*pstart = start;
if (plen)
*plen = len;
m[start] = len; // new interval
}
}
}
}
void swap(btree_interval_set<T>& other) {
m.swap(other.m);
std::swap(_size, other._size);
}
void erase(iterator &i) {
_size -= i.get_len();
assert(_size >= 0);
m.erase(i._iter);
}
void erase(T val) {
erase(val, 1);
}
void erase(T start, T len) {
typename map_t::iterator p = find_inc_m(start);
_size -= len;
assert(_size >= 0);
assert(p != m.end());
assert(p->first <= start);
T before = start - p->first;
assert(p->second >= before+len);
T after = p->second - before - len;
if (before)
p->second = before; // shorten bit before
else
m.erase(p);
if (after)
m[start+len] = after;
}
void subtract(const btree_interval_set &a) {
for (typename map_t::const_iterator p = a.m.begin();
p != a.m.end();
p++)
erase(p->first, p->second);
}
void insert(const btree_interval_set &a) {
for (typename map_t::const_iterator p = a.m.begin();
p != a.m.end();
p++)
insert(p->first, p->second);
}
void intersection_of(const btree_interval_set &a, const btree_interval_set &b) {
assert(&a != this);
assert(&b != this);
clear();
typename map_t::const_iterator pa = a.m.begin();
typename map_t::const_iterator pb = b.m.begin();
while (pa != a.m.end() && pb != b.m.end()) {
// passing?
if (pa->first + pa->second <= pb->first)
{ pa++; continue; }
if (pb->first + pb->second <= pa->first)
{ pb++; continue; }
T start = MAX(pa->first, pb->first);
T en = MIN(pa->first+pa->second, pb->first+pb->second);
assert(en > start);
insert(start, en-start);
if (pa->first+pa->second > pb->first+pb->second)
pb++;
else
pa++;
}
}
void intersection_of(const btree_interval_set& b) {
btree_interval_set a;
swap(a);
intersection_of(a, b);
}
void union_of(const btree_interval_set &a, const btree_interval_set &b) {
assert(&a != this);
assert(&b != this);
clear();
//cout << "union_of" << endl;
// a
m = a.m;
_size = a._size;
// - (a*b)
btree_interval_set ab;
ab.intersection_of(a, b);
subtract(ab);
// + b
insert(b);
return;
}
void union_of(const btree_interval_set &b) {
btree_interval_set a;
swap(a);
union_of(a, b);
}
bool subset_of(const btree_interval_set &big) const {
for (typename map_t::const_iterator i = m.begin();
i != m.end();
i++)
if (!big.contains(i->first, i->second)) return false;
return true;
}
/*
* build a subset of @other, starting at or after @start, and including
* @len worth of values, skipping holes. e.g.,
* span_of([5~10,20~5], 8, 5) -> [8~2,20~3]
*/
void span_of(const btree_interval_set &other, T start, T len) {
clear();
typename map_t::const_iterator p = other.find_inc(start);
if (p == other.m.end())
return;
if (p->first < start) {
if (p->first + p->second < start)
return;
if (p->first + p->second < start + len) {
T howmuch = p->second - (start - p->first);
insert(start, howmuch);
len -= howmuch;
p++;
} else {
insert(start, len);
return;
}
}
while (p != other.m.end() && len > 0) {
if (p->second < len) {
insert(p->first, p->second);
len -= p->second;
p++;
} else {
insert(p->first, len);
return;
}
}
}
private:
// data
int64_t _size;
map_t m; // map start -> len
};
template<class T>
inline std::ostream& operator<<(std::ostream& out, const btree_interval_set<T> &s) {
out << "[";
const char *prequel = "";
for (typename btree_interval_set<T>::const_iterator i = s.begin();
i != s.end();
++i)
{
out << prequel << i.get_start() << "~" << i.get_len();
prequel = ",";
}
out << "]";
return out;
}
template<class T>
inline void encode(const btree_interval_set<T>& s, bufferlist& bl)
{
s.encode(bl);
}
template<class T>
inline void decode(btree_interval_set<T>& s, bufferlist::iterator& p)
{
s.decode(p);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,349 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef UTIL_BTREE_BTREE_CONTAINER_H__
#define UTIL_BTREE_BTREE_CONTAINER_H__
#include <iosfwd>
#include <utility>
#include "btree.h"
namespace btree {
// A common base class for btree_set, btree_map, btree_multiset and
// btree_multimap.
template <typename Tree>
class btree_container {
typedef btree_container<Tree> self_type;
public:
typedef typename Tree::params_type params_type;
typedef typename Tree::key_type key_type;
typedef typename Tree::value_type value_type;
typedef typename Tree::key_compare key_compare;
typedef typename Tree::allocator_type allocator_type;
typedef typename Tree::pointer pointer;
typedef typename Tree::const_pointer const_pointer;
typedef typename Tree::reference reference;
typedef typename Tree::const_reference const_reference;
typedef typename Tree::size_type size_type;
typedef typename Tree::difference_type difference_type;
typedef typename Tree::iterator iterator;
typedef typename Tree::const_iterator const_iterator;
typedef typename Tree::reverse_iterator reverse_iterator;
typedef typename Tree::const_reverse_iterator const_reverse_iterator;
public:
// Default constructor.
btree_container(const key_compare &comp, const allocator_type &alloc)
: tree_(comp, alloc) {
}
// Copy constructor.
btree_container(const self_type &x)
: tree_(x.tree_) {
}
// Iterator routines.
iterator begin() { return tree_.begin(); }
const_iterator begin() const { return tree_.begin(); }
iterator end() { return tree_.end(); }
const_iterator end() const { return tree_.end(); }
reverse_iterator rbegin() { return tree_.rbegin(); }
const_reverse_iterator rbegin() const { return tree_.rbegin(); }
reverse_iterator rend() { return tree_.rend(); }
const_reverse_iterator rend() const { return tree_.rend(); }
// Lookup routines.
iterator lower_bound(const key_type &key) {
return tree_.lower_bound(key);
}
const_iterator lower_bound(const key_type &key) const {
return tree_.lower_bound(key);
}
iterator upper_bound(const key_type &key) {
return tree_.upper_bound(key);
}
const_iterator upper_bound(const key_type &key) const {
return tree_.upper_bound(key);
}
std::pair<iterator,iterator> equal_range(const key_type &key) {
return tree_.equal_range(key);
}
std::pair<const_iterator,const_iterator> equal_range(const key_type &key) const {
return tree_.equal_range(key);
}
// Utility routines.
void clear() {
tree_.clear();
}
void swap(self_type &x) {
tree_.swap(x.tree_);
}
void dump(std::ostream &os) const {
tree_.dump(os);
}
void verify() const {
tree_.verify();
}
// Size routines.
size_type size() const { return tree_.size(); }
size_type max_size() const { return tree_.max_size(); }
bool empty() const { return tree_.empty(); }
size_type height() const { return tree_.height(); }
size_type internal_nodes() const { return tree_.internal_nodes(); }
size_type leaf_nodes() const { return tree_.leaf_nodes(); }
size_type nodes() const { return tree_.nodes(); }
size_type bytes_used() const { return tree_.bytes_used(); }
static double average_bytes_per_value() {
return Tree::average_bytes_per_value();
}
double fullness() const { return tree_.fullness(); }
double overhead() const { return tree_.overhead(); }
bool operator==(const self_type& x) const {
if (size() != x.size()) {
return false;
}
for (const_iterator i = begin(), xi = x.begin(); i != end(); ++i, ++xi) {
if (*i != *xi) {
return false;
}
}
return true;
}
bool operator!=(const self_type& other) const {
return !operator==(other);
}
protected:
Tree tree_;
};
template <typename T>
inline std::ostream& operator<<(std::ostream &os, const btree_container<T> &b) {
b.dump(os);
return os;
}
// A common base class for btree_set and safe_btree_set.
template <typename Tree>
class btree_unique_container : public btree_container<Tree> {
typedef btree_unique_container<Tree> self_type;
typedef btree_container<Tree> super_type;
public:
typedef typename Tree::key_type key_type;
typedef typename Tree::value_type value_type;
typedef typename Tree::size_type size_type;
typedef typename Tree::key_compare key_compare;
typedef typename Tree::allocator_type allocator_type;
typedef typename Tree::iterator iterator;
typedef typename Tree::const_iterator const_iterator;
public:
// Default constructor.
btree_unique_container(const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
}
// Copy constructor.
btree_unique_container(const self_type &x)
: super_type(x) {
}
// Range constructor.
template <class InputIterator>
btree_unique_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
insert(b, e);
}
// Lookup routines.
iterator find(const key_type &key) {
return this->tree_.find_unique(key);
}
const_iterator find(const key_type &key) const {
return this->tree_.find_unique(key);
}
size_type count(const key_type &key) const {
return this->tree_.count_unique(key);
}
// Insertion routines.
std::pair<iterator,bool> insert(const value_type &x) {
return this->tree_.insert_unique(x);
}
iterator insert(iterator position, const value_type &x) {
return this->tree_.insert_unique(position, x);
}
template <typename InputIterator>
void insert(InputIterator b, InputIterator e) {
this->tree_.insert_unique(b, e);
}
// Deletion routines.
int erase(const key_type &key) {
return this->tree_.erase_unique(key);
}
// Erase the specified iterator from the btree. The iterator must be valid
// (i.e. not equal to end()). Return an iterator pointing to the node after
// the one that was erased (or end() if none exists).
iterator erase(const iterator &iter) {
return this->tree_.erase(iter);
}
void erase(const iterator &first, const iterator &last) {
this->tree_.erase(first, last);
}
};
// A common base class for btree_map and safe_btree_map.
template <typename Tree>
class btree_map_container : public btree_unique_container<Tree> {
typedef btree_map_container<Tree> self_type;
typedef btree_unique_container<Tree> super_type;
public:
typedef typename Tree::key_type key_type;
typedef typename Tree::data_type data_type;
typedef typename Tree::value_type value_type;
typedef typename Tree::mapped_type mapped_type;
typedef typename Tree::key_compare key_compare;
typedef typename Tree::allocator_type allocator_type;
private:
// A pointer-like object which only generates its value when
// dereferenced. Used by operator[] to avoid constructing an empty data_type
// if the key already exists in the map.
struct generate_value {
generate_value(const key_type &k)
: key(k) {
}
value_type operator*() const {
return std::make_pair(key, data_type());
}
const key_type &key;
};
public:
// Default constructor.
btree_map_container(const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
}
// Copy constructor.
btree_map_container(const self_type &x)
: super_type(x) {
}
// Range constructor.
template <class InputIterator>
btree_map_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(b, e, comp, alloc) {
}
// Insertion routines.
data_type& operator[](const key_type &key) {
return this->tree_.insert_unique(key, generate_value(key)).first->second;
}
};
// A common base class for btree_multiset and btree_multimap.
template <typename Tree>
class btree_multi_container : public btree_container<Tree> {
typedef btree_multi_container<Tree> self_type;
typedef btree_container<Tree> super_type;
public:
typedef typename Tree::key_type key_type;
typedef typename Tree::value_type value_type;
typedef typename Tree::size_type size_type;
typedef typename Tree::key_compare key_compare;
typedef typename Tree::allocator_type allocator_type;
typedef typename Tree::iterator iterator;
typedef typename Tree::const_iterator const_iterator;
public:
// Default constructor.
btree_multi_container(const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
}
// Copy constructor.
btree_multi_container(const self_type &x)
: super_type(x) {
}
// Range constructor.
template <class InputIterator>
btree_multi_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
insert(b, e);
}
// Lookup routines.
iterator find(const key_type &key) {
return this->tree_.find_multi(key);
}
const_iterator find(const key_type &key) const {
return this->tree_.find_multi(key);
}
size_type count(const key_type &key) const {
return this->tree_.count_multi(key);
}
// Insertion routines.
iterator insert(const value_type &x) {
return this->tree_.insert_multi(x);
}
iterator insert(iterator position, const value_type &x) {
return this->tree_.insert_multi(position, x);
}
template <typename InputIterator>
void insert(InputIterator b, InputIterator e) {
this->tree_.insert_multi(b, e);
}
// Deletion routines.
int erase(const key_type &key) {
return this->tree_.erase_multi(key);
}
// Erase the specified iterator from the btree. The iterator must be valid
// (i.e. not equal to end()). Return an iterator pointing to the node after
// the one that was erased (or end() if none exists).
iterator erase(const iterator &iter) {
return this->tree_.erase(iter);
}
void erase(const iterator &first, const iterator &last) {
this->tree_.erase(first, last);
}
};
} // namespace btree
#endif // UTIL_BTREE_BTREE_CONTAINER_H__

View File

@ -0,0 +1,130 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// A btree_map<> implements the STL unique sorted associative container
// interface and the pair associative container interface (a.k.a map<>) using a
// btree. A btree_multimap<> implements the STL multiple sorted associative
// container interface and the pair associtive container interface (a.k.a
// multimap<>) using a btree. See btree.h for details of the btree
// implementation and caveats.
#ifndef UTIL_BTREE_BTREE_MAP_H__
#define UTIL_BTREE_BTREE_MAP_H__
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "btree.h"
#include "btree_container.h"
namespace btree {
// The btree_map class is needed mainly for its constructors.
template <typename Key, typename Value,
typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, Value> >,
int TargetNodeSize = 256>
class btree_map : public btree_map_container<
btree<btree_map_params<Key, Value, Compare, Alloc, TargetNodeSize> > > {
typedef btree_map<Key, Value, Compare, Alloc, TargetNodeSize> self_type;
typedef btree_map_params<
Key, Value, Compare, Alloc, TargetNodeSize> params_type;
typedef btree<params_type> btree_type;
typedef btree_map_container<btree_type> super_type;
public:
typedef typename btree_type::key_compare key_compare;
typedef typename btree_type::allocator_type allocator_type;
public:
// Default constructor.
btree_map(const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
}
// Copy constructor.
btree_map(const self_type &x)
: super_type(x) {
}
// Range constructor.
template <class InputIterator>
btree_map(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(b, e, comp, alloc) {
}
};
template <typename K, typename V, typename C, typename A, int N>
inline void swap(btree_map<K, V, C, A, N> &x,
btree_map<K, V, C, A, N> &y) {
x.swap(y);
}
// The btree_multimap class is needed mainly for its constructors.
template <typename Key, typename Value,
typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, Value> >,
int TargetNodeSize = 256>
class btree_multimap : public btree_multi_container<
btree<btree_map_params<Key, Value, Compare, Alloc, TargetNodeSize> > > {
typedef btree_multimap<Key, Value, Compare, Alloc, TargetNodeSize> self_type;
typedef btree_map_params<
Key, Value, Compare, Alloc, TargetNodeSize> params_type;
typedef btree<params_type> btree_type;
typedef btree_multi_container<btree_type> super_type;
public:
typedef typename btree_type::key_compare key_compare;
typedef typename btree_type::allocator_type allocator_type;
typedef typename btree_type::data_type data_type;
typedef typename btree_type::mapped_type mapped_type;
public:
// Default constructor.
btree_multimap(const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
}
// Copy constructor.
btree_multimap(const self_type &x)
: super_type(x) {
}
// Range constructor.
template <class InputIterator>
btree_multimap(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(b, e, comp, alloc) {
}
};
template <typename K, typename V, typename C, typename A, int N>
inline void swap(btree_multimap<K, V, C, A, N> &x,
btree_multimap<K, V, C, A, N> &y) {
x.swap(y);
}
} // namespace btree
#endif // UTIL_BTREE_BTREE_MAP_H__

View File

@ -0,0 +1,60 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#ifndef CEPH_INCLUDE_ENCODING_BTREE_H
#define CEPH_INCLUDE_ENCODING_BTREE_H
#include "include/cpp-btree/btree_map.h"
template<class T, class U>
inline void encode(const btree::btree_map<T,U>& m, bufferlist& bl)
{
__u32 n = (__u32)(m.size());
encode(n, bl);
for (typename btree::btree_map<T,U>::const_iterator p = m.begin(); p != m.end(); ++p) {
encode(p->first, bl);
encode(p->second, bl);
}
}
template<class T, class U>
inline void encode(const btree::btree_map<T,U>& m, bufferlist& bl, uint64_t features)
{
__u32 n = (__u32)(m.size());
encode(n, bl);
for (typename btree::btree_map<T,U>::const_iterator p = m.begin(); p != m.end(); ++p) {
encode(p->first, bl, features);
encode(p->second, bl, features);
}
}
template<class T, class U>
inline void decode(btree::btree_map<T,U>& m, bufferlist::iterator& p)
{
__u32 n;
decode(n, p);
m.clear();
while (n--) {
T k;
decode(k, p);
decode(m[k], p);
}
}
template<class T, class U>
inline void encode_nohead(const btree::btree_map<T,U>& m, bufferlist& bl)
{
for (typename btree::btree_map<T,U>::const_iterator p = m.begin(); p != m.end(); ++p) {
encode(p->first, bl);
encode(p->second, bl);
}
}
template<class T, class U>
inline void decode_nohead(int n, btree::btree_map<T,U>& m, bufferlist::iterator& p)
{
m.clear();
while (n--) {
T k;
decode(k, p);
decode(m[k], p);
}
}
#endif

View File

@ -19,7 +19,6 @@
#include <iterator>
#include <map>
#include <ostream>
using namespace std;
#include "encoding.h"
@ -56,7 +55,7 @@ class interval_set {
}
// Dereference this iterator to get a pair.
pair < T, T > &operator*() {
std::pair < T, T > &operator*() {
return *_iter;
}
@ -93,7 +92,7 @@ class interval_set {
friend class interval_set<T>::const_iterator;
protected:
typename map<T,T>::iterator _iter;
typename std::map<T,T>::iterator _iter;
friend class interval_set<T>;
};
@ -120,7 +119,7 @@ class interval_set {
}
// Dereference this iterator to get a pair.
pair < T, T > operator*() const {
std::pair < T, T > operator*() const {
return *_iter;
}
@ -150,7 +149,7 @@ class interval_set {
}
protected:
typename map<T,T>::const_iterator _iter;
typename std::map<T,T>::const_iterator _iter;
};
interval_set() : _size(0) {}
@ -186,8 +185,8 @@ class interval_set {
// helpers
private:
typename map<T,T>::const_iterator find_inc(T start) const {
typename map<T,T>::const_iterator p = m.lower_bound(start); // p->first >= start
typename std::map<T,T>::const_iterator find_inc(T start) const {
typename std::map<T,T>::const_iterator p = m.lower_bound(start); // p->first >= start
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
@ -197,8 +196,8 @@ class interval_set {
return p;
}
typename map<T,T>::iterator find_inc_m(T start) {
typename map<T,T>::iterator p = m.lower_bound(start);
typename std::map<T,T>::iterator find_inc_m(T start) {
typename std::map<T,T>::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
@ -208,8 +207,8 @@ class interval_set {
return p;
}
typename map<T,T>::const_iterator find_adj(T start) const {
typename map<T,T>::const_iterator p = m.lower_bound(start);
typename std::map<T,T>::const_iterator find_adj(T start) const {
typename std::map<T,T>::const_iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
@ -219,8 +218,8 @@ class interval_set {
return p;
}
typename map<T,T>::iterator find_adj_m(T start) {
typename map<T,T>::iterator p = m.lower_bound(start);
typename std::map<T,T>::iterator find_adj_m(T start) {
typename std::map<T,T>::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
@ -248,7 +247,7 @@ class interval_set {
void decode(bufferlist::iterator& bl) {
::decode(m, bl);
_size = 0;
for (typename map<T,T>::const_iterator p = m.begin();
for (typename std::map<T,T>::const_iterator p = m.begin();
p != m.end();
p++)
_size += p->second;
@ -256,7 +255,7 @@ class interval_set {
void decode_nohead(int n, bufferlist::iterator& bl) {
::decode_nohead(n, m, bl);
_size = 0;
for (typename map<T,T>::const_iterator p = m.begin();
for (typename std::map<T,T>::const_iterator p = m.begin();
p != m.end();
p++)
_size += p->second;
@ -268,7 +267,7 @@ class interval_set {
}
bool contains(T i, T *pstart=0, T *plen=0) const {
typename map<T,T>::const_iterator p = find_inc(i);
typename std::map<T,T>::const_iterator p = find_inc(i);
if (p == m.end()) return false;
if (p->first > i) return false;
if (p->first+p->second <= i) return false;
@ -280,7 +279,7 @@ class interval_set {
return true;
}
bool contains(T start, T len) const {
typename map<T,T>::const_iterator p = find_inc(start);
typename std::map<T,T>::const_iterator p = find_inc(start);
if (p == m.end()) return false;
if (p->first > start) return false;
if (p->first+p->second <= start) return false;
@ -303,12 +302,12 @@ class interval_set {
}
T range_start() const {
assert(!empty());
typename map<T,T>::const_iterator p = m.begin();
typename std::map<T,T>::const_iterator p = m.begin();
return p->first;
}
T range_end() const {
assert(!empty());
typename map<T,T>::const_iterator p = m.end();
typename std::map<T,T>::const_iterator p = m.end();
p--;
return p->first+p->second;
}
@ -316,20 +315,20 @@ class interval_set {
// interval start after p (where p not in set)
bool starts_after(T i) const {
assert(!contains(i));
typename map<T,T>::const_iterator p = find_inc(i);
typename std::map<T,T>::const_iterator p = find_inc(i);
if (p == m.end()) return false;
return true;
}
T start_after(T i) const {
assert(!contains(i));
typename map<T,T>::const_iterator p = find_inc(i);
typename std::map<T,T>::const_iterator p = find_inc(i);
return p->first;
}
// interval end that contains start
T end_after(T start) const {
assert(contains(start));
typename map<T,T>::const_iterator p = find_inc(start);
typename std::map<T,T>::const_iterator p = find_inc(start);
return p->first+p->second;
}
@ -341,7 +340,7 @@ class interval_set {
//cout << "insert " << start << "~" << len << endl;
assert(len > 0);
_size += len;
typename map<T,T>::iterator p = find_adj_m(start);
typename std::map<T,T>::iterator p = find_adj_m(start);
if (p == m.end()) {
m[start] = len; // new interval
if (pstart)
@ -356,10 +355,9 @@ class interval_set {
assert(0);
}
assert(p->first + p->second == start);
p->second += len; // append to end
typename map<T,T>::iterator n = p;
typename std::map<T,T>::iterator n = p;
n++;
if (n != m.end() &&
start+len == n->first) { // combine with next, too!
@ -392,9 +390,7 @@ class interval_set {
void swap(interval_set<T>& other) {
m.swap(other.m);
int64_t t = _size;
_size = other._size;
other._size = t;
std::swap(_size, other._size);
}
void erase(iterator &i) {
@ -408,7 +404,7 @@ class interval_set {
}
void erase(T start, T len) {
typename map<T,T>::iterator p = find_inc_m(start);
typename std::map<T,T>::iterator p = find_inc_m(start);
_size -= len;
assert(_size >= 0);
@ -430,14 +426,14 @@ class interval_set {
void subtract(const interval_set &a) {
for (typename map<T,T>::const_iterator p = a.m.begin();
for (typename std::map<T,T>::const_iterator p = a.m.begin();
p != a.m.end();
p++)
erase(p->first, p->second);
}
void insert(const interval_set &a) {
for (typename map<T,T>::const_iterator p = a.m.begin();
for (typename std::map<T,T>::const_iterator p = a.m.begin();
p != a.m.end();
p++)
insert(p->first, p->second);
@ -449,8 +445,8 @@ class interval_set {
assert(&b != this);
clear();
typename map<T,T>::const_iterator pa = a.m.begin();
typename map<T,T>::const_iterator pb = b.m.begin();
typename std::map<T,T>::const_iterator pa = a.m.begin();
typename std::map<T,T>::const_iterator pb = b.m.begin();
while (pa != a.m.end() && pb != b.m.end()) {
// passing?
@ -501,7 +497,7 @@ class interval_set {
}
bool subset_of(const interval_set &big) const {
for (typename map<T,T>::const_iterator i = m.begin();
for (typename std::map<T,T>::const_iterator i = m.begin();
i != m.end();
i++)
if (!big.contains(i->first, i->second)) return false;
@ -515,7 +511,7 @@ class interval_set {
*/
void span_of(const interval_set &other, T start, T len) {
clear();
typename map<T,T>::const_iterator p = other.find_inc(start);
typename std::map<T,T>::const_iterator p = other.find_inc(start);
if (p == other.m.end())
return;
if (p->first < start) {
@ -546,12 +542,12 @@ class interval_set {
private:
// data
int64_t _size;
map<T,T> m; // map start -> len
std::map<T,T> m; // map start -> len
};
template<class T>
inline ostream& operator<<(ostream& out, const interval_set<T> &s) {
inline std::ostream& operator<<(std::ostream& out, const interval_set<T> &s) {
out << "[";
const char *prequel = "";
for (typename interval_set<T>::const_iterator i = s.begin();

View File

@ -144,9 +144,11 @@ int FreelistManager::allocate(
txn->set(prefix, newkey, newvalue);
dout(20) << __func__ << " set " << newoff << "~" << newlen
<< " (remaining tail)" << dendl;
kv_free.erase(p);
kv_free[newoff] = newlen;
} else {
kv_free.erase(p);
}
kv_free.erase(p);
} else {
assert(p->first < offset);
// shorten
@ -170,9 +172,11 @@ int FreelistManager::allocate(
dout(20) << __func__ << " set " << tailoff << "~" << taillen
<< " (remaining tail from " << p->first << "~" << p->second << ")"
<< dendl;
p->second = newlen;
kv_free[tailoff] = taillen;
} else {
p->second = newlen;
}
p->second = newlen;
}
if (g_conf->bluestore_debug_freelist)
_audit();
@ -199,7 +203,11 @@ int FreelistManager::release(
<< " (merge with previous)" << dendl;
length += p->second;
offset = p->first;
kv_free.erase(p++);
if (map_t_has_stable_iterators) {
kv_free.erase(p++);
} else {
p = kv_free.erase(p);
}
} else if (p->first + p->second > offset) {
derr << __func__ << " bad release " << offset << "~" << length
<< " overlaps with " << p->first << "~" << p->second << dendl;

View File

@ -10,12 +10,17 @@
#include <ostream>
#include "kv/KeyValueDB.h"
#include "include/cpp-btree/btree_map.h"
class FreelistManager {
std::string prefix;
std::mutex lock;
uint64_t total_free;
std::map<uint64_t, uint64_t> kv_free; ///< mirrors our kv values in the db
typedef btree::btree_map<uint64_t,uint64_t> map_t;
static const bool map_t_has_stable_iterators = false;
map_t kv_free; ///< mirrors our kv values in the db
void _audit();
void _dump();
@ -35,7 +40,7 @@ public:
return total_free;
}
const std::map<uint64_t,uint64_t>& get_freelist() {
const map_t& get_freelist() {
return kv_free;
}

View File

@ -73,7 +73,7 @@ void StupidAllocator::unreserve(uint64_t unused)
}
/// return the effective length of the extent if we align to alloc_unit
static uint64_t aligned_len(interval_set<uint64_t>::iterator p,
static uint64_t aligned_len(btree_interval_set<uint64_t>::iterator p,
uint64_t alloc_unit)
{
uint64_t skew = p.get_start() % alloc_unit;
@ -98,7 +98,7 @@ int StupidAllocator::allocate(
int bin = _choose_bin(want);
int orig_bin = bin;
interval_set<uint64_t>::iterator p = free[0].begin();
auto p = free[0].begin();
if (!hint)
hint = last_alloc;
@ -223,7 +223,7 @@ void StupidAllocator::dump(ostream& out)
for (unsigned bin = 0; bin < free.size(); ++bin) {
dout(30) << __func__ << " free bin " << bin << ": "
<< free[bin].num_intervals() << " extents" << dendl;
for (interval_set<uint64_t>::iterator p = free[bin].begin();
for (auto p = free[bin].begin();
p != free[bin].end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
@ -231,14 +231,14 @@ void StupidAllocator::dump(ostream& out)
}
dout(30) << __func__ << " committing: "
<< committing.num_intervals() << " extents" << dendl;
for (interval_set<uint64_t>::iterator p = committing.begin();
for (auto p = committing.begin();
p != committing.end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
}
dout(30) << __func__ << " uncommitted: "
<< uncommitted.num_intervals() << " extents" << dendl;
for (interval_set<uint64_t>::iterator p = uncommitted.begin();
for (auto p = uncommitted.begin();
p != uncommitted.end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
@ -257,10 +257,10 @@ void StupidAllocator::init_rm_free(uint64_t offset, uint64_t length)
{
Mutex::Locker l(lock);
dout(10) << __func__ << " " << offset << "~" << length << dendl;
interval_set<uint64_t> rm;
btree_interval_set<uint64_t> rm;
rm.insert(offset, length);
for (unsigned i = 0; i < free.size() && !rm.empty(); ++i) {
interval_set<uint64_t> overlap;
btree_interval_set<uint64_t> overlap;
overlap.intersection_of(rm, free[i]);
if (!overlap.empty()) {
dout(20) << __func__ << " bin " << i << " rm " << overlap << dendl;
@ -295,7 +295,7 @@ void StupidAllocator::commit_finish()
Mutex::Locker l(lock);
dout(10) << __func__ << " released " << num_committing
<< " in extents " << committing.num_intervals() << dendl;
for (interval_set<uint64_t>::iterator p = committing.begin();
for (auto p = committing.begin();
p != committing.end();
++p) {
_insert_free(p.get_start(), p.get_len());

View File

@ -5,7 +5,7 @@
#define CEPH_OS_BLUESTORE_STUPIDALLOCATOR_H
#include "Allocator.h"
#include "include/interval_set.h"
#include "include/btree_interval_set.h"
#include "common/Mutex.h"
class StupidAllocator : public Allocator {
@ -16,9 +16,9 @@ class StupidAllocator : public Allocator {
int64_t num_committing;
int64_t num_reserved; ///< reserved bytes
vector<interval_set<uint64_t> > free; ///< leading-edge copy
interval_set<uint64_t> uncommitted; ///< released but not yet usable
interval_set<uint64_t> committing; ///< released but not yet usable
std::vector<btree_interval_set<uint64_t> > free; ///< leading-edge copy
btree_interval_set<uint64_t> uncommitted; ///< released but not yet usable
btree_interval_set<uint64_t> committing; ///< released but not yet usable
uint64_t last_alloc;
@ -44,7 +44,7 @@ public:
uint64_t get_free();
void dump(ostream& out);
void dump(std::ostream& out);
void init_add_free(uint64_t offset, uint64_t length);
void init_rm_free(uint64_t offset, uint64_t length);

View File

@ -1370,6 +1370,23 @@ add_dependencies(check unittest_bit_vector)
set_target_properties(unittest_bit_vector PROPERTIES COMPILE_FLAGS
${UNITTEST_CXX_FLAGS})
# unittest_interval_set
add_executable(unittest_interval_set EXCLUDE_FROM_ALL
common/test_interval_set.cc
$<TARGET_OBJECTS:heap_profiler_objs>
)
add_test(unittest_interval_set unittest_interval_set)
add_dependencies(check unittest_interval_set)
target_link_libraries(unittest_interval_set
global
${CMAKE_DL_LIBS}
${ALLOC_LIBS}
${UNITTEST_LIBS})
add_test(unittest_interval_set unittest_interval_set)
add_dependencies(check unittest_interval_set)
set_target_properties(unittest_interval_set PROPERTIES COMPILE_FLAGS
${UNITTEST_CXX_FLAGS})
# unittest_subprocess
add_executable(unittest_subprocess EXCLUDE_FROM_ALL
test_subprocess.cc

View File

@ -419,6 +419,11 @@ unittest_bit_vector_CXXFLAGS = $(UNITTEST_CXXFLAGS)
unittest_bit_vector_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
check_TESTPROGRAMS += unittest_bit_vector
unittest_interval_set_SOURCES = test/common/test_interval_set.cc
unittest_interval_set_CXXFLAGS = $(UNITTEST_CXXFLAGS)
unittest_interval_set_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
check_TESTPROGRAMS += unittest_interval_set
unittest_subprocess_SOURCES = test/test_subprocess.cc
unittest_subprocess_LDADD = $(LIBCOMMON) $(UNITTEST_LDADD)
unittest_subprocess_CXXFLAGS = $(UNITTEST_CXXFLAGS)

View File

@ -16,13 +16,13 @@ bool test_object_contents();
class ObjectContents {
uint64_t _size;
map<uint64_t, unsigned int> seeds;
std::map<uint64_t, unsigned int> seeds;
interval_set<uint64_t> written;
bool _exists;
public:
class Iterator {
ObjectContents *parent;
map<uint64_t, unsigned int>::iterator iter;
std::map<uint64_t, unsigned int>::iterator iter;
unsigned int current_state;
int current_val;
uint64_t pos;
@ -100,7 +100,7 @@ public:
void debug(std::ostream &out) {
out << "_size is " << _size << std::endl;
out << "seeds is: (";
for (map<uint64_t, unsigned int>::iterator i = seeds.begin();
for (std::map<uint64_t, unsigned int>::iterator i = seeds.begin();
i != seeds.end();
++i) {
out << "[" << i->first << "," << i->second << "], ";

View File

@ -0,0 +1,564 @@
// -*- 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) 2015 Mirantis, Inc.
*
* Author: Igor Fedotov <ifedotov@mirantis.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 <gtest/gtest.h>
#include "include/interval_set.h"
#include "include/btree_interval_set.h"
using namespace ceph;
typedef uint64_t IntervalValueType;
template<typename T> // tuple<type to test on, test array size>
class IntervalSetTest : public ::testing::Test {
public:
typedef T ISet;
};
typedef ::testing::Types< interval_set<IntervalValueType> , btree_interval_set<IntervalValueType> > IntervalSetTypes;
TYPED_TEST_CASE(IntervalSetTest, IntervalSetTypes);
TYPED_TEST(IntervalSetTest, compare) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2;
ASSERT_TRUE(iset1 == iset1);
ASSERT_TRUE(iset1 == iset2);
iset1.insert(1);
ASSERT_FALSE(iset1 == iset2);
iset2.insert(1);
ASSERT_TRUE(iset1 == iset2);
iset1.insert(2, 3);
iset2.insert(2, 4);
ASSERT_FALSE(iset1 == iset2);
iset2.erase(2, 4);
iset2.erase(1);
iset2.insert(2, 3);
iset2.insert(1);
ASSERT_TRUE(iset1 == iset2);
iset1.insert(100, 10);
iset2.insert(100, 5);
ASSERT_FALSE(iset1 == iset2);
iset2.insert(105, 5);
ASSERT_TRUE(iset1 == iset2);
iset1.insert(200, 10);
iset2.insert(205, 5);
ASSERT_FALSE(iset1 == iset2);
iset2.insert(200, 1);
iset2.insert(202, 3);
ASSERT_FALSE(iset1 == iset2);
iset2.insert(201, 1);
ASSERT_TRUE(iset1 == iset2);
iset1.clear();
ASSERT_FALSE(iset1 == iset2);
iset2.clear();
ASSERT_TRUE(iset1 == iset2);
}
TYPED_TEST(IntervalSetTest, contains) {
typedef typename TestFixture::ISet ISet;
ISet iset1;
ASSERT_FALSE(iset1.contains( 1 ));
ASSERT_FALSE(iset1.contains( 0, 1 ));
iset1.insert(1);
ASSERT_TRUE(iset1.contains( 1 ));
ASSERT_FALSE(iset1.contains( 0 ));
ASSERT_FALSE(iset1.contains( 2 ));
ASSERT_FALSE(iset1.contains( 0, 1 ));
ASSERT_FALSE(iset1.contains( 0, 2 ));
ASSERT_TRUE(iset1.contains( 1, 1 ));
ASSERT_FALSE(iset1.contains( 1, 2 ));
iset1.insert(2, 3);
ASSERT_TRUE(iset1.contains( 1 ));
ASSERT_FALSE(iset1.contains( 0 ));
ASSERT_TRUE(iset1.contains( 2 ));
ASSERT_FALSE(iset1.contains( 0, 1 ));
ASSERT_FALSE(iset1.contains( 0, 2 ));
ASSERT_TRUE(iset1.contains( 1, 1 ));
ASSERT_TRUE(iset1.contains( 1, 2 ));
ASSERT_TRUE(iset1.contains( 1, 3 ));
ASSERT_TRUE(iset1.contains( 1, 4 ));
ASSERT_FALSE(iset1.contains( 1, 5 ));
ASSERT_TRUE(iset1.contains( 2, 1 ));
ASSERT_TRUE(iset1.contains( 2, 2 ));
ASSERT_TRUE(iset1.contains( 2, 3 ));
ASSERT_FALSE(iset1.contains( 2, 4 ));
ASSERT_TRUE(iset1.contains( 3, 2 ));
ASSERT_TRUE(iset1.contains( 4, 1 ));
ASSERT_FALSE(iset1.contains( 4, 2 ));
iset1.insert(10, 10);
ASSERT_TRUE(iset1.contains( 1, 4 ));
ASSERT_FALSE(iset1.contains( 1, 5 ));
ASSERT_TRUE(iset1.contains( 2, 2 ));
ASSERT_FALSE(iset1.contains( 2, 4 ));
ASSERT_FALSE(iset1.contains( 1, 10 ));
ASSERT_FALSE(iset1.contains( 9, 1 ));
ASSERT_FALSE(iset1.contains( 9 ));
ASSERT_FALSE(iset1.contains( 9, 11 ));
ASSERT_TRUE(iset1.contains( 10, 1 ));
ASSERT_TRUE(iset1.contains( 11, 9 ));
ASSERT_TRUE(iset1.contains( 11, 2 ));
ASSERT_TRUE(iset1.contains( 18, 2 ));
ASSERT_TRUE(iset1.contains( 18, 2 ));
ASSERT_TRUE(iset1.contains( 10 ));
ASSERT_TRUE(iset1.contains( 19 ));
ASSERT_FALSE(iset1.contains( 20 ));
ASSERT_FALSE(iset1.contains( 21 ));
ASSERT_FALSE(iset1.contains( 11, 11 ));
ASSERT_FALSE(iset1.contains( 18, 9 ));
iset1.clear();
ASSERT_FALSE(iset1.contains( 1 ));
ASSERT_FALSE(iset1.contains( 0 ));
ASSERT_FALSE(iset1.contains( 2 ));
ASSERT_FALSE(iset1.contains( 0, 1 ));
ASSERT_FALSE(iset1.contains( 0, 2 ));
ASSERT_FALSE(iset1.contains( 1, 1 ));
ASSERT_FALSE(iset1.contains( 10, 2 ));
}
TYPED_TEST(IntervalSetTest, intersects) {
typedef typename TestFixture::ISet ISet;
ISet iset1;
ASSERT_FALSE(iset1.intersects( 1, 1 ));
ASSERT_FALSE(iset1.intersects( 0, 1 ));
ASSERT_FALSE(iset1.intersects( 0, 10 ));
iset1.insert(1);
ASSERT_TRUE(iset1.intersects( 1, 1 ));
ASSERT_FALSE(iset1.intersects( 0, 1 ));
ASSERT_FALSE(iset1.intersects( 2, 1 ));
ASSERT_TRUE(iset1.intersects( 0, 2 ));
ASSERT_TRUE(iset1.intersects( 0, 20 ));
ASSERT_TRUE(iset1.intersects( 1, 2 ));
ASSERT_TRUE(iset1.intersects( 1, 20 ));
iset1.insert(2, 3);
ASSERT_FALSE(iset1.intersects( 0, 1 ));
ASSERT_TRUE(iset1.intersects( 0, 2 ));
ASSERT_TRUE(iset1.intersects( 0, 200 ));
ASSERT_TRUE(iset1.intersects( 1, 1 ));
ASSERT_TRUE(iset1.intersects( 1, 4 ));
ASSERT_TRUE(iset1.intersects( 1, 5 ));
ASSERT_TRUE(iset1.intersects( 2, 1 ));
ASSERT_TRUE(iset1.intersects( 2, 2 ));
ASSERT_TRUE(iset1.intersects( 2, 3 ));
ASSERT_TRUE(iset1.intersects( 2, 4 ));
ASSERT_TRUE(iset1.intersects( 3, 2 ));
ASSERT_TRUE(iset1.intersects( 4, 1 ));
ASSERT_TRUE(iset1.intersects( 4, 2 ));
ASSERT_FALSE(iset1.intersects( 5, 2 ));
iset1.insert(10, 10);
ASSERT_TRUE(iset1.intersects( 1, 4 ));
ASSERT_TRUE(iset1.intersects( 1, 5 ));
ASSERT_TRUE(iset1.intersects( 1, 10 ));
ASSERT_TRUE(iset1.intersects( 2, 2 ));
ASSERT_TRUE(iset1.intersects( 2, 4 ));
ASSERT_FALSE(iset1.intersects( 5, 1 ));
ASSERT_FALSE(iset1.intersects( 5, 2 ));
ASSERT_FALSE(iset1.intersects( 5, 5 ));
ASSERT_TRUE(iset1.intersects( 5, 12 ));
ASSERT_TRUE(iset1.intersects( 5, 20 ));
ASSERT_FALSE(iset1.intersects( 9, 1 ));
ASSERT_TRUE(iset1.intersects( 9, 2 ));
ASSERT_TRUE(iset1.intersects( 9, 11 ));
ASSERT_TRUE(iset1.intersects( 10, 1 ));
ASSERT_TRUE(iset1.intersects( 11, 9 ));
ASSERT_TRUE(iset1.intersects( 11, 2 ));
ASSERT_TRUE(iset1.intersects( 11, 11 ));
ASSERT_TRUE(iset1.intersects( 18, 2 ));
ASSERT_TRUE(iset1.intersects( 18, 9 ));
ASSERT_FALSE(iset1.intersects( 20, 1 ));
ASSERT_FALSE(iset1.intersects( 21, 12 ));
iset1.clear();
ASSERT_FALSE(iset1.intersects( 0, 1 ));
ASSERT_FALSE(iset1.intersects( 0, 2 ));
ASSERT_FALSE(iset1.intersects( 1, 1 ));
ASSERT_FALSE(iset1.intersects( 5, 2 ));
ASSERT_FALSE(iset1.intersects( 10, 2 ));
}
TYPED_TEST(IntervalSetTest, insert_erase) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2;
IntervalValueType start, len;
iset1.insert(3, 5, &start, &len);
ASSERT_TRUE( start == 3 );
ASSERT_TRUE( len == 5 );
ASSERT_TRUE( iset1.num_intervals() == 1 );
ASSERT_TRUE( iset1.size() == 5 );
//adding standalone interval
iset1.insert(15, 10, &start, &len);
ASSERT_TRUE( start == 15 );
ASSERT_TRUE( len == 10 );
ASSERT_TRUE( iset1.num_intervals() == 2 );
ASSERT_EQ( iset1.size(), 15 );
//adding leftmost standalone interval
iset1.insert(1, 1, &start, &len);
ASSERT_TRUE( start == 1 );
ASSERT_TRUE( len == 1 );
ASSERT_TRUE( iset1.num_intervals() == 3 );
ASSERT_EQ( iset1.size(), 16 );
//adding leftmost adjusent interval
iset1.insert(0, 1, &start, &len);
ASSERT_TRUE( start == 0 );
ASSERT_TRUE( len == 2 );
ASSERT_TRUE( iset1.num_intervals() == 3 );
ASSERT_EQ( iset1.size(), 17 );
//adding interim interval that merges leftmost and subseqent intervals
iset1.insert(2, 1, &start, &len);
ASSERT_TRUE( start == 0 );
ASSERT_TRUE( len == 8 );
ASSERT_TRUE( iset1.num_intervals() == 2);
ASSERT_EQ( iset1.size(), 18);
//adding rigtmost standalone interval
iset1.insert(30, 5, &start, &len);
ASSERT_TRUE( start == 30 );
ASSERT_TRUE( len == 5 );
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 23 );
//adding rigtmost adjusent interval
iset1.insert(35, 10, &start, &len);
ASSERT_TRUE( start == 30 );
ASSERT_TRUE( len == 15 );
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 33 );
//adding interim interval that merges with the interval preceeding the rightmost
iset1.insert(25, 1, &start, &len);
ASSERT_TRUE( start == 15 );
ASSERT_TRUE( len == 11 );
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 34);
//adding interim interval that merges with the rightmost and preceeding intervals
iset1.insert(26, 4, &start, &len);
ASSERT_TRUE( start == 15 );
ASSERT_TRUE( len == 30 );
ASSERT_TRUE( iset1.num_intervals() == 2);
ASSERT_EQ( iset1.size(), 38);
//and finally build single interval filling the gap at 8-15 using different interval set
iset2.insert( 8, 1 );
iset2.insert( 14, 1 );
iset2.insert( 9, 4 );
iset1.insert( iset2 );
iset1.insert(13, 1, &start, &len);
ASSERT_TRUE( start == 0 );
ASSERT_TRUE( len == 45 );
ASSERT_TRUE( iset1.num_intervals() == 1);
ASSERT_EQ( iset1.size(), 45);
//now reverses the process using subtract & erase
iset1.subtract( iset2 );
iset1.erase(13, 1);
ASSERT_TRUE( iset1.num_intervals() == 2);
ASSERT_EQ( iset1.size(), 38);
ASSERT_TRUE( iset1.contains( 7, 1 ));
ASSERT_FALSE( iset1.contains( 8, 7 ));
ASSERT_TRUE( iset1.contains( 15, 1 ));
ASSERT_TRUE( iset1.contains( 26, 4 ));
iset1.erase(26, 4);
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 34);
ASSERT_TRUE( iset1.contains( 7, 1 ));
ASSERT_FALSE( iset1.intersects( 8, 7 ));
ASSERT_TRUE( iset1.contains( 15, 1 ));
ASSERT_TRUE( iset1.contains( 25, 1 ));
ASSERT_FALSE( iset1.contains( 26, 4 ));
ASSERT_TRUE( iset1.contains( 30, 1 ));
iset1.erase(25, 1);
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 33 );
ASSERT_TRUE( iset1.contains( 24, 1 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
ASSERT_FALSE( iset1.intersects( 26, 4 ));
ASSERT_TRUE( iset1.contains( 30, 1 ));
ASSERT_TRUE( iset1.contains( 35, 10 ));
iset1.erase(35, 10);
ASSERT_TRUE( iset1.num_intervals() == 3);
ASSERT_EQ( iset1.size(), 23 );
ASSERT_TRUE( iset1.contains( 30, 5 ));
ASSERT_TRUE( iset1.contains( 34, 1 ));
ASSERT_FALSE( iset1.contains( 35, 10 ));
ASSERT_FALSE(iset1.contains( 45, 1 ));
iset1.erase(30, 5);
ASSERT_TRUE( iset1.num_intervals() == 2);
ASSERT_EQ( iset1.size(), 18);
ASSERT_TRUE( iset1.contains( 2, 1 ));
ASSERT_TRUE( iset1.contains( 24, 1 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
ASSERT_FALSE( iset1.contains( 29, 1 ));
ASSERT_FALSE( iset1.contains( 30, 5 ));
ASSERT_FALSE( iset1.contains( 35, 1 ));
iset1.erase(2, 1);
ASSERT_TRUE( iset1.num_intervals() == 3 );
ASSERT_EQ( iset1.size(), 17 );
ASSERT_TRUE( iset1.contains( 0, 1 ));
ASSERT_TRUE( iset1.contains( 1, 1 ));
ASSERT_FALSE( iset1.contains( 2, 1 ));
ASSERT_TRUE( iset1.contains( 3, 1 ));
ASSERT_TRUE( iset1.contains( 15, 1 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
iset1.erase( 0, 1);
ASSERT_TRUE( iset1.num_intervals() == 3 );
ASSERT_EQ( iset1.size(), 16 );
ASSERT_FALSE( iset1.contains( 0, 1 ));
ASSERT_TRUE( iset1.contains( 1, 1 ));
ASSERT_FALSE( iset1.contains( 2, 1 ));
ASSERT_TRUE( iset1.contains( 3, 1 ));
ASSERT_TRUE( iset1.contains( 15, 1 ));
iset1.erase(1, 1);
ASSERT_TRUE( iset1.num_intervals() == 2 );
ASSERT_EQ( iset1.size(), 15 );
ASSERT_FALSE( iset1.contains( 1, 1 ));
ASSERT_TRUE( iset1.contains( 15, 10 ));
ASSERT_TRUE( iset1.contains( 3, 5 ));
iset1.erase(15, 10);
ASSERT_TRUE( iset1.num_intervals() == 1 );
ASSERT_TRUE( iset1.size() == 5 );
ASSERT_FALSE( iset1.contains( 1, 1 ));
ASSERT_FALSE( iset1.contains( 15, 10 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
ASSERT_TRUE( iset1.contains( 3, 5 ));
iset1.erase( 3, 1);
ASSERT_TRUE( iset1.num_intervals() == 1 );
ASSERT_TRUE( iset1.size() == 4 );
ASSERT_FALSE( iset1.contains( 1, 1 ));
ASSERT_FALSE( iset1.contains( 15, 10 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
ASSERT_TRUE( iset1.contains( 4, 4 ));
ASSERT_FALSE( iset1.contains( 3, 5 ));
iset1.erase( 4, 4);
ASSERT_TRUE( iset1.num_intervals() == 0);
ASSERT_TRUE( iset1.size() == 0);
ASSERT_FALSE( iset1.contains( 1, 1 ));
ASSERT_FALSE( iset1.contains( 15, 10 ));
ASSERT_FALSE( iset1.contains( 25, 1 ));
ASSERT_FALSE( iset1.contains( 3, 4 ));
ASSERT_FALSE( iset1.contains( 3, 5 ));
ASSERT_FALSE( iset1.contains( 4, 4 ));
}
TYPED_TEST(IntervalSetTest, intersect_of) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2, iset3;
iset1.intersection_of( iset2, iset3 );
ASSERT_TRUE( iset1.num_intervals() == 0);
ASSERT_TRUE( iset1.size() == 0);
iset2.insert( 0, 1 );
iset2.insert( 5, 10 );
iset2.insert( 30, 10 );
iset3.insert( 0, 2 );
iset3.insert( 15, 1 );
iset3.insert( 20, 5 );
iset3.insert( 29, 3 );
iset3.insert( 35, 3 );
iset3.insert( 39, 3 );
iset1.intersection_of( iset2, iset3 );
ASSERT_TRUE( iset1.num_intervals() == 4);
ASSERT_TRUE( iset1.size() == 7);
ASSERT_TRUE( iset1.contains( 0, 1 ));
ASSERT_FALSE( iset1.contains( 0, 2 ));
ASSERT_FALSE( iset1.contains( 5, 11 ));
ASSERT_FALSE( iset1.contains( 4, 1 ));
ASSERT_FALSE( iset1.contains( 16, 1 ));
ASSERT_FALSE( iset1.contains( 20, 5 ));
ASSERT_FALSE( iset1.contains( 29, 1 ));
ASSERT_FALSE( iset1.contains( 30, 10 ));
ASSERT_TRUE( iset1.contains( 30, 2 ));
ASSERT_TRUE( iset1.contains( 35, 3 ));
ASSERT_FALSE( iset1.contains( 35, 4 ));
ASSERT_TRUE( iset1.contains( 39, 1 ));
ASSERT_FALSE( iset1.contains( 38, 2 ));
ASSERT_FALSE( iset1.contains( 39, 2 ));
iset3=iset1;
iset1.intersection_of(iset2);
ASSERT_TRUE( iset1 == iset3);
iset2.clear();
iset2.insert(0,1);
iset1.intersection_of(iset2);
ASSERT_TRUE( iset1.num_intervals() == 1);
ASSERT_TRUE( iset1.size() == 1);
iset1 = iset3;
iset2.clear();
iset1.intersection_of(iset2);
ASSERT_TRUE( iset1.num_intervals() == 0);
ASSERT_TRUE( iset1.size() == 0);
}
TYPED_TEST(IntervalSetTest, union_of) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2, iset3;
iset1.union_of( iset2, iset3 );
ASSERT_TRUE( iset1.num_intervals() == 0);
ASSERT_TRUE( iset1.size() == 0);
iset2.insert( 0, 1 );
iset2.insert( 5, 10 );
iset2.insert( 30, 10 );
iset3.insert( 0, 2 );
iset3.insert( 15, 1 );
iset3.insert( 20, 5 );
iset3.insert( 29, 3 );
iset3.insert( 39, 3 );
iset1.union_of( iset2, iset3 );
ASSERT_TRUE( iset1.num_intervals() == 4);
ASSERT_EQ( iset1.size(), 31);
ASSERT_TRUE( iset1.contains( 0, 2 ));
ASSERT_FALSE( iset1.contains( 0, 3 ));
ASSERT_TRUE( iset1.contains( 5, 11 ));
ASSERT_FALSE( iset1.contains( 4, 1 ));
ASSERT_FALSE( iset1.contains( 16, 1 ));
ASSERT_TRUE( iset1.contains( 20, 5 ));
ASSERT_TRUE( iset1.contains( 30, 10 ));
ASSERT_TRUE( iset1.contains( 29, 13 ));
ASSERT_FALSE( iset1.contains( 29, 14 ));
ASSERT_FALSE( iset1.contains( 42, 1 ));
iset2.clear();
iset1.union_of(iset2);
ASSERT_TRUE( iset1.num_intervals() == 4);
ASSERT_EQ( iset1.size(), 31);
iset3.clear();
iset3.insert( 29, 3 );
iset3.insert( 39, 2 );
iset1.union_of(iset3);
ASSERT_TRUE( iset1.num_intervals() == 4);
ASSERT_EQ( iset1.size(), 31); //actually we added nothing
ASSERT_TRUE( iset1.contains( 29, 13 ));
ASSERT_FALSE( iset1.contains( 29, 14 ));
ASSERT_FALSE( iset1.contains( 42, 1 ));
}
TYPED_TEST(IntervalSetTest, subset_of) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2;
ASSERT_TRUE(iset1.subset_of(iset2));
iset1.insert(5,10);
ASSERT_FALSE(iset1.subset_of(iset2));
iset2.insert(6,8);
ASSERT_FALSE(iset1.subset_of(iset2));
iset2.insert(5,1);
ASSERT_FALSE(iset1.subset_of(iset2));
iset2.insert(14,10);
ASSERT_TRUE(iset1.subset_of(iset2));
iset1.insert( 20, 4);
ASSERT_TRUE(iset1.subset_of(iset2));
iset1.insert( 24, 1);
ASSERT_FALSE(iset1.subset_of(iset2));
}
TYPED_TEST(IntervalSetTest, span_of) {
typedef typename TestFixture::ISet ISet;
ISet iset1, iset2;
iset2.insert(5,5);
iset2.insert(20,5);
iset1.span_of( iset2, 8, 5 );
ASSERT_EQ( iset1.num_intervals(), 2);
ASSERT_EQ( iset1.size(), 5);
ASSERT_TRUE( iset1.contains( 8, 2 ));
ASSERT_TRUE( iset1.contains( 20, 3 ));
iset1.span_of( iset2, 3, 5 );
ASSERT_EQ( iset1.num_intervals(), 1);
ASSERT_EQ( iset1.size(), 5);
ASSERT_TRUE( iset1.contains( 5, 5 ));
iset1.span_of( iset2, 10, 7 );
ASSERT_EQ( iset1.num_intervals(), 1);
ASSERT_EQ( iset1.size(), 5);
ASSERT_TRUE( iset1.contains( 20, 5 ));
ASSERT_FALSE( iset1.contains( 20, 6 ));
iset1.span_of( iset2, 5, 10);
ASSERT_EQ( iset1.num_intervals(), 2);
ASSERT_EQ( iset1.size(), 10);
ASSERT_TRUE( iset1.contains( 5, 5 ));
ASSERT_TRUE( iset1.contains( 20, 5 ));
iset1.span_of( iset2, 100, 5 );
ASSERT_EQ( iset1.num_intervals(), 0);
ASSERT_EQ( iset1.size(), 0);
}

View File

@ -30,7 +30,7 @@ void ContDesc::decode(bufferlist::iterator &bl)
DECODE_FINISH(bl);
}
ostream &operator<<(ostream &out, const ContDesc &rhs)
std::ostream &operator<<(std::ostream &out, const ContDesc &rhs)
{
return out << "(ObjNum " << rhs.objnum
<< " snap " << rhs.cursnap
@ -40,7 +40,7 @@ ostream &operator<<(ostream &out, const ContDesc &rhs)
}
void AppendGenerator::get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out) {
const ContDesc &cont, std::map<uint64_t, uint64_t> &out) {
RandWrap rand(cont.seqnum);
uint64_t pos = off;
uint64_t limit = off + get_append_size(cont);
@ -54,13 +54,13 @@ void AppendGenerator::get_ranges_map(
}
if (alignment)
assert(segment_length % alignment == 0);
out.insert(pair<uint64_t, uint64_t>(pos, segment_length));
out.insert(std::pair<uint64_t, uint64_t>(pos, segment_length));
pos += segment_length;
}
}
void VarLenGenerator::get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out) {
const ContDesc &cont, std::map<uint64_t, uint64_t> &out) {
RandWrap rand(cont.seqnum);
uint64_t pos = 0;
uint64_t limit = get_length(cont);
@ -73,7 +73,7 @@ void VarLenGenerator::get_ranges_map(
segment_length = limit - pos;
}
if (include) {
out.insert(pair<uint64_t, uint64_t>(pos, segment_length));
out.insert(std::pair<uint64_t, uint64_t>(pos, segment_length));
include = false;
} else {
include = true;
@ -104,7 +104,7 @@ ObjectDesc::iterator &ObjectDesc::iterator::advance(bool init) {
interval_set<uint64_t> ranges;
cur_cont->first->get_ranges(cur_cont->second, ranges);
while (!ranges.contains(pos)) {
stack.push_front(pair<list<pair<ceph::shared_ptr<ContentsGenerator>,
stack.push_front(std::pair<std::list<std::pair<ceph::shared_ptr<ContentsGenerator>,
ContDesc> >::iterator,
uint64_t>(cur_cont, limit));
uint64_t length = cur_cont->first->get_length(cur_cont->second);
@ -135,11 +135,11 @@ ObjectDesc::iterator &ObjectDesc::iterator::advance(bool init) {
}
if (!cont_iters.count(cur_cont->second)) {
cont_iters.insert(pair<ContDesc,ContentsGenerator::iterator>(
cont_iters.insert(std::pair<ContDesc,ContentsGenerator::iterator>(
cur_cont->second,
cur_cont->first->get_iterator(cur_cont->second)));
}
map<ContDesc,ContentsGenerator::iterator>::iterator j = cont_iters.find(
std::map<ContDesc,ContentsGenerator::iterator>::iterator j = cont_iters.find(
cur_cont->second);
assert(j != cont_iters.end());
j->second.seek(pos);
@ -151,7 +151,7 @@ const ContDesc &ObjectDesc::most_recent() {
}
void ObjectDesc::update(ContentsGenerator *gen, const ContDesc &next) {
layers.push_front(pair<ceph::shared_ptr<ContentsGenerator>, ContDesc>(ceph::shared_ptr<ContentsGenerator>(gen), next));
layers.push_front(std::pair<ceph::shared_ptr<ContentsGenerator>, ContDesc>(ceph::shared_ptr<ContentsGenerator>(gen), next));
return;
}

View File

@ -14,8 +14,8 @@ public:
int objnum;
int cursnap;
unsigned seqnum;
string prefix;
string oid;
std::string prefix;
std::string oid;
ContDesc() :
objnum(0), cursnap(0),
@ -24,7 +24,7 @@ public:
ContDesc(int objnum,
int cursnap,
unsigned seqnum,
const string &prefix) :
const std::string &prefix) :
objnum(objnum), cursnap(cursnap),
seqnum(seqnum), prefix(prefix) {}
@ -48,7 +48,7 @@ public:
};
WRITE_CLASS_ENCODER(ContDesc)
ostream &operator<<(ostream &out, const ContDesc &rhs);
std::ostream &operator<<(std::ostream &out, const ContDesc &rhs);
class ContentsGenerator {
public:
@ -97,11 +97,11 @@ public:
virtual uint64_t get_length(const ContDesc &in) = 0;
virtual void get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out) = 0;
const ContDesc &cont, std::map<uint64_t, uint64_t> &out) = 0;
void get_ranges(const ContDesc &cont, interval_set<uint64_t> &out) {
map<uint64_t, uint64_t> ranges;
std::map<uint64_t, uint64_t> ranges;
get_ranges_map(cont, ranges);
for (map<uint64_t, uint64_t>::iterator i = ranges.begin();
for (std::map<uint64_t, uint64_t>::iterator i = ranges.begin();
i != ranges.end();
++i) {
out.insert(i->first, i->second);
@ -207,7 +207,7 @@ public:
min_stride_size(min_stride_size),
max_stride_size(max_stride_size) {}
void get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out);
const ContDesc &cont, std::map<uint64_t, uint64_t> &out);
uint64_t get_length(const ContDesc &in) {
RandWrap rand(in.seqnum);
if (max_length == 0)
@ -223,8 +223,8 @@ public:
AttrGenerator(uint64_t max_len, uint64_t big_max_len)
: max_len(max_len), big_max_len(big_max_len) {}
void get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out) {
out.insert(pair<uint64_t, uint64_t>(0, get_length(cont)));
const ContDesc &cont, std::map<uint64_t, uint64_t> &out) {
out.insert(std::pair<uint64_t, uint64_t>(0, get_length(cont)));
}
uint64_t get_length(const ContDesc &in) {
RandWrap rand(in.seqnum);
@ -279,7 +279,7 @@ public:
return off + get_append_size(in);
}
void get_ranges_map(
const ContDesc &cont, map<uint64_t, uint64_t> &out);
const ContDesc &cont, std::map<uint64_t, uint64_t> &out);
};
class ObjectDesc {
@ -290,19 +290,19 @@ public:
ObjectDesc(const ContDesc &init, ContentsGenerator *cont_gen)
: exists(false), dirty(false),
version(0) {
layers.push_front(pair<ceph::shared_ptr<ContentsGenerator>, ContDesc>(ceph::shared_ptr<ContentsGenerator>(cont_gen), init));
layers.push_front(std::pair<ceph::shared_ptr<ContentsGenerator>, ContDesc>(ceph::shared_ptr<ContentsGenerator>(cont_gen), init));
}
class iterator {
public:
uint64_t pos;
ObjectDesc &obj;
list<pair<list<pair<ceph::shared_ptr<ContentsGenerator>,
std::list<std::pair<std::list<std::pair<ceph::shared_ptr<ContentsGenerator>,
ContDesc> >::iterator,
uint64_t> > stack;
map<ContDesc,ContentsGenerator::iterator> cont_iters;
std::map<ContDesc,ContentsGenerator::iterator> cont_iters;
uint64_t limit;
list<pair<ceph::shared_ptr<ContentsGenerator>,
std::list<std::pair<ceph::shared_ptr<ContentsGenerator>,
ContDesc> >::iterator cur_cont;
iterator(ObjectDesc &obj) :
@ -321,7 +321,7 @@ public:
if (cur_cont == obj.layers.end()) {
return '\0';
} else {
map<ContDesc,ContentsGenerator::iterator>::iterator j = cont_iters.find(
std::map<ContDesc,ContentsGenerator::iterator>::iterator j = cont_iters.find(
cur_cont->second);
assert(j != cont_iters.end());
return *(j->second);
@ -364,14 +364,14 @@ public:
ContentsGenerator *most_recent_gen() {
return layers.begin()->first.get();
}
map<string, ContDesc> attrs; // Both omap and xattrs
std::map<std::string, ContDesc> attrs; // Both omap and xattrs
bufferlist header;
bool exists;
bool dirty;
uint64_t version;
private:
list<pair<ceph::shared_ptr<ContentsGenerator>, ContDesc> > layers;
std::list<std::pair<ceph::shared_ptr<ContentsGenerator>, ContDesc> > layers;
};
#endif