From 7b9f36d78eea80ca0b2018b82e0fcbcbf0b6fbcb Mon Sep 17 00:00:00 2001 From: Pushkar Pradhan Date: Mon, 17 Aug 2015 22:54:05 +0000 Subject: [PATCH] This is the fix for TS-3848. The values for wait_for_cache are extended to the range 0-3. If none of the disks or volumes could be initialized and the wait_for_cache value is 2, traffic_server will abort. If even one or more of the disks or volumes could not be initialized and the wait_for_cache value is 3, traffic_server will abort. --- .../configuration/records.config.en.rst | 15 ++++ iocore/cache/Cache.cc | 78 +++++++++++++++++++ iocore/cache/I_Cache.h | 6 +- iocore/cache/I_Store.h | 3 + iocore/cache/Store.cc | 5 +- mgmt/RecordsConfig.cc | 5 +- 6 files changed, 108 insertions(+), 4 deletions(-) diff --git a/doc/reference/configuration/records.config.en.rst b/doc/reference/configuration/records.config.en.rst index 40775d7b76f..cdb051a3549 100644 --- a/doc/reference/configuration/records.config.en.rst +++ b/doc/reference/configuration/records.config.en.rst @@ -2883,5 +2883,20 @@ Sockets exception being if you run Traffic Server with a protocol plugin, and would like for it to not support HTTP requests at all. +.. ts:cv:: CONFIG proxy.config.http.wait_for_cache INT 0 + + If the cache cannot be initialized or read for some reason, this variable + decides whether we should continue serving the requests. This setting only + takes effect if proxy.config.http.cache.http is 1 and + proxy.config.http.wait_for_cache is 1. +===== ==================== +Value Effect +===== ==================== +0 Start listening for requests without waiting for the cache to initialize +1 Wait for the cache to initialize. +2 Wait for the cache to initialize. If none of the cache disks could be initialized, abort. +3 Wait for the cache to initialize. If even one of the disks or volumes failed to initialize, abort. +===== ==================== + .. _Traffic Shaping: https://cwiki.apache.org/confluence/display/TS/Traffic+Shaping diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index d0b59179724..3867314a505 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -733,6 +733,18 @@ CacheProcessor::start_internal(int flags) } } + // TS-3848 + if (waitForCache() >= 2) { + if (gndisks == 0) { + Fatal("no disks could be read"); + } + else if ((static_cast(gndisks) < theCacheStore.n_disks_from_config) + && waitForCache() > 2) { + Fatal("Only %d out of %d disks could be read", + gndisks, theCacheStore.n_disks_from_config); + } + } + if (gndisks == 0) { Warning("unable to open cache disk(s): Cache Disabled\n"); return -1; @@ -755,6 +767,18 @@ CacheProcessor::diskInitialized() bad_disks++; } + // TS-3848 + if (waitForCache() >= 2) { + if (gndisks == bad_disks) { + Fatal("no disks could be read"); + } + else if (waitForCache() == 3 && bad_disks) { + Fatal("disks configured = %d, bad disks = %d", + theCacheStore.n_disks_from_config, + bad_disks); + } + } + if (bad_disks != 0) { // create a new array CacheDisk **p_good_disks; @@ -792,6 +816,12 @@ CacheProcessor::diskInitialized() } if (res == -1) { + + // TS-3848 + if (waitForCache() >= 2) { + Fatal("no volumes could be configured"); + } + /* problems initializing the volume.config. Punt */ gnvol = 0; cacheInitialized(); @@ -1039,6 +1069,7 @@ CacheProcessor::cacheInitialized() Warning("cache unable to open any vols, disabled"); } if (cache_init_ok) { + // Initialize virtual cache CacheProcessor::initialized = CACHE_INITIALIZED; CacheProcessor::cache_ready = caches_ready; @@ -1052,6 +1083,11 @@ CacheProcessor::cacheInitialized() } else { CacheProcessor::initialized = CACHE_INIT_FAILED; Note("cache disabled"); + + // TS-3848 + if (cacheProcessor.waitForCache() > 1) { + Fatal("cache init failed"); + } } // Fire callback to signal initialization finished. if (cb_after_init) @@ -2078,6 +2114,20 @@ Cache::open_done() Action *register_ShowCacheInternal(Continuation * c, HTTPHdr * h); statPagesManager.register_http("cache", register_ShowCache); statPagesManager.register_http("cache-internal", register_ShowCacheInternal); + + // TS-3848 + if (cacheProcessor.waitForCache() >= 2) { + if (total_good_nvol == 0) { + Fatal("No volumes could be initialized"); + } + + if (cacheProcessor.waitForCache() == 3 && + total_nvol && + total_good_nvol < total_nvol) { + Fatal("not all volumes could be initialized"); + } + } + if (total_good_nvol == 0) { ready = CACHE_INIT_FAILED; cacheProcessor.cacheInitialized(); @@ -2091,6 +2141,12 @@ Cache::open_done() ready = CACHE_INIT_FAILED; else ready = CACHE_INITIALIZED; + + // TS-3848 + if (ready == CACHE_INIT_FAILED && cacheProcessor.waitForCache() >= 2) { + Fatal("Failed to initialize cache host table"); + } + cacheProcessor.cacheInitialized(); return 0; @@ -3244,6 +3300,22 @@ ink_cache_init(ModuleVersion v) Warning("no cache disks specified in %s: cache disabled\n", (const char *)path); // exit(1); } + + REC_ReadConfigInteger(cacheProcessor.wait_for_cache, "proxy.config.http.wait_for_cache"); + + // TS-3848 + if (cacheProcessor.waitForCache() >= 2) { + if (theCacheStore.n_disks == 0) { + Fatal("no disks could be read"); + } + else if (theCacheStore.n_disks < theCacheStore.n_disks_from_config && + cacheProcessor.waitForCache() == 3) { + Fatal("disks configured = %d, disks read = %d", + theCacheStore.n_disks_from_config, + theCacheStore.n_disks); + } + } + } //---------------------------------------------------------------------------- @@ -3314,6 +3386,12 @@ CacheProcessor::find_by_path(char const *path, int len) return 0; } +int +CacheProcessor::waitForCache() const +{ + return cacheProcessor.wait_for_cache; +} + // ---------------------------- namespace cache_bc diff --git a/iocore/cache/I_Cache.h b/iocore/cache/I_Cache.h index ecd5db4fd98..a2dd72d067b 100644 --- a/iocore/cache/I_Cache.h +++ b/iocore/cache/I_Cache.h @@ -65,7 +65,8 @@ typedef HTTPInfo CacheHTTPInfo; struct CacheProcessor : public Processor { CacheProcessor() : min_stripe_version(CACHE_DB_MAJOR_VERSION, CACHE_DB_MINOR_VERSION), - max_stripe_version(CACHE_DB_MAJOR_VERSION, CACHE_DB_MINOR_VERSION), cb_after_init(0) + max_stripe_version(CACHE_DB_MAJOR_VERSION, CACHE_DB_MINOR_VERSION), cb_after_init(0), + wait_for_cache(0) { } @@ -147,6 +148,8 @@ struct CacheProcessor : public Processor { void cacheInitialized(); + int waitForCache() const; + static volatile uint32_t cache_ready; static volatile int initialized; static volatile int start_done; @@ -160,6 +163,7 @@ struct CacheProcessor : public Processor { VersionNumber max_stripe_version; CALLBACK_FUNC cb_after_init; + int wait_for_cache; }; inline void diff --git a/iocore/cache/I_Store.h b/iocore/cache/I_Store.h index 7fed57b842c..903470e1d49 100644 --- a/iocore/cache/I_Store.h +++ b/iocore/cache/I_Store.h @@ -240,6 +240,9 @@ struct Store { Store(); ~Store(); + // The number of disks/paths defined in storage.config + unsigned n_disks_from_config; + // The number of disks/paths we could actually read unsigned n_disks; Span **disk; // diff --git a/iocore/cache/Store.cc b/iocore/cache/Store.cc index 6d41e15fc5b..881ffa3bf7b 100644 --- a/iocore/cache/Store.cc +++ b/iocore/cache/Store.cc @@ -71,7 +71,8 @@ span_file_typename(mode_t st_mode) } Ptr tmp_p; -Store::Store() : n_disks(0), disk(NULL) + Store::Store() + : n_disks_from_config(0), n_disks(0), disk(NULL) { } @@ -381,6 +382,8 @@ Store::read_config() } char *pp = Layout::get()->relative(path); + + ++n_disks_from_config; ns = new Span; Debug("cache_init", "Store::read_config - ns = new Span; ns->init(\"%s\",%" PRId64 "), forced volume=%d%s%s", pp, size, volume_num, seed ? " id=" : "", seed ? seed : ""); diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index fc0c6b6281d..8990bb59e0c 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -377,7 +377,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.http.server_ports", RECD_STRING, "8080", RECU_RESTART_TM, RR_NULL, RECC_NULL, NULL, RECA_NULL} , - {RECT_CONFIG, "proxy.config.http.wait_for_cache", RECD_INT, "0", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} + {RECT_CONFIG, "proxy.config.http.wait_for_cache", RECD_INT, "0", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-3]", RECA_NULL} , {RECT_CONFIG, "proxy.config.http.insert_request_via_str", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL} , @@ -1999,7 +1999,8 @@ static const RecordElement RecordsConfig[] = //# Temporary and esoteric values. //# //########### - {RECT_CONFIG, "proxy.config.cache.http.compatibility.4-2-0-fixup", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL} + {RECT_CONFIG, "proxy.config.cache.http.compatibility.4-2-0-fixup", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}, + }; // clang-format on