Skip to content

Commit 89e6e7a

Browse files
author
Nikita Glukhov
committed
Inline TOAST: compression
1 parent f061c82 commit 89e6e7a

File tree

8 files changed

+86
-68
lines changed

8 files changed

+86
-68
lines changed

src/backend/access/common/detoast.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,15 @@ create_detoast_iterator(struct varlena *attr)
4949
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
5050
{
5151
iter->compressed = true;
52+
iter->compression_method = VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer);
5253

5354
/* prepare buffer to received decompressed data */
5455
iter->buf = create_toast_buffer(toast_pointer.va_rawsize, false);
55-
56-
/* initialize state for pglz_decompress_iterate() */
57-
iter->ctrl = 0;
58-
iter->ctrlc = INVALID_CTRLC;
59-
iter->len = 0;
60-
iter->off = 0;
6156
}
6257
else
6358
{
6459
iter->compressed = false;
60+
iter->compression_method = TOAST_INVALID_COMPRESSION_ID;
6561

6662
/* point the buffer directly at the raw data */
6763
iter->buf = fetch_iter->buf;
@@ -95,16 +91,14 @@ create_detoast_iterator(struct varlena *attr)
9591
iter->fetch_datum_iterator->buf = buf = create_toast_buffer(VARSIZE_ANY(attr), true);
9692
iter->fetch_datum_iterator->done = true;
9793
iter->compressed = true;
94+
iter->compression_method = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
9895

9996
memcpy((void *) buf->buf, attr, VARSIZE_ANY(attr));
10097
buf->limit = (char *) buf->capacity;
10198

10299
/* prepare buffer to received decompressed data */
103100
iter->buf = create_toast_buffer(TOAST_COMPRESS_EXTSIZE(attr) + VARHDRSZ, false);
104101

105-
/* initialize state for pglz_decompress_iterate() */
106-
iter->ctrl = 0;
107-
iter->ctrlc = INVALID_CTRLC;
108102
return iter;
109103
}
110104
else

src/backend/access/common/toast_compression.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pglz_compress_datum(const struct varlena *value)
6464
len = pglz_compress(VARDATA_ANY(value),
6565
valsize,
6666
(char *) tmp + VARHDRSZ_COMPRESSED,
67+
NULL,
6768
NULL);
6869
if (len < 0)
6970
{

src/backend/access/common/toast_internals.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,28 +1135,12 @@ toast_extract_chunk_fields(Relation toastrel, TupleDesc toasttupDesc,
11351135
}
11361136
}
11371137

1138-
/* ----------
1139-
* create_fetch_datum_iterator -
1140-
*
1141-
* Initialize fetch datum iterator.
1142-
* ----------
1143-
*/
1144-
FetchDatumIterator
1145-
create_fetch_datum_iterator(struct varlena *attr)
1138+
static void
1139+
create_fetch_datum_iterator_scan(FetchDatumIterator iter)
11461140
{
11471141
int validIndex;
1148-
FetchDatumIterator iter;
1149-
1150-
if (!VARATT_IS_EXTERNAL_ONDISK(attr))
1151-
elog(ERROR, "create_fetch_datum_iterator shouldn't be called for non-ondisk datums");
1152-
1153-
iter = (FetchDatumIterator) palloc0(sizeof(FetchDatumIteratorData));
1154-
1155-
/* Must copy to access aligned fields */
1156-
VARATT_EXTERNAL_GET_POINTER(iter->toast_pointer, attr);
11571142

1158-
iter->ressize = VARATT_EXTERNAL_GET_EXTSIZE(iter->toast_pointer);
1159-
iter->numchunks = ((iter->ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
1143+
MemoryContext oldcxt = MemoryContextSwitchTo(iter->mcxt);
11601144

11611145
/*
11621146
* Open the toast relation and its indexes
@@ -1189,6 +1173,33 @@ create_fetch_datum_iterator(struct varlena *attr)
11891173
iter->toastscan = systable_beginscan_ordered(iter->toastrel, iter->toastidxs[validIndex],
11901174
&iter->snapshot, 1, &iter->toastkey);
11911175

1176+
MemoryContextSwitchTo(oldcxt);
1177+
}
1178+
1179+
/* ----------
1180+
* create_fetch_datum_iterator -
1181+
*
1182+
* Initialize fetch datum iterator.
1183+
* ----------
1184+
*/
1185+
FetchDatumIterator
1186+
create_fetch_datum_iterator(struct varlena *attr)
1187+
{
1188+
FetchDatumIterator iter;
1189+
1190+
if (!VARATT_IS_EXTERNAL_ONDISK(attr))
1191+
elog(ERROR, "create_fetch_datum_iterator shouldn't be called for non-ondisk datums");
1192+
1193+
iter = (FetchDatumIterator) palloc0(sizeof(FetchDatumIteratorData));
1194+
1195+
iter->mcxt = CurrentMemoryContext;
1196+
1197+
/* Must copy to access aligned fields */
1198+
VARATT_EXTERNAL_GET_POINTER(iter->toast_pointer, attr);
1199+
1200+
iter->ressize = VARATT_EXTERNAL_GET_EXTSIZE(iter->toast_pointer);
1201+
iter->numchunks = ((iter->ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
1202+
11921203
iter->buf = create_toast_buffer(iter->ressize + VARHDRSZ,
11931204
VARATT_EXTERNAL_IS_COMPRESSED(iter->toast_pointer));
11941205

@@ -1204,7 +1215,7 @@ free_fetch_datum_iterator(FetchDatumIterator iter)
12041215
if (iter == NULL)
12051216
return;
12061217

1207-
if (!iter->done)
1218+
if (!iter->done && iter->toastscan)
12081219
{
12091220
systable_endscan_ordered(iter->toastscan);
12101221
toast_close_indexes(iter->toastidxs, iter->num_indexes, AccessShareLock);
@@ -1236,6 +1247,9 @@ fetch_datum_iterate(FetchDatumIterator iter)
12361247

12371248
Assert(iter != NULL && !iter->done);
12381249

1250+
if (!iter->toastscan)
1251+
create_fetch_datum_iterator_scan(iter);
1252+
12391253
ttup = systable_getnext_ordered(iter->toastscan, ForwardScanDirection);
12401254
if (ttup == NULL)
12411255
{
@@ -1344,8 +1358,9 @@ ToastBuffer *
13441358
create_toast_buffer(int32 size, bool compressed)
13451359
{
13461360
ToastBuffer *buf = (ToastBuffer *) palloc0(sizeof(ToastBuffer));
1347-
buf->buf = (const char *) palloc0(size);
1348-
if (compressed) {
1361+
buf->buf = (const char *) palloc(size);
1362+
if (compressed)
1363+
{
13491364
SET_VARSIZE_COMPRESSED(buf->buf, size);
13501365
/*
13511366
* Note the constraint buf->position <= buf->limit may be broken
@@ -1375,6 +1390,7 @@ free_toast_buffer(ToastBuffer *buf)
13751390
pfree(buf);
13761391
}
13771392

1393+
#if 0
13781394
/* ----------
13791395
* pglz_decompress_iterate -
13801396
*
@@ -1392,7 +1408,7 @@ free_toast_buffer(ToastBuffer *buf)
13921408
*/
13931409
void
13941410
pglz_decompress_iterate(ToastBuffer *source, ToastBuffer *dest,
1395-
DetoastIterator iter, unsigned char *destend)
1411+
DetoastIterator iter, const char *destend)
13961412
{
13971413
const unsigned char *sp;
13981414
const unsigned char *srcend;
@@ -1525,3 +1541,4 @@ pglz_decompress_iterate(ToastBuffer *source, ToastBuffer *dest,
15251541
source->position = (char *) sp;
15261542
dest->limit = (char *) dp;
15271543
}
1544+
#endif

src/backend/access/transam/xloginsert.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ XLogCompressBackupBlock(char *page, uint16 hole_offset, uint16 hole_length,
911911
switch ((WalCompression) wal_compression)
912912
{
913913
case WAL_COMPRESSION_PGLZ:
914-
len = pglz_compress(source, orig_len, dest, PGLZ_strategy_default);
914+
len = pglz_compress(source, orig_len, dest, PGLZ_strategy_default, NULL);
915915
break;
916916

917917
case WAL_COMPRESSION_LZ4:

src/common/pg_lzcompress.c

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,10 @@ pglz_find_match(int16 *hstart, const char *input, const char *end,
507507
*/
508508
int32
509509
pglz_compress(const char *source, int32 slen, char *dest,
510-
const PGLZ_Strategy *strategy)
510+
const PGLZ_Strategy *strategy, int32 *dlen)
511511
{
512512
unsigned char *bp = (unsigned char *) dest;
513+
unsigned char *bend;
513514
unsigned char *bstart = bp;
514515
int hist_next = 1;
515516
bool hist_recycle = false;
@@ -545,6 +546,16 @@ pglz_compress(const char *source, int32 slen, char *dest,
545546
slen > strategy->max_input_size)
546547
return -1;
547548

549+
if (dlen)
550+
{
551+
if (*dlen < 4)
552+
return -1;
553+
554+
bend = bstart + *dlen - 4;
555+
}
556+
else
557+
bend = bstart + PGLZ_MAX_OUTPUT(slen);
558+
548559
/*
549560
* Limit the match parameters to the supported range.
550561
*/
@@ -627,6 +638,9 @@ pglz_compress(const char *source, int32 slen, char *dest,
627638
if (!found_match && bp - bstart >= strategy->first_success_by)
628639
return -1;
629640

641+
if (bp > bend)
642+
break;
643+
630644
/*
631645
* Try to find a match in the history
632646
*/
@@ -671,15 +685,16 @@ pglz_compress(const char *source, int32 slen, char *dest,
671685
if (result_size >= result_max)
672686
return -1;
673687

688+
if (dlen)
689+
*dlen = dp - source;
690+
674691
/* success */
675692
return result_size;
676693
}
677694

678695
/* Opaque pglz decompression state */
679696
typedef struct pglz_state
680697
{
681-
const unsigned char *sp;
682-
unsigned char *dp;
683698
int32 len;
684699
int32 off;
685700
int ctrlc;
@@ -699,28 +714,23 @@ typedef struct pglz_state
699714
* ----------
700715
*/
701716
int32
702-
pglz_decompress_state(const char *source, int32 slen, char *dest,
717+
pglz_decompress_state(const char *source, int32 *slen, char *dest,
703718
int32 dlen, bool check_complete, bool last_cource_chunk,
704719
void **pstate)
705720
{
706721
pglz_state *state = pstate ? *pstate : NULL;
707-
const unsigned char *sp;
708-
const unsigned char *srcend;
709-
unsigned char *dp;
710-
unsigned char *destend;
722+
const unsigned char *sp = (const unsigned char *) source;
723+
const unsigned char *srcend = sp + *slen;
724+
unsigned char *dp = (unsigned char *) dest;
725+
unsigned char *destend = dp + dlen;
711726
unsigned char ctrl;
712727
int ctrlc;
713728
int32 len;
714729
int32 remlen;
715730
int32 off;
716731

717-
srcend = ((const unsigned char *) source) + slen;
718-
destend = ((unsigned char *) dest) + rawsize;
719-
720732
if (state)
721733
{
722-
sp = state->sp;
723-
dp = state->dp;
724734
ctrl = state->ctrl;
725735
ctrlc = state->ctrlc;
726736

@@ -742,7 +752,7 @@ pglz_decompress_state(const char *source, int32 slen, char *dest,
742752
if (dp >= destend)
743753
{
744754
state->len = remlen;
745-
state->dp = dp;
755+
*slen = 0;
746756
return (char *) dp - dest;
747757
}
748758

@@ -757,8 +767,6 @@ pglz_decompress_state(const char *source, int32 slen, char *dest,
757767
}
758768
else
759769
{
760-
sp = (const unsigned char *) source;
761-
dp = (unsigned char *) dest;
762770
ctrl = 0;
763771
ctrlc = 8;
764772
remlen = 0;
@@ -884,10 +892,10 @@ pglz_decompress_state(const char *source, int32 slen, char *dest,
884892

885893
state->ctrl = ctrl;
886894
state->ctrlc = ctrlc;
887-
state->sp = sp;
888-
state->dp = dp;
889895
state->len = remlen;
890896
state->off = off;
897+
898+
*slen = (const char *) sp - source;
891899
}
892900

893901
/*
@@ -948,5 +956,5 @@ int32
948956
pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize,
949957
bool check_complete)
950958
{
951-
return pglz_decompress_state(source, slen, dest, rawsize, check_complete, true, NULL);
959+
return pglz_decompress_state(source, &slen, dest, rawsize, check_complete, true, NULL);
952960
}

src/include/access/detoast.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ do { \
4747
#include "postgres.h"
4848
#include "access/genam.h"
4949
#include "access/toasterapi.h"
50+
#include "access/toast_compression.h"
5051

5152
/*
5253
* TOAST buffer is a producer consumer buffer.
@@ -78,10 +79,11 @@ typedef struct FetchDatumIteratorData
7879
ToastBuffer *buf;
7980
Relation toastrel;
8081
Relation *toastidxs;
82+
MemoryContext mcxt;
8183
SysScanDesc toastscan;
8284
ScanKeyData toastkey;
8385
SnapshotData snapshot;
84-
struct varatt_external toast_pointer;
86+
struct varatt_external toast_pointer;
8587
int32 ressize;
8688
int32 nextidx;
8789
int32 numchunks;
@@ -91,22 +93,13 @@ typedef struct FetchDatumIteratorData
9193

9294
typedef struct FetchDatumIteratorData *FetchDatumIterator;
9395

94-
/*
95-
* If "ctrlc" field in iterator is equal to INVALID_CTRLC, it means that
96-
* the field is invalid and need to read the control byte from the
97-
* source buffer in the next iteration, see pglz_decompress_iterate().
98-
*/
99-
#define INVALID_CTRLC 8
100-
10196
typedef struct DetoastIteratorData
10297
{
10398
ToastBuffer *buf;
10499
FetchDatumIterator fetch_datum_iterator;
105-
unsigned char ctrl;
106-
int ctrlc;
107100
int nrefs;
108-
int32 len;
109-
int32 off;
101+
void *decompression_state;
102+
ToastCompressionId compression_method;
110103
bool compressed; /* toast value is compressed? */
111104
bool done;
112105
} DetoastIteratorData;
@@ -118,8 +111,10 @@ extern void free_fetch_datum_iterator(FetchDatumIterator iter);
118111
extern void fetch_datum_iterate(FetchDatumIterator iter);
119112
extern ToastBuffer *create_toast_buffer(int32 size, bool compressed);
120113
extern void free_toast_buffer(ToastBuffer *buf);
114+
extern void toast_decompress_iterate(ToastBuffer *source, ToastBuffer *dest,
115+
DetoastIterator iter, const char *destend);
121116
extern void pglz_decompress_iterate(ToastBuffer *source, ToastBuffer *dest,
122-
DetoastIterator iter, unsigned char *destend);
117+
DetoastIterator iter, char *destend);
123118

124119
/* ----------
125120
* create_detoast_iterator -
@@ -171,7 +166,7 @@ detoast_iterate(DetoastIterator detoast_iter, const char *destend)
171166
fetch_datum_iterate(fetch_iter);
172167

173168
if (detoast_iter->compressed)
174-
pglz_decompress_iterate(fetch_iter->buf, detoast_iter->buf, detoast_iter, (unsigned char *) destend);
169+
toast_decompress_iterate(fetch_iter->buf, detoast_iter->buf, detoast_iter, destend);
175170

176171
if (detoast_iter->buf->limit == detoast_iter->buf->capacity)
177172
detoast_iter->done = true;

src/include/access/toast_internals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ typedef struct toast_compress_header
4040
#define TOAST_COMPRESS_METHOD(ptr) \
4141
(((toast_compress_header *) (ptr))->tcinfo >> VARLENA_EXTSIZE_BITS)
4242

43+
#define TOAST_COMPRESS_HDRSZ VARHDRSZ_COMPRESSED
44+
#define TOAST_COMPRESS_RAWDATA(attr) ((char *)(attr) + TOAST_COMPRESS_HDRSZ)
45+
4346
#define TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(ptr, len, cm_method) \
4447
do { \
4548
Assert((len) > 0 && (len) <= VARLENA_EXTSIZE_MASK); \

src/include/common/pg_lzcompress.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ extern PGDLLIMPORT const PGLZ_Strategy *const PGLZ_strategy_always;
8484
* ----------
8585
*/
8686
extern int32 pglz_compress(const char *source, int32 slen, char *dest,
87-
const PGLZ_Strategy *strategy);
87+
const PGLZ_Strategy *strategy, int32 *dlen);
8888
extern int32 pglz_decompress(const char *source, int32 slen, char *dest,
8989
int32 rawsize, bool check_complete);
90-
extern int32 pglz_decompress_state(const char *source, int32 slen,
90+
extern int32 pglz_decompress_state(const char *source, int32 *slen,
9191
char *dest, int32 dlen,
9292
bool check_complete, bool last_source_chunk,
9393
void **state);

0 commit comments

Comments
 (0)