Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1tyWRi-007qsw-Md for pgsql-hackers@arkaria.postgresql.org; Sat, 29 Mar 2025 13:41:59 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1tyWRf-00B6UK-P4 for pgsql-hackers@arkaria.postgresql.org; Sat, 29 Mar 2025 13:41:55 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1tyWRe-00B6TE-Sw for pgsql-hackers@lists.postgresql.org; Sat, 29 Mar 2025 13:41:55 +0000 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1tyWRX-001nw1-32 for pgsql-hackers@postgresql.org; Sat, 29 Mar 2025 13:41:53 +0000 Received: by mail-pl1-x62e.google.com with SMTP id d9443c01a7336-227b828de00so56672415ad.1 for ; Sat, 29 Mar 2025 06:41:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1743255707; x=1743860507; darn=postgresql.org; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:from:to:cc:subject:date :message-id:reply-to; bh=q5LMq4FTNg73AijbnLZx6touaTwZtY+lV2YViVH7aFw=; b=Fqkd4gCdZXrP7w8v3FOhcW4yaGjhXQtD7hCZ4NPNLOMeUhgSBM+mWmI7E14UH5JBEq YHeueolBSqVGs/6MtCvZoXOrl/DThHEEdaBQpjsBUqM0oL7MQH0l1Qitvvkr2FacBeNh l5mN9TT1X2voItmx5IQHOlsyej4WaSlkykGwQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743255707; x=1743860507; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q5LMq4FTNg73AijbnLZx6touaTwZtY+lV2YViVH7aFw=; b=pz/ZiWZbB2gqcD4b++85q2d77HiT0unGA9lDruQ7O7aYi+uLPvNoxcCESwx8RcnjG3 E+EMCfmg77vXjqZShgor2aTB6VFfV6k0wnXgPDpYUHq3HHVGYl4XAMTwnYkwccioViKE yZofRftm6X7yUF4Eev1afRzZK91V11LK5Mr+OU/02b6RosKZKanu1u/FiwNQ85ONSFvO 03aKmIdUHUkdwDJSMYIgFDHDrIursvpkcC+azeoUdT0WsgP1X+0hDsUX2TWCkv8/aH4E /nIEoZG+CJuAW1k06DWUkCCcPE7U+vLqYz7ACKuc3xqUsBm8NEyOubWy0zk2JQejRy02 ROqw== X-Gm-Message-State: AOJu0YwaM/RZQqbuhllstxk6Y/lCLCa2YwVzFxJYXpNeL+1Lvut7w1Gm RIqrfqfa1tVbCgKId0OgpIu+92SOtJQEphyGrJ9DtUmEl+suol0kAVNFtBFr3Q== X-Gm-Gg: ASbGncs7c6413B7VbYF6dadkqGQRmC7whLXUPVD7d80iGFIOK/8miXA37768uxofRuM dmZMaHUxUF4Iysymy3qAB0uZQJiivV7FoJotTRDllhzXwDT8Zm+4BYCoQgfOvWkZYq14DOMnmdH A/3tOgFgDDYcM7zDS9aNlXcLRHeZxWj7HRhhjOMj5b4+dSBZ+5DQkOT8g+lFfthUeYdljVxGkRX uqT9RIw75P+Yprl8iCK4rIO15TluK3zvQWDcDdyFF/WAWpESHC0DozpoWFuFL5bmAIraESjUfNa M5gGvwXWd1O2eJcPSKWWzOfK/oOwhxbzBuhkUM97ug== X-Google-Smtp-Source: AGHT+IHJvhXwDlsY0rxx/jU0TRRJhBPnnDnZilvuJmjOK+VpjRCo+Qd2/ldhsilZmcgOyvxXQcU6sw== X-Received: by 2002:a17:902:ea02:b0:224:216e:332f with SMTP id d9443c01a7336-2292f9fc054mr43480015ad.48.1743255706762; Sat, 29 Mar 2025 06:41:46 -0700 (PDT) Received: from google.com ([2601:647:5600:80d0::31cd]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2291f1dee2fsm35822045ad.204.2025.03.29.06.41.45 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 29 Mar 2025 06:41:45 -0700 (PDT) Date: Sat, 29 Mar 2025 06:41:43 -0700 From: Noah Misch To: Andres Freund Cc: pgsql-hackers@postgresql.org, Thomas Munro , Heikki Linnakangas , Robert Haas , Jakub Wartak , Jelte Fennema-Nio , Antonin Houska Subject: Re: AIO v2.5 Message-ID: <20250329134143.ca.nmisch@google.com> References: <3yxd5r23zly5bytvgyktbxtxq2r3gbpi7xd4dugevh3h4w4q6c@lu6oatjjpltz> <6ak556uyqiptdwjaci4kbi5eykwkmzqgkbtkyaosjnopjhncrc@2v4ac2jwyz22> <5tyic6epvdlmd6eddgelv47syg2b5cpwffjam54axp25xyq2ga@ptwkinxqo3az> <20250328032223.34.nmisch@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Fri, Mar 28, 2025 at 11:35:23PM -0400, Andres Freund wrote: > The number of combinations is annoyingly large. It's e.g. plausible to use > ignore_checksum_failure=on and zero_damaged_pages=on at the same time for > recovery. That's intricate indeed. > But I finally got to a point where the code ends up readable, without undue > duplication. It would, leaving some nasty hack aside, require a > errhint_internal() - but I can't imagine a reason against introducing that, > given we have it for the errmsg and errhint. Introducing that is fine. > Here's the relevant code: > > /* > * Treat a read that had both zeroed buffers *and* ignored checksums as a > * special case, it's too irregular to be emitted the same way as the other > * cases. > */ > if (zeroed_any && ignored_any) > { > Assert(zeroed_any && ignored_any); > Assert(nblocks > 1); /* same block can't be both zeroed and ignored */ > Assert(result.status != PGAIO_RS_ERROR); > affected_count = zeroed_or_error_count; > > ereport(elevel, > errcode(ERRCODE_DATA_CORRUPTED), > errmsg("zeroing %u pages and ignoring %u checksum failures among blocks %u..%u of relation %s", > affected_count, checkfail_count, first, last, rpath.str), Translation stumbles on this one, because each of the first two %u are plural-sensitive. I'd do one of: - Call ereport() twice, once for zeroed pages and once for ignored checksums. Since elevel <= ERROR here, that doesn't lose the second call. - s/pages/page(s)/ like msgid "There are %d other session(s) and %d prepared transaction(s) using the database." - Something more like the style of VACUUM VERBOSE, e.g. "INTRO_TEXT: %u zeroed, %u checksums ignored". I've not written INTRO_TEXT, and this doesn't really resolve pluralization. Probably don't use this option. > affected_count > 1 ? > errdetail("Block %u held first zeroed page.", > first + first_off) : 0, > errhint("See server log for details about the other %u invalid blocks.", > affected_count + checkfail_count - 1)); > return; > } > > /* > * The other messages are highly repetitive. To avoid duplicating a long > * and complicated ereport(), gather the translated format strings > * separately and then do one common ereport. > */ > if (result.status == PGAIO_RS_ERROR) > { > Assert(!zeroed_any); /* can't have invalid pages when zeroing them */ > affected_count = zeroed_or_error_count; > msg_one = _("invalid page in block %u of relation %s"); > msg_mult = _("%u invalid pages among blocks %u..%u of relation %s"); > det_mult = _("Block %u held first invalid page."); > hint_mult = _("See server log for the other %u invalid blocks."); For each hint_mult, we would usually use ngettext() instead of _(). (Would be errhint_plural() if not separated from its ereport().) Alternatively, s/blocks/block(s)/ is fine. > } > else if (zeroed_any && !ignored_any) > { > affected_count = zeroed_or_error_count; > msg_one = _("invalid page in block %u of relation %s; zeroing out page"); > msg_mult = _("zeroing out %u invalid pages among blocks %u..%u of relation %s"); > det_mult = _("Block %u held first zeroed page."); > hint_mult = _("See server log for the other %u zeroed blocks."); > } > else if (!zeroed_any && ignored_any) > { > affected_count = checkfail_count; > msg_one = _("ignoring checksum failure in block %u of relation %s"); > msg_mult = _("ignoring %u checksum failures among blocks %u..%u of relation %s"); > det_mult = _("Block %u held first ignored page."); > hint_mult = _("See server log for the other %u ignored blocks."); > } > else > pg_unreachable(); > > ereport(elevel, > errcode(ERRCODE_DATA_CORRUPTED), > affected_count == 1 ? > errmsg_internal(msg_one, first + first_off, rpath.str) : > errmsg_internal(msg_mult, affected_count, first, last, rpath.str), > affected_count > 1 ? errdetail_internal(det_mult, first + first_off) : 0, > affected_count > 1 ? errhint_internal(hint_mult, affected_count - 1) : 0); > > Does that approach make sense? Yes. > What do you think about using > "zeroing invalid page in block %u of relation %s" > instead of > "invalid page in block %u of relation %s; zeroing out page" I like the replacement. It moves the important part to the front, and it's shorter. > I thought about instead translating "ignoring", "ignored", "zeroing", > "zeroed", etc separately, but I have doubts about how well that would actually > translate. Agreed, I wouldn't have high hopes for that. An approach like that would probably need messages that separate the independently-translated part grammatically, e.g.: /* last %s is translation of "ignore" or "zero-fill" */ "invalid page in block %u of relation %s; resolved by method \"%s\"" (Again, I'm not recommending that.)