Repository: trafficserver Updated Branches: refs/heads/ts-974-5-3-x ff379f67a -> ebd737154
Numerous fixes - can do range then full request. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/ebd73715 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/ebd73715 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/ebd73715 Branch: refs/heads/ts-974-5-3-x Commit: ebd737154e7799c1bf82531042d16586c85f50e3 Parents: ff379f6 Author: Alan M. Carroll <[email protected]> Authored: Sat Jun 6 23:15:07 2015 -0500 Committer: Alan M. Carroll <[email protected]> Committed: Sat Jun 6 23:15:07 2015 -0500 ---------------------------------------------------------------------- iocore/cache/CacheRead.cc | 4 +++ iocore/cache/CacheWrite.cc | 54 +++++++++++++++++++++++++++++------------ proxy/hdrs/HTTP.cc | 7 ++++-- proxy/hdrs/HTTP.h | 5 ++++ proxy/http/HttpSM.cc | 22 +++++++++++------ proxy/http/HttpTransact.cc | 9 ++++--- proxy/http/HttpTransact.h | 4 +-- 7 files changed, 74 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/iocore/cache/CacheRead.cc ---------------------------------------------------------------------- diff --git a/iocore/cache/CacheRead.cc b/iocore/cache/CacheRead.cc index 52a395c..915d269 100644 --- a/iocore/cache/CacheRead.cc +++ b/iocore/cache/CacheRead.cc @@ -313,6 +313,7 @@ CacheVC::openReadFromWriter(int event, Event *e) alternate.copy_shallow(od->vector.get(alternate_index)); key = earliest_key = alternate.object_key_get(); doc_len = alternate.object_size_get(); + Debug("amc", "[openReadFromWriter] - setting alternate from write_vc %p to #%d : %p", write_vc, alternate_index, alternate.m_alt); MUTEX_RELEASE(lock_od); SET_HANDLER(&CacheVC::openReadStartEarliest); return openReadStartEarliest(event, e); @@ -324,6 +325,7 @@ CacheVC::openReadFromWriter(int event, Event *e) SET_HANDLER(&CacheVC::openReadFromWriterFailure); return openReadFromWriterFailure(CACHE_EVENT_OPEN_READ_FAILED, reinterpret_cast<Event *>(-ECACHE_ALT_MISS)); } + Debug("amc", "[openReadFromWriter] select alt: %d %p (current %p)", alternate_index, od->vector.get(alternate_index)->m_alt, alternate.m_alt); write_vector = &od->vector; } else { alternate_index = 0; @@ -904,6 +906,7 @@ CacheVC::openReadVecWrite(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */ if (od->move_resident_alt) dir_insert(&od->single_doc_key, vol, &od->single_doc_dir); int alt_ndx = HttpTransactCache::SelectFromAlternates(write_vector, &request, params); + Debug("amc", "[openReadVecWrite] select alt: %d %p (current %p)", alt_ndx, write_vector->get(alt_ndx)->m_alt, alternate.m_alt); vol->close_write(this); if (alt_ndx >= 0) { vector.clear(); @@ -1038,6 +1041,7 @@ CacheVC::openReadStartHead(int event, Event *e) err = ECACHE_ALT_MISS; goto Ldone; } + Debug("amc", "[openReadStartHead] select alt: %d %p (current %p, od %p)", alternate_index, vector.get(alternate_index)->m_alt, alternate.m_alt, od); } else if (CACHE_ALT_INDEX_DEFAULT == (alternate_index = get_alternate_index(&vector, earliest_key))) alternate_index = 0; alternate_tmp = vector.get(alternate_index); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/iocore/cache/CacheWrite.cc ---------------------------------------------------------------------- diff --git a/iocore/cache/CacheWrite.cc b/iocore/cache/CacheWrite.cc index 0bd829c..f22f901 100644 --- a/iocore/cache/CacheWrite.cc +++ b/iocore/cache/CacheWrite.cc @@ -1398,16 +1398,29 @@ CacheVC::openWriteInit(int eid, Event* event) return EVENT_CONT; } - // If we're not already in the alt vector, insert. - if (earliest_key != alternate.object_key_get()) { + if (alternate.valid() && earliest_key != alternate.object_key_get()) { + // When the VC is created it sets up for a new alternate write. If we're back filling we + // need to tweak that back to the existing alternate. Debug("amc", "[CacheVC::openWriteInit] updating earliest key from alternate"); alternate.object_key_get(&earliest_key); } + // Get synchronized with the OD vector. if (-1 == (alternate_index = get_alternate_index(write_vector, earliest_key))) { - alternate_index = write_vector->insert(&alternate); + Debug("amc", "[openWriteInit] alt not found, inserted"); + alternate_index = write_vector->insert(&alternate); // not there, add it + } else { + HTTPInfo* base = write_vector->get(alternate_index); + if (!base->is_writeable()) { + // The alternate instance is mapped directly on a read buffer, which we can't modify. + // It must be replaced with a live, mutable one. + Debug("amc", "Updating OD vector element %d : 0x%p with mutable version %p", alternate_index, base, alternate.m_alt); + alternate.copy(base); // make a local copy + base->copy_shallow(&alternate); // paste the mutable copy back. + } } // mark us as an writer. write_vector->data[alternate_index]._writers.push(this); + alternate.copy_shallow(write_vector->get(alternate_index)); if (this == od->open_writer) { od->open_writer = NULL; @@ -1530,9 +1543,12 @@ Lagain: not_writing = true; } else if (alternate.is_frag_cached(fragment)) { not_writing = true; - resp_range.consume(length); // just drop it. Debug("amc", "Fragment %d already cached", fragment); - // Need to consume the actual data too (in blocks/offset). + // Consume the data, as we won't be using it. + resp_range.consume(write_len); + blocks = iobufferblock_skip(blocks, &offset, &length, write_len); + // need to kick start things again or we'll stall. + return this->handleEvent(EVENT_IMMEDIATE); } else { od->write_active(earliest_key, this, write_pos); } @@ -1851,17 +1867,23 @@ Cache::open_write(Continuation *cont, CacheKey *key, CacheHTTPInfo *info, time_t ProxyMutex *mutex = cont->mutex; c->vio.op = VIO::WRITE; c->first_key = *key; - /* - The transition from single fragment document to a multi-fragment document - would cause a problem if the key and the first_key collide. In case of - a collision, old vector data could be served to HTTP. Need to avoid that. - Also, when evacuating a fragment, we have to decide if its the first_key - or the earliest_key based on the dir_tag. - */ - do { - rand_CacheKey(&c->key, cont->mutex); - } while (DIR_MASK_TAG(c->key.slice32(2)) == DIR_MASK_TAG(c->first_key.slice32(2))); - c->earliest_key = c->key; + if (info) { + info->object_key_get(&c->key); + c->earliest_key = c->key; + } else { + /* + The transition from single fragment document to a multi-fragment document + would cause a problem if the key and the first_key collide. In case of + a collision, old vector data could be served to HTTP. Need to avoid that. + Also, when evacuating a fragment, we have to decide if its the first_key + or the earliest_key based on the dir_tag. + */ + do { + rand_CacheKey(&c->key, cont->mutex); + } while (DIR_MASK_TAG(c->key.slice32(2)) == DIR_MASK_TAG(c->first_key.slice32(2))); + c->earliest_key = c->key; + } + c->frag_type = CACHE_FRAG_TYPE_HTTP; c->vol = key_to_vol(key, hostname, host_len); Vol *vol = c->vol; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/proxy/hdrs/HTTP.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc index a3b4cef..2108766 100644 --- a/proxy/hdrs/HTTP.cc +++ b/proxy/hdrs/HTTP.cc @@ -1782,7 +1782,7 @@ HTTPCacheAlt::HTTPCacheAlt(): , m_ext_buffer(NULL) { m_flags = 0; // set all flags to false. - m_flag.writeable_p = true; + m_flag.writeable_p = true; // except this one. } void @@ -1820,10 +1820,13 @@ HTTPCacheAlt::copy(HTTPCacheAlt *that) m_request_sent_time = that->m_request_sent_time; m_response_received_time = that->m_response_received_time; + m_fixed_fragment_size = that->m_fixed_fragment_size; m_frag_count = that->m_frag_count; - ats_free(m_fragments); + if (m_flag.table_allocated_p) + ats_free(m_fragments); + if (that->m_fragments) { size_t size = FragmentDescriptorTable::calc_size(that->m_fragments->m_n); m_fragments = static_cast<FragmentDescriptorTable*>(ats_malloc(size)); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/proxy/hdrs/HTTP.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h index 4aaf550..a42d686 100644 --- a/proxy/hdrs/HTTP.h +++ b/proxy/hdrs/HTTP.h @@ -1838,6 +1838,11 @@ public: { return m_alt->m_flag.complete_p; } + bool + is_writeable() const + { + return m_alt->m_flag.writeable_p; + } /** Compute the convex hull of uncached ranges. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/proxy/http/HttpSM.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 9826283..ab5d149 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -1540,7 +1540,8 @@ HttpSM::handle_api_return() setup_blind_tunnel(true); } else { - if (t_state.range_setup == HttpTransact::RANGE_PARTIAL_WRITE && HttpTransact::CACHE_DO_WRITE == t_state.cache_info.action) { + if ((t_state.range_setup == HttpTransact::RANGE_PARTIAL_WRITE || t_state.range_setup == HttpTransact::RANGE_PARTIAL_UPDATE) && + HttpTransact::CACHE_DO_WRITE == t_state.cache_info.action) { Debug("amc", "Set up for partial read"); CacheVConnection *save_write_vc = cache_sm.cache_write_vc; tunnel.tunnel_run(setup_server_transfer_to_cache_only()); @@ -5896,21 +5897,26 @@ void HttpSM::setup_cache_write_transfer(HttpCacheSM *c_sm, VConnection *source_vc, HTTPInfo *store_info, int64_t skip_bytes, const char *name) { + bool partial_update_p = HttpTransact::RANGE_PARTIAL_UPDATE == t_state.range_setup; ink_assert(c_sm->cache_write_vc != NULL); ink_assert(t_state.request_sent_time > 0); ink_assert(t_state.response_received_time > 0); + ink_assert(store_info->valid() || partial_update_p); - store_info->request_sent_time_set(t_state.request_sent_time); - store_info->response_received_time_set(t_state.response_received_time); + if (!partial_update_p) { + store_info->request_sent_time_set(t_state.request_sent_time); + store_info->response_received_time_set(t_state.response_received_time); - if (t_state.hdr_info.response_range.isValid()) { - if (t_state.hdr_info.response_content_size != HTTP_UNDEFINED_CL) + if (t_state.hdr_info.response_range.isValid() && t_state.hdr_info.response_content_size != HTTP_UNDEFINED_CL) store_info->object_size_set(t_state.hdr_info.response_content_size); - c_sm->cache_write_vc->set_inbound_range(t_state.hdr_info.response_range._min, t_state.hdr_info.response_range._max); + + c_sm->cache_write_vc->set_http_info(store_info); + store_info->clear(); } - c_sm->cache_write_vc->set_http_info(store_info); - store_info->clear(); + if (t_state.hdr_info.response_range.isValid()) + c_sm->cache_write_vc->set_inbound_range(t_state.hdr_info.response_range._min, t_state.hdr_info.response_range._max); + tunnel.add_consumer(c_sm->cache_write_vc, source_vc, &HttpSM::tunnel_handler_cache_write, HT_CACHE_WRITE, name, skip_bytes); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/proxy/http/HttpTransact.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index e383ba9..7c71b11 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -2693,7 +2693,7 @@ HttpTransact::HandleCacheOpenReadHit(State *s) // Check if we need to get some data from the origin. if (s->state_machine->get_cache_sm().cache_read_vc->get_uncached(s->hdr_info.request_range, range)) { - Debug("amc", "Request has uncached fragments"); + Debug("amc", "Request touches uncached fragments"); find_server_and_update_current_info(s); if (!ats_is_ip(&s->current.server->addr)) { if (s->current.request_to == PARENT_PROXY) { @@ -2707,7 +2707,7 @@ HttpTransact::HandleCacheOpenReadHit(State *s) } build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, s->client_info.http_version, &range); s->cache_info.action = CACHE_PREPARE_TO_WRITE; - s->range_setup = RANGE_PARTIAL_WRITE; + s->range_setup = RANGE_PARTIAL_UPDATE; s->next_action = how_to_open_connection(s); if (s->stale_icp_lookup && s->next_action == SM_ACTION_ORIGIN_SERVER_OPEN) { s->next_action = SM_ACTION_ICP_QUERY; @@ -4465,7 +4465,10 @@ HttpTransact::handle_cache_operation_on_forward_server_response(State *s) } ink_assert(base_response->valid()); - if ((s->cache_info.action == CACHE_DO_WRITE) || (s->cache_info.action == CACHE_DO_REPLACE)) { + if (((s->cache_info.action == CACHE_DO_WRITE) || (s->cache_info.action == CACHE_DO_REPLACE)) && + s->range_setup != RANGE_PARTIAL_UPDATE + ) { + // If it's a partial write then we already have the cached headers, no need to pass these in. set_headers_for_cache_write(s, &s->cache_info.object_store, &s->hdr_info.server_request, &s->hdr_info.server_response); } // 304, 412, and 416 responses are handled here http://git-wip-us.apache.org/repos/asf/trafficserver/blob/ebd73715/proxy/http/HttpTransact.h ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h index 44d686c..de0c046 100644 --- a/proxy/http/HttpTransact.h +++ b/proxy/http/HttpTransact.h @@ -525,8 +525,8 @@ public: enum RangeSetup_t { RANGE_NONE = 0, RANGE_NOT_SATISFIABLE, - RANGE_PARTIAL_WRITE, // Do a partial write to the object. - // Includes a partial request cache miss and a cache hit with uncached ranges + RANGE_PARTIAL_WRITE, ///< Cache a range request. + RANGE_PARTIAL_UPDATE, ///< Update an existing object with a range request. }; enum CacheAuth_t {
