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 , 16 years ago) |
---|
-
backends/flint/flint_table.cc
1037 1037 CompileTimeAssert(DONT_COMPRESS != Z_RLE); 1038 1038 #endif 1039 1039 1040 z_stream stream;1040 lazy_alloc_deflate_zstream(); 1041 1041 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(); 1045 1044 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 1065 1045 // If compressed size is >= tag.size(), we don't want to compress. 1066 1046 unsigned long blk_len = tag.size() - 1; 1067 1047 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; 1070 1050 1071 err = deflate(&stream, Z_FINISH);1051 int err = deflate(deflate_zstream, Z_FINISH); 1072 1052 if (err == Z_STREAM_END) { 1073 1053 // If deflate succeeded, then the output was at least one byte 1074 1054 // 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); 1076 1056 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);1090 1057 } 1091 1058 1092 1059 delete [] blk; … … 1271 1238 1272 1239 Bytef buf[8192]; 1273 1240 1274 z_stream stream; 1275 stream.next_out = buf; 1276 stream.avail_out = (uInt)sizeof(buf); 1241 lazy_alloc_inflate_zstream(); 1277 1242 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); 1280 1245 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(); 1283 1248 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; 1299 1250 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); 1305 1256 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); 1310 1261 if (err == Z_STREAM_END) break; 1311 1262 } 1312 1263 1313 1264 if (err != Z_OK && err != Z_STREAM_END) { 1314 1265 if (err == Z_MEM_ERROR) throw std::bad_alloc(); 1315 1266 string msg = "inflate failed"; 1316 if ( stream.msg) {1267 if (inflate_zstream->msg) { 1317 1268 msg += " ("; 1318 msg += stream.msg;1269 msg += inflate_zstream->msg; 1319 1270 msg += ')'; 1320 1271 } 1321 1272 throw Xapian::DatabaseError(msg); 1322 1273 } 1323 1274 1324 1275 utag.append(reinterpret_cast<const char *>(buf), 1325 stream.next_out - buf);1276 inflate_zstream->next_out - buf); 1326 1277 } 1327 if (utag.size() != stream.total_out) {1278 if (utag.size() != inflate_zstream->total_out) { 1328 1279 string msg = "compressed tag didn't expand to the expected size: "; 1329 1280 msg += om_tostring(utag.size()); 1330 1281 msg += " != "; 1331 1282 // 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); 1333 1284 throw Xapian::DatabaseCorruptError(msg); 1334 1285 } 1335 1286 1336 err = inflateEnd(&stream);1337 if (err != Z_OK) abort();1338 1339 1287 swap(*tag, utag); 1340 1288 1341 1289 return false; … … 1612 1560 writable(!readonly_), 1613 1561 split_p(0), 1614 1562 compress_strategy(compress_strategy_), 1563 deflate_zstream(NULL), 1564 inflate_zstream(NULL), 1615 1565 lazy(lazy_) 1616 1566 { 1617 DEBUGCALL(DB, void, "FlintTable::FlintTable", 1567 DEBUGCALL(DB, void, "FlintTable::FlintTable", 1618 1568 tablename_ << "," << path_ << ", " << readonly_ << ", " << 1619 1569 compress_strategy_ << ", " << lazy_); 1620 1570 } 1621 1571 1572 void 1573 FlintTable::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 1602 void 1603 FlintTable::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 1622 1630 bool 1623 1631 FlintTable::exists() const { 1624 1632 DEBUGCALL(DB, bool, "FlintTable::exists", ""); … … 1699 1707 FlintTable::~FlintTable() { 1700 1708 DEBUGCALL(DB, void, "FlintTable::~FlintTable", ""); 1701 1709 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 } 1702 1748 } 1703 1749 1704 1750 void FlintTable::close(bool permanent) { -
backends/flint/flint_table.h
289 289 * Any outstanding changes (ie, changes made without commit() having 290 290 * subsequently been called) will be lost. 291 291 */ 292 ~FlintTable();292 virtual ~FlintTable(); 293 293 294 294 /** Close the Btree. This closes and frees any of the btree 295 295 * structures which have been created and opened. … … 587 587 return (base_letter == 'A') ? 'B' : 'A'; 588 588 } 589 589 590 void lazy_alloc_deflate_zstream() const; 591 void lazy_alloc_inflate_zstream() const; 592 590 593 /** revision number of the opened B-tree. */ 591 594 flint_revision_number_t revision_number; 592 595 … … 705 708 * Z_RLE. */ 706 709 int compress_strategy; 707 710 711 /** Zlib state object */ 712 mutable z_stream *deflate_zstream; 713 mutable z_stream *inflate_zstream; 714 708 715 /// If true, don't create the table until it's needed. 709 716 bool lazy; 710 717