1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
#include "ObjectContents.h"
#include "include/buffer.h"
#include <iostream>
#include <map>
bool test_object_contents()
{
ObjectContents c, d;
ceph_assert(!c.exists());
c.debug(std::cerr);
c.write(10, 10, 10);
ceph_assert(c.exists());
ceph_assert(c.size() == 20);
c.debug(std::cerr);
bufferlist bl;
for (ObjectContents::Iterator iter = c.get_iterator();
iter.valid();
++iter) {
bl.append(*iter);
}
ceph_assert(bl.length() == 20);
bufferlist bl2;
for (unsigned i = 0; i < 8; ++i) bl2.append(bl[i]);
c.write(10, 8, 4);
c.debug(std::cerr);
ObjectContents::Iterator iter = c.get_iterator();
iter.seek_to(8);
for (uint64_t i = 8;
i < 12;
++i, ++iter) {
bl2.append(*iter);
}
for (unsigned i = 12; i < 20; ++i) bl2.append(bl[i]);
ceph_assert(bl2.length() == 20);
for (ObjectContents::Iterator iter3 = c.get_iterator();
iter.valid();
++iter) {
ceph_assert(bl2[iter3.get_pos()] == *iter3);
}
ceph_assert(bl2[0] == '\0');
ceph_assert(bl2[7] == '\0');
interval_set<uint64_t> to_clone;
to_clone.insert(5, 10);
d.clone_range(c, to_clone);
ceph_assert(d.size() == 15);
c.debug(std::cerr);
d.debug(std::cerr);
ObjectContents::Iterator iter2 = d.get_iterator();
iter2.seek_to(5);
for (uint64_t i = 5; i < 15; ++i, ++iter2) {
std::cerr << "i is " << i << std::endl;
ceph_assert(iter2.get_pos() == i);
ceph_assert(*iter2 == bl2[i]);
}
return true;
}
unsigned int ObjectContents::Iterator::get_state(uint64_t _pos)
{
if (parent->seeds.count(_pos)) {
return parent->seeds[_pos];
}
seek_to(_pos - 1);
return current_state;
}
void ObjectContents::clone_range(ObjectContents &other,
interval_set<uint64_t> &intervals)
{
interval_set<uint64_t> written_to_clone;
written_to_clone.intersection_of(intervals, other.written);
interval_set<uint64_t> zeroed = intervals;
zeroed.subtract(written_to_clone);
written.union_of(intervals);
written.subtract(zeroed);
for (interval_set<uint64_t>::iterator i = written_to_clone.begin();
i != written_to_clone.end();
++i) {
uint64_t start = i.get_start();
uint64_t len = i.get_len();
unsigned int seed = get_iterator().get_state(start+len);
seeds[start+len] = seed;
seeds.erase(seeds.lower_bound(start), seeds.lower_bound(start+len));
seeds[start] = other.get_iterator().get_state(start);
seeds.insert(other.seeds.upper_bound(start),
other.seeds.lower_bound(start+len));
}
if (intervals.range_end() > _size)
_size = intervals.range_end();
_exists = true;
return;
}
void ObjectContents::write(unsigned int seed,
uint64_t start,
uint64_t len)
{
_exists = true;
unsigned int _seed = get_iterator().get_state(start+len);
seeds[start+len] = _seed;
seeds.erase(seeds.lower_bound(start),
seeds.lower_bound(start+len));
seeds[start] = seed;
interval_set<uint64_t> to_write;
to_write.insert(start, len);
written.union_of(to_write);
if (start + len > _size)
_size = start + len;
return;
}
|