]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
f67539c2 | 19 | #include <iterator> |
7c673cae FG |
20 | #include <sstream> |
21 | #include "os/filestore/FileStore.h" | |
22 | #include "include/Context.h" | |
23 | #include "common/ceph_argparse.h" | |
9f95a23c | 24 | #include "common/ceph_mutex.h" |
7c673cae | 25 | #include "common/Cond.h" |
9f95a23c | 26 | #include "global/global_init.h" |
7c673cae FG |
27 | #include <boost/scoped_ptr.hpp> |
28 | #include <boost/random/mersenne_twister.hpp> | |
29 | #include <boost/random/uniform_int.hpp> | |
30 | #include <boost/random/binomial_distribution.hpp> | |
31 | #include <gtest/gtest.h> | |
32 | ||
33 | #include "include/unordered_map.h" | |
34 | ||
35 | void usage(const string &name) { | |
36 | std::cerr << "Usage: " << name << " [xattr|omap] store_path store_journal" | |
37 | << std::endl; | |
38 | } | |
39 | ||
40 | const int THREADS = 5; | |
41 | ||
42 | template <typename T> | |
43 | typename T::iterator rand_choose(T &cont) { | |
f67539c2 TL |
44 | if (std::empty(cont) == 0) { |
45 | return std::end(cont); | |
7c673cae | 46 | } |
f67539c2 | 47 | return std::next(std::begin(cont), rand() % cont.size()); |
7c673cae FG |
48 | } |
49 | ||
50 | class OnApplied : public Context { | |
51 | public: | |
9f95a23c TL |
52 | ceph::mutex *lock; |
53 | ceph::condition_variable *cond; | |
7c673cae FG |
54 | int *in_progress; |
55 | ObjectStore::Transaction *t; | |
9f95a23c TL |
56 | OnApplied(ceph::mutex *lock, |
57 | ceph::condition_variable *cond, | |
7c673cae FG |
58 | int *in_progress, |
59 | ObjectStore::Transaction *t) | |
60 | : lock(lock), cond(cond), | |
61 | in_progress(in_progress), t(t) { | |
9f95a23c | 62 | std::lock_guard l{*lock}; |
7c673cae FG |
63 | (*in_progress)++; |
64 | } | |
65 | ||
66 | void finish(int r) override { | |
9f95a23c | 67 | std::lock_guard l{*lock}; |
7c673cae | 68 | (*in_progress)--; |
9f95a23c | 69 | cond->notify_all(); |
7c673cae FG |
70 | } |
71 | }; | |
72 | ||
73 | uint64_t get_time() { | |
74 | time_t start; | |
75 | time(&start); | |
76 | return start * 1000; | |
77 | } | |
78 | ||
79 | double print_time(uint64_t ms) { | |
80 | return ((double)ms)/1000; | |
81 | } | |
82 | ||
83 | uint64_t do_run(ObjectStore *store, int attrsize, int numattrs, | |
84 | int run, | |
85 | int transsize, int ops, | |
86 | ostream &out) { | |
9f95a23c TL |
87 | ceph::mutex lock = ceph::make_mutex("lock"); |
88 | ceph::condition_variable cond; | |
7c673cae FG |
89 | int in_flight = 0; |
90 | ObjectStore::Sequencer osr(__func__); | |
91 | ObjectStore::Transaction t; | |
92 | map<coll_t, pair<set<string>, ObjectStore::Sequencer*> > collections; | |
93 | for (int i = 0; i < 3*THREADS; ++i) { | |
94 | coll_t coll(spg_t(pg_t(0, i + 1000*run), shard_id_t::NO_SHARD)); | |
95 | t.create_collection(coll, 0); | |
96 | set<string> objects; | |
97 | for (int i = 0; i < transsize; ++i) { | |
98 | stringstream obj_str; | |
99 | obj_str << i; | |
100 | t.touch(coll, | |
101 | ghobject_t(hobject_t(sobject_t(obj_str.str(), CEPH_NOSNAP)))); | |
102 | objects.insert(obj_str.str()); | |
103 | } | |
104 | collections[coll] = make_pair(objects, new ObjectStore::Sequencer(coll.to_str())); | |
105 | } | |
11fdf7f2 | 106 | store->queue_transaction(&osr, std::move(t)); |
7c673cae FG |
107 | |
108 | bufferlist bl; | |
109 | for (int i = 0; i < attrsize; ++i) { | |
110 | bl.append('\0'); | |
111 | } | |
112 | ||
113 | uint64_t start = get_time(); | |
114 | for (int i = 0; i < ops; ++i) { | |
115 | { | |
9f95a23c TL |
116 | std::unique_lock l{lock}; |
117 | cond.wait(l, [&] { in_flight < THREADS; }); | |
7c673cae FG |
118 | } |
119 | ObjectStore::Transaction *t = new ObjectStore::Transaction; | |
120 | map<coll_t, pair<set<string>, ObjectStore::Sequencer*> >::iterator iter = | |
121 | rand_choose(collections); | |
122 | for (set<string>::iterator obj = iter->second.first.begin(); | |
123 | obj != iter->second.first.end(); | |
124 | ++obj) { | |
125 | for (int j = 0; j < numattrs; ++j) { | |
126 | stringstream ss; | |
127 | ss << i << ", " << j << ", " << *obj; | |
128 | t->setattr(iter->first, | |
129 | ghobject_t(hobject_t(sobject_t(*obj, CEPH_NOSNAP))), | |
130 | ss.str().c_str(), | |
131 | bl); | |
132 | } | |
133 | } | |
134 | store->queue_transaction(iter->second.second, std::move(*t), | |
135 | new OnApplied(&lock, &cond, &in_flight, | |
136 | t)); | |
137 | delete t; | |
138 | } | |
139 | { | |
9f95a23c TL |
140 | std::unique_lock l{lock}; |
141 | cond.wait(l, [&] { return in_flight == 0; }); | |
7c673cae FG |
142 | } |
143 | return get_time() - start; | |
144 | } | |
145 | ||
146 | int main(int argc, char **argv) { | |
147 | vector<const char*> args; | |
148 | argv_to_vec(argc, (const char **)argv, args); | |
11fdf7f2 TL |
149 | if (args.empty()) { |
150 | cerr << argv[0] << ": -h or --help for usage" << std::endl; | |
151 | exit(1); | |
152 | } | |
153 | if (ceph_argparse_need_usage(args)) { | |
154 | usage(argv[0]); | |
155 | exit(0); | |
156 | } | |
7c673cae FG |
157 | |
158 | auto cct = global_init(0, args, CEPH_ENTITY_TYPE_CLIENT, | |
11fdf7f2 TL |
159 | CODE_ENVIRONMENT_UTILITY, |
160 | CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); | |
7c673cae FG |
161 | common_init_finish(g_ceph_context); |
162 | ||
163 | std::cerr << "args: " << args << std::endl; | |
164 | if (args.size() < 3) { | |
165 | usage(argv[0]); | |
166 | return 1; | |
167 | } | |
168 | ||
169 | string store_path(args[1]); | |
170 | string store_dev(args[2]); | |
171 | ||
172 | boost::scoped_ptr<ObjectStore> store(new FileStore(cct.get(), store_path, | |
173 | store_dev)); | |
174 | ||
175 | std::cerr << "mkfs starting" << std::endl; | |
11fdf7f2 TL |
176 | ceph_assert(!store->mkfs()); |
177 | ceph_assert(!store->mount()); | |
7c673cae FG |
178 | std::cerr << "mounted" << std::endl; |
179 | ||
180 | std::cerr << "attrsize\tnumattrs\ttranssize\tops\ttime" << std::endl; | |
181 | int runs = 0; | |
182 | int total_size = 11; | |
183 | for (int i = 6; i < total_size; ++i) { | |
184 | for (int j = (total_size - i); j >= 0; --j) { | |
185 | std::cerr << "starting run " << runs << std::endl; | |
186 | ++runs; | |
187 | uint64_t time = do_run(store.get(), (1 << i), (1 << j), runs, | |
188 | 10, | |
189 | 1000, std::cout); | |
190 | std::cout << (1 << i) << "\t" | |
191 | << (1 << j) << "\t" | |
192 | << 10 << "\t" | |
193 | << 1000 << "\t" | |
194 | << print_time(time) << std::endl; | |
195 | } | |
196 | } | |
197 | store->umount(); | |
198 | return 0; | |
199 | } |