122
125
return get_mangled_name(*path, hoid, mangled_name, exists_out);
125
static void split_handle(collection_list_handle_t handle,
126
uint32_t *hash, uint32_t *index) {
128
*index = handle.index;
131
static collection_list_handle_t form_handle(uint32_t hash, uint32_t index) {
132
collection_list_handle_t handle;
134
handle.index = index;
138
int HashIndex::_collection_list_partial(snapid_t seq, int max_count,
139
vector<hobject_t> *ls,
140
collection_list_handle_t *last) {
142
uint32_t index, hash;
145
split_handle(*last, &hash, &index);
146
lower_bound = get_hash_str(hash);
149
max_count ? &max_count : NULL,
151
last ? &lower_bound : NULL,
152
last ? &index : NULL,
156
if (last && ls->size())
157
*last = form_handle(ls->rbegin()->hash, index);
161
128
int HashIndex::_collection_list(vector<hobject_t> *ls) {
162
129
vector<string> path;
163
return list(path, NULL, NULL, NULL, NULL, ls);
130
return list_by_hash(path, 0, 0, 0, 0, ls);
133
int HashIndex::_collection_list_partial(const hobject_t &start,
137
vector<hobject_t> *ls,
141
dout(20) << "_collection_list_partial " << start << " " << min_count << "-" << max_count << " ls.size " << ls->size() << dendl;
142
return list_by_hash(path, min_count, max_count, seq, next, ls);
166
145
int HashIndex::start_split(const vector<string> &path) {
371
350
void HashIndex::get_path_components(const hobject_t &hoid,
372
351
vector<string> *path) {
373
352
char buf[MAX_HASH_LEVEL + 1];
374
snprintf(buf, sizeof(buf), "%.*X", MAX_HASH_LEVEL, hoid.hash);
353
snprintf(buf, sizeof(buf), "%.*X", MAX_HASH_LEVEL, (uint32_t)hoid.get_filestore_key());
376
// Path components are the hex characters of hoid.hash in, least
355
// Path components are the hex characters of hoid.hash, least
377
356
// significant first
378
357
for (int i = 0; i < MAX_HASH_LEVEL; ++i) {
379
path->push_back(string(&buf[MAX_HASH_LEVEL - 1 - i], 1));
358
path->push_back(string(&buf[i], 1));
394
373
return get_hash_str(hoid.hash);
397
int HashIndex::list(const vector<string> &path,
398
const int *max_count,
400
const string *lower_bound,
402
vector<hobject_t> *out) {
405
vector<string> next_path = path;
406
next_path.push_back("");
407
set<string> hash_prefixes;
408
multimap<string, hobject_t> objects;
376
uint32_t HashIndex::hash_prefix_to_hash(string prefix) {
377
while (prefix.size() < sizeof(uint32_t) * 2) {
378
prefix.push_back('0');
381
sscanf(prefix.c_str(), "%x", &hash);
383
hash = ((hash & 0x0f0f0f0f) << 4) | ((hash & 0xf0f0f0f0) >> 4);
384
hash = ((hash & 0x00ff00ff) << 8) | ((hash & 0xff00ff00) >> 8);
385
hash = ((hash & 0x0000ffff) << 16) | ((hash & 0xffff0000) >> 16);
389
int HashIndex::get_path_contents_by_hash(const vector<string> &path,
390
const string *lower_bound,
391
const hobject_t *next_object,
393
set<string> *hash_prefixes,
394
multimap<string, hobject_t> *objects) {
409
396
map<string, hobject_t> rev_objects;
411
int max = max_count ? *max_count : 0;
412
398
string cur_prefix;
413
399
for (vector<string>::const_iterator i = path.begin();
416
402
cur_prefix.append(*i);
419
404
r = list_objects(path, 0, 0, &rev_objects);
425
410
string hash_prefix = get_path_str(i->second);
426
411
if (lower_bound && hash_prefix < *lower_bound)
413
if (next_object && i->second < *next_object)
428
415
if (seq && i->second.snap < *seq)
430
hash_prefixes.insert(hash_prefix);
431
objects.insert(pair<string, hobject_t>(hash_prefix, i->second));
417
hash_prefixes->insert(hash_prefix);
418
objects->insert(pair<string, hobject_t>(hash_prefix, i->second));
434
420
r = list_subdirs(path, &subdirs);
440
426
string candidate = cur_prefix + *i;
441
427
if (lower_bound && candidate < lower_bound->substr(0, candidate.size()))
443
hash_prefixes.insert(cur_prefix + *i);
430
candidate < get_path_str(*next_object).substr(0, candidate.size()))
432
hash_prefixes->insert(cur_prefix + *i);
446
uint32_t counter = 0;
437
int HashIndex::list_by_hash(const vector<string> &path,
442
vector<hobject_t> *out) {
444
vector<string> next_path = path;
445
next_path.push_back("");
446
set<string> hash_prefixes;
447
multimap<string, hobject_t> objects;
448
int r = get_path_contents_by_hash(path,
456
dout(20) << " prefixes " << hash_prefixes << dendl;
447
457
for (set<string>::iterator i = hash_prefixes.begin();
448
i != hash_prefixes.end() && (!max_count || max > 0);
458
i != hash_prefixes.end();
450
460
multimap<string, hobject_t>::iterator j = objects.find(*i);
451
if (j != objects.end()) {
453
for (; (!max_count || max > 0) && j != objects.end() && j->first == *i; ++j, ++counter) {
454
if (lower_bound && *lower_bound == *i && counter < *index)
456
out->push_back(j->second);
461
if (j == objects.end()) {
462
if (min_count > 0 && out->size() > (unsigned)min_count) {
464
*next = hobject_t("", "", CEPH_NOSNAP, hash_prefix_to_hash(*i));
467
*(next_path.rbegin()) = *(i->rbegin());
468
hobject_t next_recurse;
470
next_recurse = *next;
471
r = list_by_hash(next_path,
466
*(next_path.rbegin()) = *(i->rbegin());
467
int old_size = out->size();
468
assert(next_path.size() > path.size());
469
r = list(next_path, max_count ? &max : NULL, seq, lower_bound, index, out);
473
max -= out->size() - old_size;
480
if (!next_recurse.is_max()) {
482
*next = next_recurse;
486
while (j != objects.end() && j->first == *i) {
487
if (max_count > 0 && out->size() == (unsigned)max_count) {
492
if (!next || j->second >= *next) {
493
out->push_back(j->second);
500
*next = hobject_t::get_max();