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 , 16 years ago) |
---|
-
backends/chert/chert_table.h
605 605 /// The name of the table (used when writing changesets). 606 606 const char * tablename; 607 607 608 void lazy_alloc_deflate_zstream(); 609 void lazy_alloc_inflate_zstream(); 610 608 611 /** revision number of the opened B-tree. */ 609 612 chert_revision_number_t revision_number; 610 613 … … 723 726 * Z_RLE. */ 724 727 int compress_strategy; 725 728 729 /** Zlib state object */ 730 z_stream *deflate_zstream; 731 z_stream *inflate_zstream; 732 733 726 734 /// If true, don't create the table until it's needed. 727 735 bool lazy; 728 736 -
backends/chert/chert_table.cc
1058 1058 CompileTimeAssert(DONT_COMPRESS != Z_RLE); 1059 1059 #endif 1060 1060 1061 z_stream stream; 1061 lazy_alloc_deflate_zstream(); 1062 deflateReset(deflate_zstream); 1062 1063 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(); 1066 1066 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 1086 1067 // If compressed size is >= tag.size(), we don't want to compress. 1087 1068 unsigned long blk_len = tag.size() - 1; 1088 1069 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; 1091 1072 1092 err = deflate(&stream, Z_FINISH);1073 int err = deflate(deflate_zstream, Z_FINISH); 1093 1074 if (err == Z_STREAM_END) { 1094 1075 // If deflate succeeded, then the output was at least one byte 1095 1076 // 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); 1097 1078 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 1079 } else { 1109 // Deflate failed - presumably the data wasn't compressible.1110 (void)deflateEnd(&stream);1111 1080 } 1112 1081 1113 1082 delete [] blk; … … 1281 1250 1282 1251 Bytef buf[8192]; 1283 1252 1284 z_stream stream; 1285 stream.next_out = buf; 1286 stream.avail_out = (uInt)sizeof(buf); 1253 inflateReset(inflate_zstream); 1287 1254 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); 1290 1257 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(); 1293 1260 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; 1309 1262 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); 1315 1268 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); 1320 1273 if (err == Z_STREAM_END) break; 1321 1274 } 1322 1275 1323 1276 if (err != Z_OK && err != Z_STREAM_END) { 1324 1277 if (err == Z_MEM_ERROR) throw std::bad_alloc(); 1325 1278 string msg = "inflate failed"; 1326 if ( stream.msg) {1279 if (inflate_zstream->msg) { 1327 1280 msg += " ("; 1328 msg += stream.msg;1281 msg += inflate_zstream->msg; 1329 1282 msg += ')'; 1330 1283 } 1331 1284 throw Xapian::DatabaseError(msg); 1332 1285 } 1333 1286 1334 1287 utag.append(reinterpret_cast<const char *>(buf), 1335 stream.next_out - buf);1288 inflate_zstream->next_out - buf); 1336 1289 } 1337 if (utag.size() != stream.total_out) {1290 if (utag.size() != inflate_zstream->total_out) { 1338 1291 string msg = "compressed tag didn't expand to the expected size: "; 1339 1292 msg += om_tostring(utag.size()); 1340 1293 msg += " != "; 1341 1294 // 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); 1343 1296 throw Xapian::DatabaseCorruptError(msg); 1344 1297 } 1345 1298 1346 err = inflateEnd(&stream);1347 if (err != Z_OK) abort();1348 1349 1299 swap(*tag, utag); 1350 1300 1351 1301 RETURN(false); … … 1633 1583 writable(!readonly_), 1634 1584 split_p(0), 1635 1585 compress_strategy(compress_strategy_), 1586 deflate_zstream(NULL), 1587 inflate_zstream(NULL), 1636 1588 lazy(lazy_) 1637 1589 { 1638 1590 LOGCALL_CTOR(DB, "ChertTable", 1639 1591 tablename_ << "," << path_ << ", " << readonly_ << ", " << 1640 1592 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 1641 1597 } 1642 1598 1599 void 1600 ChertTable::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 1627 void 1628 ChertTable::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 1643 1653 bool 1644 1654 ChertTable::exists() const { 1645 1655 LOGCALL(DB, bool, "ChertTable::exists", ""); … … 1724 1734 ChertTable::~ChertTable() { 1725 1735 LOGCALL_DTOR(DB, "ChertTable"); 1726 1736 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 } 1727 1767 } 1728 1768 1729 1769 void ChertTable::close(bool permanent) { -
backends/flint/flint_table.cc
1038 1038 CompileTimeAssert(DONT_COMPRESS != Z_RLE); 1039 1039 #endif 1040 1040 1041 z_stream stream; 1041 lazy_alloc_deflate_zstream(); 1042 deflateReset(deflate_zstream); 1042 1043 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(); 1046 1046 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 1066 1047 // If compressed size is >= tag.size(), we don't want to compress. 1067 1048 unsigned long blk_len = tag.size() - 1; 1068 1049 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; 1071 1052 1072 err = deflate(&stream, Z_FINISH);1053 int err = deflate(deflate_zstream, Z_FINISH); 1073 1054 if (err == Z_STREAM_END) { 1074 1055 // If deflate succeeded, then the output was at least one byte 1075 1056 // 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); 1077 1058 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 1059 } else { 1089 // Deflate failed - presumably the data wasn't compressible.1090 (void)deflateEnd(&stream);1091 1060 } 1092 1061 1093 1062 delete [] blk; … … 1260 1229 1261 1230 Bytef buf[8192]; 1262 1231 1263 z_stream stream; 1264 stream.next_out = buf; 1265 stream.avail_out = (uInt)sizeof(buf); 1232 inflateReset(inflate_zstream); 1266 1233 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); 1269 1236 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(); 1272 1239 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; 1288 1241 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); 1294 1247 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); 1299 1252 if (err == Z_STREAM_END) break; 1300 1253 } 1301 1254 1302 1255 if (err != Z_OK && err != Z_STREAM_END) { 1303 1256 if (err == Z_MEM_ERROR) throw std::bad_alloc(); 1304 1257 string msg = "inflate failed"; 1305 if ( stream.msg) {1258 if (inflate_zstream->msg) { 1306 1259 msg += " ("; 1307 msg += stream.msg;1260 msg += inflate_zstream->msg; 1308 1261 msg += ')'; 1309 1262 } 1310 1263 throw Xapian::DatabaseError(msg); 1311 1264 } 1312 1265 1313 1266 utag.append(reinterpret_cast<const char *>(buf), 1314 stream.next_out - buf);1267 inflate_zstream->next_out - buf); 1315 1268 } 1316 if (utag.size() != stream.total_out) {1269 if (utag.size() != inflate_zstream->total_out) { 1317 1270 string msg = "compressed tag didn't expand to the expected size: "; 1318 1271 msg += om_tostring(utag.size()); 1319 1272 msg += " != "; 1320 1273 // 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); 1322 1275 throw Xapian::DatabaseCorruptError(msg); 1323 1276 } 1324 1277 1325 err = inflateEnd(&stream);1326 if (err != Z_OK) abort();1327 1328 1278 swap(*tag, utag); 1329 1279 1330 1280 return false; … … 1607 1557 writable(!readonly_), 1608 1558 split_p(0), 1609 1559 compress_strategy(compress_strategy_), 1560 deflate_zstream(NULL), 1561 inflate_zstream(NULL), 1610 1562 lazy(lazy_) 1611 1563 { 1612 1564 DEBUGCALL(DB, void, "FlintTable::FlintTable", 1613 1565 tablename_ << "," << path_ << ", " << readonly_ << ", " << 1614 1566 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 1615 1571 } 1616 1572 1573 1574 void 1575 FlintTable::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 1603 void 1604 FlintTable::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 1617 1629 bool 1618 1630 FlintTable::exists() const { 1619 1631 DEBUGCALL(DB, bool, "FlintTable::exists", ""); … … 1698 1710 FlintTable::~FlintTable() { 1699 1711 DEBUGCALL(DB, void, "FlintTable::~FlintTable", ""); 1700 1712 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 } 1701 1743 } 1702 1744 1703 1745 void FlintTable::close(bool permanent) { -
backends/flint/flint_table.h
595 595 return (base_letter == 'A') ? 'B' : 'A'; 596 596 } 597 597 598 void lazy_alloc_deflate_zstream(); 599 void lazy_alloc_inflate_zstream(); 600 598 601 /** revision number of the opened B-tree. */ 599 602 flint_revision_number_t revision_number; 600 603 … … 713 716 * Z_RLE. */ 714 717 int compress_strategy; 715 718 719 /** Zlib state object */ 720 z_stream *deflate_zstream; 721 z_stream *inflate_zstream; 722 723 716 724 /// If true, don't create the table until it's needed. 717 725 bool lazy; 718 726