3737#include " util/coding.h"
3838#include " util/crc32c.h"
3939#include " util/stop_watch.h"
40+ #include " util/xxhash.h"
4041
4142namespace rocksdb {
4243
@@ -231,12 +232,14 @@ Slice CompressBlock(const Slice& raw,
231232} // anonymous namespace
232233
233234// kBlockBasedTableMagicNumber was picked by running
234- // echo http://code.google.com/p/leveldb/ | sha1sum
235+ // echo rocksdb.table.block_based | sha1sum
235236// and taking the leading 64 bits.
236237// Please note that kBlockBasedTableMagicNumber may also be accessed by
237238// other .cc files so it have to be explicitly declared with "extern".
238- extern const uint64_t kBlockBasedTableMagicNumber
239- = 0xdb4775248b80fb57ull ;
239+ extern const uint64_t kBlockBasedTableMagicNumber = 0x88e241b785f4cff7ull ;
240+ // We also support reading and writing legacy block based table format (for
241+ // backwards compatibility)
242+ extern const uint64_t kLegacyBlockBasedTableMagicNumber = 0xdb4775248b80fb57ull ;
240243
241244// A collector that collects properties of interest to block-based table.
242245// For now this class looks heavy-weight since we only write one additional
@@ -289,6 +292,7 @@ struct BlockBasedTableBuilder::Rep {
289292
290293 std::string last_key;
291294 CompressionType compression_type;
295+ ChecksumType checksum_type;
292296 TableProperties props;
293297
294298 bool closed = false ; // Either Finish() or Abandon() has been called.
@@ -303,14 +307,16 @@ struct BlockBasedTableBuilder::Rep {
303307
304308 Rep (const Options& opt, const InternalKeyComparator& icomparator,
305309 WritableFile* f, FlushBlockPolicyFactory* flush_block_policy_factory,
306- CompressionType compression_type, IndexType index_block_type)
310+ CompressionType compression_type, IndexType index_block_type,
311+ ChecksumType checksum_type)
307312 : options(opt),
308313 internal_comparator (icomparator),
309314 file(f),
310315 data_block(options, &internal_comparator),
311316 index_builder(
312317 CreateIndexBuilder (index_block_type, &internal_comparator)),
313318 compression_type(compression_type),
319+ checksum_type(checksum_type),
314320 filter_block(opt.filter_policy == nullptr
315321 ? nullptr
316322 : new FilterBlockBuilder(opt, &internal_comparator)),
@@ -330,7 +336,8 @@ BlockBasedTableBuilder::BlockBasedTableBuilder(
330336 : rep_(new Rep(options, internal_comparator, file,
331337 table_options.flush_block_policy_factory.get(),
332338 compression_type,
333- BlockBasedTableOptions::IndexType::kBinarySearch)) {
339+ BlockBasedTableOptions::IndexType::kBinarySearch,
340+ table_options.checksum)) {
334341 if (rep_->filter_block != nullptr ) {
335342 rep_->filter_block ->StartBlock (0 );
336343 }
@@ -443,9 +450,27 @@ void BlockBasedTableBuilder::WriteRawBlock(const Slice& block_contents,
443450 if (r->status .ok ()) {
444451 char trailer[kBlockTrailerSize ];
445452 trailer[0 ] = type;
446- uint32_t crc = crc32c::Value (block_contents.data (), block_contents.size ());
447- crc = crc32c::Extend (crc, trailer, 1 ); // Extend crc to cover block type
448- EncodeFixed32 (trailer+1 , crc32c::Mask (crc));
453+ char * trailer_without_type = trailer + 1 ;
454+ switch (r->checksum_type ) {
455+ case kNoChecksum :
456+ // we don't support no checksum yet
457+ assert (false );
458+ // intentional fallthrough in release binary
459+ case kCRC32c : {
460+ auto crc = crc32c::Value (block_contents.data (), block_contents.size ());
461+ crc = crc32c::Extend (crc, trailer, 1 ); // Extend to cover block type
462+ EncodeFixed32 (trailer_without_type, crc32c::Mask (crc));
463+ break ;
464+ }
465+ case kxxHash: {
466+ void * xxh = XXH32_init (0 );
467+ XXH32_update (xxh, block_contents.data (), block_contents.size ());
468+ XXH32_update (xxh, trailer, 1 ); // Extend to cover block type
469+ EncodeFixed32 (trailer_without_type, XXH32_digest (xxh));
470+ break ;
471+ }
472+ }
473+
449474 r->status = r->file ->Append (Slice (trailer, kBlockTrailerSize ));
450475 if (r->status .ok ()) {
451476 r->status = InsertBlockInCache (block_contents, type, handle);
@@ -596,9 +621,19 @@ Status BlockBasedTableBuilder::Finish() {
596621
597622 // Write footer
598623 if (ok ()) {
599- Footer footer (kBlockBasedTableMagicNumber );
624+ // No need to write out new footer if we're using default checksum.
625+ // We're writing legacy magic number because we want old versions of RocksDB
626+ // be able to read files generated with new release (just in case if
627+ // somebody wants to roll back after an upgrade)
628+ // TODO(icanadi) at some point in the future, when we're absolutely sure
629+ // nobody will roll back to RocksDB 2.x versions, retire the legacy magic
630+ // number and always write new table files with new magic number
631+ bool legacy = (r->checksum_type == kCRC32c );
632+ Footer footer (legacy ? kLegacyBlockBasedTableMagicNumber
633+ : kBlockBasedTableMagicNumber );
600634 footer.set_metaindex_handle (metaindex_block_handle);
601635 footer.set_index_handle (index_block_handle);
636+ footer.set_checksum (r->checksum_type );
602637 std::string footer_encoding;
603638 footer.EncodeTo (&footer_encoding);
604639 r->status = r->file ->Append (footer_encoding);
0 commit comments