Skip to content

Commit 8fbd401

Browse files
authored
Try both old(9.2) and new cache key generation (#12271)
1 parent ab25c40 commit 8fbd401

9 files changed

Lines changed: 200 additions & 2 deletions

File tree

doc/admin-guide/files/records.yaml.en.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,19 @@ Cache Control
23902390
Establishes a guaranteed maximum lifetime boundary for object freshness.
23912391
Setting this to ``0`` disables the feature.
23922392

2393+
.. ts:cv:: CONFIG proxy.config.http.cache.try_compat_key_read INT 0
2394+
:reloadable:
2395+
2396+
When enabled (``1``), |TS| will try to lookup the cached object using the
2397+
previous cache key generation algorithm, but will always write new objects
2398+
using the newest key generation. This might be temporarily necessary
2399+
if a large cache was created by the previous version of ATS but the new
2400+
version changed the way cache keys are generated. If this is turned on,
2401+
a metric called `proxy.process.http.cache.compat_key_reads` will be
2402+
incremented any time the compat cache lookup successfully finds the object.
2403+
You can monitor this metric and know when its safe to turn this feature off
2404+
as the cache wraps around.
2405+
23932406
.. ts:cv:: CONFIG proxy.config.http.cache.range.lookup INT 1
23942407
:overridable:
23952408

include/proxy/hdrs/URL.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ void url_called_set(URLImpl *url);
217217
char *url_string_get_buf(URLImpl *url, char *dstbuf, int dstbuf_size, int *length);
218218

219219
void url_CryptoHash_get(const URLImpl *url, CryptoHash *hash, bool ignore_query = false, cache_generation_t generation = -1);
220+
void url_CryptoHash_get_92(const URLImpl *url, CryptoHash *hash, bool ignore_query = false, cache_generation_t generation = -1);
220221
void url_host_CryptoHash_get(URLImpl *url, CryptoHash *hash);
221222

222223
constexpr bool USE_STRICT_URI_PARSING = true;
@@ -278,6 +279,7 @@ class URL : public HdrHeapSDKHandle
278279
char *string_get_ref(int *length = nullptr, unsigned normalization_flags = URLNormalize::NONE) const;
279280
char *string_get_buf(char *dstbuf, int dsbuf_size, int *length = nullptr) const;
280281
void hash_get(CryptoHash *hash, bool ignore_query = false, cache_generation_t generation = -1) const;
282+
void hash_get92(CryptoHash *hash, bool ignore_query = false, cache_generation_t generation = -1) const;
281283
void host_hash_get(CryptoHash *hash) const;
282284

283285
const char *scheme_get(int *length);
@@ -496,6 +498,16 @@ URL::hash_get(CryptoHash *hash, bool ignore_query, cache_generation_t generation
496498
url_CryptoHash_get(m_url_impl, hash, ignore_query, generation);
497499
}
498500

501+
/*-------------------------------------------------------------------------
502+
-------------------------------------------------------------------------*/
503+
504+
inline void
505+
URL::hash_get92(CryptoHash *hash, bool ignore_query, cache_generation_t generation) const
506+
{
507+
ink_assert(valid());
508+
url_CryptoHash_get_92(m_url_impl, hash, ignore_query, generation);
509+
}
510+
499511
/*-------------------------------------------------------------------------
500512
-------------------------------------------------------------------------*/
501513

include/proxy/http/HttpConfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct HttpStatsBlock {
329329
Metrics::Counter::AtomicType *origin_server_speed_bytes_per_sec_400M;
330330
Metrics::Counter::AtomicType *origin_server_speed_bytes_per_sec_800M;
331331
Metrics::Counter::AtomicType *origin_server_speed_bytes_per_sec_1G;
332+
Metrics::Counter::AtomicType *cache_compat_key_reads;
332333
};
333334

334335
enum class CacheOpenWriteFailAction_t {
@@ -813,6 +814,8 @@ struct HttpConfigParams : public ConfigInfo {
813814
MgmtByte http_host_sni_policy = 0;
814815
MgmtByte scheme_proto_mismatch_policy = 2;
815816

817+
MgmtByte cache_try_compat_key_read = 0;
818+
816819
// noncopyable
817820
/////////////////////////////////////
818821
// operator = and copy constructor //

include/proxy/http/HttpSM.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ class PostDataBuffers
174174
~PostDataBuffers();
175175
};
176176

177+
enum class CompatibilityCacheLookup {
178+
COMPAT_CACHE_LOOKUP_NORMAL = 0,
179+
COMPAT_CACHE_LOOKUP_92,
180+
COMPAT_CACHE_LAST,
181+
};
182+
177183
class HttpSM : public Continuation, public PluginUserArgs<TS_USER_ARGS_TXN>
178184
{
179185
friend class HttpTransact;
@@ -533,6 +539,8 @@ class HttpSM : public Continuation, public PluginUserArgs<TS_USER_ARGS_TXN>
533539
const char *plugin_tag = nullptr;
534540
int64_t plugin_id = 0;
535541

542+
CompatibilityCacheLookup compatibility_cache_lookup = CompatibilityCacheLookup::COMPAT_CACHE_LOOKUP_NORMAL;
543+
536544
private:
537545
HttpTunnel tunnel;
538546

src/iocore/cache/P_CacheInternal.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,11 @@ struct Cache {
471471
static void generate_key(CryptoHash *hash, CacheURL *url);
472472
static void generate_key(HttpCacheKey *hash, CacheURL *url, bool ignore_query = false, cache_generation_t generation = -1);
473473

474+
// These generate functions are used for backward compatibility with caches created with ATS9.2
475+
// see `proxy.config.http.cache.try_compat_key_read`
476+
static void generate_key92(CryptoHash *hash, CacheURL *url);
477+
static void generate_key92(HttpCacheKey *hash, CacheURL *url, bool ignore_query = false, cache_generation_t generation = -1);
478+
474479
void vol_initialized(bool result);
475480

476481
int open_done();
@@ -496,6 +501,19 @@ Cache::generate_key(HttpCacheKey *key, CacheURL *url, bool ignore_query, cache_g
496501
url->hash_get(&key->hash, ignore_query, generation);
497502
}
498503

504+
inline void
505+
Cache::generate_key92(CryptoHash *hash, CacheURL *url)
506+
{
507+
url->hash_get92(hash);
508+
}
509+
510+
inline void
511+
Cache::generate_key92(HttpCacheKey *key, CacheURL *url, bool ignore_query, cache_generation_t generation)
512+
{
513+
key->hostname = url->host_get(&key->hostlen);
514+
url->hash_get92(&key->hash, ignore_query, generation);
515+
}
516+
499517
inline unsigned int
500518
cache_hash(const CryptoHash &hash)
501519
{

src/proxy/hdrs/URL.cc

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,123 @@ url_CryptoHash_get(const URLImpl *url, CryptoHash *hash, bool ignore_query, cach
18951895
}
18961896
}
18971897

1898+
static inline void
1899+
url_CryptoHash_get_general_92(const URLImpl *url, CryptoContext &ctx, CryptoHash &hash, bool ignore_query,
1900+
cache_generation_t generation)
1901+
{
1902+
char buffer[BUFSIZE];
1903+
char *p, *e;
1904+
const char *strs[13], *ends[13];
1905+
const char *t;
1906+
in_port_t port;
1907+
int i, s;
1908+
1909+
strs[0] = url->m_ptr_scheme;
1910+
strs[1] = "://";
1911+
strs[2] = url->m_ptr_user;
1912+
strs[3] = ":";
1913+
strs[4] = url->m_ptr_password;
1914+
strs[5] = "@";
1915+
strs[6] = url->m_ptr_host;
1916+
strs[7] = "/";
1917+
strs[8] = url->m_ptr_path;
1918+
1919+
ends[0] = strs[0] + url->m_len_scheme;
1920+
ends[1] = strs[1] + 3;
1921+
ends[2] = strs[2] + url->m_len_user;
1922+
ends[3] = strs[3] + 1;
1923+
ends[4] = strs[4] + url->m_len_password;
1924+
ends[5] = strs[5] + 1;
1925+
ends[6] = strs[6] + url->m_len_host;
1926+
ends[7] = strs[7] + 1;
1927+
ends[8] = strs[8] + url->m_len_path;
1928+
1929+
strs[9] = ";";
1930+
strs[10] = url->m_ptr_params;
1931+
strs[11] = "?";
1932+
1933+
// Special case for the query paramters, allowing us to ignore them if requested
1934+
if (!ignore_query) {
1935+
strs[12] = url->m_ptr_query;
1936+
ends[12] = strs[12] + url->m_len_query;
1937+
} else {
1938+
strs[12] = nullptr;
1939+
ends[12] = nullptr;
1940+
}
1941+
1942+
ends[9] = strs[9] + 1;
1943+
ends[10] = strs[10] + url->m_len_params;
1944+
ends[11] = strs[11] + 1;
1945+
1946+
p = buffer;
1947+
e = buffer + BUFSIZE;
1948+
1949+
for (i = 0; i < 13; i++) {
1950+
if (strs[i]) {
1951+
t = strs[i];
1952+
s = 0;
1953+
1954+
while (t < ends[i]) {
1955+
if ((i == 0) || (i == 6)) { // scheme and host
1956+
unescape_str_tolower(p, e, t, ends[i], s);
1957+
} else if (i == 8 || i == 10 || i == 12) { // path, params, query
1958+
// Don't unescape the parts of the URI that are processed by the
1959+
// origin since it may behave differently based upon whether these are
1960+
// escaped or not. Therefore differently encoded strings should be
1961+
// cached separately via differentiated hashes.
1962+
int path_len = ends[i] - t;
1963+
int min_len = std::min(path_len, static_cast<int>(e - p));
1964+
memcpy(p, t, min_len);
1965+
p += min_len;
1966+
t += min_len;
1967+
} else {
1968+
unescape_str(p, e, t, ends[i], s);
1969+
}
1970+
1971+
if (p == e) {
1972+
ctx.update(buffer, BUFSIZE);
1973+
p = buffer;
1974+
}
1975+
}
1976+
}
1977+
}
1978+
1979+
if (p != buffer) {
1980+
ctx.update(buffer, p - buffer);
1981+
}
1982+
int buffer_len = static_cast<int>(p - buffer);
1983+
port = url_canonicalize_port(url->m_url_type, url->m_port);
1984+
1985+
ctx.update(&port, sizeof(port));
1986+
if (generation != -1) {
1987+
ctx.update(&generation, sizeof(generation));
1988+
Dbg(dbg_ctl_url_cachekey, "Final url string for cache hash key %.*s%d%d", buffer_len, buffer, port,
1989+
static_cast<int>(generation));
1990+
} else {
1991+
Dbg(dbg_ctl_url_cachekey, "Final url string for cache hash key %.*s%d", buffer_len, buffer, port);
1992+
}
1993+
ctx.finalize(hash);
1994+
}
1995+
1996+
void
1997+
url_CryptoHash_get_92(const URLImpl *url, CryptoHash *hash, bool ignore_query, cache_generation_t generation)
1998+
{
1999+
URLHashContext ctx;
2000+
if ((url_hash_method != 0) && (url->m_url_type == URLType::HTTP) &&
2001+
((url->m_len_user + url->m_len_password + url->m_len_params + (ignore_query ? 0 : url->m_len_query)) == 0) &&
2002+
(3 + 1 + 1 + 1 + 1 + 1 + 2 + url->m_len_scheme + url->m_len_host + url->m_len_path < BUFSIZE) &&
2003+
(memchr(url->m_ptr_host, '%', url->m_len_host) == nullptr) && (memchr(url->m_ptr_path, '%', url->m_len_path) == nullptr)) {
2004+
url_CryptoHash_get_fast(url, ctx, hash, generation);
2005+
#ifdef DEBUG
2006+
CryptoHash hash_general;
2007+
url_CryptoHash_get_general_92(url, ctx, hash_general, ignore_query, generation);
2008+
ink_assert(*hash == hash_general);
2009+
#endif
2010+
} else {
2011+
url_CryptoHash_get_general_92(url, ctx, *hash, ignore_query, generation);
2012+
}
2013+
}
2014+
18982015
#undef BUFSIZE
18992016

19002017
/*-------------------------------------------------------------------------

src/proxy/http/HttpConfig.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ register_stat_callbacks()
590590
Metrics::Counter::createPtr("proxy.process.http.origin_server_speed_bytes_per_sec_800M");
591591
http_rsb.origin_server_speed_bytes_per_sec_1G =
592592
Metrics::Counter::createPtr("proxy.process.http.origin_server_speed_bytes_per_sec_1G");
593+
http_rsb.cache_compat_key_reads = Metrics::Counter::createPtr("proxy.process.http.cache.compat_key_reads");
593594

594595
Metrics::Derived::derive({
595596
// Total bytes of client request body + headers
@@ -1107,7 +1108,7 @@ HttpConfig::startup()
11071108
HttpEstablishStaticConfigLongLong(c.post_copy_size, "proxy.config.http.post_copy_size");
11081109
HttpEstablishStaticConfigStringAlloc(c.redirect_actions_string, "proxy.config.http.redirect.actions");
11091110
HttpEstablishStaticConfigByte(c.http_host_sni_policy, "proxy.config.http.host_sni_policy");
1110-
1111+
HttpEstablishStaticConfigByte(c.cache_try_compat_key_read, "proxy.config.http.cache.try_compat_key_read");
11111112
HttpEstablishStaticConfigStringAlloc(c.oride.ssl_client_sni_policy, "proxy.config.ssl.client.sni_policy");
11121113
HttpEstablishStaticConfigStringAlloc(c.oride.ssl_client_alpn_protocols, "proxy.config.ssl.client.alpn_protocols");
11131114
HttpEstablishStaticConfigByte(c.scheme_proto_mismatch_policy, "proxy.config.ssl.client.scheme_proto_mismatch_policy");
@@ -1408,6 +1409,8 @@ HttpConfig::reconfigure()
14081409
params->oride.plugin_vc_default_buffer_index = m_master.oride.plugin_vc_default_buffer_index;
14091410
params->oride.plugin_vc_default_buffer_water_mark = m_master.oride.plugin_vc_default_buffer_water_mark;
14101411

1412+
params->cache_try_compat_key_read = m_master.cache_try_compat_key_read;
1413+
14111414
m_id = configProcessor.set(m_id, params);
14121415
}
14131416

src/proxy/http/HttpSM.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
2323
*/
2424

25+
#include "proxy/http/HttpConfig.h"
26+
#include "tsutil/Metrics.h"
2527
#include "tsutil/ts_bw_format.h"
2628
#include "proxy/ProxyTransaction.h"
2729
#include "proxy/http/HttpSM.h"
@@ -2589,6 +2591,10 @@ HttpSM::state_cache_open_read(int event, void *data)
25892591
t_state.cache_info.hit_miss_code = SQUID_HIT_DISK;
25902592
}
25912593

2594+
if (compatibility_cache_lookup == CompatibilityCacheLookup::COMPAT_CACHE_LOOKUP_92) {
2595+
Metrics::Counter::increment(http_rsb.cache_compat_key_reads);
2596+
}
2597+
25922598
ink_assert(t_state.cache_info.object_read != nullptr);
25932599
call_transact_and_set_next_state(HttpTransact::HandleCacheOpenRead);
25942600
break;
@@ -2605,6 +2611,13 @@ HttpSM::state_cache_open_read(int event, void *data)
26052611
if (cache_sm.get_last_error() == -ECACHE_DOC_BUSY) {
26062612
t_state.cache_lookup_result = HttpTransact::CacheLookupResult_t::DOC_BUSY;
26072613
} else {
2614+
if (t_state.http_config_param->cache_try_compat_key_read &&
2615+
compatibility_cache_lookup == CompatibilityCacheLookup::COMPAT_CACHE_LOOKUP_NORMAL) {
2616+
// do the retry
2617+
compatibility_cache_lookup = CompatibilityCacheLookup::COMPAT_CACHE_LOOKUP_92;
2618+
do_cache_lookup_and_read();
2619+
return 0;
2620+
}
26082621
t_state.cache_lookup_result = HttpTransact::CacheLookupResult_t::MISS;
26092622
}
26102623

@@ -5015,7 +5028,11 @@ HttpSM::do_cache_lookup_and_read()
50155028
SMDbg(dbg_ctl_http_seq, "Issuing cache lookup for URL %s", c_url->string_get(&t_state.arena));
50165029

50175030
HttpCacheKey key;
5018-
Cache::generate_key(&key, c_url, t_state.txn_conf->cache_ignore_query, t_state.txn_conf->cache_generation_number);
5031+
if (compatibility_cache_lookup == CompatibilityCacheLookup::COMPAT_CACHE_LOOKUP_92) {
5032+
Cache::generate_key92(&key, c_url, t_state.txn_conf->cache_ignore_query, t_state.txn_conf->cache_generation_number);
5033+
} else {
5034+
Cache::generate_key(&key, c_url, t_state.txn_conf->cache_ignore_query, t_state.txn_conf->cache_generation_number);
5035+
}
50195036

50205037
t_state.hdr_info.cache_request.copy(&t_state.hdr_info.client_request);
50215038
HttpTransactHeaders::normalize_accept_encoding(t_state.txn_conf, &t_state.hdr_info.cache_request);

src/records/RecordsConfig.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,13 @@ static const RecordElement RecordsConfig[] =
638638
{RECT_CONFIG, "proxy.config.http.cache.guaranteed_max_lifetime", RECD_INT, "31536000", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
639639
,
640640

641+
// ###################
642+
// # Cache Compat #
643+
// ###################
644+
{RECT_CONFIG, "proxy.config.http.cache.try_compat_key_read", RECD_INT, "0", RECU_NULL, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
645+
,
646+
647+
641648
// ###################
642649
// # Error Reporting #
643650
// ###################

0 commit comments

Comments
 (0)