Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / bench / small_io_bench.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
3 #include <boost/scoped_ptr.hpp>
4 #include <boost/lexical_cast.hpp>
5 #include <boost/program_options/option.hpp>
6 #include <boost/program_options/options_description.hpp>
7 #include <boost/program_options/variables_map.hpp>
8 #include <boost/program_options/cmdline.hpp>
9 #include <boost/program_options/parsers.hpp>
10 #include <iostream>
11 #include <set>
12 #include <sstream>
13 #include <stdlib.h>
14 #include <fstream>
15
16 #include "common/Formatter.h"
17
18 #include "bencher.h"
19 #include "rados_backend.h"
20 #include "detailed_stat_collector.h"
21 #include "distribution.h"
22
23 namespace po = boost::program_options;
24 using namespace std;
25
26 int main(int argc, char **argv)
27 {
28   po::options_description desc("Allowed options");
29   desc.add_options()
30     ("help", "produce help message")
31     ("num-concurrent-ops", po::value<unsigned>()->default_value(10),
32      "set number of concurrent ops")
33     ("num-objects", po::value<unsigned>()->default_value(500),
34      "set number of objects to use")
35     ("object-size", po::value<unsigned>()->default_value(4<<20),
36      "set object size")
37     ("io-size", po::value<unsigned>()->default_value(4<<10),
38      "set io size")
39     ("write-ratio", po::value<double>()->default_value(0.75),
40      "set ratio of read to write")
41     ("duration", po::value<unsigned>()->default_value(0),
42      "set max duration, 0 for unlimited")
43     ("max-ops", po::value<unsigned>()->default_value(0),
44      "set max ops, 0 for unlimited")
45     ("seed", po::value<unsigned>(),
46      "seed")
47     ("ceph-client-id", po::value<string>()->default_value("admin"),
48      "set ceph client id")
49     ("pool-name", po::value<string>()->default_value("data"),
50      "set pool")
51     ("op-dump-file", po::value<string>()->default_value(""),
52      "set file for dumping op details, omit for stderr")
53     ("init-only", po::value<bool>()->default_value(false),
54      "populate object set")
55     ("do-not-init", po::value<bool>()->default_value(false),
56      "use existing object set")
57     ("use-prefix", po::value<string>()->default_value(""),
58      "use previously populated prefix")
59     ("offset-align", po::value<unsigned>()->default_value(4096),
60      "align offset by")
61     ("sequential", po::value<bool>()->default_value(false),
62      "use sequential access pattern")
63     ("disable-detailed-ops", po::value<bool>()->default_value(false),
64      "don't dump per op stats")
65     ;
66
67   po::variables_map vm;
68   po::store(po::parse_command_line(argc, argv, desc), vm);
69   po::notify(vm);
70
71   if (vm.count("help")) {
72     cout << desc << std::endl;
73     return 1;
74   }
75
76   if (vm["do-not-init"].as<bool>() && !vm["use-prefix"].as<string>().size()) {
77     cout << "Must supply prefix if do-not-init is specified" << std::endl;
78     cout << desc << std::endl;
79     return 1;
80   }
81
82   if (vm["init-only"].as<bool>() && !vm["use-prefix"].as<string>().size()) {
83     cout << "Must supply prefix for init-only" << std::endl;
84     cout << desc << std::endl;
85     return 1;
86   }
87
88   string prefix;
89   if (vm["use-prefix"].as<string>().size()) {
90     prefix = vm["use-prefix"].as<string>();
91   } else {
92     char hostname_cstr[100];
93     gethostname(hostname_cstr, 100);
94     stringstream hostpid;
95     hostpid << hostname_cstr << getpid() << "-";
96     prefix = hostpid.str();
97   }
98
99   set<string> objects;
100   for (unsigned i = 0; i < vm["num-objects"].as<unsigned>();
101        ++i) {
102     stringstream name;
103     name << prefix << "-object_" << i;
104     objects.insert(name.str());
105   }
106
107   rngen_t rng;
108   if (vm.count("seed"))
109     rng = rngen_t(vm["seed"].as<unsigned>());
110
111   set<pair<double, Bencher::OpType> > ops;
112   ops.insert(make_pair(vm["write-ratio"].as<double>(), Bencher::WRITE));
113   ops.insert(make_pair(1-vm["write-ratio"].as<double>(), Bencher::READ));
114
115   librados::Rados rados;
116   librados::IoCtx ioctx;
117   int r = rados.init(vm["ceph-client-id"].as<string>().c_str());
118   if (r < 0) {
119     cerr << "error in init r=" << r << std::endl;
120     return -r;
121   }
122   r = rados.conf_read_file(NULL);
123   if (r < 0) {
124     cerr << "error in conf_read_file r=" << r << std::endl;
125     return -r;
126   }
127   r = rados.conf_parse_env(NULL);
128   if (r < 0) {
129     cerr << "error in conf_parse_env r=" << r << std::endl;
130     return -r;
131   }
132   r = rados.connect();
133   if (r < 0) {
134     cerr << "error in connect r=" << r << std::endl;
135     return -r;
136   }
137   r = rados.ioctx_create(vm["pool-name"].as<string>().c_str(), ioctx);
138   if (r < 0) {
139     cerr << "error in ioctx_create r=" << r << std::endl;
140     return -r;
141   }
142
143   ostream *detailed_ops = 0;
144   ofstream myfile;
145   if (vm["disable-detailed-ops"].as<bool>()) {
146     detailed_ops = 0;
147   } else if (vm["op-dump-file"].as<string>().size()) {
148     myfile.open(vm["op-dump-file"].as<string>().c_str());
149     detailed_ops = &myfile;
150   } else {
151     detailed_ops = &cerr;
152   }
153
154   Distribution<
155     boost::tuple<string, uint64_t, uint64_t, Bencher::OpType> > *gen = 0;
156   if (vm["sequential"].as<bool>()) {
157     std::cout << "Using Sequential generator" << std::endl;
158     gen = new SequentialLoad(
159       objects,
160       vm["object-size"].as<unsigned>(),
161       vm["io-size"].as<unsigned>(),
162       new WeightedDist<Bencher::OpType>(rng, ops)
163       );
164   } else {
165     std::cout << "Using random generator" << std::endl;
166     gen = new FourTupleDist<string, uint64_t, uint64_t, Bencher::OpType>(
167       new RandomDist<string>(rng, objects),
168       new Align(
169         new UniformRandom(
170           rng,
171           0,
172           vm["object-size"].as<unsigned>() - vm["io-size"].as<unsigned>()),
173         vm["offset-align"].as<unsigned>()
174         ),
175       new Uniform(vm["io-size"].as<unsigned>()),
176       new WeightedDist<Bencher::OpType>(rng, ops)
177       );
178   }
179
180   Bencher bencher(
181     gen,
182     new DetailedStatCollector(1, new JSONFormatter, detailed_ops, &cout),
183     new RadosBackend(&ioctx),
184     vm["num-concurrent-ops"].as<unsigned>(),
185     vm["duration"].as<unsigned>(),
186     vm["max-ops"].as<unsigned>());
187
188   if (!vm["do-not-init"].as<bool>()) {
189     bencher.init(objects, vm["object-size"].as<unsigned>(), &std::cout);
190     cout << "Created objects..." << std::endl;
191   } else {
192     cout << "Not initing objects..." << std::endl;
193   }
194
195   if (!vm["init-only"].as<bool>()) {
196     bencher.run_bench();
197   } else {
198     cout << "init-only" << std::endl;
199   }
200
201   rados.shutdown();
202   if (vm["op-dump-file"].as<string>().size()) {
203     myfile.close();
204   }
205   return 0;
206 }