Ticket #325: Refactor-zlib-usage-in-FlintTable-and-ChertTable-to-avoid-reallocat.3.patch

File Refactor-zlib-usage-in-FlintTable-and-ChertTable-to-avoid-reallocat.3.patch, 18.6 KB (added by Richard Boulton, 16 years ago)

Improved patch - don't call lazy_alloc from FlintTable::FlintTable

  • backends/chert/chert_table.h

     
    300300         *  Any outstanding changes (ie, changes made without commit() having
    301301         *  subsequently been called) will be lost.
    302302         */
    303         ~ChertTable();
     303        virtual ~ChertTable();
    304304
    305305        /** Close the Btree.  This closes and frees any of the btree
    306306         *  structures which have been created and opened.
     
    605605        /// The name of the table (used when writing changesets).
    606606        const char * tablename;
    607607
     608        void lazy_alloc_deflate_zstream() const;
     609        void lazy_alloc_inflate_zstream() const;
     610
    608611        /** revision number of the opened B-tree. */
    609612        chert_revision_number_t revision_number;
    610613
     
    723726         *  Z_RLE. */
    724727        int compress_strategy;
    725728
     729        /** Zlib state object */
     730        mutable z_stream *deflate_zstream;
     731        mutable z_stream *inflate_zstream;
     732
    726733        /// If true, don't create the table until it's needed.
    727734        bool lazy;
    728735
  • backends/chert/chert_table.cc

     
    10581058        CompileTimeAssert(DONT_COMPRESS != Z_RLE);
    10591059#endif
    10601060
    1061         z_stream stream;
     1061        lazy_alloc_deflate_zstream();
    10621062
    1063         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1064         stream.zfree = reinterpret_cast<free_func>(0);
    1065         stream.opaque = (voidpf)0;
     1063        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1064        deflate_zstream->avail_in = (uInt)tag.size();
    10661065
    1067         // -15 means raw deflate with 32K LZ77 window (largest)
    1068         // memLevel 9 is the highest (8 is default)
    1069         int err;
    1070         err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
    1071                            compress_strategy);
    1072         if (err != Z_OK) {
    1073             if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1074             string msg = "deflateInit2 failed";
    1075             if (stream.msg) {
    1076                 msg += " (";
    1077                 msg += stream.msg;
    1078                 msg += ')';
    1079             }
    1080             throw Xapian::DatabaseError(msg);
    1081         }
    1082 
    1083         stream.next_in = (Bytef *)const_cast<char *>(tag.data());
    1084         stream.avail_in = (uInt)tag.size();
    1085 
    10861066        // If compressed size is >= tag.size(), we don't want to compress.
    10871067        unsigned long blk_len = tag.size() - 1;
    10881068        unsigned char * blk = new unsigned char[blk_len];
    1089         stream.next_out = blk;
    1090         stream.avail_out = (uInt)blk_len;
     1069        deflate_zstream->next_out = blk;
     1070        deflate_zstream->avail_out = (uInt)blk_len;
    10911071
    1092         err = deflate(&stream, Z_FINISH);
     1072        int err = deflate(deflate_zstream, Z_FINISH);
    10931073        if (err == Z_STREAM_END) {
    10941074            // If deflate succeeded, then the output was at least one byte
    10951075            // smaller than the input.
    1096             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1076            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10971077            compressed = true;
    1098             err = deflateEnd(&stream);
    1099             if (err != Z_OK) {
    1100                 string msg = "deflateEnd failed";
    1101                 if (stream.msg) {
    1102                     msg += " (";
    1103                     msg += stream.msg;
    1104                     msg += ')';
    1105                 }
    1106                 throw Xapian::DatabaseError(msg);
    1107             }
    1108         } else {
    1109             // Deflate failed - presumably the data wasn't compressible.
    1110             (void)deflateEnd(&stream);
    11111078        }
    11121079
    11131080        delete [] blk;
     
    12811248
    12821249    Bytef buf[8192];
    12831250
    1284     z_stream stream;
    1285     stream.next_out = buf;
    1286     stream.avail_out = (uInt)sizeof(buf);
     1251    lazy_alloc_inflate_zstream();
    12871252
    1288     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1289     stream.zfree = reinterpret_cast<free_func>(0);
     1253    inflate_zstream->next_out = buf;
     1254    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12901255
    1291     stream.next_in = Z_NULL;
    1292     stream.avail_in = 0;
     1256    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1257    inflate_zstream->avail_in = (uInt)tag->size();
    12931258
    1294     int err = inflateInit2(&stream, -15);
    1295     if (err != Z_OK) {
    1296         if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1297         string msg = "inflateInit2 failed";
    1298         if (stream.msg) {
    1299             msg += " (";
    1300             msg += stream.msg;
    1301             msg += ')';
    1302         }
    1303         throw Xapian::DatabaseError(msg);
    1304     }
    1305 
    1306     stream.next_in = (Bytef*)const_cast<char *>(tag->data());
    1307     stream.avail_in = (uInt)tag->size();
    1308 
     1259    int err = Z_OK;
    13091260    while (err != Z_STREAM_END) {
    1310         stream.next_out = buf;
    1311         stream.avail_out = (uInt)sizeof(buf);
    1312         err = inflate(&stream, Z_SYNC_FLUSH);
    1313         if (err == Z_BUF_ERROR && stream.avail_in == 0) {
    1314             LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << stream.adler);
     1261        inflate_zstream->next_out = buf;
     1262        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1263        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1264        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1265            LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    13151266            Bytef header2[4];
    1316             setint4(header2, 0, stream.adler);
    1317             stream.next_in = header2;
    1318             stream.avail_in = 4;
    1319             err = inflate(&stream, Z_SYNC_FLUSH);
     1267            setint4(header2, 0, inflate_zstream->adler);
     1268            inflate_zstream->next_in = header2;
     1269            inflate_zstream->avail_in = 4;
     1270            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    13201271            if (err == Z_STREAM_END) break;
    13211272        }
    13221273
    13231274        if (err != Z_OK && err != Z_STREAM_END) {
    13241275            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13251276            string msg = "inflate failed";
    1326             if (stream.msg) {
     1277            if (inflate_zstream->msg) {
    13271278                msg += " (";
    1328                 msg += stream.msg;
     1279                msg += inflate_zstream->msg;
    13291280                msg += ')';
    13301281            }
    13311282            throw Xapian::DatabaseError(msg);
    13321283        }
    13331284
    13341285        utag.append(reinterpret_cast<const char *>(buf),
    1335                     stream.next_out - buf);
     1286                    inflate_zstream->next_out - buf);
    13361287    }
    1337     if (utag.size() != stream.total_out) {
     1288    if (utag.size() != inflate_zstream->total_out) {
    13381289        string msg = "compressed tag didn't expand to the expected size: ";
    13391290        msg += om_tostring(utag.size());
    13401291        msg += " != ";
    13411292        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1342         msg += om_tostring((size_t)stream.total_out);
     1293        msg += om_tostring((size_t)inflate_zstream->total_out);
    13431294        throw Xapian::DatabaseCorruptError(msg);
    13441295    }
    13451296
    1346     err = inflateEnd(&stream);
    1347     if (err != Z_OK) abort();
    1348 
    13491297    swap(*tag, utag);
    13501298
    13511299    RETURN(false);
     
    16331581          writable(!readonly_),
    16341582          split_p(0),
    16351583          compress_strategy(compress_strategy_),
     1584          deflate_zstream(NULL),
     1585          inflate_zstream(NULL),
    16361586          lazy(lazy_)
    16371587{
    16381588    LOGCALL_CTOR(DB, "ChertTable",
     
    16401590                 compress_strategy_ << ", " << lazy_);
    16411591}
    16421592
     1593void
     1594ChertTable::lazy_alloc_deflate_zstream() const {
     1595    if (deflate_zstream) {
     1596        deflateReset(deflate_zstream);
     1597        return;
     1598    }
     1599
     1600    deflate_zstream = new z_stream;
     1601
     1602    deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1603    deflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1604    deflate_zstream->opaque = (voidpf)0;
     1605
     1606    // -15 means raw deflate with 32K LZ77 window (largest)
     1607    // memLevel 9 is the highest (8 is default)
     1608    int err;
     1609    err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
     1610                       compress_strategy);
     1611    if (err != Z_OK) {
     1612        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1613        string msg = "deflateInit2 failed. err = " + err;
     1614        if (deflate_zstream->msg) {
     1615            msg += " (";
     1616            msg += deflate_zstream->msg;
     1617            msg += ')';
     1618        }
     1619        throw Xapian::DatabaseError(msg);
     1620    }
     1621}
     1622
     1623void
     1624ChertTable::lazy_alloc_inflate_zstream() const {
     1625    if (inflate_zstream) {
     1626        inflateReset(inflate_zstream);
     1627        return;
     1628    }
     1629
     1630    inflate_zstream = new z_stream;
     1631
     1632    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1633    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1634
     1635    inflate_zstream->next_in = Z_NULL;
     1636    inflate_zstream->avail_in = 0;
     1637
     1638    int err = inflateInit2(inflate_zstream, -15);
     1639    if (err != Z_OK) {
     1640        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1641        string msg = "inflateInit2 failed";
     1642        if (inflate_zstream->msg) {
     1643            msg += " (";
     1644            msg += inflate_zstream->msg;
     1645            msg += ')';
     1646        }
     1647        throw Xapian::DatabaseError(msg);
     1648    }
     1649}
     1650
    16431651bool
    16441652ChertTable::exists() const {
    16451653    LOGCALL(DB, bool, "ChertTable::exists", "");
     
    17241732ChertTable::~ChertTable() {
    17251733    LOGCALL_DTOR(DB, "ChertTable");
    17261734    ChertTable::close();
     1735
     1736    if (deflate_zstream) {
     1737        int err = deflateEnd(deflate_zstream);
     1738        if (err != Z_OK) {
     1739            // FIXME - display the warning message somewhere.
     1740            //string msg = "deflateEnd failed. err = " + err;
     1741            //if (deflate_zstream->msg) {
     1742            //    msg += " (";
     1743            //    msg += deflate_zstream->msg;
     1744            //    msg += ')';
     1745            //}
     1746            //
     1747            // Note - we mustn't throw an exception because we're in a
     1748            // destructor.  If the destructor was called due to stack
     1749            // unwinding for another exception, this will result in a
     1750            // call to terminate().
     1751        }
     1752        delete deflate_zstream;
     1753    }
     1754
     1755    if (inflate_zstream) {
     1756        int err = inflateEnd(inflate_zstream);
     1757        if (err != Z_OK) {
     1758            // FIXME - display the warning message somewhere.
     1759            //string msg = "inflateEnd failed. err = " + err;
     1760            //if (inflate_zstream->msg) {
     1761            //    msg += " (";
     1762            //    msg += inflate_zstream->msg;
     1763            //    msg += ')';
     1764            //}
     1765            //
     1766            // Note - we mustn't throw an exception because we're in a
     1767            // destructor.  If the destructor was called due to stack
     1768            // unwinding for another exception, this will result in a
     1769            // call to terminate().
     1770        }
     1771        delete inflate_zstream;
     1772    }
    17271773}
    17281774
    17291775void ChertTable::close(bool permanent) {
  • backends/flint/flint_table.cc

     
    10381038        CompileTimeAssert(DONT_COMPRESS != Z_RLE);
    10391039#endif
    10401040
    1041         z_stream stream;
     1041        lazy_alloc_deflate_zstream();
    10421042
    1043         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1044         stream.zfree = reinterpret_cast<free_func>(0);
    1045         stream.opaque = (voidpf)0;
     1043        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1044        deflate_zstream->avail_in = (uInt)tag.size();
    10461045
    1047         // -15 means raw deflate with 32K LZ77 window (largest)
    1048         // memLevel 9 is the highest (8 is default)
    1049         int err;
    1050         err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
    1051                            compress_strategy);
    1052         if (err != Z_OK) {
    1053             if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1054             string msg = "deflateInit2 failed";
    1055             if (stream.msg) {
    1056                 msg += " (";
    1057                 msg += stream.msg;
    1058                 msg += ')';
    1059             }
    1060             throw Xapian::DatabaseError(msg);
    1061         }
    1062 
    1063         stream.next_in = (Bytef *)const_cast<char *>(tag.data());
    1064         stream.avail_in = (uInt)tag.size();
    1065 
    10661046        // If compressed size is >= tag.size(), we don't want to compress.
    10671047        unsigned long blk_len = tag.size() - 1;
    10681048        unsigned char * blk = new unsigned char[blk_len];
    1069         stream.next_out = blk;
    1070         stream.avail_out = (uInt)blk_len;
     1049        deflate_zstream->next_out = blk;
     1050        deflate_zstream->avail_out = (uInt)blk_len;
    10711051
    1072         err = deflate(&stream, Z_FINISH);
     1052        int err = deflate(deflate_zstream, Z_FINISH);
    10731053        if (err == Z_STREAM_END) {
    10741054            // If deflate succeeded, then the output was at least one byte
    10751055            // smaller than the input.
    1076             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1056            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10771057            compressed = true;
    1078             err = deflateEnd(&stream);
    1079             if (err != Z_OK) {
    1080                 string msg = "deflateEnd failed";
    1081                 if (stream.msg) {
    1082                     msg += " (";
    1083                     msg += stream.msg;
    1084                     msg += ')';
    1085                 }
    1086                 throw Xapian::DatabaseError(msg);
    1087             }
    1088         } else {
    1089             // Deflate failed - presumably the data wasn't compressible.
    1090             (void)deflateEnd(&stream);
    10911058        }
    10921059
    10931060        delete [] blk;
     
    12601227
    12611228    Bytef buf[8192];
    12621229
    1263     z_stream stream;
    1264     stream.next_out = buf;
    1265     stream.avail_out = (uInt)sizeof(buf);
     1230    lazy_alloc_inflate_zstream();
    12661231
    1267     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1268     stream.zfree = reinterpret_cast<free_func>(0);
     1232    inflate_zstream->next_out = buf;
     1233    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12691234
    1270     stream.next_in = Z_NULL;
    1271     stream.avail_in = 0;
     1235    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1236    inflate_zstream->avail_in = (uInt)tag->size();
    12721237
    1273     int err = inflateInit2(&stream, -15);
    1274     if (err != Z_OK) {
    1275         if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1276         string msg = "inflateInit2 failed";
    1277         if (stream.msg) {
    1278             msg += " (";
    1279             msg += stream.msg;
    1280             msg += ')';
    1281         }
    1282         throw Xapian::DatabaseError(msg);
    1283     }
    1284 
    1285     stream.next_in = (Bytef*)const_cast<char *>(tag->data());
    1286     stream.avail_in = (uInt)tag->size();
    1287 
     1238    int err = Z_OK;
    12881239    while (err != Z_STREAM_END) {
    1289         stream.next_out = buf;
    1290         stream.avail_out = (uInt)sizeof(buf);
    1291         err = inflate(&stream, Z_SYNC_FLUSH);
    1292         if (err == Z_BUF_ERROR && stream.avail_in == 0) {
    1293             LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << stream.adler);
     1240        inflate_zstream->next_out = buf;
     1241        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1242        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1243        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1244            LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    12941245            Bytef header2[4];
    1295             setint4(header2, 0, stream.adler);
    1296             stream.next_in = header2;
    1297             stream.avail_in = 4;
    1298             err = inflate(&stream, Z_SYNC_FLUSH);
     1246            setint4(header2, 0, inflate_zstream->adler);
     1247            inflate_zstream->next_in = header2;
     1248            inflate_zstream->avail_in = 4;
     1249            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    12991250            if (err == Z_STREAM_END) break;
    13001251        }
    13011252
    13021253        if (err != Z_OK && err != Z_STREAM_END) {
    13031254            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13041255            string msg = "inflate failed";
    1305             if (stream.msg) {
     1256            if (inflate_zstream->msg) {
    13061257                msg += " (";
    1307                 msg += stream.msg;
     1258                msg += inflate_zstream->msg;
    13081259                msg += ')';
    13091260            }
    13101261            throw Xapian::DatabaseError(msg);
    13111262        }
    13121263
    13131264        utag.append(reinterpret_cast<const char *>(buf),
    1314                     stream.next_out - buf);
     1265                    inflate_zstream->next_out - buf);
    13151266    }
    1316     if (utag.size() != stream.total_out) {
     1267    if (utag.size() != inflate_zstream->total_out) {
    13171268        string msg = "compressed tag didn't expand to the expected size: ";
    13181269        msg += om_tostring(utag.size());
    13191270        msg += " != ";
    13201271        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1321         msg += om_tostring((size_t)stream.total_out);
     1272        msg += om_tostring((size_t)inflate_zstream->total_out);
    13221273        throw Xapian::DatabaseCorruptError(msg);
    13231274    }
    13241275
    1325     err = inflateEnd(&stream);
    1326     if (err != Z_OK) abort();
    1327 
    13281276    swap(*tag, utag);
    13291277
    13301278    return false;
     
    16071555          writable(!readonly_),
    16081556          split_p(0),
    16091557          compress_strategy(compress_strategy_),
     1558          deflate_zstream(NULL),
     1559          inflate_zstream(NULL),
    16101560          lazy(lazy_)
    16111561{
    1612     DEBUGCALL(DB, void, "FlintTable::FlintTable", 
     1562    DEBUGCALL(DB, void, "FlintTable::FlintTable",
    16131563              tablename_ << "," << path_ << ", " << readonly_ << ", " <<
    16141564              compress_strategy_ << ", " << lazy_);
    16151565}
    16161566
     1567void
     1568FlintTable::lazy_alloc_deflate_zstream() const {
     1569    if (deflate_zstream) {
     1570        deflateReset(deflate_zstream);
     1571        return;
     1572    }
     1573
     1574    deflate_zstream = new z_stream;
     1575
     1576    deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1577    deflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1578    deflate_zstream->opaque = (voidpf)0;
     1579
     1580    // -15 means raw deflate with 32K LZ77 window (largest)
     1581    // memLevel 9 is the highest (8 is default)
     1582    int err;
     1583    err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
     1584                       compress_strategy);
     1585    if (err != Z_OK) {
     1586        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1587        string msg = "deflateInit2 failed. err = " + err;
     1588        if (deflate_zstream->msg) {
     1589            msg += " (";
     1590            msg += deflate_zstream->msg;
     1591            msg += ')';
     1592        }
     1593        throw Xapian::DatabaseError(msg);
     1594    }
     1595}
     1596
     1597void
     1598FlintTable::lazy_alloc_inflate_zstream() const {
     1599    if (inflate_zstream) {
     1600        inflateReset(inflate_zstream);
     1601        return;
     1602    }
     1603
     1604    inflate_zstream = new z_stream;
     1605
     1606    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1607    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1608
     1609    inflate_zstream->next_in = Z_NULL;
     1610    inflate_zstream->avail_in = 0;
     1611
     1612    int err = inflateInit2(inflate_zstream, -15);
     1613    if (err != Z_OK) {
     1614        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1615        string msg = "inflateInit2 failed";
     1616        if (inflate_zstream->msg) {
     1617            msg += " (";
     1618            msg += inflate_zstream->msg;
     1619            msg += ')';
     1620        }
     1621        throw Xapian::DatabaseError(msg);
     1622    }
     1623}
     1624
    16171625bool
    16181626FlintTable::exists() const {
    16191627    DEBUGCALL(DB, bool, "FlintTable::exists", "");
     
    16981706FlintTable::~FlintTable() {
    16991707    DEBUGCALL(DB, void, "FlintTable::~FlintTable", "");
    17001708    FlintTable::close();
     1709
     1710    if (deflate_zstream) {
     1711        int err = deflateEnd(deflate_zstream);
     1712        if (err != Z_OK) {
     1713            // FIXME - display the warning message somewhere.
     1714            //string msg = "deflateEnd failed. err = " + err;
     1715            //if (deflate_zstream->msg) {
     1716            //    msg += " (";
     1717            //    msg += deflate_zstream->msg;
     1718            //    msg += ')';
     1719            //}
     1720            //
     1721            // Note - we mustn't throw an exception because we're in a
     1722            // destructor.  If the destructor was called due to stack
     1723            // unwinding for another exception, this will result in a
     1724            // call to terminate().
     1725        }
     1726        delete deflate_zstream;
     1727    }
     1728
     1729    if (inflate_zstream) {
     1730        int err = inflateEnd(inflate_zstream);
     1731        if (err != Z_OK) {
     1732            // FIXME - display the warning message somewhere.
     1733            //string msg = "inflateEnd failed. err = " + err;
     1734            //if (inflate_zstream->msg) {
     1735            //    msg += " (";
     1736            //    msg += inflate_zstream->msg;
     1737            //    msg += ')';
     1738            //}
     1739            //
     1740            // Note - we mustn't throw an exception because we're in a
     1741            // destructor.  If the destructor was called due to stack
     1742            // unwinding for another exception, this will result in a
     1743            // call to terminate().
     1744        }
     1745        delete inflate_zstream;
     1746    }
    17011747}
    17021748
    17031749void FlintTable::close(bool permanent) {
  • backends/flint/flint_table.h

     
    290290         *  Any outstanding changes (ie, changes made without commit() having
    291291         *  subsequently been called) will be lost.
    292292         */
    293         ~FlintTable();
     293        virtual ~FlintTable();
    294294
    295295        /** Close the Btree.  This closes and frees any of the btree
    296296         *  structures which have been created and opened.
     
    595595           return (base_letter == 'A') ? 'B' : 'A';
    596596        }
    597597
     598        void lazy_alloc_deflate_zstream() const;
     599        void lazy_alloc_inflate_zstream() const;
     600
    598601        /** revision number of the opened B-tree. */
    599602        flint_revision_number_t revision_number;
    600603
     
    713716         *  Z_RLE. */
    714717        int compress_strategy;
    715718
     719        /** Zlib state object */
     720        mutable z_stream *deflate_zstream;
     721        mutable z_stream *inflate_zstream;
     722
    716723        /// If true, don't create the table until it's needed.
    717724        bool lazy;
    718725