From patchwork Sat Nov 6 02:42:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Frank Ch. Eigler" X-Patchwork-Id: 47146 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2F1843858034 for ; Sat, 6 Nov 2021 02:43:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F1843858034 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1636166585; bh=Q3MW4EiKbuVVgpIWjzaglhqLcsokkVx3PqqOVQlTT6g=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Help: List-Subscribe:From:Reply-To:From; b=qLlZ+dqLYRgcCgQnlYDw3cokSQrnDDidPr2FUIrLpbMlsDvrj1hZMWdM4ikC8czDR ixdDUCcBAOZajBuSog1vkhCSvoJMZcfwIsvFdvTHhGmtg/v20uzxsupdRQc5XgnbYI TmntkdxH5ePKMakRu6fr318rRymCpeNVX1Cx0xX8= X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTPS id E41E4385802A for ; Sat, 6 Nov 2021 02:42:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E41E4385802A Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-395-lrfq7m6nO5yJuNE_pjJAPQ-1; Fri, 05 Nov 2021 22:42:48 -0400 X-MC-Unique: lrfq7m6nO5yJuNE_pjJAPQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3B8231005E4D for ; Sat, 6 Nov 2021 02:42:47 +0000 (UTC) Received: from redhat.com (ovpn-113-80.phx2.redhat.com [10.3.113.80]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EC8E55C25D for ; Sat, 6 Nov 2021 02:42:46 +0000 (UTC) Received: from fche by redhat.com with local (Exim 4.94.2) (envelope-from ) id 1mjBfJ-0001LC-Ja for elfutils-devel@sourceware.org; Fri, 05 Nov 2021 22:42:45 -0400 Date: Fri, 5 Nov 2021 22:42:45 -0400 To: elfutils-devel@sourceware.org Subject: PATCH: PR28430: debuginfod --passive mode Message-ID: <20211106024245.GC3305@redhat.com> MIME-Version: 1.0 User-Agent: Mutt/1.12.0 (2019-05-25) X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Elfutils-devel mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Frank Ch. Eigler via Elfutils-devel" From: "Frank Ch. Eigler" Reply-To: "Frank Ch. Eigler" Errors-To: elfutils-devel-bounces+patchwork=sourceware.org@sourceware.org Sender: "Elfutils-devel" Hi - I speculate this one will be handy for even larger debuginfod installations, where one must pool multiple servers together, but without duplicating indexing/grooming efforts. (The diff is larger than it needs to be, by virtue of nesting previous code into a conditional block.) commit 8f2623a9ff8ac311c0ec829d982863a8dda4154a Author: Frank Ch. Eigler Date: Fri Nov 5 22:26:35 2021 -0400 PR28430: debuginfod: support --passive mode Add support for a limited mode for debuginfod that uses a pure read-only sqlite index. This mode is useful for load spreading based on naively shared or replicated databases. Signed-off-by: Frank Ch. Eigler diff --git a/NEWS b/NEWS index b812b7438967..709c4cd9e7f5 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ debuginfod: Supply extra HTTP response headers, describing archive/file Add -r option to use -I/-X regexes for grooming stale files. Protect against wasted CPU from duplicate concurrent requests. Limit the duration of groom ops roughly to rescan (-t) times. + Add --passive mode for serving from read-only database. Several other performance improvements & prometheus metrics. Version 0.185 diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog index 15b2ba40fa0f..f06d3ee3ecf4 100644 --- a/debuginfod/ChangeLog +++ b/debuginfod/ChangeLog @@ -1,3 +1,11 @@ +2021-11-05 Frank Ch. Eigler + + PR28430 + * debuginfod.cxx (parse_opt): Add "--passive" flag. Complain + about inconsistent flags. + (main): In passive mode, suppress scan/groom/traverse threads and + other read-write database ops. + 2021-11-04 Frank Ch. Eigler PR28514 diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index 45981d8d4279..28217e6d92d4 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -376,6 +376,8 @@ static const struct argp_option options[] = prefetch cache.", 0}, #define ARGP_KEY_FORWARDED_TTL_LIMIT 0x1007 {"forwarded-ttl-limit", ARGP_KEY_FORWARDED_TTL_LIMIT, "NUM", 0, "Limit of X-Forwarded-For hops, default 8.", 0}, +#define ARGP_KEY_PASSIVE 0x1008 + { "passive", ARGP_KEY_PASSIVE, NULL, 0, "Do not scan or groom, read-only database.", 0 }, { NULL, 0, NULL, 0, NULL, 0 }, }; @@ -425,6 +427,8 @@ static long fdcache_prefetch_mbs; static long fdcache_prefetch_fds; static unsigned forwarded_ttl_limit = 8; static string tmpdir; +static bool passive_p = false; + static void set_metric(const string& key, double value); // static void inc_metric(const string& key); @@ -524,36 +528,56 @@ parse_opt (int key, char *arg, } break; case 'L': + if (passive_p) + argp_failure(state, 1, EINVAL, "-L option inconsistent with passive mode"); traverse_logical = true; break; - case 'D': extra_ddl.push_back(string(arg)); break; + case 'D': + if (passive_p) + argp_failure(state, 1, EINVAL, "-D option inconsistent with passive mode"); + extra_ddl.push_back(string(arg)); + break; case 't': + if (passive_p) + argp_failure(state, 1, EINVAL, "-t option inconsistent with passive mode"); rescan_s = (unsigned) atoi(arg); break; case 'g': + if (passive_p) + argp_failure(state, 1, EINVAL, "-g option inconsistent with passive mode"); groom_s = (unsigned) atoi(arg); break; case 'G': + if (passive_p) + argp_failure(state, 1, EINVAL, "-G option inconsistent with passive mode"); maxigroom = true; break; case 'c': + if (passive_p) + argp_failure(state, 1, EINVAL, "-c option inconsistent with passive mode"); concurrency = (unsigned) atoi(arg); if (concurrency < 1) concurrency = 1; break; case 'I': // NB: no problem with unconditional free here - an earlier failed regcomp would exit program + if (passive_p) + argp_failure(state, 1, EINVAL, "-I option inconsistent with passive mode"); regfree (&file_include_regex); rc = regcomp (&file_include_regex, arg, REG_EXTENDED|REG_NOSUB); if (rc != 0) argp_failure(state, 1, EINVAL, "regular expression"); break; case 'X': + if (passive_p) + argp_failure(state, 1, EINVAL, "-X option inconsistent with passive mode"); regfree (&file_exclude_regex); rc = regcomp (&file_exclude_regex, arg, REG_EXTENDED|REG_NOSUB); if (rc != 0) argp_failure(state, 1, EINVAL, "regular expression"); break; case 'r': + if (passive_p) + argp_failure(state, 1, EINVAL, "-r option inconsistent with passive mode"); regex_groom = true; break; case ARGP_KEY_FDCACHE_FDS: @@ -586,6 +610,15 @@ parse_opt (int key, char *arg, if ( fdcache_prefetch_mbs < 0) argp_failure(state, 1, EINVAL, "fdcache prefetch mbs"); break; + case ARGP_KEY_PASSIVE: + passive_p = true; + if (source_paths.size() > 0 || + maxigroom || + extra_ddl.size() > 0 || + traverse_logical) + // other conflicting options tricky to check + argp_failure(state, 1, EINVAL, "inconsistent options with passive mode"); + break; // case 'h': argp_state_help (state, stderr, ARGP_HELP_LONG|ARGP_HELP_EXIT_OK); default: return ARGP_ERR_UNKNOWN; } @@ -3732,22 +3765,25 @@ main (int argc, char *argv[]) (void) signal (SIGUSR2, sigusr2_handler); // end-user /* Get database ready. */ - rc = sqlite3_open_v2 (db_path.c_str(), &db, (SQLITE_OPEN_READWRITE - |SQLITE_OPEN_URI - |SQLITE_OPEN_PRIVATECACHE - |SQLITE_OPEN_CREATE - |SQLITE_OPEN_FULLMUTEX), /* thread-safe */ - NULL); - if (rc == SQLITE_CORRUPT) - { - (void) unlink (db_path.c_str()); - error (EXIT_FAILURE, 0, - "cannot open %s, deleted database: %s", db_path.c_str(), sqlite3_errmsg(db)); - } - else if (rc) - { - error (EXIT_FAILURE, 0, - "cannot open %s, consider deleting database: %s", db_path.c_str(), sqlite3_errmsg(db)); + if (! passive_p) + { + rc = sqlite3_open_v2 (db_path.c_str(), &db, (SQLITE_OPEN_READWRITE + |SQLITE_OPEN_URI + |SQLITE_OPEN_PRIVATECACHE + |SQLITE_OPEN_CREATE + |SQLITE_OPEN_FULLMUTEX), /* thread-safe */ + NULL); + if (rc == SQLITE_CORRUPT) + { + (void) unlink (db_path.c_str()); + error (EXIT_FAILURE, 0, + "cannot open %s, deleted database: %s", db_path.c_str(), sqlite3_errmsg(db)); + } + else if (rc) + { + error (EXIT_FAILURE, 0, + "cannot open %s, consider deleting database: %s", db_path.c_str(), sqlite3_errmsg(db)); + } } // open the readonly query variant @@ -3765,8 +3801,10 @@ main (int argc, char *argv[]) } - obatched(clog) << "opened database " << db_path << endl; + obatched(clog) << "opened database " << db_path + << (db?" rw":"") << (dbq?" ro":"") << endl; obatched(clog) << "sqlite version " << sqlite3_version << endl; + obatched(clog) << "service mode " << (passive_p ? "passive":"active") << endl; // add special string-prefix-similarity function used in rpm sref/sdef resolution rc = sqlite3_create_function(dbq, "sharedprefix", 2, SQLITE_UTF8, NULL, @@ -3775,13 +3813,16 @@ main (int argc, char *argv[]) error (EXIT_FAILURE, 0, "cannot create sharedprefix function: %s", sqlite3_errmsg(dbq)); - if (verbose > 3) - obatched(clog) << "ddl: " << DEBUGINFOD_SQLITE_DDL << endl; - rc = sqlite3_exec (db, DEBUGINFOD_SQLITE_DDL, NULL, NULL, NULL); - if (rc != SQLITE_OK) + if (! passive_p) { - error (EXIT_FAILURE, 0, - "cannot run database schema ddl: %s", sqlite3_errmsg(db)); + if (verbose > 3) + obatched(clog) << "ddl: " << DEBUGINFOD_SQLITE_DDL << endl; + rc = sqlite3_exec (db, DEBUGINFOD_SQLITE_DDL, NULL, NULL, NULL); + if (rc != SQLITE_OK) + { + error (EXIT_FAILURE, 0, + "cannot run database schema ddl: %s", sqlite3_errmsg(db)); + } } // Start httpd server threads. Separate pool for IPv4 and IPv6, in @@ -3845,27 +3886,31 @@ main (int argc, char *argv[]) } // run extra -D sql if given - for (auto&& i: extra_ddl) - { - if (verbose > 1) - obatched(clog) << "extra ddl:\n" << i << endl; - rc = sqlite3_exec (db, i.c_str(), NULL, NULL, NULL); - if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW) - error (0, 0, - "warning: cannot run database extra ddl %s: %s", i.c_str(), sqlite3_errmsg(db)); - } - - if (maxigroom) - obatched(clog) << "maxigroomed database" << endl; + if (! passive_p) + for (auto&& i: extra_ddl) + { + if (verbose > 1) + obatched(clog) << "extra ddl:\n" << i << endl; + rc = sqlite3_exec (db, i.c_str(), NULL, NULL, NULL); + if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW) + error (0, 0, + "warning: cannot run database extra ddl %s: %s", i.c_str(), sqlite3_errmsg(db)); + + if (maxigroom) + obatched(clog) << "maxigroomed database" << endl; + } - obatched(clog) << "search concurrency " << concurrency << endl; - obatched(clog) << "rescan time " << rescan_s << endl; + if (! passive_p) + obatched(clog) << "search concurrency " << concurrency << endl; + if (! passive_p) + obatched(clog) << "rescan time " << rescan_s << endl; obatched(clog) << "fdcache fds " << fdcache_fds << endl; obatched(clog) << "fdcache mbs " << fdcache_mbs << endl; obatched(clog) << "fdcache prefetch " << fdcache_prefetch << endl; obatched(clog) << "fdcache tmpdir " << tmpdir << endl; obatched(clog) << "fdcache tmpdir min% " << fdcache_mintmp << endl; - obatched(clog) << "groom time " << groom_s << endl; + if (! passive_p) + obatched(clog) << "groom time " << groom_s << endl; obatched(clog) << "prefetch fds " << fdcache_prefetch_fds << endl; obatched(clog) << "prefetch mbs " << fdcache_prefetch_mbs << endl; obatched(clog) << "forwarded ttl limit " << forwarded_ttl_limit << endl; @@ -3873,7 +3918,7 @@ main (int argc, char *argv[]) if (scan_archives.size()>0) { obatched ob(clog); - auto& o = ob << "scanning archive types "; + auto& o = ob << "accepting archive types "; for (auto&& arch : scan_archives) o << arch.first << "(" << arch.second << ") "; o << endl; @@ -3884,37 +3929,40 @@ main (int argc, char *argv[]) vector all_threads; - pthread_t pt; - rc = pthread_create (& pt, NULL, thread_main_groom, NULL); - if (rc) - error (EXIT_FAILURE, rc, "cannot spawn thread to groom database\n"); - else - { -#ifdef HAVE_PTHREAD_SETNAME_NP - (void) pthread_setname_np (pt, "groom"); -#endif - all_threads.push_back(pt); - } - - if (scan_files || scan_archives.size() > 0) + if (! passive_p) { - rc = pthread_create (& pt, NULL, thread_main_fts_source_paths, NULL); + pthread_t pt; + rc = pthread_create (& pt, NULL, thread_main_groom, NULL); if (rc) - error (EXIT_FAILURE, rc, "cannot spawn thread to traverse source paths\n"); + error (EXIT_FAILURE, rc, "cannot spawn thread to groom database\n"); + else + { #ifdef HAVE_PTHREAD_SETNAME_NP - (void) pthread_setname_np (pt, "traverse"); + (void) pthread_setname_np (pt, "groom"); #endif - all_threads.push_back(pt); - - for (unsigned i=0; i 0) { - rc = pthread_create (& pt, NULL, thread_main_scanner, NULL); + rc = pthread_create (& pt, NULL, thread_main_fts_source_paths, NULL); if (rc) - error (EXIT_FAILURE, rc, "cannot spawn thread to scan source files / archives\n"); + error (EXIT_FAILURE, rc, "cannot spawn thread to traverse source paths\n"); #ifdef HAVE_PTHREAD_SETNAME_NP - (void) pthread_setname_np (pt, "scan"); + (void) pthread_setname_np (pt, "traverse"); #endif all_threads.push_back(pt); + + for (unsigned i=0; i + + PR28430 + * debuginfod.8 (--passive): Document new flag & operation mode. + 2021-08-28 Di Chen * debuginfod.8 (-d): Document ":memory:" as in-memory database. diff --git a/doc/debuginfod.8 b/doc/debuginfod.8 index fde06bb8da6d..1e56f6568322 100644 --- a/doc/debuginfod.8 +++ b/doc/debuginfod.8 @@ -74,9 +74,10 @@ all. If no PATH is listed, or none of the scanning options is given, then \fBdebuginfod\fP will simply serve content that it accumulated into -its index in all previous runs, and federate to any upstream -debuginfod servers. - +its index in all previous runs, periodically groom the database, and +federate to any upstream debuginfod servers. In \fIpassive\fP mode, +\fBdebuginfod\fP will only serve content from a read-only index and +federated upstream servers, but will not scan or groom. .SH OPTIONS @@ -122,6 +123,16 @@ testing the magic string ":memory:" can be used to use an one-time memory-only database. The default database file is \%$HOME/.debuginfod.sqlite. +.TP +.B "\-\-passive" +Set the server to passive mode, where it only services webapi +requests, including participating in federation. It performs no +scanning, no grooming, and so only opens the sqlite database +read-only. This way a database can be safely shared between a active +scanner/groomer server and multiple passive ones, thereby sharing +service load. Archive pattern options must still be given, so +debuginfod can recognize file name extensions for unpacking. + .TP .B "\-D SQL" "\-\-ddl=SQL" Execute given sqlite statement after the database is opened and @@ -365,22 +376,22 @@ be helpful to apply tight \-I or \-X regular-expression constraints to exclude files from scanning that you know have no debuginfo-relevant content. -As debuginfod runs, it periodically rescans its target directories, -and any new content found is added to the database. Old content, such -as data for files that have disappeared or that have been replaced -with newer versions is removed at a periodic \fIgrooming\fP pass. -This means that the sqlite files grow fast during initial indexing, -slowly during index rescans, and periodically shrink during grooming. -There is also an optional one-shot \fImaximal grooming\fP pass is -available. It removes information debuginfo-unrelated data from the -archive content index such as file names found in archives ("archive -sdef" records) that are not referred to as source files from any -binaries find in archives ("archive sref" records). This can save -considerable disk space. However, it is slow and temporarily requires -up to twice the database size as free space. Worse: it may result in -missing source-code info if the archive traversals were interrupted, -so that not all source file references were known. Use it rarely to -polish a complete index. +As debuginfod runs in normal \fIactive\fP mode, it periodically +rescans its target directories, and any new content found is added to +the database. Old content, such as data for files that have +disappeared or that have been replaced with newer versions is removed +at a periodic \fIgrooming\fP pass. This means that the sqlite files +grow fast during initial indexing, slowly during index rescans, and +periodically shrink during grooming. There is also an optional +one-shot \fImaximal grooming\fP pass is available. It removes +information debuginfo-unrelated data from the archive content index +such as file names found in archives ("archive sdef" records) that are +not referred to as source files from any binaries find in archives +("archive sref" records). This can save considerable disk space. +However, it is slow and temporarily requires up to twice the database +size as free space. Worse: it may result in missing source-code info +if the archive traversals were interrupted, so that not all source +file references were known. Use it rarely to polish a complete index. You should ensure that ample disk space remains available. (The flood of error messages on -ENOSPC is ugly and nagging. But, like for most @@ -413,6 +424,11 @@ worry about disk space. If a system crash corrupts the database, or you want to force debuginfod to reset and start over, simply erase the sqlite file before restarting debuginfod. +In contrast, in \fIpassive\fP mode, all scanning and grooming is +disabled, and the index database remains read-only. This makes the +database more suitable for sharing between servers or sites with +simple one-way replication, and data management considerations are +generally moot. .SH SECURITY diff --git a/tests/ChangeLog b/tests/ChangeLog index b791cd7f0d95..394241c7e179 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2021-11-05 Frank Ch. Eigler + + PR28430 + * run-debuginfod-extraction-passive.sh: New test. + * Makefile.am (TESTS, EXTRA_DIST): Add it. + 2021-11-04 Frank Ch. Eigler PR28514 diff --git a/tests/Makefile.am b/tests/Makefile.am index 54b389549046..fdcc57116646 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -233,7 +233,8 @@ TESTS += run-debuginfod-dlopen.sh \ run-debuginfod-federation-metrics.sh \ run-debuginfod-percent-escape.sh \ run-debuginfod-x-forwarded-for.sh \ - run-debuginfod-response-headers.sh + run-debuginfod-response-headers.sh \ + run-debuginfod-extraction-passive.sh endif endif @@ -528,6 +529,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-debuginfod-archive-test.sh \ run-debuginfod-percent-escape.sh \ run-debuginfod-response-headers.sh \ + run-debuginfod-extraction-passive.sh \ debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm \ debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm \ debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm \ diff --git a/tests/run-debuginfod-extraction-passive.sh b/tests/run-debuginfod-extraction-passive.sh new file mode 100755 index 000000000000..fdef63ef0acb --- /dev/null +++ b/tests/run-debuginfod-extraction-passive.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2019-2021 Red Hat, Inc. +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. $srcdir/debuginfod-subr.sh + +# for test case debugging, uncomment: +set -x +unset VALGRIND_CMD + +mkdir Z +# This variable is essential and ensures no time-race for claiming ports occurs +# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test +base=11000 +get_ports + +DB=${PWD}/.debuginfod.sqlite +tempfiles $DB +export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache + +cp -rvp ${abs_srcdir}/debuginfod-tars Z +tempfiles Z + +env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 -t0 -g0 -v Z > vlog$PORT1 2>&1 & +PID1=$! +tempfiles vlog$PORT1 +errfiles vlog$PORT1 + +wait_ready $PORT1 'ready' 1 + +# Start second passive server with same database +env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE --passive -d $DB -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT2 -v > vlog$PORT2 2>&1 & +PID2=$! + +tempfiles vlog$PORT2 +errfiles vlog$PORT2 + +wait_ready $PORT2 'ready' 1 + +# Wait for first server to finish indexing +wait_ready $PORT1 'thread_work_total{role="traverse"}' 1 +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 +wait_ready $PORT1 'thread_busy{role="scan"}' 0 + +# No similar metrics for the passive server +! (curl http://localhost:$PORT2/metrics | egrep 'role="scan"|role="groom"|role="traverse"') + +# Confirm no active threads +! (ps -q $PID2 -e -L -o '%p %c %a' | egrep 'scan|groom|traverse') + +# Do a random lookup via passive server +env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://localhost:$PORT2 ${abs_builddir}/../debuginfod/debuginfod-find debuginfo cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb + +tempfiles $DB* + +kill $PID1 +wait $PID1 +PID1=0 + +kill $PID2 +wait $PID2 +PID2=0 + +exit 0