1
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
#include "common/Mutex.h"
3
#include "common/Cond.h"
14
#include "test/osd/RadosModel.h"
18
class WeightedTestGenerator : public TestOpGenerator
22
WeightedTestGenerator(int ops,
24
map<TestOpType, unsigned int> op_weights,
27
m_nextop(NULL), m_op(0), m_ops(ops), m_seconds(max_seconds), m_objects(objects), m_stats(stats),
31
for (map<TestOpType, unsigned int>::const_iterator it = op_weights.begin();
32
it != op_weights.end();
34
m_total_weight += it->second;
35
m_weight_sums.insert(pair<TestOpType, unsigned int>(it->first,
40
TestOp *next(RadosTestContext &context)
42
TestOp *retval = NULL;
45
if (m_op <= m_objects) {
48
cout << m_op << ": Writing initial " << oid.str() << std::endl;
49
return new WriteOp(&context, oid.str());
50
} else if (m_op >= m_ops) {
60
while (retval == NULL) {
61
unsigned int rand_val = rand() % m_total_weight;
64
if (m_seconds && now - m_start > m_seconds)
67
for (map<TestOpType, unsigned int>::const_iterator it = m_weight_sums.begin();
68
it != m_weight_sums.end();
70
if (rand_val < it->second) {
72
retval = gen_op(context, it->first);
82
TestOp *gen_op(RadosTestContext &context, TestOpType type)
87
oid = *(rand_choose(context.oid_not_in_use));
88
cout << "Reading " << oid << std::endl;
89
return new ReadOp(&context, oid, m_stats);
92
oid = *(rand_choose(context.oid_not_in_use));
93
cout << "Writing " << oid << " current snap is "
94
<< context.current_snap << std::endl;
95
return new WriteOp(&context, oid, m_stats);
98
oid = *(rand_choose(context.oid_not_in_use));
99
cout << "Deleting " << oid << " current snap is "
100
<< context.current_snap << std::endl;
101
return new DeleteOp(&context, oid, m_stats);
103
case TEST_OP_SNAP_CREATE:
104
cout << "Snapping" << std::endl;
105
return new SnapCreateOp(&context, m_stats);
107
case TEST_OP_SNAP_REMOVE:
108
if (context.snaps.empty()) {
111
int snap = rand_choose(context.snaps)->first;
112
cout << "RemovingSnap " << snap << std::endl;
113
return new SnapRemoveOp(&context, snap, m_stats);
116
case TEST_OP_ROLLBACK:
117
if (context.snaps.empty()) {
120
int snap = rand_choose(context.snaps)->first;
121
string oid = *(rand_choose(context.oid_not_in_use));
122
cout << "RollingBack " << oid << " to " << snap << std::endl;
123
m_nextop = new ReadOp(&context, oid, m_stats);
124
return new RollbackOp(&context, oid, snap);
128
cerr << "Invalid op type " << type << std::endl;
140
map<TestOpType, unsigned int> m_weight_sums;
141
unsigned int m_total_weight;
144
int main(int argc, char **argv)
148
int max_in_flight = 16;
149
int64_t size = 4000000; // 4 MB
150
int64_t min_stride_size = -1, max_stride_size = -1;
157
{ TEST_OP_READ, "read" },
158
{ TEST_OP_WRITE, "write" },
159
{ TEST_OP_DELETE, "delete" },
160
{ TEST_OP_SNAP_CREATE, "snap_create" },
161
{ TEST_OP_SNAP_REMOVE, "snap_remove" },
162
{ TEST_OP_ROLLBACK, "rollback" },
163
{ TEST_OP_READ /* grr */, NULL },
166
map<TestOpType, unsigned int> op_weights;
168
for (int i = 1; i < argc; ++i) {
169
if (strcmp(argv[i], "--max-ops") == 0)
170
ops = atoi(argv[++i]);
171
else if (strcmp(argv[i], "--max-seconds") == 0)
172
max_seconds = atoi(argv[++i]);
173
else if (strcmp(argv[i], "--objects") == 0)
174
objects = atoi(argv[++i]);
175
else if (strcmp(argv[i], "--max-in-flight") == 0)
176
max_in_flight = atoi(argv[++i]);
177
else if (strcmp(argv[i], "--size") == 0)
178
size = atoi(argv[++i]);
179
else if (strcmp(argv[i], "--min-stride-size") == 0)
180
min_stride_size = atoi(argv[++i]);
181
else if (strcmp(argv[i], "--max-stride-size") == 0)
182
max_stride_size = atoi(argv[++i]);
183
else if (strcmp(argv[i], "--op") == 0) {
186
for (j = 0; op_types[j].name; ++j) {
187
if (strcmp(op_types[j].name, argv[i]) == 0) {
191
if (!op_types[j].name) {
192
cerr << "unknown op " << argv[i] << std::endl;
195
int weight = atoi(argv[++i]);
197
cerr << "Weights must be nonnegative." << std::endl;
200
cout << "adding op weight " << op_types[j].name << " -> " << weight << std::endl;
201
op_weights.insert(pair<TestOpType, unsigned int>(op_types[j].op, weight));
203
cerr << "unknown arg " << argv[i] << std::endl;
209
if (min_stride_size < 0)
210
min_stride_size = size / 10;
211
if (max_stride_size < 0)
212
max_stride_size = size / 5;
214
cout << "Configuration:" << std::endl
215
<< "\tNumber of operations: " << ops << std::endl
216
<< "\tNumber of objects: " << objects << std::endl
217
<< "\tMax in flight operations: " << max_in_flight << std::endl
218
<< "\tObject size (in bytes): " << size << std::endl
219
<< "\tWrite stride min: " << min_stride_size << std::endl
220
<< "\tWrite stride max: " << max_stride_size << std::endl;
222
if (min_stride_size > max_stride_size) {
223
cerr << "Error: min_stride_size cannot be more than max_stride_size"
228
if (min_stride_size > size || max_stride_size > size) {
229
cerr << "Error: min_stride_size and max_stride_size must be "
230
<< "smaller than object size" << std::endl;
234
if (max_in_flight > objects) {
235
cerr << "Error: max_in_flight must be less than the number of objects"
240
char *id = getenv("CEPH_CLIENT_ID");
241
string pool_name = "data";
242
VarLenGenerator cont_gen(size, min_stride_size, max_stride_size);
243
RadosTestContext context(pool_name, max_in_flight, cont_gen, id);
246
WeightedTestGenerator gen = WeightedTestGenerator(ops, objects,
247
op_weights, &stats, max_seconds);
251
cerr << context.errors << " errors." << std::endl;
252
cerr << stats << std::endl;