Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / bench / small_io_bench_dumb.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
3 #include "acconfig.h"
4
5 #include <boost/scoped_ptr.hpp>
6 #include <boost/lexical_cast.hpp>
7 #include <boost/program_options/option.hpp>
8 #include <boost/program_options/options_description.hpp>
9 #include <boost/program_options/variables_map.hpp>
10 #include <boost/program_options/cmdline.hpp>
11 #include <boost/program_options/parsers.hpp>
12 #include <iostream>
13 #include <set>
14 #include <sstream>
15 #include <stdlib.h>
16 #include <fstream>
17
18 #include "common/Formatter.h"
19
20 #include "bencher.h"
21 #include "rados_backend.h"
22 #include "detailed_stat_collector.h"
23 #include "distribution.h"
24 #include "global/global_init.h"
25 #include "os/ObjectStore.h"
26 #include "dumb_backend.h"
27
28 namespace po = boost::program_options;
29 using namespace std;
30
31 int main(int argc, char **argv)
32 {
33   po::options_description desc("Allowed options");
34   desc.add_options()
35     ("help", "produce help message")
36     ("num-concurrent-ops", po::value<unsigned>()->default_value(10),
37      "set number of concurrent ops")
38     ("num-objects", po::value<unsigned>()->default_value(500),
39      "set number of objects to use")
40     ("object-size", po::value<unsigned>()->default_value(4<<20),
41      "set object size")
42     ("io-size", po::value<unsigned>()->default_value(4<<10),
43      "set io size")
44     ("write-ratio", po::value<double>()->default_value(0.75),
45      "set ratio of read to write")
46     ("duration", po::value<unsigned>()->default_value(0),
47      "set max duration, 0 for unlimited")
48     ("max-ops", po::value<unsigned>()->default_value(0),
49      "set max ops, 0 for unlimited")
50     ("seed", po::value<unsigned>(),
51      "seed")
52     ("num-colls", po::value<unsigned>()->default_value(20),
53      "number of collections")
54     ("op-dump-file", po::value<string>()->default_value(""),
55      "set file for dumping op details, omit for stderr")
56     ("filestore-path", po::value<string>(),
57      "path to filestore directory, mandatory")
58     ("offset-align", po::value<unsigned>()->default_value(4096),
59      "align offset by")
60     ("fsync", po::value<bool>()->default_value(false),
61      "fsync after each write")
62     ("sync-file-range", po::value<bool>()->default_value(false),
63      "sync-file-range after each write")
64     ("fadvise", po::value<bool>()->default_value(false),
65      "fadvise after each write")
66     ("sync-interval", po::value<unsigned>()->default_value(30),
67      "frequency to sync")
68     ("sequential", po::value<bool>()->default_value(false),
69      "use sequential access pattern")
70     ("disable-detailed-ops", po::value<bool>()->default_value(false),
71      "don't dump per op stats")
72     ;
73
74   vector<string> ceph_option_strings;
75   po::variables_map vm;
76   try {
77     po::parsed_options parsed =
78       po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
79     po::store(
80               parsed,
81               vm);
82     po::notify(vm);
83
84     ceph_option_strings = po::collect_unrecognized(parsed.options,
85                                                    po::include_positional);
86   } catch(po::error &e) {
87     std::cerr << e.what() << std::endl;
88     return 1;
89   }
90   vector<const char *> ceph_options, def_args;
91   ceph_options.reserve(ceph_option_strings.size());
92   for (vector<string>::iterator i = ceph_option_strings.begin();
93        i != ceph_option_strings.end();
94        ++i) {
95     ceph_options.push_back(i->c_str());
96   }
97
98   auto cct = global_init(
99     &def_args, ceph_options, CEPH_ENTITY_TYPE_CLIENT,
100     CODE_ENVIRONMENT_UTILITY,
101     CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
102   common_init_finish(g_ceph_context);
103   g_ceph_context->_conf->apply_changes(NULL);
104
105   if (!vm.count("filestore-path")) {
106     cout << "Must provide filestore-path" << std::endl
107          << desc << std::endl;
108     return 1;
109   }
110
111   if (vm.count("help")) {
112     cout << desc << std::endl;
113     return 1;
114   }
115
116   rngen_t rng;
117   if (vm.count("seed"))
118     rng = rngen_t(vm["seed"].as<unsigned>());
119
120   set<pair<double, Bencher::OpType> > ops;
121   ops.insert(make_pair(vm["write-ratio"].as<double>(), Bencher::WRITE));
122   ops.insert(make_pair(1-vm["write-ratio"].as<double>(), Bencher::READ));
123
124   cout << "Creating objects.." << std::endl;
125   bufferlist bl;
126   for (uint64_t i = 0; i < vm["object-size"].as<unsigned>(); ++i) {
127     bl.append(0);
128   }
129   set<string> objects;
130
131   for (uint64_t num = 0; num < vm["num-objects"].as<unsigned>(); ++num) {
132     unsigned col_num = num % vm["num-colls"].as<unsigned>();
133     stringstream coll, obj;
134     coll << "collection_" << col_num;
135     obj << "obj_" << num;
136     if (num == col_num) {
137       std::cout << "collection " << coll.str() << std::endl;
138       string coll_str(
139         vm["filestore-path"].as<string>() + string("/") + coll.str());
140       int r = ::mkdir(
141         coll_str.c_str(),
142         0777);
143       if (r < 0) {
144         std::cerr << "Error " << errno << " creating collection" << std::endl;
145         return 1;
146       }
147     }
148     objects.insert(coll.str() + "/" + obj.str());
149   }
150   string meta_str(vm["filestore-path"].as<string>() + string("/meta"));
151   int r = ::mkdir(
152     meta_str.c_str(),
153     0777);
154   if (r < 0) {
155     std::cerr << "Error " << errno << " creating collection" << std::endl;
156     return 1;
157   }
158   r = ::open(meta_str.c_str(), 0);
159   if (r < 0) {
160     std::cerr << "Error " << errno << " opening meta" << std::endl;
161     return 1;
162   }
163   int sync_fd = r;
164
165   ostream *detailed_ops = 0;
166   ofstream myfile;
167   if (vm["disable-detailed-ops"].as<bool>()) {
168     detailed_ops = 0;
169   } else if (vm["op-dump-file"].as<string>().size()) {
170     myfile.open(vm["op-dump-file"].as<string>().c_str());
171     detailed_ops = &myfile;
172   } else {
173     detailed_ops = &cerr;
174   }
175
176   Distribution<
177     boost::tuple<string, uint64_t, uint64_t, Bencher::OpType> > *gen = 0;
178   if (vm["sequential"].as<bool>()) {
179     std::cout << "Using Sequential generator" << std::endl;
180     gen = new SequentialLoad(
181       objects,
182       vm["object-size"].as<unsigned>(),
183       vm["io-size"].as<unsigned>(),
184       new WeightedDist<Bencher::OpType>(rng, ops)
185       );
186   } else {
187     std::cout << "Using random generator" << std::endl;
188     gen = new FourTupleDist<string, uint64_t, uint64_t, Bencher::OpType>(
189       new RandomDist<string>(rng, objects),
190       new Align(
191         new UniformRandom(
192           rng,
193           0,
194           vm["object-size"].as<unsigned>() - vm["io-size"].as<unsigned>()),
195         vm["offset-align"].as<unsigned>()
196         ),
197       new Uniform(vm["io-size"].as<unsigned>()),
198       new WeightedDist<Bencher::OpType>(rng, ops)
199       );
200   }
201
202 #ifndef HAVE_SYNC_FILE_RANGE
203   if (vm["sync-file-range"].as<bool>())
204     std::cerr << "Warning: sync_file_range(2) not supported!" << std::endl;
205 #endif
206
207 #ifndef HAVE_POSIX_FADVISE
208   if (vm["fadvise"].as<bool>())
209     std::cerr << "Warning: posix_fadvise(2) not supported!" << std::endl;
210 #endif
211
212   Bencher bencher(
213     gen,
214     new DetailedStatCollector(1, new JSONFormatter, detailed_ops, &cout),
215     new DumbBackend(
216       vm["filestore-path"].as<string>(),
217       vm["fsync"].as<bool>(),
218       vm["sync-file-range"].as<bool>(),
219       vm["fadvise"].as<bool>(),
220       vm["sync-interval"].as<unsigned>(),
221       sync_fd,
222       10,
223       g_ceph_context),
224     vm["num-concurrent-ops"].as<unsigned>(),
225     vm["duration"].as<unsigned>(),
226     vm["max-ops"].as<unsigned>());
227
228   bencher.init(objects, vm["object-size"].as<unsigned>(), &std::cout);
229   cout << "Created objects..." << std::endl;
230
231   bencher.run_bench();
232
233   if (vm["op-dump-file"].as<string>().size()) {
234     myfile.close();
235   }
236   return 0;
237 }