Ticket #325: Refactor-zlib-usage-in-FlintTable-1.0-branch-to-avoid-reallocat.patch

File Refactor-zlib-usage-in-FlintTable-1.0-branch-to-avoid-reallocat.patch, 9.4 KB (added by Richard Boulton, 15 years ago)

Backport of my fixed-up patch to 1.0 branch

  • backends/flint/flint_table.cc

     
    10371037        CompileTimeAssert(DONT_COMPRESS != Z_RLE);
    10381038#endif
    10391039
    1040         z_stream stream;
     1040        lazy_alloc_deflate_zstream();
    10411041
    1042         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1043         stream.zfree = reinterpret_cast<free_func>(0);
    1044         stream.opaque = (voidpf)0;
     1042        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1043        deflate_zstream->avail_in = (uInt)tag.size();
    10451044
    1046         // -15 means raw deflate with 32K LZ77 window (largest)
    1047         // memLevel 9 is the highest (8 is default)
    1048         int err;
    1049         err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
    1050                            compress_strategy);
    1051         if (err != Z_OK) {
    1052             if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1053             string msg = "deflateInit2 failed";
    1054             if (stream.msg) {
    1055                 msg += " (";
    1056                 msg += stream.msg;
    1057                 msg += ')';
    1058             }
    1059             throw Xapian::DatabaseError(msg);
    1060         }
    1061 
    1062         stream.next_in = (Bytef *)const_cast<char *>(tag.data());
    1063         stream.avail_in = (uInt)tag.size();
    1064 
    10651045        // If compressed size is >= tag.size(), we don't want to compress.
    10661046        unsigned long blk_len = tag.size() - 1;
    10671047        unsigned char * blk = new unsigned char[blk_len];
    1068         stream.next_out = blk;
    1069         stream.avail_out = (uInt)blk_len;
     1048        deflate_zstream->next_out = blk;
     1049        deflate_zstream->avail_out = (uInt)blk_len;
    10701050
    1071         err = deflate(&stream, Z_FINISH);
     1051        int err = deflate(deflate_zstream, Z_FINISH);
    10721052        if (err == Z_STREAM_END) {
    10731053            // If deflate succeeded, then the output was at least one byte
    10741054            // smaller than the input.
    1075             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1055            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10761056            compressed = true;
    1077             err = deflateEnd(&stream);
    1078             if (err != Z_OK) {
    1079                 string msg = "deflateEnd failed";
    1080                 if (stream.msg) {
    1081                     msg += " (";
    1082                     msg += stream.msg;
    1083                     msg += ')';
    1084                 }
    1085                 throw Xapian::DatabaseError(msg);
    1086             }
    1087         } else {
    1088             // Deflate failed - presumably the data wasn't compressible.
    1089             (void)deflateEnd(&stream);
    10901057        }
    10911058
    10921059        delete [] blk;
     
    12711238
    12721239    Bytef buf[8192];
    12731240
    1274     z_stream stream;
    1275     stream.next_out = buf;
    1276     stream.avail_out = (uInt)sizeof(buf);
     1241    lazy_alloc_inflate_zstream();
    12771242
    1278     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1279     stream.zfree = reinterpret_cast<free_func>(0);
     1243    inflate_zstream->next_out = buf;
     1244    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12801245
    1281     stream.next_in = Z_NULL;
    1282     stream.avail_in = 0;
     1246    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1247    inflate_zstream->avail_in = (uInt)tag->size();
    12831248
    1284     int err = inflateInit2(&stream, -15);
    1285     if (err != Z_OK) {
    1286         if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1287         string msg = "inflateInit2 failed";
    1288         if (stream.msg) {
    1289             msg += " (";
    1290             msg += stream.msg;
    1291             msg += ')';
    1292         }
    1293         throw Xapian::DatabaseError(msg);
    1294     }
    1295 
    1296     stream.next_in = (Bytef*)const_cast<char *>(tag->data());
    1297     stream.avail_in = (uInt)tag->size();
    1298 
     1249    int err = Z_OK;
    12991250    while (err != Z_STREAM_END) {
    1300         stream.next_out = buf;
    1301         stream.avail_out = (uInt)sizeof(buf);
    1302         err = inflate(&stream, Z_SYNC_FLUSH);
    1303         if (err == Z_BUF_ERROR && stream.avail_in == 0) {
    1304             DEBUGLINE(DB, "Z_BUF_ERROR - faking checksum of " << stream.adler);
     1251        inflate_zstream->next_out = buf;
     1252        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1253        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1254        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1255            DEBUGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    13051256            Bytef header2[4];
    1306             setint4(header2, 0, stream.adler);
    1307             stream.next_in = header2;
    1308             stream.avail_in = 4;
    1309             err = inflate(&stream, Z_SYNC_FLUSH);
     1257            setint4(header2, 0, inflate_zstream->adler);
     1258            inflate_zstream->next_in = header2;
     1259            inflate_zstream->avail_in = 4;
     1260            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    13101261            if (err == Z_STREAM_END) break;
    13111262        }
    13121263
    13131264        if (err != Z_OK && err != Z_STREAM_END) {
    13141265            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13151266            string msg = "inflate failed";
    1316             if (stream.msg) {
     1267            if (inflate_zstream->msg) {
    13171268                msg += " (";
    1318                 msg += stream.msg;
     1269                msg += inflate_zstream->msg;
    13191270                msg += ')';
    13201271            }
    13211272            throw Xapian::DatabaseError(msg);
    13221273        }
    13231274
    13241275        utag.append(reinterpret_cast<const char *>(buf),
    1325                     stream.next_out - buf);
     1276                    inflate_zstream->next_out - buf);
    13261277    }
    1327     if (utag.size() != stream.total_out) {
     1278    if (utag.size() != inflate_zstream->total_out) {
    13281279        string msg = "compressed tag didn't expand to the expected size: ";
    13291280        msg += om_tostring(utag.size());
    13301281        msg += " != ";
    13311282        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1332         msg += om_tostring((size_t)stream.total_out);
     1283        msg += om_tostring((size_t)inflate_zstream->total_out);
    13331284        throw Xapian::DatabaseCorruptError(msg);
    13341285    }
    13351286
    1336     err = inflateEnd(&stream);
    1337     if (err != Z_OK) abort();
    1338 
    13391287    swap(*tag, utag);
    13401288
    13411289    return false;
     
    16121560          writable(!readonly_),
    16131561          split_p(0),
    16141562          compress_strategy(compress_strategy_),
     1563          deflate_zstream(NULL),
     1564          inflate_zstream(NULL),
    16151565          lazy(lazy_)
    16161566{
    1617     DEBUGCALL(DB, void, "FlintTable::FlintTable", 
     1567    DEBUGCALL(DB, void, "FlintTable::FlintTable",
    16181568              tablename_ << "," << path_ << ", " << readonly_ << ", " <<
    16191569              compress_strategy_ << ", " << lazy_);
    16201570}
    16211571
     1572void
     1573FlintTable::lazy_alloc_deflate_zstream() const {
     1574    if (deflate_zstream) {
     1575        deflateReset(deflate_zstream);
     1576        return;
     1577    }
     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
     1602void
     1603FlintTable::lazy_alloc_inflate_zstream() const {
     1604    if (inflate_zstream) {
     1605        inflateReset(inflate_zstream);
     1606        return;
     1607    }
     1608
     1609    inflate_zstream = new z_stream;
     1610
     1611    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1612    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1613
     1614    inflate_zstream->next_in = Z_NULL;
     1615    inflate_zstream->avail_in = 0;
     1616
     1617    int err = inflateInit2(inflate_zstream, -15);
     1618    if (err != Z_OK) {
     1619        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1620        string msg = "inflateInit2 failed";
     1621        if (inflate_zstream->msg) {
     1622            msg += " (";
     1623            msg += inflate_zstream->msg;
     1624            msg += ')';
     1625        }
     1626        throw Xapian::DatabaseError(msg);
     1627    }
     1628}
     1629
    16221630bool
    16231631FlintTable::exists() const {
    16241632    DEBUGCALL(DB, bool, "FlintTable::exists", "");
     
    16991707FlintTable::~FlintTable() {
    17001708    DEBUGCALL(DB, void, "FlintTable::~FlintTable", "");
    17011709    FlintTable::close();
     1710
     1711    if (deflate_zstream) {
     1712        int err = deflateEnd(deflate_zstream);
     1713        if (err != Z_OK) {
     1714            // FIXME - display the warning message somewhere.
     1715            //string msg = "deflateEnd failed. err = " + err;
     1716            //if (deflate_zstream->msg) {
     1717            //    msg += " (";
     1718            //    msg += deflate_zstream->msg;
     1719            //    msg += ')';
     1720            //}
     1721            //
     1722            // Note - we mustn't throw an exception because we're in a
     1723            // destructor.  If the destructor was called due to stack
     1724            // unwinding for another exception, this will result in a
     1725            // call to terminate().
     1726        }
     1727        delete deflate_zstream;
     1728    }
     1729
     1730    if (inflate_zstream) {
     1731        int err = inflateEnd(inflate_zstream);
     1732        if (err != Z_OK) {
     1733            // FIXME - display the warning message somewhere.
     1734            //string msg = "inflateEnd failed. err = " + err;
     1735            //if (inflate_zstream->msg) {
     1736            //    msg += " (";
     1737            //    msg += inflate_zstream->msg;
     1738            //    msg += ')';
     1739            //}
     1740            //
     1741            // Note - we mustn't throw an exception because we're in a
     1742            // destructor.  If the destructor was called due to stack
     1743            // unwinding for another exception, this will result in a
     1744            // call to terminate().
     1745        }
     1746        delete inflate_zstream;
     1747    }
    17021748}
    17031749
    17041750void FlintTable::close(bool permanent) {
  • backends/flint/flint_table.h

     
    289289         *  Any outstanding changes (ie, changes made without commit() having
    290290         *  subsequently been called) will be lost.
    291291         */
    292         ~FlintTable();
     292        virtual ~FlintTable();
    293293
    294294        /** Close the Btree.  This closes and frees any of the btree
    295295         *  structures which have been created and opened.
     
    587587           return (base_letter == 'A') ? 'B' : 'A';
    588588        }
    589589
     590        void lazy_alloc_deflate_zstream() const;
     591        void lazy_alloc_inflate_zstream() const;
     592
    590593        /** revision number of the opened B-tree. */
    591594        flint_revision_number_t revision_number;
    592595
     
    705708         *  Z_RLE. */
    706709        int compress_strategy;
    707710
     711        /** Zlib state object */
     712        mutable z_stream *deflate_zstream;
     713        mutable z_stream *inflate_zstream;
     714
    708715        /// If true, don't create the table until it's needed.
    709716        bool lazy;
    710717