| 354 | } |
| 355 | |
| 356 | static int table_iter_seek_indexed(struct table_iter *ti, |
| 357 | struct reftable_record *rec) |
| 358 | { |
| 359 | struct reftable_record want_index = { |
| 360 | .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT } |
| 361 | }; |
| 362 | struct reftable_record index_result = { |
| 363 | .type = REFTABLE_BLOCK_TYPE_INDEX, |
| 364 | .u.idx = { .last_key = REFTABLE_BUF_INIT }, |
| 365 | }; |
| 366 | int err; |
| 367 | |
| 368 | err = reftable_record_key(rec, &want_index.u.idx.last_key); |
| 369 | if (err < 0) |
| 370 | goto done; |
| 371 | |
| 372 | /* |
| 373 | * The index may consist of multiple levels, where each level may have |
| 374 | * multiple index blocks. We start by doing a linear search in the |
| 375 | * highest layer that identifies the relevant index block as well as |
| 376 | * the record inside that block that corresponds to our wanted key. |
| 377 | */ |
| 378 | err = table_iter_seek_linear(ti, &want_index); |
| 379 | if (err < 0) |
| 380 | goto done; |
| 381 | |
| 382 | /* |
| 383 | * Traverse down the levels until we find a non-index entry. |
| 384 | */ |
| 385 | while (1) { |
| 386 | /* |
| 387 | * In case we seek a record that does not exist the index iter |
| 388 | * will tell us that the iterator is over. This works because |
| 389 | * the last index entry of the current level will contain the |
| 390 | * last key it knows about. So in case our seeked key is larger |
| 391 | * than the last indexed key we know that it won't exist. |
| 392 | * |
| 393 | * There is one subtlety in the layout of the index section |
| 394 | * that makes this work as expected: the highest-level index is |
| 395 | * at end of the section and will point backwards and thus we |
| 396 | * start reading from the end of the index section, not the |
| 397 | * beginning. |
| 398 | * |
| 399 | * If that wasn't the case and the order was reversed then the |
| 400 | * linear seek would seek into the lower levels and traverse |
| 401 | * all levels of the index only to find out that the key does |
| 402 | * not exist. |
| 403 | */ |
| 404 | err = table_iter_next(ti, &index_result); |
| 405 | if (err != 0) |
| 406 | goto done; |
| 407 | |
| 408 | err = table_iter_seek_to(ti, index_result.u.idx.offset, 0); |
| 409 | if (err != 0) |
| 410 | goto done; |
| 411 | |
| 412 | block_iter_init(&ti->bi, &ti->block); |
| 413 |
no test coverage detected