Skip to content

Commit 9b0fe4e

Browse files
Jan WieckJan Wieck
authored andcommitted
Fixed memory allocation problems when compressing multi-MB
items. Lookup history is now a double linked list, used in a wrap-around style. Jan
1 parent 6a00a7e commit 9b0fe4e

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

src/backend/utils/adt/pg_lzcompress.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* ----------
22
* pg_lzcompress.c -
33
*
4-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.7 2000/07/06 21:02:07 wieck Exp $
4+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.8 2000/07/20 14:23:28 wieck Exp $
55
*
66
* This is an implementation of LZ compression for PostgreSQL.
77
* It uses a simple history table and generates 2-3 byte tags
@@ -185,9 +185,9 @@
185185
* Local definitions
186186
* ----------
187187
*/
188-
#define PGLZ_HISTORY_SIZE 8192
188+
#define PGLZ_HISTORY_LISTS 8192
189189
#define PGLZ_HISTORY_MASK 0x1fff
190-
#define PGLZ_HISTORY_PREALLOC 8192
190+
#define PGLZ_HISTORY_SIZE 4096
191191
#define PGLZ_MAX_MATCH 273
192192

193193

@@ -200,6 +200,7 @@
200200
typedef struct PGLZ_HistEntry
201201
{
202202
struct PGLZ_HistEntry *next;
203+
struct PGLZ_HistEntry *prev;
203204
char *pos;
204205
} PGLZ_HistEntry;
205206

@@ -209,7 +210,7 @@ typedef struct PGLZ_HistEntry
209210
* ----------
210211
*/
211212
static PGLZ_Strategy strategy_default_data = {
212-
256, /* Data chunks smaller 256 bytes are nott
213+
256, /* Data chunks smaller 256 bytes are not
213214
* compressed */
214215
6144, /* Data chunks greater equal 6K force
215216
* compression */
@@ -247,6 +248,12 @@ static PGLZ_Strategy strategy_never_data = {
247248
};
248249
PGLZ_Strategy *PGLZ_strategy_never = &strategy_never_data;
249250

251+
/* ----------
252+
* Global arrays for history
253+
* ----------
254+
*/
255+
static PGLZ_HistEntry *hist_start[PGLZ_HISTORY_LISTS];
256+
static PGLZ_HistEntry hist_entries[PGLZ_HISTORY_SIZE];
250257

251258

252259
/* ----------
@@ -276,11 +283,26 @@ PGLZ_Strategy *PGLZ_strategy_never = &strategy_never_data;
276283
* Adds a new entry to the history table.
277284
* ----------
278285
*/
279-
#define pglz_hist_add(_hs,_hn,_s,_e) { \
286+
#define pglz_hist_add(_hs,_he,_hn,_s,_e) { \
280287
int __hindex = pglz_hist_idx((_s),(_e)); \
281-
(_hn)->next = (_hs)[__hindex]; \
282-
(_hn)->pos = (_s); \
283-
(_hs)[__hindex] = (_hn)++; \
288+
if ((_he)[(_hn)].prev == NULL) { \
289+
(_hs)[__hindex] = (_he)[(_hn)].next; \
290+
} else { \
291+
(_he)[(_hn)].prev->next = (_he)[(_hn)].next; \
292+
} \
293+
if ((_he)[(_hn)].next != NULL) { \
294+
(_he)[(_hn)].next->prev = (_he)[(_hn)].prev; \
295+
} \
296+
(_he)[(_hn)].next = (_hs)[__hindex]; \
297+
(_he)[(_hn)].prev = NULL; \
298+
(_he)[(_hn)].pos = (_s); \
299+
if ((_hs)[__hindex] != NULL) { \
300+
(_hs)[__hindex]->prev = &((_he)[(_hn)]); \
301+
} \
302+
(_hs)[__hindex] = &((_he)[(_hn)]); \
303+
if (++(_hn) >= PGLZ_HISTORY_SIZE) { \
304+
(_hn) = 0; \
305+
} \
284306
}
285307

286308

@@ -454,10 +476,7 @@ pglz_find_match(PGLZ_HistEntry **hstart, char *input, char *end,
454476
int
455477
pglz_compress(char *source, int slen, PGLZ_Header *dest, PGLZ_Strategy *strategy)
456478
{
457-
PGLZ_HistEntry *hist_start[PGLZ_HISTORY_SIZE];
458-
PGLZ_HistEntry *hist_alloc;
459-
PGLZ_HistEntry hist_prealloc[PGLZ_HISTORY_PREALLOC];
460-
PGLZ_HistEntry *hist_next;
479+
int hist_next = 0;
461480

462481
unsigned char *bp = ((unsigned char *) dest) + sizeof(PGLZ_Header);
463482
unsigned char *bstart = bp;
@@ -524,17 +543,12 @@ pglz_compress(char *source, int slen, PGLZ_Header *dest, PGLZ_Strategy *strategy
524543

525544
/* ----------
526545
* Initialize the history tables. For inputs smaller than
527-
* PGLZ_HISTORY_PREALLOC, we already have a big enough history
546+
* PGLZ_HISTORY_SIZE, we already have a big enough history
528547
* table on the stack frame.
529548
* ----------
530549
*/
531550
memset((void *) hist_start, 0, sizeof(hist_start));
532-
if (slen + 1 <= PGLZ_HISTORY_PREALLOC)
533-
hist_alloc = hist_prealloc;
534-
else
535-
hist_alloc = (PGLZ_HistEntry *)
536-
palloc(sizeof(PGLZ_HistEntry) * (slen + 1));
537-
hist_next = hist_alloc;
551+
memset((void *) hist_entries, 0, sizeof(hist_entries));
538552

539553
/* ----------
540554
* Compute the maximum result size allowed by the strategy.
@@ -588,7 +602,7 @@ pglz_compress(char *source, int slen, PGLZ_Header *dest, PGLZ_Strategy *strategy
588602
pglz_out_tag(ctrlp, ctrlb, ctrl, bp, match_len, match_off);
589603
while (match_len--)
590604
{
591-
pglz_hist_add(hist_start, hist_next, dp, dend);
605+
pglz_hist_add(hist_start, hist_entries, hist_next, dp, dend);
592606
dp++; /* Do not do this ++ in the line above! */
593607
/* The macro would do it four times - Jan. */
594608
}
@@ -600,19 +614,12 @@ pglz_compress(char *source, int slen, PGLZ_Header *dest, PGLZ_Strategy *strategy
600614
* ----------
601615
*/
602616
pglz_out_literal(ctrlp, ctrlb, ctrl, bp, *dp);
603-
pglz_hist_add(hist_start, hist_next, dp, dend);
617+
pglz_hist_add(hist_start, hist_entries, hist_next, dp, dend);
604618
dp++; /* Do not do this ++ in the line above! */
605619
/* The macro would do it four times - Jan. */
606620
}
607621
}
608622

609-
/* ----------
610-
* Get rid of the history (if allocated)
611-
* ----------
612-
*/
613-
if (hist_alloc != hist_prealloc)
614-
pfree((void *) hist_alloc);
615-
616623
/* ----------
617624
* If we are still in compressing mode, write out the last
618625
* control byte and determine if the compression gained the

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy