From d6cc5943250a7c19adb42ef86dc9a186d4e52166 Mon Sep 17 00:00:00 2001 From: Jay Zhuang Date: Sun, 14 Jan 2018 20:42:57 -0800 Subject: [PATCH] New Bloomfilter format without changing the byte ordering patch by Jay Zhuang; reviewed by jasobrown for CASSANDRA-9067 --- CHANGES.txt | 1 + .../io/sstable/format/SSTableReader.java | 8 +- .../cassandra/io/sstable/format/Version.java | 7 ++ .../io/sstable/format/big/BigFormat.java | 14 ++- .../io/sstable/format/big/BigTableWriter.java | 2 +- .../utils/BloomFilterSerializer.java | 8 +- .../apache/cassandra/utils/FilterFactory.java | 14 --- .../apache/cassandra/utils/obs/IBitSet.java | 4 +- .../cassandra/utils/obs/OffHeapBitSet.java | 60 +++++++---- .../na-1-big-CompressionInfo.db | Bin 87 -> 87 bytes .../legacy_na_clust/na-1-big-Data.db | Bin 5215 -> 5259 bytes .../legacy_na_clust/na-1-big-Digest.crc32 | 2 +- .../legacy_na_clust/na-1-big-Filter.db | Bin 24 -> 24 bytes .../legacy_na_clust/na-1-big-Index.db | Bin 157553 -> 157553 bytes .../legacy_na_clust/na-1-big-Statistics.db | Bin 7095 -> 7095 bytes .../legacy_na_clust/na-1-big-TOC.txt | 6 +- .../na-1-big-CompressionInfo.db | Bin 79 -> 79 bytes .../legacy_na_clust_counter/na-1-big-Data.db | Bin 5781 -> 5888 bytes .../na-1-big-Digest.crc32 | 2 +- .../na-1-big-Filter.db | Bin 24 -> 24 bytes .../legacy_na_clust_counter/na-1-big-Index.db | Bin 157553 -> 157553 bytes .../na-1-big-Statistics.db | Bin 7104 -> 7104 bytes .../legacy_na_clust_counter/na-1-big-TOC.txt | 6 +- .../legacy_na_simple/na-1-big-Data.db | Bin 89 -> 89 bytes .../legacy_na_simple/na-1-big-Digest.crc32 | 2 +- .../legacy_na_simple/na-1-big-Filter.db | Bin 24 -> 24 bytes .../legacy_na_simple/na-1-big-Statistics.db | Bin 4648 -> 4648 bytes .../legacy_na_simple/na-1-big-TOC.txt | 6 +- .../legacy_na_simple_counter/na-1-big-Data.db | Bin 146 -> 140 bytes .../na-1-big-Digest.crc32 | 2 +- .../na-1-big-Filter.db | Bin 24 -> 24 bytes .../na-1-big-Statistics.db | Bin 4657 -> 4657 bytes .../legacy_na_simple_counter/na-1-big-TOC.txt | 6 +- .../4.0/utils.BloomFilter1000.bin | Bin 0 -> 2500016 bytes .../BloomFilterSerializerBench.java | 99 ++++++++++++++++++ .../io/sstable/LegacySSTableTest.java | 3 +- .../cassandra/utils/BloomFilterTest.java | 24 +++-- .../cassandra/utils/SerializationsTest.java | 49 +++++++-- .../utils/obs/OffHeapBitSetTest.java | 21 ++-- 39 files changed, 257 insertions(+), 89 deletions(-) create mode 100644 test/data/serialization/4.0/utils.BloomFilter1000.bin create mode 100644 test/microbench/org/apache/cassandra/test/microbench/BloomFilterSerializerBench.java diff --git a/CHANGES.txt b/CHANGES.txt index 65a7a40b58..fd0acb9be9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0 + * BloomFilter serialization format should not change byte ordering (CASSANDRA-9067) * Remove unused on-heap BloomFilter implementation (CASSANDRA-14152) * Delete temp test files on exit (CASSANDRA-14153) * Make PartitionUpdate and Mutation immutable (CASSANDRA-13867) diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java index 6722e1bfc4..757b9a87cf 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java @@ -75,6 +75,7 @@ import org.apache.cassandra.utils.*; import org.apache.cassandra.utils.concurrent.OpOrder; import org.apache.cassandra.utils.concurrent.Ref; import org.apache.cassandra.utils.concurrent.SelfRefCounted; +import org.apache.cassandra.utils.BloomFilterSerializer; import static org.apache.cassandra.db.Directories.SECONDARY_INDEX_NAME_SEPARATOR; @@ -728,7 +729,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted= 0; hasPendingRepair = version.compareTo("na") >= 0; hasMetadataChecksum = version.compareTo("na") >= 0; + hasOldBfFormat = version.compareTo("na") < 0; } @Override @@ -197,5 +203,11 @@ public class BigFormat implements SSTableFormat { return hasMaxCompressedLength; } + + @Override + public boolean hasOldBfFormat() + { + return hasOldBfFormat; + } } } diff --git a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableWriter.java b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableWriter.java index 04c7bbfd14..b5488ed346 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableWriter.java +++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableWriter.java @@ -484,7 +484,7 @@ public class BigTableWriter extends SSTableWriter DataOutputStreamPlus stream = new BufferedDataOutputStreamPlus(fos)) { // bloom filter - FilterFactory.serialize(bf, stream); + BloomFilterSerializer.serialize((BloomFilter) bf, stream); stream.flush(); SyncUtil.sync(fos); } diff --git a/src/java/org/apache/cassandra/utils/BloomFilterSerializer.java b/src/java/org/apache/cassandra/utils/BloomFilterSerializer.java index 9e9d15ae92..d3c08b53cb 100644 --- a/src/java/org/apache/cassandra/utils/BloomFilterSerializer.java +++ b/src/java/org/apache/cassandra/utils/BloomFilterSerializer.java @@ -17,7 +17,7 @@ */ package org.apache.cassandra.utils; -import java.io.DataInput; +import java.io.DataInputStream; import java.io.IOException; import org.apache.cassandra.db.TypeSizes; @@ -25,7 +25,7 @@ import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.obs.IBitSet; import org.apache.cassandra.utils.obs.OffHeapBitSet; -final class BloomFilterSerializer +public final class BloomFilterSerializer { private BloomFilterSerializer() { @@ -38,10 +38,10 @@ final class BloomFilterSerializer } @SuppressWarnings("resource") - public static BloomFilter deserialize(DataInput in) throws IOException + public static BloomFilter deserialize(DataInputStream in, boolean oldBfFormat) throws IOException { int hashes = in.readInt(); - IBitSet bs = OffHeapBitSet.deserialize(in); + IBitSet bs = OffHeapBitSet.deserialize(in, oldBfFormat); return new BloomFilter(hashes, bs); } diff --git a/src/java/org/apache/cassandra/utils/FilterFactory.java b/src/java/org/apache/cassandra/utils/FilterFactory.java index 947945228c..4cf0cbf74d 100644 --- a/src/java/org/apache/cassandra/utils/FilterFactory.java +++ b/src/java/org/apache/cassandra/utils/FilterFactory.java @@ -17,13 +17,9 @@ */ package org.apache.cassandra.utils; -import java.io.DataInput; -import java.io.IOException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.obs.IBitSet; import org.apache.cassandra.utils.obs.OffHeapBitSet; @@ -34,16 +30,6 @@ public class FilterFactory private static final Logger logger = LoggerFactory.getLogger(FilterFactory.class); private static final long BITSET_EXCESS = 20; - public static void serialize(IFilter bf, DataOutputPlus output) throws IOException - { - BloomFilterSerializer.serialize((BloomFilter) bf, output); - } - - public static IFilter deserialize(DataInput input) throws IOException - { - return BloomFilterSerializer.deserialize(input); - } - /** * @return A BloomFilter with the lowest practical false positive * probability for the given number of elements. diff --git a/src/java/org/apache/cassandra/utils/obs/IBitSet.java b/src/java/org/apache/cassandra/utils/obs/IBitSet.java index 15ff361fbd..b262cf5f87 100644 --- a/src/java/org/apache/cassandra/utils/obs/IBitSet.java +++ b/src/java/org/apache/cassandra/utils/obs/IBitSet.java @@ -18,9 +18,9 @@ package org.apache.cassandra.utils.obs; import java.io.Closeable; -import java.io.DataOutput; import java.io.IOException; +import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.concurrent.Ref; public interface IBitSet extends Closeable @@ -44,7 +44,7 @@ public interface IBitSet extends Closeable */ public void clear(long index); - public void serialize(DataOutput out) throws IOException; + public void serialize(DataOutputPlus out) throws IOException; public long serializedSize(); diff --git a/src/java/org/apache/cassandra/utils/obs/OffHeapBitSet.java b/src/java/org/apache/cassandra/utils/obs/OffHeapBitSet.java index d2c15ca93d..486ec388d8 100644 --- a/src/java/org/apache/cassandra/utils/obs/OffHeapBitSet.java +++ b/src/java/org/apache/cassandra/utils/obs/OffHeapBitSet.java @@ -18,11 +18,17 @@ package org.apache.cassandra.utils.obs; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; import java.io.IOException; +import com.google.common.annotations.VisibleForTesting; + import org.apache.cassandra.db.TypeSizes; +import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.io.util.Memory; +import org.apache.cassandra.io.util.MemoryOutputStream; +import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.concurrent.Ref; /** @@ -109,19 +115,26 @@ public class OffHeapBitSet implements IBitSet bytes.setMemory(0, bytes.size(), (byte) 0); } - public void serialize(DataOutput out) throws IOException + public void serialize(DataOutputPlus out) throws IOException { out.writeInt((int) (bytes.size() / 8)); - for (long i = 0; i < bytes.size();) + out.write(bytes, 0, bytes.size()); + } + + @VisibleForTesting + public void serializeOldBfFormat(DataOutputPlus out) throws IOException + { + out.writeInt((int) (bytes.size() / 8)); + for (long i = 0; i < bytes.size(); ) { long value = ((bytes.getByte(i++) & 0xff) << 0) - + ((bytes.getByte(i++) & 0xff) << 8) - + ((bytes.getByte(i++) & 0xff) << 16) - + ((long) (bytes.getByte(i++) & 0xff) << 24) - + ((long) (bytes.getByte(i++) & 0xff) << 32) - + ((long) (bytes.getByte(i++) & 0xff) << 40) - + ((long) (bytes.getByte(i++) & 0xff) << 48) - + ((long) bytes.getByte(i++) << 56); + + ((bytes.getByte(i++) & 0xff) << 8) + + ((bytes.getByte(i++) & 0xff) << 16) + + ((long) (bytes.getByte(i++) & 0xff) << 24) + + ((long) (bytes.getByte(i++) & 0xff) << 32) + + ((long) (bytes.getByte(i++) & 0xff) << 40) + + ((long) (bytes.getByte(i++) & 0xff) << 48) + + ((long) bytes.getByte(i++) << 56); out.writeLong(value); } } @@ -132,21 +145,28 @@ public class OffHeapBitSet implements IBitSet } @SuppressWarnings("resource") - public static OffHeapBitSet deserialize(DataInput in) throws IOException + public static OffHeapBitSet deserialize(DataInputStream in, boolean oldBfFormat) throws IOException { long byteCount = in.readInt() * 8L; Memory memory = Memory.allocate(byteCount); - for (long i = 0; i < byteCount;) + if (oldBfFormat) { - long v = in.readLong(); - memory.setByte(i++, (byte) (v >>> 0)); - memory.setByte(i++, (byte) (v >>> 8)); - memory.setByte(i++, (byte) (v >>> 16)); - memory.setByte(i++, (byte) (v >>> 24)); - memory.setByte(i++, (byte) (v >>> 32)); - memory.setByte(i++, (byte) (v >>> 40)); - memory.setByte(i++, (byte) (v >>> 48)); - memory.setByte(i++, (byte) (v >>> 56)); + for (long i = 0; i < byteCount; ) + { + long v = in.readLong(); + memory.setByte(i++, (byte) (v >>> 0)); + memory.setByte(i++, (byte) (v >>> 8)); + memory.setByte(i++, (byte) (v >>> 16)); + memory.setByte(i++, (byte) (v >>> 24)); + memory.setByte(i++, (byte) (v >>> 32)); + memory.setByte(i++, (byte) (v >>> 40)); + memory.setByte(i++, (byte) (v >>> 48)); + memory.setByte(i++, (byte) (v >>> 56)); + } + } + else + { + FBUtilities.copy(in, new MemoryOutputStream(memory), byteCount); } return new OffHeapBitSet(memory); } diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-CompressionInfo.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-CompressionInfo.db index 935d8630bf4a994f85bf13377271e8ddc8e3da49..ceaa5a3b35be388650d827072b29e64465f0769a 100644 GIT binary patch delta 58 lcmWF!pP*zqm4ShQ4TzBd^92ZpeLIBao(-Y-8zHoC3;?&s1!n*N delta 58 lcmWF!pP*zqnSp_U4TzBd^Cbv}eLaNcZh+AI2@qOX2LQ9P1oHp@ diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Data.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Data.db index 9982578898151e315a3b0c585b57fb2bbe79ece2..69687207681ea7af8d7dbf24f6ac0c74944d9cd7 100644 GIT binary patch literal 5259 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 literal 5215 zcmd6r|8o>)9mn@b4w4IHgOeZ)I1e%zr4GY$xm=RN!tL48nhc@Ih&ZHJARI@&=Pn@^ zlACgO7N|!Hh@cY0Du~H~P6rZ-1x(>CxpN}67@Uq1kg-UsMLTVwmMLPx`uRM2yZh`7 ze*nK^^8P%Z=h^q}eqPV#*%JhduurhqBZ{I#;eSOa7Pb%C?In&J-!Bib9Z;s27ho( z*WSCy*WJ+E;M*K(Yz_ImjjbCS{Ovw}L#V9{>t;Gw(rIHx zrw(NMqu<}*`N3f~gojEbHFaHVhdaK@W9^>hxMCI4Hx-G-c6j1H3Pf!|Qd-Uu55Rnj z$4YRg2WMF&)}$VUZj&Z z;jTn=i2<6(buWW)UCuPiM|mkFzO+Cn)aOcx;=5=uJy%LB95YF0ADS)Ihh0(TRe6kg ztpTsUzFz>(S5NTNhHda>jKDG%E_gv?6X2bC5;eDsOUQKP1h3W{;}r1@d-b(t+EQuU zv`jb8<}*X#wL#)kUC1y38IdXp`H~F|}@}NnbJ@-17nFz1#g120R3lGrv)02%L-AwjNQhe307xYqHH$7el zdI{?HYZ0uePr*8u;vJO_2fl-gEq&sLmLuY8xV1cCk*sv9AXx*y zvXMyR$+A$S4QrND-abQk-(YKFL_2*c_=u&pzQ%8b$eOGs(Szs zeND1<(V=vLOrPtGAXSbi+X4pYh;MlvKi*_VG}Pr}(y?o8hv2T$)|Y9|I5$k6KZ9P< z$#i>+SFsLW?S*|3=-1Zm3vUjJD*6Lb;=T0|0_4nHJxyS7bHZirj5;m@a*(@1w-07_LHnWnreF3&nG zjtR;Q41aM!8hS?ro-BiYkB!*(NMq`yMZ)l^=bhD_M@RcJ`)sG$YnbBI#;9Qg}iSg(JJ9G zeQ`Ap$)4)E4&nYvZ7G@Vo5>F!^b~dLWqRZ!H$?jnq9v__Uv1>oX%~+-Jv)!1~Ex4-3E3`Rm5d7c7LmpOx`r9abD54dp$*lp^19l(6uUFy*C@}>4e{O zZ_^2v>4HA);n5FnaudnNZ|pVzr~f&N&qF0#rvHoanMydOXAVfoX&&Rz4bWsBKT4D0 z@ZXJOnw%AmfgiP>%XDE>DS#sf^z*t}cDjD@&gBRL8jjiNe$5W1UsaJFb=E#4NLRdt zEpU;TH%(cOll)bC%~fS2{?a_FH0_E z4HM@S!vscs@CQiG$ZbVnNqI(Y*I}%YJPB+e*2x}LGdkwU=xQ9-F;8yy@R-Ad*aCI; zXD51@EUGd!>s>SXW-inH*Ks)w(F0?=I&_j#~xTioSC-I!G!9Mw{F*ZO` zR%S1~&VZE4%{L9_pEtG*$S&Zelq$Fw7x62t=nJ*@6EhZ#^4X53SqF&=kX+{o%x=d?S3>uZfYv>KJhRv5MpL%r}AuXf($)o#-+ z@xw8G?8p2rK@axvZJoTrPR8o79r|W1*Eh)##chC3`lGh)^r2m*#}~&%!`WaCf4$dk zaf+OY4RO?y;hiQKf5{}1FAsGHOJ6nG`kU@PuB|V0MTpV!>3Ai7p^2@p=nYsV*O*G9 zPTnz%y=zkM^NN0OBuca!%U8dwtJ^Ej?Vl%@zpMi)$ElBZJ{%kmIp ZRyegd8<&3kiezoA#UJV{t#AL;_kYBD%!U8} diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Digest.crc32 b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Digest.crc32 index 1e6cbfc56c..f1c192bebe 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Digest.crc32 +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Digest.crc32 @@ -1 +1 @@ -4285275084 \ No newline at end of file +4004129384 \ No newline at end of file diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Filter.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Filter.db index 2e1d5d29ca0683d58365c1bda385a89ced35f1f9..8868e5c18008783c106cc95dcb2a5942cf662a48 100644 GIT binary patch literal 24 fcmZQzU|?lnU|?!-Qe$fMoVHB)pV_-Bo#LEKb7#|kygmX-eNbx~908#BE-v9sr diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Statistics.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust/na-1-big-Statistics.db index 59969c279db4076932379c3c2c65ff892b519951..970e3851b31eed4f38584731795342a38c3a251b 100644 GIT binary patch delta 121 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 literal 5781 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 delta 110 zcmex(j`QO=&JBi6jGwnBSTN>uGVa}e!I80$lg0JmjnA9)E&xSNZ=QFvh?6mRv*6=G xPR85YH$Gx4;ABjge7DM$QF(j98%DuuHU>tcgD-sG9OFZGO5q%n!x!d3H~`o}tE&-#NaChJT0vUpo8@B{#Hi7MX! diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust_counter/na-1-big-TOC.txt b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust_counter/na-1-big-TOC.txt index 734a80d3cd..bb800f8592 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust_counter/na-1-big-TOC.txt +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_clust_counter/na-1-big-TOC.txt @@ -1,8 +1,8 @@ -Index.db -TOC.txt +Digest.crc32 Filter.db CompressionInfo.db +Index.db Summary.db Data.db +TOC.txt Statistics.db -Digest.crc32 diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Data.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Data.db index 414ff070a514ca9e9f6a868ebc81c55044a7c29e..c665dfb00ed7fa366a970445c79ee9c88ea43385 100644 GIT binary patch delta 50 zcma!yoS>t7#CL)+gS3${gUxZ{13;EBkahC-3n0rxnZfi-*9T>W0EMK)D#puhPk#Xb Dh0_q{ delta 50 zcma!yoS>t7NLoOdLE1=}!RBzh2ash9WF5(P0c4pdGngJtyQs_%ppcYU#h4^+UkCt8 Cwhd+g diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Digest.crc32 b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Digest.crc32 index 1dfec4f889..c6c24a74bb 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Digest.crc32 +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Digest.crc32 @@ -1 +1 @@ -2354437953 \ No newline at end of file +3772296151 \ No newline at end of file diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Filter.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-Filter.db index 2e1d5d29ca0683d58365c1bda385a89ced35f1f9..8868e5c18008783c106cc95dcb2a5942cf662a48 100644 GIT binary patch literal 24 fcmZQzU|?lnU|?!-Qe>UgY8WZ)zCO;B%Vv#9!?E?Vsts+|h diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-TOC.txt b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-TOC.txt index 734a80d3cd..bb800f8592 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-TOC.txt +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple/na-1-big-TOC.txt @@ -1,8 +1,8 @@ -Index.db -TOC.txt +Digest.crc32 Filter.db CompressionInfo.db +Index.db Summary.db Data.db +TOC.txt Statistics.db -Digest.crc32 diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Data.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Data.db index ed0dadb82521d7e247ee1f8ad23d3fbe1e4f3443..d9fe576f958c8d841cca8931877e933a2d7480e3 100644 GIT binary patch delta 119 zcmbQl*uywMreH2Z-#6cOZ-GVnziqy}t1V(+O}Z+su=0ZjLnZ?wBLkzM6+^xjKf@6# z4jTq`bCm-ZY#3yWY#8*9YuGSwn5%Ev0puIoFxa2ml28Fupk)mdmoWhfoGH%$>NueD P%Yy*|7#UMv=>Gr!sv{x% delta 125 zcmeBSoWwXmrYuSHR7NqAi{T`HkA@|!`uYs4(aW>C)B-dZG8q^d85j+%81l9F84ht5 z+Ay%2_i$~nVURJhVX!~!zY-{*-0N-4z*xZ`V+<5J5^DeyGVY7$uw`J_!XRS;6gwI% U0TesXA6CEs0gQ})l;l1E036>RNdN!< diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Digest.crc32 b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Digest.crc32 index 1480f5db63..de7baed426 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Digest.crc32 +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Digest.crc32 @@ -1 +1 @@ -2023874595 \ No newline at end of file +4035692752 \ No newline at end of file diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Filter.db b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-Filter.db index 2e1d5d29ca0683d58365c1bda385a89ced35f1f9..8868e5c18008783c106cc95dcb2a5942cf662a48 100644 GIT binary patch literal 24 fcmZQzU|?lnU|?!-Qee|)L#E%9kXYBbp!*0#zZ}_$&UoRS>_(e GSPcMzj4lBH diff --git a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-TOC.txt b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-TOC.txt index 734a80d3cd..bb800f8592 100644 --- a/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-TOC.txt +++ b/test/data/legacy-sstables/na/legacy_tables/legacy_na_simple_counter/na-1-big-TOC.txt @@ -1,8 +1,8 @@ -Index.db -TOC.txt +Digest.crc32 Filter.db CompressionInfo.db +Index.db Summary.db Data.db +TOC.txt Statistics.db -Digest.crc32 diff --git a/test/data/serialization/4.0/utils.BloomFilter1000.bin b/test/data/serialization/4.0/utils.BloomFilter1000.bin new file mode 100644 index 0000000000000000000000000000000000000000..b1bfe99a9902432c99a1b2195c70b102f7d27b40 GIT binary patch literal 2500016 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¬o~Sxb^bOap31GInP9MY%5ul;oRh?s1 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 literal 0 HcmV?d00001 diff --git a/test/microbench/org/apache/cassandra/test/microbench/BloomFilterSerializerBench.java b/test/microbench/org/apache/cassandra/test/microbench/BloomFilterSerializerBench.java new file mode 100644 index 0000000000..922281145f --- /dev/null +++ b/test/microbench/org/apache/cassandra/test/microbench/BloomFilterSerializerBench.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.test.microbench; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; + +import org.apache.cassandra.db.BufferDecoratedKey; +import org.apache.cassandra.dht.Murmur3Partitioner; +import org.apache.cassandra.io.util.BufferedDataOutputStreamPlus; +import org.apache.cassandra.io.util.DataOutputStreamPlus; +import org.apache.cassandra.io.util.FileUtils; +import org.apache.cassandra.utils.BloomFilter; +import org.apache.cassandra.utils.BloomFilterSerializer; +import org.apache.cassandra.utils.FilterFactory; +import org.apache.cassandra.utils.IFilter; +import org.apache.cassandra.utils.SerializationsTest; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 2, time = 4, timeUnit = TimeUnit.SECONDS) +@Fork(value = 2) +@State(Scope.Benchmark) +public class BloomFilterSerializerBench +{ + + @Param({"1", "10", "100", "1024"}) + private long numElemsInK; + + @Param({"true", "false"}) + public boolean oldBfFormat; + + static final IFilter.FilterKey wrap(ByteBuffer buf) + { + return new BufferDecoratedKey(new Murmur3Partitioner.LongToken(0L), buf); + } + + private ByteBuffer testVal = ByteBuffer.wrap(new byte[] { 0, 1}); + + @Benchmark + public void serializationTest() throws IOException + { + File file = FileUtils.createTempFile("bloomFilterTest-", ".dat"); + try + { + BloomFilter filter = (BloomFilter) FilterFactory.getFilter(numElemsInK * 1024, 0.01d); + filter.add(wrap(testVal)); + DataOutputStreamPlus out = new BufferedDataOutputStreamPlus(new FileOutputStream(file)); + if (oldBfFormat) + SerializationsTest.serializeOldBfFormat(filter, out); + else + BloomFilterSerializer.serialize(filter, out); + out.close(); + filter.close(); + + DataInputStream in = new DataInputStream(new FileInputStream(file)); + BloomFilter filter2 = BloomFilterSerializer.deserialize(in, oldBfFormat); + FileUtils.closeQuietly(in); + filter2.close(); + } + finally + { + file.delete(); + } + } + +} diff --git a/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java b/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java index 48921842ce..6e7d1730bc 100644 --- a/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java @@ -94,7 +94,7 @@ public class LegacySSTableTest { String scp = System.getProperty(LEGACY_SSTABLE_PROP); Assert.assertNotNull("System property " + LEGACY_SSTABLE_ROOT + " not set", scp); - + LEGACY_SSTABLE_ROOT = new File(scp).getAbsoluteFile(); Assert.assertTrue("System property " + LEGACY_SSTABLE_ROOT + " does not specify a directory", LEGACY_SSTABLE_ROOT.isDirectory()); @@ -270,7 +270,6 @@ public class LegacySSTableTest logger.debug("for pk={} ck={}", pk, ck); String pkValue = Integer.toString(pk); - UntypedResultSet rs; if (ck == 0) { readSimpleTable(legacyVersion, pkValue); diff --git a/test/unit/org/apache/cassandra/utils/BloomFilterTest.java b/test/unit/org/apache/cassandra/utils/BloomFilterTest.java index 581248c297..1c3afff2ef 100644 --- a/test/unit/org/apache/cassandra/utils/BloomFilterTest.java +++ b/test/unit/org/apache/cassandra/utils/BloomFilterTest.java @@ -43,19 +43,23 @@ public class BloomFilterTest { public IFilter bfInvHashes; - public BloomFilterTest() - { - } - public static IFilter testSerialize(IFilter f) throws IOException + public static IFilter testSerialize(IFilter f, boolean oldBfFormat) throws IOException { f.add(FilterTestHelper.bytes("a")); DataOutputBuffer out = new DataOutputBuffer(); - FilterFactory.serialize(f, out); + if (oldBfFormat) + { + SerializationsTest.serializeOldBfFormat((BloomFilter) f, out); + } + else + { + BloomFilterSerializer.serialize((BloomFilter) f, out); + } ByteArrayInputStream in = new ByteArrayInputStream(out.getData(), 0, out.getLength()); - IFilter f2 = FilterFactory.deserialize(new DataInputStream(in)); + IFilter f2 = BloomFilterSerializer.deserialize(new DataInputStream(in), oldBfFormat); assert f2.isPresent(FilterTestHelper.bytes("a")); assert !f2.isPresent(FilterTestHelper.bytes("b")); @@ -132,7 +136,8 @@ public class BloomFilterTest @Test public void testSerialize() throws IOException { - BloomFilterTest.testSerialize(bfInvHashes).close(); + BloomFilterTest.testSerialize(bfInvHashes, true).close(); + BloomFilterTest.testSerialize(bfInvHashes, false).close(); } @Test @@ -206,13 +211,12 @@ public class BloomFilterTest BloomFilter filter = (BloomFilter) FilterFactory.getFilter(((long) Integer.MAX_VALUE / 8) + 1, 0.01d); filter.add(FilterTestHelper.wrap(test)); DataOutputStreamPlus out = new BufferedDataOutputStreamPlus(new FileOutputStream(file)); - FilterFactory.serialize(filter, out); - filter.bitset.serialize(out); + BloomFilterSerializer.serialize(filter, out); out.close(); filter.close(); DataInputStream in = new DataInputStream(new FileInputStream(file)); - BloomFilter filter2 = (BloomFilter) FilterFactory.deserialize(in); + BloomFilter filter2 = BloomFilterSerializer.deserialize(in, false); Assert.assertTrue(filter2.isPresent(FilterTestHelper.wrap(test))); FileUtils.closeQuietly(in); filter2.close(); diff --git a/test/unit/org/apache/cassandra/utils/SerializationsTest.java b/test/unit/org/apache/cassandra/utils/SerializationsTest.java index 8da4a92e83..f26042850d 100644 --- a/test/unit/org/apache/cassandra/utils/SerializationsTest.java +++ b/test/unit/org/apache/cassandra/utils/SerializationsTest.java @@ -31,30 +31,42 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.db.marshal.Int32Type; import org.apache.cassandra.io.util.DataInputPlus.DataInputStreamPlus; +import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.io.util.DataOutputStreamPlus; -import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Murmur3Partitioner; +import org.apache.cassandra.utils.obs.OffHeapBitSet; import java.io.File; import java.io.FileInputStream; public class SerializationsTest extends AbstractSerializationsTester { + // Helper function to serialize old Bloomfilter format, should be removed once the old format is not supported + public static void serializeOldBfFormat(BloomFilter bf, DataOutputPlus out) throws IOException + { + out.writeInt(bf.hashCount); + Assert.assertTrue(bf.bitset instanceof OffHeapBitSet); + ((OffHeapBitSet) bf.bitset).serializeOldBfFormat(out); + } + @BeforeClass public static void initDD() { DatabaseDescriptor.daemonInitialization(); } - private static void testBloomFilterWrite1000() throws IOException + private static void testBloomFilterWrite1000(boolean oldBfFormat) throws IOException { try (IFilter bf = FilterFactory.getFilter(1000000, 0.0001)) { for (int i = 0; i < 1000; i++) bf.add(Util.dk(Int32Type.instance.decompose(i))); - try (DataOutputStreamPlus out = getOutput("3.0", "utils.BloomFilter1000.bin")) + try (DataOutputStreamPlus out = getOutput(oldBfFormat ? "3.0" : "4.0", "utils.BloomFilter1000.bin")) { - FilterFactory.serialize(bf, out); + if (oldBfFormat) + serializeOldBfFormat((BloomFilter) bf, out); + else + BloomFilterSerializer.serialize((BloomFilter) bf, out); } } } @@ -63,10 +75,29 @@ public class SerializationsTest extends AbstractSerializationsTester public void testBloomFilterRead1000() throws IOException { if (EXECUTE_WRITES) - testBloomFilterWrite1000(); + { + testBloomFilterWrite1000(false); + testBloomFilterWrite1000(true); + } + + try (DataInputStream in = getInput("4.0", "utils.BloomFilter1000.bin"); + IFilter filter = BloomFilterSerializer.deserialize(in, false)) + { + boolean present; + for (int i = 0 ; i < 1000 ; i++) + { + present = filter.isPresent(Util.dk(Int32Type.instance.decompose(i))); + Assert.assertTrue(present); + } + for (int i = 1000 ; i < 2000 ; i++) + { + present = filter.isPresent(Util.dk(Int32Type.instance.decompose(i))); + Assert.assertFalse(present); + } + } try (DataInputStream in = getInput("3.0", "utils.BloomFilter1000.bin"); - IFilter filter = FilterFactory.deserialize(in)) + IFilter filter = BloomFilterSerializer.deserialize(in, true)) { boolean present; for (int i = 0 ; i < 1000 ; i++) @@ -85,15 +116,15 @@ public class SerializationsTest extends AbstractSerializationsTester @Test public void testBloomFilterTable() throws Exception { - testBloomFilterTable("test/data/bloom-filter/la/foo/la-1-big-Filter.db"); + testBloomFilterTable("test/data/bloom-filter/la/foo/la-1-big-Filter.db", true); } - private static void testBloomFilterTable(String file) throws Exception + private static void testBloomFilterTable(String file, boolean oldBfFormat) throws Exception { Murmur3Partitioner partitioner = new Murmur3Partitioner(); try (DataInputStream in = new DataInputStream(new FileInputStream(new File(file))); - IFilter filter = FilterFactory.deserialize(in)) + IFilter filter = BloomFilterSerializer.deserialize(in, oldBfFormat)) { for (int i = 1; i <= 10; i++) { diff --git a/test/unit/org/apache/cassandra/utils/obs/OffHeapBitSetTest.java b/test/unit/org/apache/cassandra/utils/obs/OffHeapBitSetTest.java index f0325da41f..49b4c94dd3 100644 --- a/test/unit/org/apache/cassandra/utils/obs/OffHeapBitSetTest.java +++ b/test/unit/org/apache/cassandra/utils/obs/OffHeapBitSetTest.java @@ -25,11 +25,9 @@ import java.util.List; import java.util.Random; import com.google.common.collect.Lists; +import org.apache.cassandra.io.util.DataOutputBuffer; import org.junit.Assert; import org.junit.Test; -import org.junit.rules.ExpectedException; - -import org.apache.cassandra.io.util.DataOutputBuffer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -46,8 +44,7 @@ public class OffHeapBitSetTest Assert.assertEquals(bs.get(i), newbs.get(i)); } - @Test - public void testOffHeapSerialization() throws IOException + private void testOffHeapSerialization(boolean oldBfFormat) throws IOException { try (OffHeapBitSet bs = new OffHeapBitSet(100000)) { @@ -56,16 +53,26 @@ public class OffHeapBitSetTest bs.set(i); DataOutputBuffer out = new DataOutputBuffer(); - bs.serialize(out); + if (oldBfFormat) + bs.serializeOldBfFormat(out); + else + bs.serialize(out); DataInputStream in = new DataInputStream(new ByteArrayInputStream(out.getData())); - try (OffHeapBitSet newbs = OffHeapBitSet.deserialize(in)) + try (OffHeapBitSet newbs = OffHeapBitSet.deserialize(in, oldBfFormat)) { compare(bs, newbs); } } } + @Test + public void testSerialization() throws IOException + { + testOffHeapSerialization(true); + testOffHeapSerialization(false); + } + @Test public void testBitSetGetClear() {