Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pcwYf-0003uN-4A for pgsql-hackers@arkaria.postgresql.org; Thu, 16 Mar 2023 22:58:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pcwYb-0002i3-JF for pgsql-hackers@arkaria.postgresql.org; Thu, 16 Mar 2023 22:58:49 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pcwYb-0002hu-23 for pgsql-hackers@lists.postgresql.org; Thu, 16 Mar 2023 22:58:49 +0000 Received: from mail-io1-xd36.google.com ([2607:f8b0:4864:20::d36]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pcwYX-0006nD-QZ for pgsql-hackers@lists.postgresql.org; Thu, 16 Mar 2023 22:58:47 +0000 Received: by mail-io1-xd36.google.com with SMTP id o12so1525769iow.6 for ; Thu, 16 Mar 2023 15:58:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20210112.gappssmtp.com; s=20210112; t=1679007524; h=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=GDdZ1XMynpXKrp6HVPB6B6uuvgmSPr89PtCyw7Sk6P0=; b=Agm4EPwBeRAPVRd7fM4VtsKKOf7Dnjd1phVIJPm4OckuVrGWxrzq4fcZE+VR/6absj J9zr4aC5c+vsVkqzs0k+SYkA+uNpPS8cFG+TGi3Mlbh1qHKNq+S9wYxIn4VLDEJRQhN8 +BDTJfE3ew8nFBKwZ1k/z8FrTNCZg3ur9PgVC9WZw9pWHhXnrbgVpskaPYfwXfgP+VS/ Y8XUM7ZG3enIC4QJy9FBwtqaopBFII2WpDb2eUffALOpT+6OVRQv0aAnMrlddl5bBe6l 608xuZ20dotcCJHuTVBhEvfXK/G2+SNyoMzb/FWrhS9kDNgfY4jhhxiti60Pq7MQWLnd HSQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679007524; h=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=GDdZ1XMynpXKrp6HVPB6B6uuvgmSPr89PtCyw7Sk6P0=; b=ZSacjSQE4nW0HhmwSDu9retVeBu8in56/TUHuOWFF835wEZ2lkUaGezdlyQHBIeNaH /OhMFAoFSQyfUlY+hsHLXeeo2WoxlVTW06nmDWG21gVIxPW4NgxBN7IsyzOEGlNKVrzx 0X4ILmxsWG+UiCNIO0VYEwrmCKX7pYm7C0ayaHNGU+xdUIfn42zdwVkW0F4oc6S6oiuQ xv+PU3MaEZcnuBE894UekUZt0pNqeVXy/uQl7sKkffQ12Te8yh5cioABeOGBFY0dI0W+ gcToDoIjbTQRMJCskrfd41K3eHLbTAqt9DqW1ui4clyXBgrGA2hN6CSFJ7AR598NJkPW 3UHA== X-Gm-Message-State: AO0yUKX6u0vLQFnK+WfVSsrPXIw3qiEz+cOZGCPRivoX1hYkrO10SpuC t9hdbp5W6fi9jmhWhxBItHQ4hA== X-Google-Smtp-Source: AK7set+tKDj7FIYevwZW3MjfpWS4KySjO/piLRFioRDOzZvcIyR1NQlPeoIKzsNr50Xad6WzXJpEwA== X-Received: by 2002:a5e:d914:0:b0:74c:99e8:5de1 with SMTP id n20-20020a5ed914000000b0074c99e85de1mr366526iop.17.1679007524554; Thu, 16 Mar 2023 15:58:44 -0700 (PDT) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id n4-20020a056638110400b00400d715c57dsm183394jal.29.2023.03.16.15.58.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Mar 2023 15:58:44 -0700 (PDT) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 15B9B800BBF; Thu, 16 Mar 2023 17:58:43 -0500 (CDT) Date: Thu, 16 Mar 2023 17:58:42 -0500 From: Justin Pryzby To: Tomas Vondra Cc: gkokolatos@pm.me, shiy.fnst@fujitsu.com, Michael Paquier , pgsql-hackers@lists.postgresql.org, Rachel Heaton Subject: Re: Add LZ4 compression in pg_dump Message-ID: References: <22cb80ed-ec87-54c7-fd5b-cdcf79766bb1@enterprisedb.com> <8421f53d-c9f7-c02e-3278-9f9522a8e8f3@enterprisedb.com> <20230228235834.GC30529@telsasoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, Mar 16, 2023 at 11:30:50PM +0100, Tomas Vondra wrote: > On 3/16/23 01:20, Justin Pryzby wrote: > > But try reading the diff while looking for the cause of a bug. It's the > > difference between reading 50, two-line changes, and reading a hunk that > > replaces 100 lines with a different 100 lines, with empty/unrelated > > lines randomly thrown in as context. > > I don't know, maybe I'm doing something wrong or maybe I just am bad at > looking at diffs, but if I apply the patch you submitted on 8/3 and do > the git-diff above (output attached), it seems pretty incomprehensible > to me :-( I don't see 50 two-line changes (I certainly wouldn't be able > to identify the root cause of the bug based on that). It's true that most of the diff is still incomprehensible... But look at the part relevant to the "empty-data" bug: [... incomprehensible changes elided ...] > static void > -InitCompressorZlib(CompressorState *cs, int level) > +DeflateCompressorInit(CompressorState *cs) > { > + GzipCompressorState *gzipcs; > z_streamp zp; > > - zp = cs->zp = (z_streamp) pg_malloc(sizeof(z_stream)); > + gzipcs = (GzipCompressorState *) pg_malloc0(sizeof(GzipCompressorState)); > + zp = gzipcs->zp = (z_streamp) pg_malloc(sizeof(z_stream)); > zp->zalloc = Z_NULL; > zp->zfree = Z_NULL; > zp->opaque = Z_NULL; > > /* > - * zlibOutSize is the buffer size we tell zlib it can output to. We > - * actually allocate one extra byte because some routines want to append a > - * trailing zero byte to the zlib output. > + * outsize is the buffer size we tell zlib it can output to. We actually > + * allocate one extra byte because some routines want to append a trailing > + * zero byte to the zlib output. > */ > - cs->zlibOut = (char *) pg_malloc(ZLIB_OUT_SIZE + 1); > - cs->zlibOutSize = ZLIB_OUT_SIZE; > + gzipcs->outbuf = pg_malloc(ZLIB_OUT_SIZE + 1); > + gzipcs->outsize = ZLIB_OUT_SIZE; > > - if (deflateInit(zp, level) != Z_OK) > - pg_fatal("could not initialize compression library: %s", > - zp->msg); > + /* -Z 0 uses the "None" compressor -- not zlib with no compression */ > + Assert(cs->compression_spec.level != 0); > + > + if (deflateInit(zp, cs->compression_spec.level) != Z_OK) > + pg_fatal("could not initialize compression library: %s", zp->msg); > > /* Just be paranoid - maybe End is called after Start, with no Write */ > - zp->next_out = (void *) cs->zlibOut; > - zp->avail_out = cs->zlibOutSize; > + zp->next_out = gzipcs->outbuf; > + zp->avail_out = gzipcs->outsize; > + > + /* Keep track of gzipcs */ > + cs->private_data = gzipcs; > } > > static void > -EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs) > +DeflateCompressorEnd(ArchiveHandle *AH, CompressorState *cs) > { > - z_streamp zp = cs->zp; > + GzipCompressorState *gzipcs = (GzipCompressorState *) cs->private_data; > + z_streamp zp; > > + zp = gzipcs->zp; > zp->next_in = NULL; > zp->avail_in = 0; > > /* Flush any remaining data from zlib buffer */ > - DeflateCompressorZlib(AH, cs, true); > + DeflateCompressorCommon(AH, cs, true); > > if (deflateEnd(zp) != Z_OK) > pg_fatal("could not close compression stream: %s", zp->msg); > > - free(cs->zlibOut); > - free(cs->zp); > + pg_free(gzipcs->outbuf); > + pg_free(gzipcs->zp); > + pg_free(gzipcs); > + cs->private_data = NULL; > } > > static void > -DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) > +DeflateCompressorCommon(ArchiveHandle *AH, CompressorState *cs, bool flush) > { > - z_streamp zp = cs->zp; > - char *out = cs->zlibOut; > + GzipCompressorState *gzipcs = (GzipCompressorState *) cs->private_data; > + z_streamp zp = gzipcs->zp; > + void *out = gzipcs->outbuf; > int res = Z_OK; > > - while (cs->zp->avail_in != 0 || flush) > + while (gzipcs->zp->avail_in != 0 || flush) > { > res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH); > if (res == Z_STREAM_ERROR) > pg_fatal("could not compress data: %s", zp->msg); > - if ((flush && (zp->avail_out < cs->zlibOutSize)) > + if ((flush && (zp->avail_out < gzipcs->outsize)) > || (zp->avail_out == 0) > || (zp->avail_in != 0) > ) > @@ -289,18 +122,18 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) > * chunk is the EOF marker in the custom format. This should never > * happen but ... > */ > - if (zp->avail_out < cs->zlibOutSize) > + if (zp->avail_out < gzipcs->outsize) > { > /* > * Any write function should do its own error checking but to > * make sure we do a check here as well ... > */ > - size_t len = cs->zlibOutSize - zp->avail_out; > + size_t len = gzipcs->outsize - zp->avail_out; > > - cs->writeF(AH, out, len); > + cs->writeF(AH, (char *) out, len); > } > - zp->next_out = (void *) out; > - zp->avail_out = cs->zlibOutSize; > + zp->next_out = out; > + zp->avail_out = gzipcs->outsize; > } > > if (res == Z_STREAM_END) > @@ -309,16 +142,26 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) > } > > static void > -WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, > - const char *data, size_t dLen) > +EndCompressorGzip(ArchiveHandle *AH, CompressorState *cs) > { > - cs->zp->next_in = (void *) unconstify(char *, data); > - cs->zp->avail_in = dLen; > - DeflateCompressorZlib(AH, cs, false); > + /* If deflation was initialized, finalize it */ > + if (cs->private_data) > + DeflateCompressorEnd(AH, cs); > } > > static void > -ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF) > +WriteDataToArchiveGzip(ArchiveHandle *AH, CompressorState *cs, > + const void *data, size_t dLen) > +{ > + GzipCompressorState *gzipcs = (GzipCompressorState *) cs->private_data; > + > + gzipcs->zp->next_in = (void *) unconstify(void *, data); > + gzipcs->zp->avail_in = dLen; > + DeflateCompressorCommon(AH, cs, false); > +} > + > +static void > +ReadDataFromArchiveGzip(ArchiveHandle *AH, CompressorState *cs) > { > z_streamp zp; > char *out; > @@ -342,7 +185,7 @@ ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF) > zp->msg); > > /* no minimal chunk size for zlib */ > - while ((cnt = readF(AH, &buf, &buflen))) > + while ((cnt = cs->readF(AH, &buf, &buflen))) > { > zp->next_in = (void *) buf; > zp->avail_in = cnt; > @@ -382,389 +225,196 @@ ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF) > free(out); > free(zp); > } [... more incomprehensible changes elided ...]