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

File Refactor-zlib-usage-in-FlintTable-and-ChertTable-to-avoid-reallocat.patch, 17.8 KB (added by Richard Boulton, 15 years ago)
  • backends/chert/chert_table.h

     
    605605        /// The name of the table (used when writing changesets).
    606606        const char * tablename;
    607607
     608    void lazy_alloc_deflate_zstream();
     609    void lazy_alloc_inflate_zstream();
     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    z_stream *deflate_zstream;
     731    z_stream *inflate_zstream;
     732
     733
    726734        /// If true, don't create the table until it's needed.
    727735        bool lazy;
    728736
  • backends/chert/chert_table.cc

     
    10581058        CompileTimeAssert(DONT_COMPRESS != Z_RLE);
    10591059#endif
    10601060
    1061         z_stream stream;
     1061        lazy_alloc_deflate_zstream();
     1062        deflateReset(deflate_zstream);
    10621063
    1063         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1064         stream.zfree = reinterpret_cast<free_func>(0);
    1065         stream.opaque = (voidpf)0;
     1064        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1065        deflate_zstream->avail_in = (uInt)tag.size();
    10661066
    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 
    10861067        // If compressed size is >= tag.size(), we don't want to compress.
    10871068        unsigned long blk_len = tag.size() - 1;
    10881069        unsigned char * blk = new unsigned char[blk_len];
    1089         stream.next_out = blk;
    1090         stream.avail_out = (uInt)blk_len;
     1070        deflate_zstream->next_out = blk;
     1071        deflate_zstream->avail_out = (uInt)blk_len;
    10911072
    1092         err = deflate(&stream, Z_FINISH);
     1073        int err = deflate(deflate_zstream, Z_FINISH);
    10931074        if (err == Z_STREAM_END) {
    10941075            // If deflate succeeded, then the output was at least one byte
    10951076            // smaller than the input.
    1096             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1077            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10971078            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             }
    11081079        } else {
    1109             // Deflate failed - presumably the data wasn't compressible.
    1110             (void)deflateEnd(&stream);
    11111080        }
    11121081
    11131082        delete [] blk;
     
    12811250
    12821251    Bytef buf[8192];
    12831252
    1284     z_stream stream;
    1285     stream.next_out = buf;
    1286     stream.avail_out = (uInt)sizeof(buf);
     1253    inflateReset(inflate_zstream);
    12871254
    1288     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1289     stream.zfree = reinterpret_cast<free_func>(0);
     1255    inflate_zstream->next_out = buf;
     1256    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12901257
    1291     stream.next_in = Z_NULL;
    1292     stream.avail_in = 0;
     1258    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1259    inflate_zstream->avail_in = (uInt)tag->size();
    12931260
    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 
     1261    int err = Z_OK;
    13091262    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);
     1263        inflate_zstream->next_out = buf;
     1264        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1265        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1266        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1267            LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    13151268            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);
     1269            setint4(header2, 0, inflate_zstream->adler);
     1270            inflate_zstream->next_in = header2;
     1271            inflate_zstream->avail_in = 4;
     1272            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    13201273            if (err == Z_STREAM_END) break;
    13211274        }
    13221275
    13231276        if (err != Z_OK && err != Z_STREAM_END) {
    13241277            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13251278            string msg = "inflate failed";
    1326             if (stream.msg) {
     1279            if (inflate_zstream->msg) {
    13271280                msg += " (";
    1328                 msg += stream.msg;
     1281                msg += inflate_zstream->msg;
    13291282                msg += ')';
    13301283            }
    13311284            throw Xapian::DatabaseError(msg);
    13321285        }
    13331286
    13341287        utag.append(reinterpret_cast<const char *>(buf),
    1335                     stream.next_out - buf);
     1288                    inflate_zstream->next_out - buf);
    13361289    }
    1337     if (utag.size() != stream.total_out) {
     1290    if (utag.size() != inflate_zstream->total_out) {
    13381291        string msg = "compressed tag didn't expand to the expected size: ";
    13391292        msg += om_tostring(utag.size());
    13401293        msg += " != ";
    13411294        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1342         msg += om_tostring((size_t)stream.total_out);
     1295        msg += om_tostring((size_t)inflate_zstream->total_out);
    13431296        throw Xapian::DatabaseCorruptError(msg);
    13441297    }
    13451298
    1346     err = inflateEnd(&stream);
    1347     if (err != Z_OK) abort();
    1348 
    13491299    swap(*tag, utag);
    13501300
    13511301    RETURN(false);
     
    16331583          writable(!readonly_),
    16341584          split_p(0),
    16351585          compress_strategy(compress_strategy_),
     1586          deflate_zstream(NULL),
     1587          inflate_zstream(NULL),
    16361588          lazy(lazy_)
    16371589{
    16381590    LOGCALL_CTOR(DB, "ChertTable",
    16391591                 tablename_ << "," << path_ << ", " << readonly_ << ", " <<
    16401592                 compress_strategy_ << ", " << lazy_);
     1593
     1594    // We want to do this lazily, but the read functions are const so we can't :(
     1595    lazy_alloc_inflate_zstream();
     1596
    16411597}
    16421598
     1599void
     1600ChertTable::lazy_alloc_deflate_zstream() {
     1601    if (deflate_zstream)
     1602        return;
     1603
     1604    deflate_zstream = new z_stream;
     1605       
     1606    deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1607    deflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1608    deflate_zstream->opaque = (voidpf)0;
     1609
     1610    // -15 means raw deflate with 32K LZ77 window (largest)
     1611    // memLevel 9 is the highest (8 is default)
     1612    int err;
     1613    err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
     1614                       compress_strategy);
     1615    if (err != Z_OK) {
     1616        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1617        string msg = "deflateInit2 failed. err = " + err;
     1618        if (deflate_zstream->msg) {
     1619            msg += " (";
     1620            msg += deflate_zstream->msg;
     1621            msg += ')';
     1622        }
     1623        throw Xapian::DatabaseError(msg);
     1624    }
     1625}
     1626
     1627void
     1628ChertTable::lazy_alloc_inflate_zstream() {
     1629    if (inflate_zstream)
     1630        return;
     1631
     1632    inflate_zstream = new z_stream;
     1633
     1634    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1635    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1636
     1637    inflate_zstream->next_in = Z_NULL;
     1638    inflate_zstream->avail_in = 0;
     1639
     1640    int err = inflateInit2(inflate_zstream, -15);
     1641    if (err != Z_OK) {
     1642        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1643        string msg = "inflateInit2 failed";
     1644        if (inflate_zstream->msg) {
     1645            msg += " (";
     1646            msg += inflate_zstream->msg;
     1647            msg += ')';
     1648        }
     1649        throw Xapian::DatabaseError(msg);
     1650    }
     1651}
     1652
    16431653bool
    16441654ChertTable::exists() const {
    16451655    LOGCALL(DB, bool, "ChertTable::exists", "");
     
    17241734ChertTable::~ChertTable() {
    17251735    LOGCALL_DTOR(DB, "ChertTable");
    17261736    ChertTable::close();
     1737
     1738    if (deflate_zstream) {
     1739        int err = deflateEnd(deflate_zstream);
     1740        if (err != Z_OK) {
     1741            string msg = "deflateEnd failed. err = " + err;
     1742            if (deflate_zstream->msg) {
     1743                msg += " (";
     1744                msg += deflate_zstream->msg;
     1745                msg += ')';
     1746            }
     1747            delete deflate_zstream;
     1748            throw Xapian::DatabaseError(msg);
     1749        }
     1750        delete deflate_zstream;       
     1751    }
     1752
     1753    if (inflate_zstream) {
     1754        int err = inflateEnd(inflate_zstream);
     1755        if (err != Z_OK) {
     1756            string msg = "inflateEnd failed. err = " + err;
     1757            if (inflate_zstream->msg) {
     1758                msg += " (";
     1759                msg += inflate_zstream->msg;
     1760                msg += ')';
     1761            }
     1762            delete inflate_zstream;
     1763            throw Xapian::DatabaseError(msg);
     1764        }
     1765        delete inflate_zstream;
     1766    }
    17271767}
    17281768
    17291769void 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();
     1042        deflateReset(deflate_zstream);
    10421043
    1043         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1044         stream.zfree = reinterpret_cast<free_func>(0);
    1045         stream.opaque = (voidpf)0;
     1044        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1045        deflate_zstream->avail_in = (uInt)tag.size();
    10461046
    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 
    10661047        // If compressed size is >= tag.size(), we don't want to compress.
    10671048        unsigned long blk_len = tag.size() - 1;
    10681049        unsigned char * blk = new unsigned char[blk_len];
    1069         stream.next_out = blk;
    1070         stream.avail_out = (uInt)blk_len;
     1050        deflate_zstream->next_out = blk;
     1051        deflate_zstream->avail_out = (uInt)blk_len;
    10711052
    1072         err = deflate(&stream, Z_FINISH);
     1053        int err = deflate(deflate_zstream, Z_FINISH);
    10731054        if (err == Z_STREAM_END) {
    10741055            // If deflate succeeded, then the output was at least one byte
    10751056            // smaller than the input.
    1076             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1057            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10771058            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             }
    10881059        } else {
    1089             // Deflate failed - presumably the data wasn't compressible.
    1090             (void)deflateEnd(&stream);
    10911060        }
    10921061
    10931062        delete [] blk;
     
    12601229
    12611230    Bytef buf[8192];
    12621231
    1263     z_stream stream;
    1264     stream.next_out = buf;
    1265     stream.avail_out = (uInt)sizeof(buf);
     1232    inflateReset(inflate_zstream);
    12661233
    1267     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1268     stream.zfree = reinterpret_cast<free_func>(0);
     1234    inflate_zstream->next_out = buf;
     1235    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12691236
    1270     stream.next_in = Z_NULL;
    1271     stream.avail_in = 0;
     1237    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1238    inflate_zstream->avail_in = (uInt)tag->size();
    12721239
    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 
     1240    int err = Z_OK;
    12881241    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);
     1242        inflate_zstream->next_out = buf;
     1243        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1244        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1245        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1246            LOGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    12941247            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);
     1248            setint4(header2, 0, inflate_zstream->adler);
     1249            inflate_zstream->next_in = header2;
     1250            inflate_zstream->avail_in = 4;
     1251            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    12991252            if (err == Z_STREAM_END) break;
    13001253        }
    13011254
    13021255        if (err != Z_OK && err != Z_STREAM_END) {
    13031256            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13041257            string msg = "inflate failed";
    1305             if (stream.msg) {
     1258            if (inflate_zstream->msg) {
    13061259                msg += " (";
    1307                 msg += stream.msg;
     1260                msg += inflate_zstream->msg;
    13081261                msg += ')';
    13091262            }
    13101263            throw Xapian::DatabaseError(msg);
    13111264        }
    13121265
    13131266        utag.append(reinterpret_cast<const char *>(buf),
    1314                     stream.next_out - buf);
     1267                    inflate_zstream->next_out - buf);
    13151268    }
    1316     if (utag.size() != stream.total_out) {
     1269    if (utag.size() != inflate_zstream->total_out) {
    13171270        string msg = "compressed tag didn't expand to the expected size: ";
    13181271        msg += om_tostring(utag.size());
    13191272        msg += " != ";
    13201273        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1321         msg += om_tostring((size_t)stream.total_out);
     1274        msg += om_tostring((size_t)inflate_zstream->total_out);
    13221275        throw Xapian::DatabaseCorruptError(msg);
    13231276    }
    13241277
    1325     err = inflateEnd(&stream);
    1326     if (err != Z_OK) abort();
    1327 
    13281278    swap(*tag, utag);
    13291279
    13301280    return false;
     
    16071557          writable(!readonly_),
    16081558          split_p(0),
    16091559          compress_strategy(compress_strategy_),
     1560          deflate_zstream(NULL),
     1561          inflate_zstream(NULL),
    16101562          lazy(lazy_)
    16111563{
    16121564    DEBUGCALL(DB, void, "FlintTable::FlintTable",
    16131565              tablename_ << "," << path_ << ", " << readonly_ << ", " <<
    16141566              compress_strategy_ << ", " << lazy_);
     1567
     1568    // We want to do this lazily, but the read functions are const so we can't :(
     1569    lazy_alloc_inflate_zstream();
     1570
    16151571}
    16161572
     1573
     1574void
     1575FlintTable::lazy_alloc_deflate_zstream() {
     1576    if (deflate_zstream)
     1577        return;
     1578
     1579    deflate_zstream = new z_stream;
     1580       
     1581    deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1582    deflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1583    deflate_zstream->opaque = (voidpf)0;
     1584
     1585    // -15 means raw deflate with 32K LZ77 window (largest)
     1586    // memLevel 9 is the highest (8 is default)
     1587    int err;
     1588    err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
     1589                       compress_strategy);
     1590    if (err != Z_OK) {
     1591        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1592        string msg = "deflateInit2 failed. err = " + err;
     1593        if (deflate_zstream->msg) {
     1594            msg += " (";
     1595            msg += deflate_zstream->msg;
     1596            msg += ')';
     1597        }
     1598        throw Xapian::DatabaseError(msg);
     1599    }
     1600}
     1601
     1602
     1603void
     1604FlintTable::lazy_alloc_inflate_zstream() {
     1605    if (inflate_zstream)
     1606        return;
     1607
     1608    inflate_zstream = new z_stream;
     1609
     1610    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1611    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1612
     1613    inflate_zstream->next_in = Z_NULL;
     1614    inflate_zstream->avail_in = 0;
     1615
     1616    int err = inflateInit2(inflate_zstream, -15);
     1617    if (err != Z_OK) {
     1618        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1619        string msg = "inflateInit2 failed";
     1620        if (inflate_zstream->msg) {
     1621            msg += " (";
     1622            msg += inflate_zstream->msg;
     1623            msg += ')';
     1624        }
     1625        throw Xapian::DatabaseError(msg);
     1626    }
     1627}
     1628
    16171629bool
    16181630FlintTable::exists() const {
    16191631    DEBUGCALL(DB, bool, "FlintTable::exists", "");
     
    16981710FlintTable::~FlintTable() {
    16991711    DEBUGCALL(DB, void, "FlintTable::~FlintTable", "");
    17001712    FlintTable::close();
     1713
     1714    if (deflate_zstream) {
     1715        int err = deflateEnd(deflate_zstream);
     1716        if (err != Z_OK) {
     1717            string msg = "deflateEnd failed. err = " + err;
     1718            if (deflate_zstream->msg) {
     1719                msg += " (";
     1720                msg += deflate_zstream->msg;
     1721                msg += ')';
     1722            }
     1723            delete deflate_zstream;
     1724            throw Xapian::DatabaseError(msg);
     1725        }
     1726        delete deflate_zstream;       
     1727    }
     1728
     1729    if (inflate_zstream) {
     1730        int err = inflateEnd(inflate_zstream);
     1731        if (err != Z_OK) {
     1732            string msg = "inflateEnd failed. err = " + err;
     1733            if (inflate_zstream->msg) {
     1734                msg += " (";
     1735                msg += inflate_zstream->msg;
     1736                msg += ')';
     1737            }
     1738            delete inflate_zstream;
     1739            throw Xapian::DatabaseError(msg);
     1740        }
     1741        delete inflate_zstream;
     1742    }
    17011743}
    17021744
    17031745void FlintTable::close(bool permanent) {
  • backends/flint/flint_table.h

     
    595595           return (base_letter == 'A') ? 'B' : 'A';
    596596        }
    597597
     598    void lazy_alloc_deflate_zstream();
     599    void lazy_alloc_inflate_zstream();
     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    z_stream *deflate_zstream;
     721    z_stream *inflate_zstream;
     722
     723
    716724        /// If true, don't create the table until it's needed.
    717725        bool lazy;
    718726