mirror of
https://github.com/ceph/ceph
synced 2025-02-21 18:17:42 +00:00
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:
commit
9c30be93e3
@ -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 \
|
||||
|
584
src/include/btree_interval_set.h
Normal file
584
src/include/btree_interval_set.h
Normal 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
|
2394
src/include/cpp-btree/btree.h
Normal file
2394
src/include/cpp-btree/btree.h
Normal file
File diff suppressed because it is too large
Load Diff
349
src/include/cpp-btree/btree_container.h
Normal file
349
src/include/cpp-btree/btree_container.h
Normal 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__
|
130
src/include/cpp-btree/btree_map.h
Normal file
130
src/include/cpp-btree/btree_map.h
Normal 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__
|
60
src/include/encoding_btree.h
Normal file
60
src/include/encoding_btree.h
Normal 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
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 << "], ";
|
||||
|
564
src/test/common/test_interval_set.cc
Normal file
564
src/test/common/test_interval_set.cc
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user