Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / xattr_bench.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include <stdio.h>
16 #include <time.h>
17 #include <string.h>
18 #include <iostream>
19 #include <sstream>
20 #include "os/filestore/FileStore.h"
21 #include "include/Context.h"
22 #include "common/ceph_argparse.h"
23 #include "global/global_init.h"
24 #include "common/Mutex.h"
25 #include "common/Cond.h"
26 #include <boost/scoped_ptr.hpp>
27 #include <boost/random/mersenne_twister.hpp>
28 #include <boost/random/uniform_int.hpp>
29 #include <boost/random/binomial_distribution.hpp>
30 #include <gtest/gtest.h>
31
32 #include "include/unordered_map.h"
33
34 void usage(const string &name) {
35   std::cerr << "Usage: " << name << " [xattr|omap] store_path store_journal"
36             << std::endl;
37 }
38
39 const int THREADS = 5;
40
41 template <typename T>
42 typename T::iterator rand_choose(T &cont) {
43   if (cont.size() == 0) {
44     return cont.end();
45   }
46   int index = rand() % cont.size();
47   typename T::iterator retval = cont.begin();
48
49   for (; index > 0; --index) ++retval;
50   return retval;
51 }
52
53 class OnApplied : public Context {
54 public:
55   Mutex *lock;
56   Cond *cond;
57   int *in_progress;
58   ObjectStore::Transaction *t;
59   OnApplied(Mutex *lock,
60             Cond *cond,
61             int *in_progress,
62             ObjectStore::Transaction *t)
63     : lock(lock), cond(cond),
64       in_progress(in_progress), t(t) {
65     Mutex::Locker l(*lock);
66     (*in_progress)++;
67   }
68
69   void finish(int r) override {
70     Mutex::Locker l(*lock);
71     (*in_progress)--;
72     cond->Signal();
73   }
74 };
75
76 uint64_t get_time() {
77   time_t start;
78   time(&start);
79   return start * 1000;
80 }
81
82 double print_time(uint64_t ms) {
83   return ((double)ms)/1000;
84 }
85
86 uint64_t do_run(ObjectStore *store, int attrsize, int numattrs,
87                 int run,
88                 int transsize, int ops,
89                 ostream &out) {
90   Mutex lock("lock");
91   Cond cond;
92   int in_flight = 0;
93   ObjectStore::Sequencer osr(__func__);
94   ObjectStore::Transaction t;
95   map<coll_t, pair<set<string>, ObjectStore::Sequencer*> > collections;
96   for (int i = 0; i < 3*THREADS; ++i) {
97     coll_t coll(spg_t(pg_t(0, i + 1000*run), shard_id_t::NO_SHARD));
98     t.create_collection(coll, 0);
99     set<string> objects;
100     for (int i = 0; i < transsize; ++i) {
101       stringstream obj_str;
102       obj_str << i;
103       t.touch(coll,
104               ghobject_t(hobject_t(sobject_t(obj_str.str(), CEPH_NOSNAP))));
105       objects.insert(obj_str.str());
106     }
107     collections[coll] = make_pair(objects, new ObjectStore::Sequencer(coll.to_str()));
108   }
109   store->apply_transaction(&osr, std::move(t));
110
111   bufferlist bl;
112   for (int i = 0; i < attrsize; ++i) {
113     bl.append('\0');
114   }
115
116   uint64_t start = get_time();
117   for (int i = 0; i < ops; ++i) {
118     {
119       Mutex::Locker l(lock);
120       while (in_flight >= THREADS)
121         cond.Wait(lock);
122     }
123     ObjectStore::Transaction *t = new ObjectStore::Transaction;
124     map<coll_t, pair<set<string>, ObjectStore::Sequencer*> >::iterator iter =
125       rand_choose(collections);
126     for (set<string>::iterator obj = iter->second.first.begin();
127          obj != iter->second.first.end();
128          ++obj) {
129       for (int j = 0; j < numattrs; ++j) {
130         stringstream ss;
131         ss << i << ", " << j << ", " << *obj;
132         t->setattr(iter->first,
133                    ghobject_t(hobject_t(sobject_t(*obj, CEPH_NOSNAP))),
134                    ss.str().c_str(),
135                    bl);
136       }
137     }
138     store->queue_transaction(iter->second.second, std::move(*t),
139                              new OnApplied(&lock, &cond, &in_flight,
140                                            t));
141     delete t;
142   }
143   {
144     Mutex::Locker l(lock);
145     while (in_flight)
146       cond.Wait(lock);
147   }
148   return get_time() - start;
149 }
150
151 int main(int argc, char **argv) {
152   vector<const char*> args;
153   argv_to_vec(argc, (const char **)argv, args);
154
155   auto cct = global_init(0, args, CEPH_ENTITY_TYPE_CLIENT,
156                          CODE_ENVIRONMENT_UTILITY, 0);
157   common_init_finish(g_ceph_context);
158
159   std::cerr << "args: " << args << std::endl;
160   if (args.size() < 3) {
161     usage(argv[0]);
162     return 1;
163   }
164
165   string store_path(args[1]);
166   string store_dev(args[2]);
167
168   boost::scoped_ptr<ObjectStore> store(new FileStore(cct.get(), store_path,
169                                                      store_dev));
170
171   std::cerr << "mkfs starting" << std::endl;
172   assert(!store->mkfs());
173   assert(!store->mount());
174   std::cerr << "mounted" << std::endl;
175
176   std::cerr << "attrsize\tnumattrs\ttranssize\tops\ttime" << std::endl;
177   int runs = 0;
178   int total_size = 11;
179   for (int i = 6; i < total_size; ++i) {
180     for (int j = (total_size - i); j >= 0; --j) {
181       std::cerr << "starting run " << runs << std::endl;
182       ++runs;
183       uint64_t time = do_run(store.get(), (1 << i), (1 << j), runs,
184                              10,
185                              1000, std::cout);
186       std::cout << (1 << i) << "\t"
187                 << (1 << j) << "\t"
188                 << 10 << "\t"
189                 << 1000 << "\t"
190                 << print_time(time) << std::endl;
191     }
192   }
193   store->umount();
194   return 0;
195 }