Author: jbellis Date: Thu Nov 10 02:24:46 2011 New Revision: 1200100 URL: http://svn.apache.org/viewvc?rev=1200100&view=rev Log: add sstable forward-compatibility patch by jbellis; reviewed by ymorishita for CASSANDRA-3478
Modified: cassandra/branches/cassandra-1.0/CHANGES.txt cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/db/ColumnFamilyStore.java cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/sstable/Descriptor.java cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/streaming/StreamIn.java cassandra/branches/cassandra-1.0/test/unit/org/apache/cassandra/streaming/BootstrapTest.java Modified: cassandra/branches/cassandra-1.0/CHANGES.txt URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/CHANGES.txt?rev=1200100&r1=1200099&r2=1200100&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/CHANGES.txt (original) +++ cassandra/branches/cassandra-1.0/CHANGES.txt Thu Nov 10 02:24:46 2011 @@ -6,6 +6,7 @@ subcolumns or old subcolumn versions (CASSANDRA-3446) * automatically compute sha1 sum for uncompressed data files (CASSANDRA-3456) * fix reading metadata/statistics component for version < h (CASSANDRA-3474) + * add sstable forward-compatibility (CASSANDRA-3478) Merged from 0.8: * Make counter shard merging thread safe (CASSANDRA-3178) * fix updating CF row_cache_provider (CASSANDRA-3414) Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/db/ColumnFamilyStore.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=1200100&r1=1200099&r2=1200100&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Thu Nov 10 02:24:46 2011 @@ -324,11 +324,9 @@ public class ColumnFamilyStore implement if (!desc.cfname.equals(columnFamily)) continue; generations.add(desc.generation); - if (desc.isFromTheFuture()) - { - throw new RuntimeException(String.format("Can't open sstables from the future! Current version %s, found file: %s", + if (!desc.isCompatible()) + throw new RuntimeException(String.format("Can't open incompatible SSTable! Current version %s, found file: %s", Descriptor.CURRENT_VERSION, desc)); - } } } Collections.sort(generations); @@ -551,8 +549,8 @@ public class ColumnFamilyStore implement if (!descriptor.cfname.equals(columnFamily)) continue; - if (descriptor.isFromTheFuture()) - throw new RuntimeException(String.format("Can't open sstables from the future! Current version %s, found file: %s", + if (!descriptor.isCompatible()) + throw new RuntimeException(String.format("Can't open incompatible SSTable! Current version %s, found file: %s", Descriptor.CURRENT_VERSION, descriptor)); Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/sstable/Descriptor.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/sstable/Descriptor.java?rev=1200100&r1=1200099&r2=1200100&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/sstable/Descriptor.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/sstable/Descriptor.java Thu Nov 10 02:24:46 2011 @@ -40,6 +40,14 @@ import static org.apache.cassandra.io.ss */ public class Descriptor { + // versions are denoted as [major][minor]. Minor versions must be forward-compatible: + // new fields are allowed in e.g. the metadata component, but fields can't be removed + // or have their size changed. + // + // Minor versions were introduced with version "hb" for Cassandra 1.0.3; prior to that, + // we always incremented the major version. In particular, versions g and h are + // forwards-compatible with version f, so if the above convention had been followed, + // we would have labeled them fb and fc. public static final String LEGACY_VERSION = "a"; // "pre-history" // b (0.7.0): added version to sstable filenames // c (0.7.0): bloom filter component computes hashes over raw key bytes instead of strings @@ -251,9 +259,26 @@ public class Descriptor return ver != null && ver.matches("[a-z]+"); } - public boolean isFromTheFuture() + /** + * @return true if the current Cassandra version can read the given sstable version + */ + public boolean isCompatible() + { + return version.charAt(0) <= CURRENT_VERSION.charAt(0); + } + + /** + * @return true if the current Cassandra version can stream the given sstable version + * from another node. This is stricter than opening it locally [isCompatible] because + * streaming needs to rebuild all the non-data components, and it only knows how to write + * the latest version. + */ + public boolean isStreamCompatible() { - return version.compareTo(CURRENT_VERSION) > 0; + // we could add compatibility for earlier versions with the new single-pass streaming + // (see SSTableWriter.appendFromStream) but versions earlier than 0.7.1 don't have the + // MessagingService version awareness anyway so there's no point. + return isCompatible() && version.charAt(0) >= 'f'; } @Override Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/streaming/StreamIn.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/streaming/StreamIn.java?rev=1200100&r1=1200099&r2=1200100&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/streaming/StreamIn.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/streaming/StreamIn.java Thu Nov 10 02:24:46 2011 @@ -82,6 +82,9 @@ public class StreamIn { /* Create a local sstable for each remote sstable */ Descriptor remotedesc = remote.desc; + if (!remotedesc.isStreamCompatible()) + throw new UnsupportedOperationException(String.format("SSTable %s is not compatible with current version %s", + remote.getFilename(), Descriptor.CURRENT_VERSION)); // new local sstable Table table = Table.open(remotedesc.ksname); Modified: cassandra/branches/cassandra-1.0/test/unit/org/apache/cassandra/streaming/BootstrapTest.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/test/unit/org/apache/cassandra/streaming/BootstrapTest.java?rev=1200100&r1=1200099&r2=1200100&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/test/unit/org/apache/cassandra/streaming/BootstrapTest.java (original) +++ cassandra/branches/cassandra-1.0/test/unit/org/apache/cassandra/streaming/BootstrapTest.java Thu Nov 10 02:24:46 2011 @@ -36,8 +36,8 @@ public class BootstrapTest extends Schem @Test public void testGetNewNames() throws IOException { - Descriptor desc = Descriptor.fromFilename(new File("Keyspace1", "Standard1-500-Data.db").toString()); - assert !desc.isLatestVersion; // deliberately test old version; see CASSANDRA-2283 + Descriptor desc = Descriptor.fromFilename(new File("Keyspace1", "Standard1-f-500-Data.db").toString()); + assert !desc.isLatestVersion; // deliberately test old version PendingFile inContext = new PendingFile(null, desc, "Data.db", Arrays.asList(new Pair<Long,Long>(0L, 1L)), OperationType.BOOTSTRAP); PendingFile outContext = StreamIn.getContextMapping(inContext);