1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
21 #include "os/filestore/FileStore.h"
22 #include "include/Context.h"
23 #include "common/ceph_argparse.h"
24 #include "common/ceph_mutex.h"
25 #include "common/Cond.h"
26 #include "global/global_init.h"
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>
33 #include "include/unordered_map.h"
35 void usage(const string
&name
) {
36 std::cerr
<< "Usage: " << name
<< " [xattr|omap] store_path store_journal"
40 const int THREADS
= 5;
43 typename
T::iterator
rand_choose(T
&cont
) {
44 if (std::empty(cont
) == 0) {
45 return std::end(cont
);
47 return std::next(std::begin(cont
), rand() % cont
.size());
50 class OnApplied
: public Context
{
53 ceph::condition_variable
*cond
;
55 ObjectStore::Transaction
*t
;
56 OnApplied(ceph::mutex
*lock
,
57 ceph::condition_variable
*cond
,
59 ObjectStore::Transaction
*t
)
60 : lock(lock
), cond(cond
),
61 in_progress(in_progress
), t(t
) {
62 std::lock_guard l
{*lock
};
66 void finish(int r
) override
{
67 std::lock_guard l
{*lock
};
79 double print_time(uint64_t ms
) {
80 return ((double)ms
)/1000;
83 uint64_t do_run(ObjectStore
*store
, int attrsize
, int numattrs
,
85 int transsize
, int ops
,
87 ceph::mutex lock
= ceph::make_mutex("lock");
88 ceph::condition_variable cond
;
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);
97 for (int i
= 0; i
< transsize
; ++i
) {
101 ghobject_t(hobject_t(sobject_t(obj_str
.str(), CEPH_NOSNAP
))));
102 objects
.insert(obj_str
.str());
104 collections
[coll
] = make_pair(objects
, new ObjectStore::Sequencer(coll
.to_str()));
106 store
->queue_transaction(&osr
, std::move(t
));
109 for (int i
= 0; i
< attrsize
; ++i
) {
113 uint64_t start
= get_time();
114 for (int i
= 0; i
< ops
; ++i
) {
116 std::unique_lock l
{lock
};
117 cond
.wait(l
, [&] { in_flight
< THREADS
; });
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();
125 for (int j
= 0; j
< numattrs
; ++j
) {
127 ss
<< i
<< ", " << j
<< ", " << *obj
;
128 t
->setattr(iter
->first
,
129 ghobject_t(hobject_t(sobject_t(*obj
, CEPH_NOSNAP
))),
134 store
->queue_transaction(iter
->second
.second
, std::move(*t
),
135 new OnApplied(&lock
, &cond
, &in_flight
,
140 std::unique_lock l
{lock
};
141 cond
.wait(l
, [&] { return in_flight
== 0; });
143 return get_time() - start
;
146 int main(int argc
, char **argv
) {
147 auto args
= argv_to_vec(argc
, argv
);
149 cerr
<< argv
[0] << ": -h or --help for usage" << std::endl
;
152 if (ceph_argparse_need_usage(args
)) {
157 auto cct
= global_init(0, args
, CEPH_ENTITY_TYPE_CLIENT
,
158 CODE_ENVIRONMENT_UTILITY
,
159 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
160 common_init_finish(g_ceph_context
);
162 std::cerr
<< "args: " << args
<< std::endl
;
163 if (args
.size() < 3) {
168 string
store_path(args
[1]);
169 string
store_dev(args
[2]);
171 boost::scoped_ptr
<ObjectStore
> store(new FileStore(cct
.get(), store_path
,
174 std::cerr
<< "mkfs starting" << std::endl
;
175 ceph_assert(!store
->mkfs());
176 ceph_assert(!store
->mount());
177 std::cerr
<< "mounted" << std::endl
;
179 std::cerr
<< "attrsize\tnumattrs\ttranssize\tops\ttime" << std::endl
;
182 for (int i
= 6; i
< total_size
; ++i
) {
183 for (int j
= (total_size
- i
); j
>= 0; --j
) {
184 std::cerr
<< "starting run " << runs
<< std::endl
;
186 uint64_t time
= do_run(store
.get(), (1 << i
), (1 << j
), runs
,
189 std::cout
<< (1 << i
) << "\t"
193 << print_time(time
) << std::endl
;