| 534 | } |
| 535 | |
| 536 | int |
| 537 | CacheVC::openReadMain(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) |
| 538 | { |
| 539 | cancel_trigger(); |
| 540 | Doc *doc = reinterpret_cast<Doc *>(buf->data()); |
| 541 | int64_t ntodo = vio.ntodo(); |
| 542 | int64_t bytes = doc->len - doc_pos; |
| 543 | IOBufferBlock *b = nullptr; |
| 544 | if (seek_to) { // handle do_io_pread |
| 545 | if (seek_to >= doc_len) { |
| 546 | vio.ndone = doc_len; |
| 547 | return calluser(VC_EVENT_EOS); |
| 548 | } |
| 549 | HTTPInfo::FragOffset *frags = alternate.get_frag_table(); |
| 550 | if (dbg_ctl_cache_seek.on()) { |
| 551 | char b[CRYPTO_HEX_SIZE], c[CRYPTO_HEX_SIZE]; |
| 552 | Dbg(dbg_ctl_cache_seek, "Seek @ %" PRId64 " in %s from #%d @ %" PRId64 "/%d:%s", seek_to, first_key.toHexStr(b), fragment, |
| 553 | doc_pos, doc->len, doc->key.toHexStr(c)); |
| 554 | } |
| 555 | /* Because single fragment objects can migrate to hang off an alt vector |
| 556 | they can appear to the VC as multi-fragment when they are not really. |
| 557 | The essential difference is the existence of a fragment table. |
| 558 | */ |
| 559 | if (frags) { |
| 560 | int target = 0; |
| 561 | HTTPInfo::FragOffset next_off = frags[target]; |
| 562 | int lfi = static_cast<int>(alternate.get_frag_offset_count()) - 1; |
| 563 | ink_assert(lfi >= 0); // because it's not a single frag doc. |
| 564 | |
| 565 | /* Note: frag[i].offset is the offset of the first byte past the |
| 566 | i'th fragment. So frag[0].offset is the offset of the first |
| 567 | byte of fragment 1. In addition the # of fragments is one |
| 568 | more than the fragment table length, the start of the last |
| 569 | fragment being the last offset in the table. |
| 570 | */ |
| 571 | if (fragment == 0 || seek_to < frags[fragment - 1] || (fragment <= lfi && frags[fragment] <= seek_to)) { |
| 572 | // search from frag 0 on to find the proper frag |
| 573 | while (seek_to >= next_off && target < lfi) { |
| 574 | next_off = frags[++target]; |
| 575 | } |
| 576 | if (target == lfi && seek_to >= next_off) { |
| 577 | ++target; |
| 578 | } |
| 579 | } else { // shortcut if we are in the fragment already |
| 580 | target = fragment; |
| 581 | } |
| 582 | if (target != fragment) { |
| 583 | // Lread will read the next fragment always, so if that |
| 584 | // is the one we want, we don't need to do anything |
| 585 | int cfi = fragment; |
| 586 | --target; |
| 587 | while (target > fragment) { |
| 588 | next_CacheKey(&key, &key); |
| 589 | ++fragment; |
| 590 | } |
| 591 | while (target < fragment) { |
| 592 | prev_CacheKey(&key, &key); |
| 593 | --fragment; |
nothing calls this directly
no test coverage detected