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) 2012 New Dream Network
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.
19 #include "os/ObjectStore.h"
20 #include "common/ceph_argparse.h"
21 #include "global/global_init.h"
22 #include "common/debug.h"
23 #include <boost/scoped_ptr.hpp>
24 #include <boost/lexical_cast.hpp>
25 #include "TestObjectStoreState.h"
26 #include "include/assert.h"
28 #define dout_context g_ceph_context
29 #define dout_subsys ceph_subsys_filestore
31 #define dout_prefix *_dout << "ceph_test_objectstore_state "
33 void TestObjectStoreState::init(int colls
, int objs
)
35 dout(5) << "init " << colls
<< " colls " << objs
<< " objs" << dendl
;
37 ObjectStore::Sequencer
osr(__func__
);
38 ObjectStore::Transaction t
;
40 t
.create_collection(coll_t::meta(), 0);
41 m_store
->apply_transaction(&osr
, std::move(t
));
46 for (int i
= 0; i
< colls
; i
++) {
48 coll_entry_t
*entry
= coll_create(coll_id
);
49 dout(5) << "init create collection " << entry
->m_coll
.to_str()
50 << " meta " << entry
->m_meta_obj
<< dendl
;
52 ObjectStore::Transaction
*t
= new ObjectStore::Transaction
;
53 t
->create_collection(entry
->m_coll
, 32);
55 uint32_t pg_num
= colls
;
56 uint64_t num_objs
= uint64_t(objs
/ colls
);
57 ::encode(pg_num
, hint
);
58 ::encode(num_objs
, hint
);
59 t
->collection_hint(entry
->m_coll
, ObjectStore::Transaction::COLL_HINT_EXPECTED_NUM_OBJECTS
, hint
);
60 dout(5) << "give collection hint, number of objects per collection: " << num_objs
<< dendl
;
61 t
->touch(coll_t::meta(), entry
->m_meta_obj
);
63 for (int i
= 0; i
< objs
; i
++) {
64 hobject_t
*obj
= entry
->touch_obj(i
+ baseid
);
65 t
->touch(entry
->m_coll
, ghobject_t(*obj
));
66 ceph_assert(i
+ baseid
== m_num_objects
);
71 m_store
->queue_transaction(&(entry
->m_osr
), std::move(*t
),
72 new C_OnFinished(this));
76 m_collections
.insert(make_pair(coll_id
, entry
));
77 m_collections_ids
.push_back(coll_id
);
80 dout(5) << "init has " << m_in_flight
.load() << "in-flight transactions" << dendl
;
82 dout(5) << "init finished" << dendl
;
85 TestObjectStoreState::coll_entry_t
*TestObjectStoreState::coll_create(int id
)
90 memset(meta_buf
, 0, 100);
91 snprintf(buf
, 100, "0.%d_head", id
);
92 snprintf(meta_buf
, 100, "pglog_0.%d_head", id
);
93 return (new coll_entry_t(id
, buf
, meta_buf
));
96 TestObjectStoreState::coll_entry_t
*
97 TestObjectStoreState::get_coll(int key
, bool erase
)
99 dout(5) << "get_coll id " << key
<< dendl
;
101 coll_entry_t
*entry
= NULL
;
102 map
<int, coll_entry_t
*>::iterator it
= m_collections
.find(key
);
103 if (it
!= m_collections
.end()) {
106 m_collections
.erase(it
);
107 vector
<int>::iterator cid_it
= m_collections_ids
.begin()+(entry
->m_id
);
108 dout(20) << __func__
<< " removing key " << key
<< " coll_id " << entry
->m_id
109 << " iterator's entry id " << (*cid_it
) << dendl
;
110 m_collections_ids
.erase(cid_it
);
114 dout(5) << "get_coll id " << key
;
116 *_dout
<< " non-existent";
118 *_dout
<< " name " << entry
->m_coll
.to_str();
123 TestObjectStoreState::coll_entry_t
*
124 TestObjectStoreState::get_coll_at(int pos
, bool erase
)
126 dout(5) << "get_coll_at pos " << pos
<< dendl
;
128 if (m_collections
.empty())
131 assert((size_t) pos
< m_collections_ids
.size());
133 int coll_id
= m_collections_ids
[pos
];
134 coll_entry_t
*entry
= m_collections
[coll_id
];
137 dout(5) << "get_coll_at pos " << pos
<< " non-existent" << dendl
;
142 m_collections
.erase(coll_id
);
143 vector
<int>::iterator it
= m_collections_ids
.begin()+(pos
);
144 dout(20) << __func__
<< " removing pos " << pos
<< " coll_id " << coll_id
145 << " iterator's entry id " << (*it
) << dendl
;
146 m_collections_ids
.erase(it
);
149 dout(5) << "get_coll_at pos " << pos
<< ": "
150 << entry
->m_coll
<< "(removed: " << erase
<< ")" << dendl
;
155 TestObjectStoreState::coll_entry_t::~coll_entry_t()
157 if (m_objects
.size() > 0) {
158 map
<int, hobject_t
*>::iterator it
= m_objects
.begin();
159 for (; it
!= m_objects
.end(); ++it
) {
160 hobject_t
*obj
= it
->second
;
169 bool TestObjectStoreState::coll_entry_t::check_for_obj(int id
)
171 if (m_objects
.count(id
))
176 hobject_t
*TestObjectStoreState::coll_entry_t::touch_obj(int id
)
178 map
<int, hobject_t
*>::iterator it
= m_objects
.find(id
);
179 if (it
!= m_objects
.end()) {
180 dout(5) << "touch_obj coll id " << m_id
181 << " name " << it
->second
->oid
.name
<< dendl
;
187 snprintf(buf
, 100, "obj%d", id
);
189 hobject_t
*obj
= new hobject_t(sobject_t(object_t(buf
), CEPH_NOSNAP
));
190 m_objects
.insert(make_pair(id
, obj
));
192 dout(5) << "touch_obj coll id " << m_id
<< " name " << buf
<< dendl
;
196 hobject_t
*TestObjectStoreState::coll_entry_t::get_obj(int id
)
198 return get_obj(id
, false);
202 * remove_obj - Removes object without freeing it.
203 * @param id Object's id in the map.
204 * @return The object or NULL in case of error.
206 hobject_t
*TestObjectStoreState::coll_entry_t::remove_obj(int id
)
208 return get_obj(id
, true);
211 hobject_t
*TestObjectStoreState::coll_entry_t::get_obj(int id
, bool remove
)
213 map
<int, hobject_t
*>::iterator it
= m_objects
.find(id
);
214 if (it
== m_objects
.end()) {
215 dout(5) << "get_obj coll " << m_coll
.to_str()
216 << " obj #" << id
<< " non-existent" << dendl
;
220 hobject_t
*obj
= it
->second
;
224 dout(5) << "get_obj coll " << m_coll
.to_str() << " id " << id
225 << ": " << obj
->oid
.name
<< "(removed: " << remove
<< ")" << dendl
;
230 hobject_t
*TestObjectStoreState::coll_entry_t::get_obj_at(int pos
, int *key
)
232 return get_obj_at(pos
, false, key
);
236 * remove_obj_at - Removes object without freeing it.
237 * @param pos The map's position in which the object lies.
238 * @return The object or NULL in case of error.
240 hobject_t
*TestObjectStoreState::coll_entry_t::remove_obj_at(int pos
, int *key
)
242 return get_obj_at(pos
, true, key
);
245 hobject_t
*TestObjectStoreState::coll_entry_t::get_obj_at(int pos
,
246 bool remove
, int *key
)
248 if (m_objects
.empty()) {
249 dout(5) << "get_obj_at coll " << m_coll
.to_str() << " pos " << pos
250 << " in an empty collection" << dendl
;
254 hobject_t
*ret
= NULL
;
255 map
<int, hobject_t
*>::iterator it
= m_objects
.begin();
256 for (int i
= 0; it
!= m_objects
.end(); ++it
, i
++) {
264 dout(5) << "get_obj_at coll " << m_coll
.to_str() << " pos " << pos
265 << " non-existent" << dendl
;
275 dout(5) << "get_obj_at coll id " << m_id
<< " pos " << pos
276 << ": " << ret
->oid
.name
<< "(removed: " << remove
<< ")" << dendl
;
282 TestObjectStoreState::coll_entry_t::replace_obj(int id
, hobject_t
*obj
) {
283 hobject_t
*old_obj
= remove_obj(id
);
284 m_objects
.insert(make_pair(id
, obj
));
288 int TestObjectStoreState::coll_entry_t::get_random_obj_id(rngen_t
& gen
)
290 ceph_assert(!m_objects
.empty());
292 boost::uniform_int
<> orig_obj_rng(0, m_objects
.size()-1);
293 int pos
= orig_obj_rng(gen
);
294 map
<int, hobject_t
*>::iterator it
= m_objects
.begin();
295 for (int i
= 0; it
!= m_objects
.end(); ++it
, i
++) {
300 ceph_assert(0 == "INTERNAL ERROR");