uint32_t pos)
{
shared_lock rl(rwlock);
+ list_context->pos = hobject_t(object_t(), string(), CEPH_NOSNAP,
+ pos, list_context->pool_id, string());
+ ldout(cct, 10) << __func__ << list_context
+ << " pos " << pos << " -> " << list_context->pos << dendl;
pg_t actual = osdmap->raw_pg_to_pg(pg_t(pos, list_context->pool_id));
- ldout(cct, 10) << "list_objects_seek " << list_context
- << " pos " << pos << " -> " << actual << dendl;
list_context->current_pg = actual.ps();
- list_context->cookie = collection_list_handle_t();
- list_context->at_end_of_pg = false;
list_context->at_end_of_pool = false;
- list_context->current_pg_epoch = 0;
- return list_context->current_pg;
+ return pos;
}
void Objecter::list_nobjects(NListContext *list_context, Context *onfinish)
{
- ldout(cct, 10) << "list_objects" << dendl;
- ldout(cct, 20) << " pool_id " << list_context->pool_id
- << " pool_snap_seq " << list_context->pool_snap_seq
- << " max_entries " << list_context->max_entries
- << " list_context " << list_context
- << " onfinish " << onfinish
- << " list_context->current_pg " << list_context->current_pg
- << " list_context->cookie " << list_context->cookie << dendl;
-
- if (list_context->at_end_of_pg) {
- list_context->at_end_of_pg = false;
- ++list_context->current_pg;
- list_context->current_pg_epoch = 0;
- list_context->cookie = collection_list_handle_t();
- if (list_context->current_pg >= list_context->starting_pg_num) {
- list_context->at_end_of_pool = true;
- ldout(cct, 20) << " no more pgs; reached end of pool" << dendl;
- } else {
- ldout(cct, 20) << " move to next pg " << list_context->current_pg
- << dendl;
- }
- }
- if (list_context->at_end_of_pool) {
- // release the listing context's budget once all
- // OPs (in the session) are finished
- put_nlist_context_budget(list_context);
- onfinish->complete(0);
- return;
- }
+ ldout(cct, 10) << __func__ << " pool_id " << list_context->pool_id
+ << " pool_snap_seq " << list_context->pool_snap_seq
+ << " max_entries " << list_context->max_entries
+ << " list_context " << list_context
+ << " onfinish " << onfinish
+ << " current_pg " << list_context->current_pg
+ << " pos " << list_context->pos << dendl;
shared_lock rl(rwlock);
const pg_pool_t *pool = osdmap->get_pg_pool(list_context->pool_id);
}
int pg_num = pool->get_pg_num();
bool sort_bitwise = osdmap->test_flag(CEPH_OSDMAP_SORTBITWISE);
- rl.unlock();
- if (list_context->starting_pg_num == 0) { // there can't be zero pgs!
- list_context->starting_pg_num = pg_num;
+ if (list_context->pos.is_min()) {
+ list_context->starting_pg_num = 0;
list_context->sort_bitwise = sort_bitwise;
- ldout(cct, 20) << pg_num << " placement groups" << dendl;
+ list_context->starting_pg_num = pg_num;
}
if (list_context->sort_bitwise != sort_bitwise) {
- ldout(cct, 10) << " hobject sort order changed, restarting this pg"
- << dendl;
- list_context->cookie = collection_list_handle_t();
+ list_context->pos = hobject_t(
+ object_t(), string(), CEPH_NOSNAP,
+ list_context->current_pg, list_context->pool_id, string());
list_context->sort_bitwise = sort_bitwise;
+ ldout(cct, 10) << " hobject sort order changed, restarting this pg at "
+ << list_context->pos << dendl;
}
if (list_context->starting_pg_num != pg_num) {
- // start reading from the beginning; the pgs have changed
- ldout(cct, 10) << " pg_num changed; restarting with " << pg_num << dendl;
- list_context->current_pg = 0;
- list_context->cookie = collection_list_handle_t();
- list_context->current_pg_epoch = 0;
+ if (!sort_bitwise) {
+ // start reading from the beginning; the pgs have changed
+ ldout(cct, 10) << " pg_num changed; restarting with " << pg_num << dendl;
+ list_context->pos = collection_list_handle_t();
+ }
list_context->starting_pg_num = pg_num;
}
- assert(list_context->current_pg < pg_num);
+
+ if (list_context->pos.is_max()) {
+ ldout(cct, 20) << __func__ << " end of pool, list "
+ << list_context->list << dendl;
+ if (list_context->list.empty()) {
+ list_context->at_end_of_pool = true;
+ }
+ // release the listing context's budget once all
+ // OPs (in the session) are finished
+ put_nlist_context_budget(list_context);
+ onfinish->complete(0);
+ return;
+ }
ObjectOperation op;
op.pg_nls(list_context->max_entries, list_context->filter,
- list_context->cookie, list_context->current_pg_epoch);
+ list_context->pos, osdmap->get_epoch());
list_context->bl.clear();
C_NList *onack = new C_NList(list_context, onfinish, this);
object_locator_t oloc(list_context->pool_id, list_context->nspace);
+ // note current_pg in case we don't have (or lose) SORTBITWISE
+ list_context->current_pg = pool->raw_hash_to_pg(list_context->pos.get_hash());
+ rl.unlock();
+
pg_read(list_context->current_pg, oloc, op,
&list_context->bl, 0, onack, &onack->epoch,
&list_context->ctx_budget);
void Objecter::_nlist_reply(NListContext *list_context, int r,
Context *final_finish, epoch_t reply_epoch)
{
- ldout(cct, 10) << "_list_reply" << dendl;
+ ldout(cct, 10) << __func__ << " " << list_context << dendl;
bufferlist::iterator iter = list_context->bl.begin();
pg_nls_response_t response;
if (!iter.end()) {
::decode(extra_info, iter);
}
- list_context->cookie = response.handle;
- if (!list_context->current_pg_epoch) {
- // first pgls result, set epoch marker
- ldout(cct, 20) << " first pgls piece, reply_epoch is "
- << reply_epoch << dendl;
- list_context->current_pg_epoch = reply_epoch;
+
+ // if the osd returns 1 (newer code), or handle MAX, it means we
+ // hit the end of the pg.
+ if ((response.handle.is_max() || r == 1) &&
+ !list_context->sort_bitwise) {
+ // legacy OSD and !sortbitwise, figure out the next PG on our own
+ ++list_context->current_pg;
+ if (list_context->current_pg == list_context->starting_pg_num) {
+ // end of pool
+ list_context->pos = hobject_t::get_max();
+ } else {
+ // next pg
+ list_context->pos = hobject_t(object_t(), string(), CEPH_NOSNAP,
+ list_context->current_pg,
+ list_context->pool_id, string());
+ }
+ } else {
+ list_context->pos = response.handle;
}
int response_size = response.entries.size();
ldout(cct, 20) << " response.entries.size " << response_size
<< ", response.entries " << response.entries
- << ", handle " << response.handle << dendl;
+ << ", handle " << response.handle
+ << ", tentative new pos " << list_context->pos << dendl;
list_context->extra_info.append(extra_info);
if (response_size) {
list_context->list.merge(response.entries);
}
- // if the osd returns 1 (newer code), or handle MAX, it means we
- // hit the end of the pg.
- if (response.handle.is_max() || r == 1) {
- ldout(cct, 20) << " at end of pg" << dendl;
- list_context->at_end_of_pg = true;
- } else {
- // there is more for this pg; get it?
- if (response_size < list_context->max_entries) {
- list_context->max_entries -= response_size;
- list_nobjects(list_context, final_finish);
- return;
- }
- }
- if (!list_context->list.empty()) {
- ldout(cct, 20) << " returning results so far" << dendl;
+ if (list_context->list.size() >= list_context->max_entries) {
+ ldout(cct, 20) << " hit max, returning results so far, "
+ << list_context->list << dendl;
// release the listing context's budget once all
// OPs (in the session) are finished
put_nlist_context_budget(list_context);
list_nobjects(list_context, final_finish);
}
-void Objecter::put_nlist_context_budget(NListContext *list_context) {
- if (list_context->ctx_budget >= 0) {
- ldout(cct, 10) << " release listing context's budget " <<
- list_context->ctx_budget << dendl;
- put_op_budget_bytes(list_context->ctx_budget);
- list_context->ctx_budget = -1;
- }
+void Objecter::put_nlist_context_budget(NListContext *list_context)
+{
+ if (list_context->ctx_budget >= 0) {
+ ldout(cct, 10) << " release listing context's budget " <<
+ list_context->ctx_budget << dendl;
+ put_op_budget_bytes(list_context->ctx_budget);
+ list_context->ctx_budget = -1;
}
+}
uint32_t Objecter::list_objects_seek(ListContext *list_context,
uint32_t pos)