]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/objectstore/TestObjectStoreState.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / objectstore / TestObjectStoreState.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) 2012 New Dream Network
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 #include <stdio.h>
14 #include <string.h>
15 #include <iostream>
16 #include <time.h>
17 #include <stdlib.h>
18 #include <signal.h>
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"
27
28 #define dout_context g_ceph_context
29 #define dout_subsys ceph_subsys_filestore
30 #undef dout_prefix
31 #define dout_prefix *_dout << "ceph_test_objectstore_state "
32
33 void TestObjectStoreState::init(int colls, int objs)
34 {
35 dout(5) << "init " << colls << " colls " << objs << " objs" << dendl;
36
37 ObjectStore::Sequencer osr(__func__);
38 ObjectStore::Transaction t;
39
40 t.create_collection(coll_t::meta(), 0);
41 m_store->apply_transaction(&osr, std::move(t));
42
43 wait_for_ready();
44
45 int baseid = 0;
46 for (int i = 0; i < colls; i++) {
47 int coll_id = 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;
51
52 ObjectStore::Transaction *t = new ObjectStore::Transaction;
53 t->create_collection(entry->m_coll, 32);
54 bufferlist hint;
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);
62
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);
67 m_num_objects++;
68 }
69 baseid += objs;
70
71 m_store->queue_transaction(&(entry->m_osr), std::move(*t),
72 new C_OnFinished(this));
73 delete t;
74 inc_in_flight();
75
76 m_collections.insert(make_pair(coll_id, entry));
77 m_collections_ids.push_back(coll_id);
78 m_next_coll_nr++;
79 }
80 dout(5) << "init has " << m_in_flight.load() << "in-flight transactions" << dendl;
81 wait_for_done();
82 dout(5) << "init finished" << dendl;
83 }
84
85 TestObjectStoreState::coll_entry_t *TestObjectStoreState::coll_create(int id)
86 {
87 char buf[100];
88 char meta_buf[100];
89 memset(buf, 0, 100);
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));
94 }
95
96 TestObjectStoreState::coll_entry_t*
97 TestObjectStoreState::get_coll(int key, bool erase)
98 {
99 dout(5) << "get_coll id " << key << dendl;
100
101 coll_entry_t *entry = NULL;
102 map<int, coll_entry_t*>::iterator it = m_collections.find(key);
103 if (it != m_collections.end()) {
104 entry = it->second;
105 if (erase) {
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);
111 }
112 }
113
114 dout(5) << "get_coll id " << key;
115 if (!entry)
116 *_dout << " non-existent";
117 else
118 *_dout << " name " << entry->m_coll.to_str();
119 *_dout << dendl;
120 return entry;
121 }
122
123 TestObjectStoreState::coll_entry_t*
124 TestObjectStoreState::get_coll_at(int pos, bool erase)
125 {
126 dout(5) << "get_coll_at pos " << pos << dendl;
127
128 if (m_collections.empty())
129 return NULL;
130
131 assert((size_t) pos < m_collections_ids.size());
132
133 int coll_id = m_collections_ids[pos];
134 coll_entry_t *entry = m_collections[coll_id];
135
136 if (entry == NULL) {
137 dout(5) << "get_coll_at pos " << pos << " non-existent" << dendl;
138 return NULL;
139 }
140
141 if (erase) {
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);
147 }
148
149 dout(5) << "get_coll_at pos " << pos << ": "
150 << entry->m_coll << "(removed: " << erase << ")" << dendl;
151
152 return entry;
153 }
154
155 TestObjectStoreState::coll_entry_t::~coll_entry_t()
156 {
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;
161 if (obj) {
162 delete obj;
163 }
164 }
165 m_objects.clear();
166 }
167 }
168
169 bool TestObjectStoreState::coll_entry_t::check_for_obj(int id)
170 {
171 if (m_objects.count(id))
172 return true;
173 return false;
174 }
175
176 hobject_t *TestObjectStoreState::coll_entry_t::touch_obj(int id)
177 {
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;
182 return it->second;
183 }
184
185 char buf[100];
186 memset(buf, 0, 100);
187 snprintf(buf, 100, "obj%d", id);
188
189 hobject_t *obj = new hobject_t(sobject_t(object_t(buf), CEPH_NOSNAP));
190 m_objects.insert(make_pair(id, obj));
191
192 dout(5) << "touch_obj coll id " << m_id << " name " << buf << dendl;
193 return obj;
194 }
195
196 hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id)
197 {
198 return get_obj(id, false);
199 }
200
201 /**
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.
205 */
206 hobject_t *TestObjectStoreState::coll_entry_t::remove_obj(int id)
207 {
208 return get_obj(id, true);
209 }
210
211 hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id, bool remove)
212 {
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;
217 return NULL;
218 }
219
220 hobject_t *obj = it->second;
221 if (remove)
222 m_objects.erase(it);
223
224 dout(5) << "get_obj coll " << m_coll.to_str() << " id " << id
225 << ": " << obj->oid.name << "(removed: " << remove << ")" << dendl;
226
227 return obj;
228 }
229
230 hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos, int *key)
231 {
232 return get_obj_at(pos, false, key);
233 }
234
235 /**
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.
239 */
240 hobject_t *TestObjectStoreState::coll_entry_t::remove_obj_at(int pos, int *key)
241 {
242 return get_obj_at(pos, true, key);
243 }
244
245 hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos,
246 bool remove, int *key)
247 {
248 if (m_objects.empty()) {
249 dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
250 << " in an empty collection" << dendl;
251 return NULL;
252 }
253
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++) {
257 if (i == pos) {
258 ret = it->second;
259 break;
260 }
261 }
262
263 if (ret == NULL) {
264 dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
265 << " non-existent" << dendl;
266 return NULL;
267 }
268
269 if (key != NULL)
270 *key = it->first;
271
272 if (remove)
273 m_objects.erase(it);
274
275 dout(5) << "get_obj_at coll id " << m_id << " pos " << pos
276 << ": " << ret->oid.name << "(removed: " << remove << ")" << dendl;
277
278 return ret;
279 }
280
281 hobject_t*
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));
285 return old_obj;
286 }
287
288 int TestObjectStoreState::coll_entry_t::get_random_obj_id(rngen_t& gen)
289 {
290 ceph_assert(!m_objects.empty());
291
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++) {
296 if (i == pos) {
297 return it->first;
298 }
299 }
300 ceph_assert(0 == "INTERNAL ERROR");
301 }