Re: Remove nested functions from readelf.c

2021-02-02 Thread Timm Bäder via Elfutils-devel

On 01/02/2021 15:21, Mark Wielaard wrote:

On Fri, 2021-01-08 at 09:16 +0100, Timm Bäder via Elfutils-devel wrote:

here another round for src/readelf.c. I think they are simple, but I'm
not happy with the advance_pc() commit. I'm open for suggestions here
but I can't come up with something better right now. I'll keep looking
in to that in the meantime.


Yeah, the advance_pc function is really why you want nested functions
in the first place IMHO. Passing around the captured state as 6 extra
arguments seems to not really make the code much clearer. Especially
because on its own it isn't immediately clear what the code is about or
that it is to be used as part of the special opcode or
DW_LNS_advance_pc opcode (where DW_LNS_const_add_pc acts like special
opcode 255) handling.

It might be helpful to spell out in a comment to the function which
part of the DWARF4 6.2.5.1 Special Opcodes handling the advance_pc
function is responsible for.

But honestly in this case I think just keeping the nested function is
the cleanest way to handle this.

Cheers,

Mark



That's what I was worried about as well of course. But I think I can
work on this a bit and solve it in a cleaner way, with some additional
refactorings. I'll try to come up with some patches.


- Timm


--
Red Hat GmbH, http://www.de.redhat.com/, Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Michael O'Neill, Tom Savage, Eric 
Shander




[PATCH] readelf: Remove show_op_index variable

2021-02-02 Thread Timm Bäder via Elfutils-devel
From: Timm Bäder 

advance_pc() uses show_op_index to save whether the current op_index is
> 0 OR the new op_index is > 0.

The new op index is calculated via

new_op_index = (op_index + op_advance) % max_ops_per_instr;

since all of the variables involved are unsigned,
new_op_index >= op_index is always true.

So...

if op_index > 0, then new_op_index > 0
if op_index == 0, then new_op_index >= 0

and if the new_op_index is > 0, then the old one was as well.

In any case, we only need to check the new_op_index, since show_op_index
used to OR the two comparisons.

In other words:

 op_index > 0  |  new_op_index > 0  || show_op_index
 
  true   truetrue
 false   truetrue
  true  falsetrue xx
 false  falsefalse

... but since the third line (marked with xx) is not possible,
the table becomes:

 op_index > 0  |  new_op_index > 0  || show_op_index
 
  true   truetrue
 false   truetrue
 false  falsefalse

... and show_op_index is equal to (new_op_index > 0).
So, remove the show_op_index variable and simply replace it by comparing
the new op_index > 0.
---
 src/ChangeLog | 5 +
 src/readelf.c | 9 +++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 1f53ca7b..9e30df31 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2021-02-02 Timm Bäder 
+
+   * readelf.c (print_debug_line_section): Remove unnecessary
+   show_op_index variable, replace with (op_index > 0).
+
 2021-01-08  Timm Bäder  
 
* readelf.c (print_cfa_program): Lift regname function to...
diff --git a/src/readelf.c b/src/readelf.c
index 9943c211..11692bb5 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8752,14 +8752,11 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl 
*ebl, GElf_Ehdr *ehdr,
   /* Apply the "operation advance" from a special opcode
 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
   unsigned int op_addr_advance;
-  bool show_op_index;
   inline void advance_pc (unsigned int op_advance)
   {
op_addr_advance = minimum_instr_len * ((op_index + op_advance)
   / max_ops_per_instr);
address += op_addr_advance;
-   show_op_index = (op_index > 0 ||
-(op_index + op_advance) % max_ops_per_instr > 0);
op_index = (op_index + op_advance) % max_ops_per_instr;
   }
 
@@ -8803,7 +8800,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
  printf (_(" special opcode %u: address+%u = "),
  opcode, op_addr_advance);
  print_dwarf_addr (dwflmod, 0, address, address);
- if (show_op_index)
+ if (op_index > 0)
printf (_(", op_index = %u, line%+d = %zu\n"),
op_index, line_increment, line);
  else
@@ -8921,7 +8918,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
printf (_(" advance address by %u to "),
op_addr_advance);
print_dwarf_addr (dwflmod, 0, address, address);
-   if (show_op_index)
+   if (op_index > 0)
  printf (_(", op_index to %u"), op_index);
printf ("\n");
  }
@@ -8982,7 +8979,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
printf (_(" advance address by constant %u to "),
op_addr_advance);
print_dwarf_addr (dwflmod, 0, address, address);
-   if (show_op_index)
+   if (op_index > 0)
  printf (_(", op_index to %u"), op_index);
printf ("\n");
  }
-- 
2.26.2



Re: [PATCH 3/4] ar: Pull should_truncate_fname() into file scope

2021-02-02 Thread Timm Bäder via Elfutils-devel

On 29/01/2021 21:48, Mark Wielaard wrote:

Hi Timm,

On Fri, 2021-01-08 at 09:13 +0100, Timm Bäder via Elfutils-devel wrote:

Get rid of a nested function this way.


Skipping this one for now since I don't believe I understand this code.
Could you explain what the code does what it does and why it works fine
when moved this way?


Right, I guess you mean because the old code used to assign a new value
to name_max, but the new code doesn't do that? I fixed that locally
now by taking a size_t* inout argument instead, so assigning to
name_max should have the desired effect again.


- Timm


--
Red Hat GmbH, http://www.de.redhat.com/, Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Michael O'Neill, Tom Savage, Eric 
Shander




[Bug debuginfod/27323] New: concurrency during grooming/scanning

2021-02-02 Thread fche at redhat dot com via Elfutils-devel
https://sourceware.org/bugzilla/show_bug.cgi?id=27323

Bug ID: 27323
   Summary: concurrency during grooming/scanning
   Product: elfutils
   Version: unspecified
Status: NEW
  Severity: normal
  Priority: P2
 Component: debuginfod
  Assignee: unassigned at sourceware dot org
  Reporter: fche at redhat dot com
CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

Further to bug #26775, which made grooming interruptible, we need more. 
Grooming involves some long-running operations, like the database-stats
count(*) queries, which can take MINUTES of run time on a large server. 
sqlite's single-thread-per-connection model means that during those times, web
queries cannot be served, and just pile up.

We need to add a little more concurrency to debuginfod, at the sqlite
connection level.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

PATCH PR27323 debuginfod concurrency++

2021-02-02 Thread Frank Ch. Eigler via Elfutils-devel
Hi -

Some patches for the 0.183 release.  This and PR27092 (low memory)
will be important, maybe PR27277 coming too.


commit d1608c045c46d2ab3d42ef668474e365c4b54e84 (HEAD -> master)
Author: Frank Ch. Eigler 
Date:   Tue Feb 2 16:49:19 2021 -0500

PR27323 debuginfod: improve query concurrency with grooming

Start using a second sqlite3 database connection for webapi query
servicing.  This allows much better concurrency when long-running
grooming operations are in progress.

No testsuite impact.  Grooming times are too short to try to hit with
concurrent requests.  OTOH the existing tests did show some
interesting regressions that needed fixing, like needing not to
dual-wield db and dbq when doing rpm-dwz-related lookups from during
scanning, and the way in which corrupted databases are reported.
These needed some automated invocations of gdb on the running
debuginfod binaries that just failed their testing, for in-situ
debugging.

Hand-tested for function on a huge 20GB index file.  Allowed webapi
queries to be run throughout random points of the grooming process,
including especially the long count(*) report loops before & after.

Signed-off-by: Frank Ch. Eigler 

diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 43a3b9a37932..2872d667fc37 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,3 +1,17 @@
+2021-02-02  Frank Ch. Eigler 
+
+   PR27323
+   * debuginfod.cxx (dbq): New read-only database connection for queries
+   only.
+   (signal_handler): Interrupt it.
+   (main): Open / close it.
+   (handle_buildid): Use it for webapi queries only.
+   (database_stats_report): Make more interruptible.  Report sqlite3
+   operation times to the prometheus metrics.
+   (groom): Make more interruptible.
+   (thread_main_fts_source_paths, thread_main_groom): Ensure
+   state/progress metrics are fresh even in case of exceptions.
+
 2020-12-20  Dmitry V. Levin  
 
* .gitignore: New file.
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index 9a6971868277..c9c0dc9bb819 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -1,5 +1,5 @@
 /* Debuginfo-over-http server.
-   Copyright (C) 2019-2020 Red Hat, Inc.
+   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
@@ -385,7 +385,8 @@ static struct argp argp =
 
 
 static string db_path;
-static sqlite3 *db; // single connection, serialized across all our threads!
+static sqlite3 *db;  // single connection, serialized across all our threads!
+static sqlite3 *dbq; // webapi query-servicing readonly connection, serialized 
ditto!
 static unsigned verbose;
 static volatile sig_atomic_t interrupted = 0;
 static volatile sig_atomic_t forced_rescan_count = 0;
@@ -1569,11 +1570,15 @@ handle_buildid (MHD_Connection* conn,
 obatched(clog) << "searching for buildid=" << buildid << " artifacttype=" 
<< artifacttype
  << " suffix=" << suffix << endl;
 
+  // If invoked from the scanner threads, use the scanners' read-write
+  // connection.  Otherwise use the web query threads' read-only connection.
+  sqlite3 *thisdb = (conn == 0) ? db : dbq;
+  
   sqlite_ps *pp = 0;
 
   if (atype_code == "D")
 {
-  pp = new sqlite_ps (db, "mhd-query-d",
+  pp = new sqlite_ps (thisdb, "mhd-query-d",
   "select mtime, sourcetype, source0, source1 from " 
BUILDIDS "_query_d where buildid = ? "
   "order by mtime desc");
   pp->reset();
@@ -1581,7 +1586,7 @@ handle_buildid (MHD_Connection* conn,
 }
   else if (atype_code == "E")
 {
-  pp = new sqlite_ps (db, "mhd-query-e",
+  pp = new sqlite_ps (thisdb, "mhd-query-e",
   "select mtime, sourcetype, source0, source1 from " 
BUILDIDS "_query_e where buildid = ? "
   "order by mtime desc");
   pp->reset();
@@ -1593,7 +1598,7 @@ handle_buildid (MHD_Connection* conn,
   // Incoming source queries may come in with either dwarf-level OR 
canonicalized paths.
   // We let the query pass with either one.
 
-  pp = new sqlite_ps (db, "mhd-query-s",
+  pp = new sqlite_ps (thisdb, "mhd-query-s",
   "select mtime, sourcetype, source0, source1 from " 
BUILDIDS "_query_s where buildid = ? and artifactsrc in (?,?) "
   "order by sharedprefix(source0,source0ref) desc, 
mtime desc");
   pp->reset();
@@ -1629,6 +1634,7 @@ handle_buildid (MHD_Connection* conn,
   if (r)
 return r;
 }
+  pp->reset();
 
   // We couldn't find it in the database.  Last ditch effort
   // is to defer to other debuginfo servers.
@@ -2971,19 +2977,21 @@ thread_main_fts_source_paths (void* arg)
   rescan_now = true;
 }
   if (rescan_now)
-try
-