Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / bench / small_io_bench_rbd.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
3 #include <boost/lexical_cast.hpp>
4 #include <boost/program_options/option.hpp>
5 #include <boost/program_options/options_description.hpp>
6 #include <boost/program_options/variables_map.hpp>
7 #include <boost/program_options/cmdline.hpp>
8 #include <boost/program_options/parsers.hpp>
9 #include <iostream>
10 #include <set>
11 #include <sstream>
12 #include <stdlib.h>
13 #include <fstream>
14
15 #include "common/Formatter.h"
16
17 #include "bencher.h"
18 #include "rbd_backend.h"
19 #include "detailed_stat_collector.h"
20 #include "distribution.h"
21
22 namespace po = boost::program_options;
23 using namespace std;
24
25 int main(int argc, char **argv)
26 {
27   po::options_description desc("Allowed options");
28   desc.add_options()
29     ("help", "produce help message")
30     ("num-concurrent-ops", po::value<unsigned>()->default_value(10),
31      "set number of concurrent ops")
32     ("num-images", po::value<unsigned>()->default_value(2),
33      "set number of rbd images to use")
34     ("image-size", po::value<unsigned>()->default_value(4096),
35      "set image size in megabytes")
36     ("order", po::value<unsigned>()->default_value(22),
37      "set log_2(object size)")
38     ("io-size", po::value<unsigned>()->default_value(4<<10),
39      "set io size")
40     ("write-ratio", po::value<double>()->default_value(0.25),
41      "set ratio of read to write")
42     ("duration", po::value<unsigned>()->default_value(0),
43      "set max duration, 0 for unlimited")
44     ("max-ops", po::value<unsigned>()->default_value(0),
45      "set max ops, 0 for unlimited")
46     ("seed", po::value<unsigned>(),
47      "seed")
48     ("ceph-client-id", po::value<string>()->default_value("admin"),
49      "set ceph client id")
50     ("pool-name", po::value<string>()->default_value("data"),
51      "set pool")
52     ("op-dump-file", po::value<string>()->default_value(""),
53      "set file for dumping op details, omit for stderr")
54     ("offset-align", po::value<unsigned>()->default_value(4096),
55      "align offset by")
56     ("sequential", po::value<bool>()->default_value(false),
57      "use sequential access pattern")
58     ("disable-detailed-ops", po::value<bool>()->default_value(false),
59      "don't dump per op stats")
60     ;
61
62   po::variables_map vm;
63   po::store(po::parse_command_line(argc, argv, desc), vm);
64   po::notify(vm);
65
66   if (vm.count("help")) {
67     cout << desc << std::endl;
68     return 1;
69   }
70
71   string prefix;
72   char hostname_cstr[100];
73   gethostname(hostname_cstr, 100);
74   stringstream hostpid;
75   hostpid << hostname_cstr << getpid() << "-";
76   prefix = hostpid.str();
77
78   set<string> image_names;
79   for (unsigned i = 0; i < vm["num-images"].as<unsigned>();
80        ++i) {
81     stringstream name;
82     name << prefix << "-image_" << i;
83     image_names.insert(name.str());
84   }
85
86   rngen_t rng;
87   if (vm.count("seed"))
88     rng = rngen_t(vm["seed"].as<unsigned>());
89
90   set<pair<double, Bencher::OpType> > ops;
91   ops.insert(make_pair(vm["write-ratio"].as<double>(), Bencher::WRITE));
92   ops.insert(make_pair(1-vm["write-ratio"].as<double>(), Bencher::READ));
93
94   librados::Rados rados;
95   librados::IoCtx ioctx;
96   int r = rados.init(vm["ceph-client-id"].as<string>().c_str());
97   if (r < 0) {
98     cerr << "error in init r=" << r << std::endl;
99     return -r;
100   }
101   r = rados.conf_read_file(NULL);
102   if (r < 0) {
103     cerr << "error in conf_read_file r=" << r << std::endl;
104     return -r;
105   }
106   r = rados.conf_parse_env(NULL);
107   if (r < 0) {
108     cerr << "error in conf_parse_env r=" << r << std::endl;
109     return -r;
110   }
111   r = rados.connect();
112   if (r < 0) {
113     cerr << "error in connect r=" << r << std::endl;
114     return -r;
115   }
116   r = rados.ioctx_create(vm["pool-name"].as<string>().c_str(), ioctx);
117   if (r < 0) {
118     cerr << "error in ioctx_create r=" << r << std::endl;
119     return -r;
120   }
121
122   ostream *detailed_ops = 0;
123   ofstream myfile;
124   if (vm["disable-detailed-ops"].as<bool>()) {
125     detailed_ops = 0;
126   } else if (vm["op-dump-file"].as<string>().size()) {
127     myfile.open(vm["op-dump-file"].as<string>().c_str());
128     detailed_ops = &myfile;
129   } else {
130     detailed_ops = &cerr;
131   }
132
133   librbd::RBD rbd;
134   {
135     map<string, ceph::shared_ptr<librbd::Image> > images;
136     int order = vm["order"].as<unsigned>();
137     uint64_t image_size = ((uint64_t)vm["image-size"].as<unsigned>()) << 20;
138     for (set<string>::const_iterator i = image_names.begin();
139          i != image_names.end(); ++i) {
140       r = rbd.create(ioctx, i->c_str(), image_size, &order);
141       if (r < 0) {
142         cerr << "error creating image " << *i << " r=" << r << std::endl;
143         return -r;
144       }
145       ceph::shared_ptr<librbd::Image> image(new librbd::Image());
146       r = rbd.open(ioctx, *image, i->c_str());
147       if (r < 0) {
148         cerr << "error opening image " << *i << " r=" << r << std::endl;
149         return -r;
150       }
151       images[*i] = image;
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         image_names,
160         image_size,
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, image_names),
168         new Align(
169           new UniformRandom(
170             rng,
171             0,
172             image_size - 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 RBDBackend(&images),
184       vm["num-concurrent-ops"].as<unsigned>(),
185       vm["duration"].as<unsigned>(),
186       vm["max-ops"].as<unsigned>());
187
188     bencher.run_bench();
189   }
190
191   for (set<string>::const_iterator i = image_names.begin();
192        i != image_names.end(); ++i) {
193     rbd.remove(ioctx, i->c_str());
194   }
195   rados.shutdown();
196   if (vm["op-dump-file"].as<string>().size()) {
197     myfile.close();
198   }
199   return 0;
200 }