PostgreSQL Source Code  git master
pg_lzcompress.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PGLZ_Strategy
 

Macros

#define PGLZ_MAX_OUTPUT(_dlen)   ((_dlen) + 4)
 

Typedefs

typedef struct PGLZ_Strategy PGLZ_Strategy
 

Functions

int32 pglz_compress (const char *source, int32 slen, char *dest, const PGLZ_Strategy *strategy)
 
int32 pglz_decompress (const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
 
int32 pglz_maximum_compressed_size (int32 rawsize, int32 total_compressed_size)
 

Variables

PGDLLIMPORT const PGLZ_Strategy *const PGLZ_strategy_default
 
PGDLLIMPORT const PGLZ_Strategy *const PGLZ_strategy_always
 

Macro Definition Documentation

◆ PGLZ_MAX_OUTPUT

#define PGLZ_MAX_OUTPUT (   _dlen)    ((_dlen) + 4)

Definition at line 21 of file pg_lzcompress.h.

Typedef Documentation

◆ PGLZ_Strategy

typedef struct PGLZ_Strategy PGLZ_Strategy

Function Documentation

◆ pglz_compress()

int32 pglz_compress ( const char *  source,
int32  slen,
char *  dest,
const PGLZ_Strategy strategy 
)

Definition at line 509 of file pg_lzcompress.c.

511 {
512  unsigned char *bp = (unsigned char *) dest;
513  unsigned char *bstart = bp;
514  int hist_next = 1;
515  bool hist_recycle = false;
516  const char *dp = source;
517  const char *dend = source + slen;
518  unsigned char ctrl_dummy = 0;
519  unsigned char *ctrlp = &ctrl_dummy;
520  unsigned char ctrlb = 0;
521  unsigned char ctrl = 0;
522  bool found_match = false;
523  int32 match_len;
524  int32 match_off;
525  int32 good_match;
526  int32 good_drop;
527  int32 result_size;
528  int32 result_max;
529  int32 need_rate;
530  int hashsz;
531  int mask;
532 
533  /*
534  * Our fallback strategy is the default.
535  */
536  if (strategy == NULL)
537  strategy = PGLZ_strategy_default;
538 
539  /*
540  * If the strategy forbids compression (at all or if source chunk size out
541  * of range), fail.
542  */
543  if (strategy->match_size_good <= 0 ||
544  slen < strategy->min_input_size ||
545  slen > strategy->max_input_size)
546  return -1;
547 
548  /*
549  * Limit the match parameters to the supported range.
550  */
551  good_match = strategy->match_size_good;
552  if (good_match > PGLZ_MAX_MATCH)
553  good_match = PGLZ_MAX_MATCH;
554  else if (good_match < 17)
555  good_match = 17;
556 
557  good_drop = strategy->match_size_drop;
558  if (good_drop < 0)
559  good_drop = 0;
560  else if (good_drop > 100)
561  good_drop = 100;
562 
563  need_rate = strategy->min_comp_rate;
564  if (need_rate < 0)
565  need_rate = 0;
566  else if (need_rate > 99)
567  need_rate = 99;
568 
569  /*
570  * Compute the maximum result size allowed by the strategy, namely the
571  * input size minus the minimum wanted compression rate. This had better
572  * be <= slen, else we might overrun the provided output buffer.
573  */
574  if (slen > (INT_MAX / 100))
575  {
576  /* Approximate to avoid overflow */
577  result_max = (slen / 100) * (100 - need_rate);
578  }
579  else
580  result_max = (slen * (100 - need_rate)) / 100;
581 
582  /*
583  * Experiments suggest that these hash sizes work pretty well. A large
584  * hash table minimizes collision, but has a higher startup cost. For a
585  * small input, the startup cost dominates. The table size must be a power
586  * of two.
587  */
588  if (slen < 128)
589  hashsz = 512;
590  else if (slen < 256)
591  hashsz = 1024;
592  else if (slen < 512)
593  hashsz = 2048;
594  else if (slen < 1024)
595  hashsz = 4096;
596  else
597  hashsz = 8192;
598  mask = hashsz - 1;
599 
600  /*
601  * Initialize the history lists to empty. We do not need to zero the
602  * hist_entries[] array; its entries are initialized as they are used.
603  */
604  memset(hist_start, 0, hashsz * sizeof(int16));
605 
606  /*
607  * Compress the source directly into the output buffer.
608  */
609  while (dp < dend)
610  {
611  /*
612  * If we already exceeded the maximum result size, fail.
613  *
614  * We check once per loop; since the loop body could emit as many as 4
615  * bytes (a control byte and 3-byte tag), PGLZ_MAX_OUTPUT() had better
616  * allow 4 slop bytes.
617  */
618  if (bp - bstart >= result_max)
619  return -1;
620 
621  /*
622  * If we've emitted more than first_success_by bytes without finding
623  * anything compressible at all, fail. This lets us fall out
624  * reasonably quickly when looking at incompressible input (such as
625  * pre-compressed data).
626  */
627  if (!found_match && bp - bstart >= strategy->first_success_by)
628  return -1;
629 
630  /*
631  * Try to find a match in the history
632  */
633  if (pglz_find_match(hist_start, dp, dend, &match_len,
634  &match_off, good_match, good_drop, mask))
635  {
636  /*
637  * Create the tag and add history entries for all matched
638  * characters.
639  */
640  pglz_out_tag(ctrlp, ctrlb, ctrl, bp, match_len, match_off);
641  while (match_len--)
642  {
644  hist_next, hist_recycle,
645  dp, dend, mask);
646  dp++; /* Do not do this ++ in the line above! */
647  /* The macro would do it four times - Jan. */
648  }
649  found_match = true;
650  }
651  else
652  {
653  /*
654  * No match found. Copy one literal byte.
655  */
656  pglz_out_literal(ctrlp, ctrlb, ctrl, bp, *dp);
658  hist_next, hist_recycle,
659  dp, dend, mask);
660  dp++; /* Do not do this ++ in the line above! */
661  /* The macro would do it four times - Jan. */
662  }
663  }
664 
665  /*
666  * Write out the last control byte and check that we haven't overrun the
667  * output size allowed by the strategy.
668  */
669  *ctrlp = ctrlb;
670  result_size = bp - bstart;
671  if (result_size >= result_max)
672  return -1;
673 
674  /* success */
675  return result_size;
676 }
int16_t int16
Definition: c.h:480
int32_t int32
Definition: c.h:481
static int16 hist_start[PGLZ_MAX_HISTORY_LISTS]
const PGLZ_Strategy *const PGLZ_strategy_default
static int pglz_find_match(int16 *hstart, const char *input, const char *end, int *lenp, int *offp, int good_match, int good_drop, int mask)
#define PGLZ_MAX_MATCH
static PGLZ_HistEntry hist_entries[PGLZ_HISTORY_SIZE+1]
#define pglz_out_tag(_ctrlp, _ctrlb, _ctrl, _buf, _len, _off)
#define pglz_out_literal(_ctrlp, _ctrlb, _ctrl, _buf, _byte)
#define pglz_hist_add(_hs, _he, _hn, _recycle, _s, _e, _mask)
static rewind_source * source
Definition: pg_rewind.c:89
int32 first_success_by
Definition: pg_lzcompress.h:62
int32 match_size_drop
Definition: pg_lzcompress.h:64
int32 match_size_good
Definition: pg_lzcompress.h:63
int32 min_comp_rate
Definition: pg_lzcompress.h:61
int32 max_input_size
Definition: pg_lzcompress.h:60

References generate_unaccent_rules::dest, PGLZ_Strategy::first_success_by, hist_entries, hist_start, PGLZ_Strategy::match_size_drop, PGLZ_Strategy::match_size_good, PGLZ_Strategy::max_input_size, PGLZ_Strategy::min_comp_rate, pglz_find_match(), pglz_hist_add, PGLZ_MAX_MATCH, pglz_out_literal, pglz_out_tag, PGLZ_strategy_default, and source.

Referenced by pglz_compress_datum(), and XLogCompressBackupBlock().

◆ pglz_decompress()

int32 pglz_decompress ( const char *  source,
int32  slen,
char *  dest,
int32  rawsize,
bool  check_complete 
)

Definition at line 692 of file pg_lzcompress.c.

694 {
695  const unsigned char *sp;
696  const unsigned char *srcend;
697  unsigned char *dp;
698  unsigned char *destend;
699 
700  sp = (const unsigned char *) source;
701  srcend = ((const unsigned char *) source) + slen;
702  dp = (unsigned char *) dest;
703  destend = dp + rawsize;
704 
705  while (sp < srcend && dp < destend)
706  {
707  /*
708  * Read one control byte and process the next 8 items (or as many as
709  * remain in the compressed input).
710  */
711  unsigned char ctrl = *sp++;
712  int ctrlc;
713 
714  for (ctrlc = 0; ctrlc < 8 && sp < srcend && dp < destend; ctrlc++)
715  {
716  if (ctrl & 1)
717  {
718  /*
719  * Set control bit means we must read a match tag. The match
720  * is coded with two bytes. First byte uses lower nibble to
721  * code length - 3. Higher nibble contains upper 4 bits of the
722  * offset. The next following byte contains the lower 8 bits
723  * of the offset. If the length is coded as 18, another
724  * extension tag byte tells how much longer the match really
725  * was (0-255).
726  */
727  int32 len;
728  int32 off;
729 
730  len = (sp[0] & 0x0f) + 3;
731  off = ((sp[0] & 0xf0) << 4) | sp[1];
732  sp += 2;
733  if (len == 18)
734  len += *sp++;
735 
736  /*
737  * Check for corrupt data: if we fell off the end of the
738  * source, or if we obtained off = 0, or if off is more than
739  * the distance back to the buffer start, we have problems.
740  * (We must check for off = 0, else we risk an infinite loop
741  * below in the face of corrupt data. Likewise, the upper
742  * limit on off prevents accessing outside the buffer
743  * boundaries.)
744  */
745  if (unlikely(sp > srcend || off == 0 ||
746  off > (dp - (unsigned char *) dest)))
747  return -1;
748 
749  /*
750  * Don't emit more data than requested.
751  */
752  len = Min(len, destend - dp);
753 
754  /*
755  * Now we copy the bytes specified by the tag from OUTPUT to
756  * OUTPUT (copy len bytes from dp - off to dp). The copied
757  * areas could overlap, so to avoid undefined behavior in
758  * memcpy(), be careful to copy only non-overlapping regions.
759  *
760  * Note that we cannot use memmove() instead, since while its
761  * behavior is well-defined, it's also not what we want.
762  */
763  while (off < len)
764  {
765  /*
766  * We can safely copy "off" bytes since that clearly
767  * results in non-overlapping source and destination.
768  */
769  memcpy(dp, dp - off, off);
770  len -= off;
771  dp += off;
772 
773  /*----------
774  * This bit is less obvious: we can double "off" after
775  * each such step. Consider this raw input:
776  * 112341234123412341234
777  * This will be encoded as 5 literal bytes "11234" and
778  * then a match tag with length 16 and offset 4. After
779  * memcpy'ing the first 4 bytes, we will have emitted
780  * 112341234
781  * so we can double "off" to 8, then after the next step
782  * we have emitted
783  * 11234123412341234
784  * Then we can double "off" again, after which it is more
785  * than the remaining "len" so we fall out of this loop
786  * and finish with a non-overlapping copy of the
787  * remainder. In general, a match tag with off < len
788  * implies that the decoded data has a repeat length of
789  * "off". We can handle 1, 2, 4, etc repetitions of the
790  * repeated string per memcpy until we get to a situation
791  * where the final copy step is non-overlapping.
792  *
793  * (Another way to understand this is that we are keeping
794  * the copy source point dp - off the same throughout.)
795  *----------
796  */
797  off += off;
798  }
799  memcpy(dp, dp - off, len);
800  dp += len;
801  }
802  else
803  {
804  /*
805  * An unset control bit means LITERAL BYTE. So we just copy
806  * one from INPUT to OUTPUT.
807  */
808  *dp++ = *sp++;
809  }
810 
811  /*
812  * Advance the control bit
813  */
814  ctrl >>= 1;
815  }
816  }
817 
818  /*
819  * If requested, check we decompressed the right amount.
820  */
821  if (check_complete && (dp != destend || sp != srcend))
822  return -1;
823 
824  /*
825  * That's it.
826  */
827  return (char *) dp - dest;
828 }
#define Min(x, y)
Definition: c.h:958
#define unlikely(x)
Definition: c.h:330
const void size_t len

References generate_unaccent_rules::dest, len, Min, source, and unlikely.

Referenced by pglz_decompress_datum(), pglz_decompress_datum_slice(), and RestoreBlockImage().

◆ pglz_maximum_compressed_size()

int32 pglz_maximum_compressed_size ( int32  rawsize,
int32  total_compressed_size 
)

Definition at line 846 of file pg_lzcompress.c.

847 {
848  int64 compressed_size;
849 
850  /*
851  * pglz uses one control bit per byte, so if the entire desired prefix is
852  * represented as literal bytes, we'll need (rawsize * 9) bits. We care
853  * about bytes though, so be sure to round up not down.
854  *
855  * Use int64 here to prevent overflow during calculation.
856  */
857  compressed_size = ((int64) rawsize * 9 + 7) / 8;
858 
859  /*
860  * The above fails to account for a corner case: we could have compressed
861  * data that starts with N-1 or N-2 literal bytes and then has a match tag
862  * of 2 or 3 bytes. It's therefore possible that we need to fetch 1 or 2
863  * more bytes in order to have the whole match tag. (Match tags earlier
864  * in the compressed data don't cause a problem, since they should
865  * represent more decompressed bytes than they occupy themselves.)
866  */
867  compressed_size += 2;
868 
869  /*
870  * Maximum compressed size can't be larger than total compressed size.
871  * (This also ensures that our result fits in int32.)
872  */
873  compressed_size = Min(compressed_size, total_compressed_size);
874 
875  return (int32) compressed_size;
876 }
int64_t int64
Definition: c.h:482

References Min.

Referenced by detoast_attr_slice().

Variable Documentation

◆ PGLZ_strategy_always

PGDLLIMPORT const PGLZ_Strategy* const PGLZ_strategy_always
extern

Definition at line 248 of file pg_lzcompress.c.

◆ PGLZ_strategy_default

PGDLLIMPORT const PGLZ_Strategy* const PGLZ_strategy_default
extern

Definition at line 236 of file pg_lzcompress.c.

Referenced by pglz_compress(), pglz_compress_datum(), and XLogCompressBackupBlock().