On Wed, Jan 03, 2024 at 07:59:45AM +0000, Bertrand Drouvot wrote:
> +1 to add a test and put in a place that would produce failures at build time.
> I think that having the test in the script that generates the header file is 
> more
> appropriate (as building the documentation looks less usual to me when 
> working on
> a patch).

Okay, I did that in v2.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com
>From 587f6a2c108fc7496fcb3d5764ca06ac5fb21326 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nat...@postgresql.org>
Date: Fri, 5 Jan 2024 00:07:40 -0600
Subject: [PATCH v2 1/1] verify lists of predefined LWLocks in lwlocknames.txt
 and wait_event_names.txt match

---
 src/backend/Makefile                          |  2 +-
 src/backend/storage/lmgr/Makefile             |  4 +-
 .../storage/lmgr/generate-lwlocknames.pl      | 63 +++++++++++++++++++
 .../utils/activity/wait_event_names.txt       | 10 +++
 src/include/storage/meson.build               |  2 +-
 5 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/src/backend/Makefile b/src/backend/Makefile
index 816461aa17..7d2ea7d54a 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -130,7 +130,7 @@ $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 parser/gram.h: parser/gram.y
 	$(MAKE) -C parser gram.h
 
-storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
+storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt utils/activity/wait_event_names.txt
 	$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
 
 utils/activity/wait_event_types.h: utils/activity/generate-wait_event_types.pl utils/activity/wait_event_names.txt
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index c48ba943c4..504480e847 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -39,8 +39,8 @@ s_lock_test: s_lock.c $(top_builddir)/src/common/libpgcommon.a $(top_builddir)/s
 lwlocknames.c: lwlocknames.h
 	touch $@
 
-lwlocknames.h: $(top_srcdir)/src/backend/storage/lmgr/lwlocknames.txt generate-lwlocknames.pl
-	$(PERL) $(srcdir)/generate-lwlocknames.pl $<
+lwlocknames.h: $(top_srcdir)/src/backend/storage/lmgr/lwlocknames.txt $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt generate-lwlocknames.pl
+	$(PERL) $(srcdir)/generate-lwlocknames.pl $^
 
 check: s_lock_test
 	./s_lock_test
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index bef5e16e11..9afee7984b 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -15,6 +15,7 @@ my $continue = "\n";
 GetOptions('outdir:s' => \$output_path);
 
 open my $lwlocknames, '<', $ARGV[0] or die;
+open my $wait_event_names, '<', $ARGV[1] or die;
 
 # Include PID in suffix in case parallel make runs this multiple times.
 my $htmp = "$output_path/lwlocknames.h.tmp$$";
@@ -30,6 +31,59 @@ print $c $autogen, "\n";
 
 print $c "const char *const IndividualLWLockNames[] = {";
 
+#
+# First, record the predefined LWLocks listed in wait_event_names.txt.  We'll
+# cross-check those with the ones in lwlocknames.txt.
+#
+my @wait_event_lwlocks;
+my $found_lwlock_section = 0;
+my $recording_lwlocks = 0;
+
+while (<$wait_event_names>)
+{
+	chomp;
+
+	# Skip comments
+	next if /^#/;
+
+	# Skip empty lines
+	if (/^\s*$/)
+	{
+		#
+		# If we encounter an empty line while recording the LWLocks listed in
+		# wait_event_names.txt, we are done.
+		#
+		last if $recording_lwlocks;
+
+		#
+		# Begin recording the LWLocks listed in wait_event_names.txt following
+		# the empty line after the WaitEventLWLock section declaration.
+		#
+		$recording_lwlocks = 1 if $found_lwlock_section;
+		next;
+	}
+
+	#
+	# Prepare to record the LWLocks when we find the WaitEventLWLock section
+	# declaration.
+	#
+	if (/^Section: ClassName(.*)/)
+	{
+		my $section_name = $_;
+		$section_name =~ s/^.*- //;
+		$found_lwlock_section = 1 if $section_name eq "WaitEventLWLock";
+		next;
+	}
+
+	# Go to the next line if we are not yet recording LWLocks.
+	next if not $recording_lwlocks;
+
+	# Record the LWLock.
+	(my $waiteventname, my $waitevendocsentence) = split(/\t/, $_);
+	push(@wait_event_lwlocks, $waiteventname . "Lock");
+}
+
+my $i = 0;
 while (<$lwlocknames>)
 {
 	chomp;
@@ -50,6 +104,12 @@ while (<$lwlocknames>)
 	die "lwlocknames.txt not in order" if $lockidx < $lastlockidx;
 	die "lwlocknames.txt has duplicates" if $lockidx == $lastlockidx;
 
+	die $lockname . " defined in lwlocknames.txt but missing from wait_event_names.txt"
+	  unless $i < scalar(@wait_event_lwlocks);
+	die "lists of predefined LWLocks in lwlocknames.txt and wait_event_names.txt do not match"
+	  unless $wait_event_lwlocks[$i] eq $lockname;
+	$i++;
+
 	while ($lastlockidx < $lockidx - 1)
 	{
 		++$lastlockidx;
@@ -63,6 +123,9 @@ while (<$lwlocknames>)
 	print $h "#define $lockname (&MainLWLockArray[$lockidx].lock)\n";
 }
 
+die $wait_event_lwlocks[$i] . " defined in wait_event_names.txt but missing from lwlocknames.txt"
+  unless scalar(@wait_event_lwlocks) eq $i;
+
 printf $c "\n};\n";
 print $h "\n";
 printf $h "#define NUM_INDIVIDUAL_LWLOCKS		%s\n", $lastlockidx + 1;
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 088eb977d4..fed50079fd 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -276,6 +276,10 @@ Extension	"Waiting in an extension."
 # This class of wait events has its own set of C structure, so these are
 # only used for the documentation.
 #
+# NB: Predefined locks (those declared in lwlocknames.txt) must be listed in
+# the top section of locks and must be listed in the same order as in
+# lwlocknames.txt.
+#
 
 Section: ClassName - WaitEventLWLock
 
@@ -326,6 +330,12 @@ NotifyQueueTail	"Waiting to update limit on <command>NOTIFY</command> message st
 WaitEventExtension	"Waiting to read or update custom wait events information for extensions."
 WALSummarizer	"Waiting to read or update WAL summarization state."
 
+#
+# Predefined LWLocks (those declared in lwlocknames.txt) must be listed in the
+# section above and must be listed in the same order as in lwlocknames.txt.
+# Other LWLocks must be listed in the section below.
+#
+
 XactBuffer	"Waiting for I/O on a transaction status SLRU buffer."
 CommitTsBuffer	"Waiting for I/O on a commit timestamp SLRU buffer."
 SubtransBuffer	"Waiting for I/O on a sub-transaction SLRU buffer."
diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build
index 2a88248464..8df8b404f5 100644
--- a/src/include/storage/meson.build
+++ b/src/include/storage/meson.build
@@ -1,7 +1,7 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
 lwlocknames = custom_target('lwlocknames',
-  input: files('../../backend/storage/lmgr/lwlocknames.txt'),
+  input: [files('../../backend/storage/lmgr/lwlocknames.txt'), files('../../backend/utils/activity/wait_event_names.txt')],
   output: ['lwlocknames.h', 'lwlocknames.c'],
   command: [
     perl, files('../../backend/storage/lmgr/generate-lwlocknames.pl'),
-- 
2.25.1

Reply via email to