Hi Josef,

On Wed, Mar 18, 2026 at 7:02 AM Josef Cejka <[email protected]> wrote:
>
> This patch extends current metadata by search by buildid.
> It allows clients to query for all packages (with exact versions)
> and files associated with a specific buildid.
>
> I'd like to use the exact package versions during core dump
> analysis to match them with already known issues/bugs,
> to check that involved packages are reasonable up-to-date
> and to identify other invalid setup, such as mixing packages
> from different Linux distros.
>
> Search by buildid prepares alternative db query, handling
> of results incl. gathering results from federated servers
> remains the same.
> It does not search for source files or source file archives.
>
> Signed-off-by: Josef Cejka <[email protected]>

Thanks for this patch. I've pushed this with one line added to
doc/debuginfod-find.1 mentioning the new buildid key.

Aaron

> ---
>  debuginfod/debuginfod-find.c          |  2 +-
>  debuginfod/debuginfod.cxx             | 77 ++++++++++++++++++++-------
>  tests/run-debuginfod-find-metadata.sh |  6 +++
>  3 files changed, 66 insertions(+), 19 deletions(-)
>
> diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
> index 39de65c3..2f90a567 100644
> --- a/debuginfod/debuginfod-find.c
> +++ b/debuginfod/debuginfod-find.c
> @@ -54,7 +54,7 @@ static const char args_doc[] = N_("debuginfo BUILDID\n"
>                                    "source PATH /FILENAME\n"
>                                    "section BUILDID SECTION-NAME\n"
>                                    "section PATH SECTION-NAME\n"
> -                                  "metadata (glob|file|KEY) 
> (GLOB|FILENAME|VALUE)\n"
> +                                  "metadata (glob|file|buildid|KEY) 
> (GLOB|FILENAME|BUILDID|VALUE)\n"
>                                    );
>
>  /* Definitions of arguments for argp functions.  */
> diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
> index 049570ae..2cf77bcc 100644
> --- a/debuginfod/debuginfod.cxx
> +++ b/debuginfod/debuginfod.cxx
> @@ -3578,25 +3578,9 @@ handle_metrics (off_t* size)
>    return r;
>  }
>
> -
> -static struct MHD_Response*
> -handle_metadata (MHD_Connection* conn,
> -                 string key, string value, off_t* size)
> +static sqlite_ps*
> +handle_metadata_glob(sqlite3* thisdb, const string& key, const string& value)
>  {
> -  MHD_Response* r;
> -  // Because this query can take on the order of many seconds, we need
> -  // to prevent DoS against the other normal quick queries, so we use
> -  // a dedicated database connection.
> -  sqlite3 *thisdb = 0;
> -  int rc = sqlite3_open_v2 (db_path.c_str(), &thisdb, (SQLITE_OPEN_READONLY
> -                                                       |SQLITE_OPEN_URI
> -                                                       
> |SQLITE_OPEN_PRIVATECACHE
> -                                                       
> |SQLITE_OPEN_NOMUTEX), /* private to us */
> -                            NULL);
> -  if (rc)
> -    throw sqlite_exception(rc, "cannot open database for metadata query");
> -  defer_dtor<sqlite3*,int> sqlite_db_closer (thisdb, sqlite3_close_v2);
> -
>    // Query locally for matching e, d files
>    string op;
>    if (key == "glob")
> @@ -3670,6 +3654,63 @@ handle_metadata (MHD_Connection* conn,
>    pp->bind(2, bname);
>    pp->bind(3, dirname);
>    pp->bind(4, bname);
> +  return pp;
> +}
> +
> +static sqlite_ps*
> +handle_metadata_buildid(sqlite3* thisdb, const string& value)
> +{
> +  string sql = string(
> +                      "select d1.executable_p, d1.debuginfo_p, 0 as 
> source_p, "
> +                      "       b1.hex, f1d.name || '/' || f1b.name as file, 
> a1.name as archive "
> +                      "from " BUILDIDS "_r_de d1, " BUILDIDS "_files f1, " 
> BUILDIDS "_fileparts f1b, " BUILDIDS "_fileparts f1d, "
> +                      BUILDIDS "_buildids b1, " BUILDIDS "_files_v a1 "
> +                      "where f1.id = d1.content and a1.id = d1.file and 
> d1.buildid = b1.id "
> +                      "      and b1.hex = ? and f1.dirname = f1d.id and 
> f1.basename = f1b.id "
> +                      "union all \n"
> +                      "select d2.executable_p, d2.debuginfo_p, 0, "
> +                      "       b2.hex, f2d.name || '/' || f2b.name, NULL "
> +                      "from " BUILDIDS "_f_de d2, " BUILDIDS "_files f2, " 
> BUILDIDS "_fileparts f2b, " BUILDIDS "_fileparts f2d, "
> +                      BUILDIDS "_buildids b2 "
> +                      "where f2.id = d2.file and d2.buildid = b2.id "
> +                      "      and b2.hex = ? "
> +                      "      and f2.dirname = f2d.id and f2.basename = 
> f2b.id");
> +
> +  sqlite_ps *pp = new sqlite_ps (thisdb, "mhd-query-meta-buildid", sql);
> +  pp->reset();
> +  pp->bind(1, value); // Bind buildid for the first select (_r_de)
> +  pp->bind(2, value); // Bind buildid for the second select (_f_de)
> +  return pp;
> +}
> +
> +static struct MHD_Response*
> +handle_metadata (MHD_Connection* conn,
> +                 string key, string value, off_t* size)
> +{
> +  MHD_Response* r;
> +  // Because this query can take on the order of many seconds, we need
> +  // to prevent DoS against the other normal quick queries, so we use
> +  // a dedicated database connection.
> +  sqlite3 *thisdb = 0;
> +  int rc = sqlite3_open_v2 (db_path.c_str(), &thisdb, (SQLITE_OPEN_READONLY
> +                                                       |SQLITE_OPEN_URI
> +                                                       
> |SQLITE_OPEN_PRIVATECACHE
> +                                                       
> |SQLITE_OPEN_NOMUTEX), /* private to us */
> +                            NULL);
> +  if (rc)
> +    throw sqlite_exception(rc, "cannot open database for metadata query");
> +  defer_dtor<sqlite3*,int> sqlite_db_closer (thisdb, sqlite3_close_v2);
> +
> +  sqlite_ps *pp = nullptr;
> +
> +  if (key == "glob" || key == "file") {
> +    pp = handle_metadata_glob(thisdb, key, value);
> +  } else if (key == "buildid") {
> +    pp = handle_metadata_buildid(thisdb, value);
> +  } else {
> +    throw reportable_exception("/metadata webapi error, unsupported key");
> +  }
> +
>    unique_ptr<sqlite_ps> ps_closer(pp); // release pp if exception or return
>    pp->reset_timeout(metadata_maxtime_s);
>
> diff --git a/tests/run-debuginfod-find-metadata.sh 
> b/tests/run-debuginfod-find-metadata.sh
> index 99759cff..fd42fb8e 100755
> --- a/tests/run-debuginfod-find-metadata.sh
> +++ b/tests/run-debuginfod-find-metadata.sh
> @@ -75,6 +75,10 @@ RESULTJ=`env LD_LIBRARY_PATH=$ldpath ${VALGRIND_CMD} 
> ${abs_builddir}/../debuginf
>  echo $RESULTJ
>  N_FOUND=`echo $RESULTJ | jq '.results | length'`
>  test $N_FOUND -eq 2
> +RESULTJ=`env LD_LIBRARY_PATH=$ldpath ${VALGRIND_CMD} 
> ${abs_builddir}/../debuginfod/debuginfod-find metadata buildid 
> "f17a29b5a25bd4960531d82aa6b07c8abe84fa66"`
> +echo $RESULTJ
> +N_FOUND=`echo $RESULTJ | jq '.results | length'`
> +test $N_FOUND -eq 2
>
>
>  # Query via the webapi as well
> @@ -85,6 +89,8 @@ curl -s -i 
> http://127.0.0.1:$PORT2'/metadata?key=glob&value=/usr/bin/*hi*' | gre
>  test `curl -s 
> http://127.0.0.1:$PORT2'/metadata?key=glob&value=/usr/bin/*hi*' | jq 
> '.results[0].buildid == "f17a29b5a25bd4960531d82aa6b07c8abe84fa66"'` = 'true'
>  test `curl -s 
> http://127.0.0.1:$PORT2'/metadata?key=glob&value=/usr/bin/*hi*' | jq 
> '.results[0].file == "/usr/bin/hithere"'` = 'true'
>  test `curl -s 
> http://127.0.0.1:$PORT2'/metadata?key=glob&value=/usr/bin/*hi*' | jq 
> '.results[0].archive | test(".*hithere.*deb")'` = 'true'
> +test `curl -s 
> http://127.0.0.1:$PORT1'/metadata?key=buildid&value=bc1febfd03ca05e030f0d205f7659db29f8a4b30'
>  | jq '.results[0].archive | test(".*hello2.*rpm")'` = 'true'
> +test `curl -s 
> http://127.0.0.1:$PORT2'/metadata?key=buildid&value=bc1febfd03ca05e030f0d205f7659db29f8a4b30'
>  | jq '.results[0].archive | test(".*hello2.*rpm")'` = 'true'
>  # Note we query the upstream server too, since the downstream will have an 
> incomplete result due to the badurl
>  test `curl -s 
> http://127.0.0.1:$PORT1'/metadata?key=glob&value=/usr/bin/*hi*' | jq 
> '.complete == true'` = 'true'
>  test `curl -s 
> http://127.0.0.1:$PORT2'/metadata?key=glob&value=/usr/bin/*hi*' | jq 
> '.complete == false'` = 'true'
> --
> 2.51.0
>

Reply via email to