http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/SSTableTxnWriter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/SSTableTxnWriter.java b/src/java/org/apache/cassandra/io/sstable/SSTableTxnWriter.java new file mode 100644 index 0000000..8514dcc --- /dev/null +++ b/src/java/org/apache/cassandra/io/sstable/SSTableTxnWriter.java @@ -0,0 +1,101 @@ +/* + * 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.io.sstable; + +import org.apache.cassandra.db.RowIndexEntry; +import org.apache.cassandra.db.SerializationHeader; +import org.apache.cassandra.db.compaction.OperationType; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; +import org.apache.cassandra.db.rows.UnfilteredRowIterator; +import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableWriter; +import org.apache.cassandra.utils.concurrent.Transactional; + +/** + * A wrapper for SSTableWriter and LifecycleTransaction to be used when + * the writer is the only participant in the transaction and therefore + * it can safely own the transaction. + */ +public class SSTableTxnWriter extends Transactional.AbstractTransactional implements Transactional +{ + private final LifecycleTransaction txn; + private final SSTableWriter writer; + + public SSTableTxnWriter(LifecycleTransaction txn, SSTableWriter writer) + { + this.txn = txn; + this.writer = writer; + } + + public RowIndexEntry append(UnfilteredRowIterator iterator) + { + return writer.append(iterator); + } + + public String getFilename() + { + return writer.getFilename(); + } + + public long getFilePointer() + { + return writer.getFilePointer(); + } + + protected Throwable doCommit(Throwable accumulate) + { + return txn.commit(writer.commit(accumulate)); + } + + protected Throwable doAbort(Throwable accumulate) + { + return txn.abort(writer.abort(accumulate)); + } + + protected void doPrepare() + { + writer.prepareToCommit(); + txn.prepareToCommit(); + } + + public SSTableReader finish(boolean openResult) + { + writer.setOpenResult(openResult); + finish(); + return writer.finished(); + } + + public static SSTableTxnWriter create(Descriptor descriptor, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header) + { + LifecycleTransaction txn = LifecycleTransaction.offline(OperationType.WRITE, descriptor.directory); + SSTableWriter writer = SSTableWriter.create(descriptor, keyCount, repairedAt, sstableLevel, header, txn); + return new SSTableTxnWriter(txn, writer); + } + + public static SSTableTxnWriter create(String filename, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header) + { + Descriptor desc = Descriptor.fromFilename(filename); + return create(desc, keyCount, repairedAt, sstableLevel, header); + } + + public static SSTableTxnWriter create(String filename, long keyCount, long repairedAt, SerializationHeader header) + { + return create(filename, keyCount, repairedAt, 0, header); + } +}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java ---------------------------------------------------------------------- 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 3d9fe82..6a09d5a 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java @@ -26,7 +26,6 @@ import java.util.concurrent.atomic.AtomicLong; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.collect.Ordering; import com.google.common.primitives.Longs; @@ -35,7 +34,6 @@ import com.google.common.util.concurrent.RateLimiter; import com.clearspring.analytics.stream.cardinality.CardinalityMergeException; import com.clearspring.analytics.stream.cardinality.HyperLogLogPlus; import com.clearspring.analytics.stream.cardinality.ICardinality; -import com.codahale.metrics.Counter; import org.apache.cassandra.cache.CachingOptions; import org.apache.cassandra.cache.InstrumentingCache; import org.apache.cassandra.cache.KeyCacheKey; @@ -47,7 +45,7 @@ import org.apache.cassandra.db.filter.ColumnFilter; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.db.commitlog.ReplayPosition; import org.apache.cassandra.db.index.SecondaryIndex; -import org.apache.cassandra.db.lifecycle.Tracker; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.dht.*; import org.apache.cassandra.io.FSError; import org.apache.cassandra.io.compress.CompressionMetadata; @@ -651,6 +649,11 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS keyCache = CacheService.instance.keyCache; } + public boolean isKeyCacheSetup() + { + return keyCache != null; + } + private void load(ValidationMetadata validation) throws IOException { if (metadata.getBloomFilterFpChance() == 1.0) @@ -989,7 +992,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS } } - // runOnClose must NOT be an anonymous or non-static inner class, nor must it retain a reference chain to this reader + // These runnables must NOT be an anonymous or non-static inner class, nor must it retain a reference chain to this reader public void runOnClose(final Runnable runOnClose) { synchronized (tidy.global) @@ -1166,6 +1169,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS long newSize = bytesOnDisk(); StorageMetrics.load.inc(newSize - oldSize); parent.metric.liveDiskSpaceUsed.inc(newSize - oldSize); + parent.metric.totalDiskSpaceUsed.inc(newSize - oldSize); return cloneAndReplace(first, OpenReason.METADATA_CHANGE, newSummary); } @@ -1646,7 +1650,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS * @return true if the this is the first time the file was marked obsolete. Calling this * multiple times is usually buggy (see exceptions in Tracker.unmarkCompacting and removeOldSSTablesSize). */ - public boolean markObsolete(Tracker tracker) + public void markObsolete(TransactionLogs.SSTableTidier tidier) { if (logger.isDebugEnabled()) logger.debug("Marking {} compacted", getFilename()); @@ -1654,18 +1658,16 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS synchronized (tidy.global) { assert !tidy.isReplaced; + assert tidy.global.obsoletion == null: this + " was already marked compacted"; + + tidy.global.obsoletion = tidier; + tidy.global.stopReadMeterPersistence(); } - if (!tidy.global.isCompacted.getAndSet(true)) - { - tidy.type.markObsolete(this, tracker); - return true; - } - return false; } public boolean isMarkedCompacted() { - return tidy.global.isCompacted.get(); + return tidy.global.obsoletion != null; } public void markSuspect() @@ -1759,6 +1761,8 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS for (Component component : components) { File sourceFile = new File(descriptor.filenameFor(component)); + if (!sourceFile.exists()) + continue; File targetLink = new File(snapshotDirectoryPath, sourceFile.getName()); FileUtils.createHardLink(sourceFile, targetLink); } @@ -2065,12 +2069,12 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS * InstanceTidier => DescriptorTypeTitdy => GlobalTidy * * We can create many InstanceTidiers (one for every time we reopen an sstable with MOVED_START for example), but there can only be - * two DescriptorTypeTidy (FINAL and TEMPLINK) and only one GlobalTidy for one single logical sstable. + * one GlobalTidy for one single logical sstable. * - * When the InstanceTidier cleansup, it releases its reference to its DescriptorTypeTidy; when all InstanceTidiers - * for that type have run, the DescriptorTypeTidy cleansup. DescriptorTypeTidy behaves in the same way towards GlobalTidy. + * When the InstanceTidier cleansup, it releases its reference to its GlobalTidy; when all InstanceTidiers + * for that type have run, the GlobalTidy cleans up. * - * For ease, we stash a direct reference to both our type-shared and global tidier + * For ease, we stash a direct reference to our global tidier */ private static final class InstanceTidier implements Tidy { @@ -2084,13 +2088,9 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS private Runnable runOnClose; private boolean isReplaced = false; - // a reference to our shared per-Descriptor.Type tidy instance, that + // a reference to our shared tidy instance, that // we will release when we are ourselves released - private Ref<DescriptorTypeTidy> typeRef; - - // a convenience stashing of the shared per-descriptor-type tidy instance itself - // and the per-logical-sstable globally shared state that it is linked to - private DescriptorTypeTidy type; + private Ref<GlobalTidy> globalRef; private GlobalTidy global; private boolean setup; @@ -2103,9 +2103,8 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS this.dfile = reader.dfile; this.ifile = reader.ifile; // get a new reference to the shared descriptor-type tidy - this.typeRef = DescriptorTypeTidy.get(reader); - this.type = typeRef.get(); - this.global = type.globalRef.get(); + this.globalRef = GlobalTidy.get(reader); + this.global = globalRef.get(); if (!isOffline) global.ensureReadMeter(); } @@ -2148,7 +2147,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS dfile.close(); if (ifile != null) ifile.close(); - typeRef.release(); + globalRef.release(); } }); } @@ -2167,102 +2166,16 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS } /** - * One shared between all instances of a given Descriptor.Type. - * Performs only two things: the deletion of the sstables for the type, - * if necessary; and the shared reference to the globally shared state. + * One instance per logical sstable. This both tracks shared cleanup and some shared state related + * to the sstable's lifecycle. * * All InstanceTidiers, on setup(), ask the static get() method for their shared state, * and stash a reference to it to be released when they are. Once all such references are - * released, the shared tidy will be performed. - */ - static final class DescriptorTypeTidy implements Tidy - { - // keyed by REAL descriptor (TMPLINK/FINAL), mapping to the shared DescriptorTypeTidy for that descriptor - static final ConcurrentMap<Descriptor, Ref<DescriptorTypeTidy>> lookup = new ConcurrentHashMap<>(); - - private final Descriptor desc; - private final Ref<GlobalTidy> globalRef; - private final Set<Component> components; - private long sizeOnDelete; - private Counter totalDiskSpaceUsed; - - DescriptorTypeTidy(Descriptor desc, SSTableReader sstable) - { - this.desc = desc; - // get a new reference to the shared global tidy - this.globalRef = GlobalTidy.get(sstable); - this.components = sstable.components; - } - - void markObsolete(SSTableReader instance, Tracker tracker) - { - // the tracker is used only to notify listeners of deletion of the sstable; - // since deletion of a non-final file is not really deletion of the sstable, - // we don't want to notify the listeners in this event - if (tracker != null && tracker.cfstore != null && desc.type == Descriptor.Type.FINAL) - { - sizeOnDelete = instance.bytesOnDisk(); - totalDiskSpaceUsed = tracker.cfstore.metric.totalDiskSpaceUsed; - tracker.notifyDeleting(instance); - } - } - - public void tidy() - { - lookup.remove(desc); - boolean isCompacted = globalRef.get().isCompacted.get(); - globalRef.release(); - switch (desc.type) - { - case FINAL: - if (isCompacted) - new SSTableDeletingTask(desc, components, totalDiskSpaceUsed, sizeOnDelete).run(); - break; - case TEMPLINK: - new SSTableDeletingTask(desc, components, null, 0).run(); - break; - default: - throw new IllegalStateException(); - } - } - - public String name() - { - return desc.toString(); - } - - // get a new reference to the shared DescriptorTypeTidy for this sstable - @SuppressWarnings("resource") - public static Ref<DescriptorTypeTidy> get(SSTableReader sstable) - { - Descriptor desc = sstable.descriptor; - if (sstable.openReason == OpenReason.EARLY) - desc = desc.asType(Descriptor.Type.TEMPLINK); - Ref<DescriptorTypeTidy> refc = lookup.get(desc); - if (refc != null) - return refc.ref(); - final DescriptorTypeTidy tidy = new DescriptorTypeTidy(desc, sstable); - refc = new Ref<>(tidy, tidy); - Ref<?> ex = lookup.putIfAbsent(desc, refc); - if (ex != null) - { - refc.close(); - throw new AssertionError(); - } - return refc; - } - } - - /** - * One instance per logical sstable. This both tracks shared cleanup and some shared state related - * to the sstable's lifecycle. All DescriptorTypeTidy instances, on construction, obtain a reference to us - * via our static get(). There should only ever be at most two such references extant at any one time, - * since only TMPLINK and FINAL type descriptors should be open as readers. When all files of both - * kinds have been released, this shared tidy will be performed. + * released, this shared tidy will be performed. */ static final class GlobalTidy implements Tidy { - // keyed by FINAL descriptor, mapping to the shared GlobalTidy for that descriptor + // keyed by descriptor, mapping to the shared GlobalTidy for that descriptor static final ConcurrentMap<Descriptor, Ref<GlobalTidy>> lookup = new ConcurrentHashMap<>(); private final Descriptor desc; @@ -2272,14 +2185,12 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS // the scheduled persistence of the readMeter, that we will cancel once all instances of this logical // sstable have been released private ScheduledFuture readMeterSyncFuture; - // shared state managing if the logical sstable has been compacted; this is used in cleanup both here - // and in the FINAL type tidier - private final AtomicBoolean isCompacted; + // shared state managing if the logical sstable has been compacted; this is used in cleanup + private volatile TransactionLogs.SSTableTidier obsoletion; GlobalTidy(final SSTableReader reader) { this.desc = reader.descriptor; - this.isCompacted = new AtomicBoolean(); } void ensureReadMeter() @@ -2302,7 +2213,7 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS { public void run() { - if (!isCompacted.get()) + if (obsoletion == null) { meterSyncThrottle.acquire(); SystemKeyspace.persistSSTableReadMeter(desc.ksname, desc.cfname, desc.generation, readMeter); @@ -2311,13 +2222,22 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS }, 1, 5, TimeUnit.MINUTES); } - public void tidy() + private void stopReadMeterPersistence() { - lookup.remove(desc); if (readMeterSyncFuture != null) + { readMeterSyncFuture.cancel(true); - if (isCompacted.get()) - SystemKeyspace.clearSSTableReadMeter(desc.ksname, desc.cfname, desc.generation); + readMeterSyncFuture = null; + } + } + + public void tidy() + { + lookup.remove(desc); + + if (obsoletion != null) + obsoletion.run(); + // don't ideally want to dropPageCache for the file until all instances have been released CLibrary.trySkipCache(desc.filenameFor(Component.DATA), 0, 0); CLibrary.trySkipCache(desc.filenameFor(Component.PRIMARY_INDEX), 0, 0); @@ -2352,7 +2272,6 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS public static void resetTidying() { GlobalTidy.lookup.clear(); - DescriptorTypeTidy.lookup.clear(); } public static abstract class Factory http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java index 900c948..08a9dcc 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Sets; import org.apache.cassandra.config.CFMetaData; @@ -30,6 +31,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.RowIndexEntry; import org.apache.cassandra.db.SerializationHeader; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.db.rows.UnfilteredRowIterator; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.io.sstable.Component; @@ -68,7 +70,13 @@ public abstract class SSTableWriter extends SSTable implements Transactional protected boolean openResult; } - protected SSTableWriter(Descriptor descriptor, long keyCount, long repairedAt, CFMetaData metadata, IPartitioner partitioner, MetadataCollector metadataCollector, SerializationHeader header) + protected SSTableWriter(Descriptor descriptor, + long keyCount, + long repairedAt, + CFMetaData metadata, + IPartitioner partitioner, + MetadataCollector metadataCollector, + SerializationHeader header) { super(descriptor, components(metadata), metadata, partitioner); this.keyCount = keyCount; @@ -84,21 +92,17 @@ public abstract class SSTableWriter extends SSTable implements Transactional CFMetaData metadata, IPartitioner partitioner, MetadataCollector metadataCollector, - SerializationHeader header) + SerializationHeader header, + LifecycleTransaction txn) { Factory writerFactory = descriptor.getFormat().getWriterFactory(); - return writerFactory.open(descriptor, keyCount, repairedAt, metadata, partitioner, metadataCollector, header); + return writerFactory.open(descriptor, keyCount, repairedAt, metadata, partitioner, metadataCollector, header, txn); } - public static SSTableWriter create(Descriptor descriptor, long keyCount, long repairedAt, SerializationHeader header) - { - return create(descriptor, keyCount, repairedAt, 0, header); - } - - public static SSTableWriter create(Descriptor descriptor, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header) + public static SSTableWriter create(Descriptor descriptor, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header, LifecycleTransaction txn) { CFMetaData metadata = Schema.instance.getCFMetaData(descriptor); - return create(metadata, descriptor, keyCount, repairedAt, sstableLevel, DatabaseDescriptor.getPartitioner(), header); + return create(metadata, descriptor, keyCount, repairedAt, sstableLevel, DatabaseDescriptor.getPartitioner(), header, txn); } public static SSTableWriter create(CFMetaData metadata, @@ -107,20 +111,22 @@ public abstract class SSTableWriter extends SSTable implements Transactional long repairedAt, int sstableLevel, IPartitioner partitioner, - SerializationHeader header) + SerializationHeader header, + LifecycleTransaction txn) { MetadataCollector collector = new MetadataCollector(metadata.comparator).sstableLevel(sstableLevel); - return create(descriptor, keyCount, repairedAt, metadata, partitioner, collector, header); + return create(descriptor, keyCount, repairedAt, metadata, partitioner, collector, header, txn); } - public static SSTableWriter create(String filename, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header) + public static SSTableWriter create(String filename, long keyCount, long repairedAt, int sstableLevel, SerializationHeader header,LifecycleTransaction txn) { - return create(Descriptor.fromFilename(filename), keyCount, repairedAt, sstableLevel, header); + return create(Descriptor.fromFilename(filename), keyCount, repairedAt, sstableLevel, header, txn); } - public static SSTableWriter create(String filename, long keyCount, long repairedAt, SerializationHeader header) + @VisibleForTesting + public static SSTableWriter create(String filename, long keyCount, long repairedAt, SerializationHeader header, LifecycleTransaction txn) { - return create(Descriptor.fromFilename(filename), keyCount, repairedAt, 0, header); + return create(Descriptor.fromFilename(filename), keyCount, repairedAt, 0, header, txn); } private static Set<Component> components(CFMetaData metadata) @@ -207,7 +213,7 @@ public abstract class SSTableWriter extends SSTable implements Transactional public SSTableReader finish(boolean openResult) { - txnProxy.openResult = openResult; + setOpenResult(openResult); txnProxy.finish(); return finished(); } @@ -260,13 +266,6 @@ public abstract class SSTableWriter extends SSTable implements Transactional return (StatsMetadata) finalizeMetadata().get(MetadataType.STATS); } - public static Descriptor rename(Descriptor tmpdesc, Set<Component> components) - { - Descriptor newdesc = tmpdesc.asType(Descriptor.Type.FINAL); - rename(tmpdesc, newdesc, components); - return newdesc; - } - public static void rename(Descriptor tmpdesc, Descriptor newdesc, Set<Component> components) { for (Component component : Sets.difference(components, Sets.newHashSet(Component.DATA, Component.SUMMARY))) @@ -290,6 +289,7 @@ public abstract class SSTableWriter extends SSTable implements Transactional CFMetaData metadata, IPartitioner partitioner, MetadataCollector metadataCollector, - SerializationHeader header); + SerializationHeader header, + LifecycleTransaction txn); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java b/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java index a5419f1..a072d4d 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java +++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java @@ -22,6 +22,7 @@ import java.util.Set; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.db.RowIndexEntry; import org.apache.cassandra.db.SerializationHeader; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.io.sstable.Component; import org.apache.cassandra.io.sstable.Descriptor; @@ -81,9 +82,16 @@ public class BigFormat implements SSTableFormat static class WriterFactory extends SSTableWriter.Factory { @Override - public SSTableWriter open(Descriptor descriptor, long keyCount, long repairedAt, CFMetaData metadata, IPartitioner partitioner, MetadataCollector metadataCollector, SerializationHeader header) + public SSTableWriter open(Descriptor descriptor, + long keyCount, + long repairedAt, + CFMetaData metadata, + IPartitioner partitioner, + MetadataCollector metadataCollector, + SerializationHeader header, + LifecycleTransaction txn) { - return new BigTableWriter(descriptor, keyCount, repairedAt, metadata, partitioner, metadataCollector, header); + return new BigTableWriter(descriptor, keyCount, repairedAt, metadata, partitioner, metadataCollector, header, txn); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/format/big/BigTableWriter.java ---------------------------------------------------------------------- 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 6759293..13c9954 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 @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; import org.apache.cassandra.db.*; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.io.sstable.*; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableWriter; @@ -45,7 +46,6 @@ import org.apache.cassandra.utils.FilterFactory; import org.apache.cassandra.utils.IFilter; import org.apache.cassandra.utils.concurrent.Transactional; -import static org.apache.cassandra.utils.Throwables.merge; import org.apache.cassandra.utils.SyncUtil; public class BigTableWriter extends SSTableWriter @@ -58,9 +58,17 @@ public class BigTableWriter extends SSTableWriter private DecoratedKey lastWrittenKey; private FileMark dataMark; - public BigTableWriter(Descriptor descriptor, Long keyCount, Long repairedAt, CFMetaData metadata, IPartitioner partitioner, MetadataCollector metadataCollector, SerializationHeader header) + public BigTableWriter(Descriptor descriptor, + Long keyCount, + Long repairedAt, + CFMetaData metadata, + IPartitioner partitioner, + MetadataCollector metadataCollector, + SerializationHeader header, + LifecycleTransaction txn) { super(descriptor, keyCount, repairedAt, metadata, partitioner, metadataCollector, header); + txn.trackNew(this); // must track before any files are created if (compression) { @@ -76,6 +84,10 @@ public class BigTableWriter extends SSTableWriter dbuilder = SegmentedFile.getBuilder(DatabaseDescriptor.getDiskAccessMode(), false); } iwriter = new IndexWriter(keyCount, dataFile); + + // txnLogs will delete if safe to do so (early readers) + iwriter.indexFile.deleteFile(false); + dataFile.deleteFile(false); } public void mark() @@ -220,18 +232,6 @@ public class BigTableWriter extends SSTableWriter } } - private Descriptor makeTmpLinks() - { - // create temp links if they don't already exist - Descriptor link = descriptor.asType(Descriptor.Type.TEMPLINK); - if (!new File(link.filenameFor(Component.PRIMARY_INDEX)).exists()) - { - FileUtils.createHardLink(new File(descriptor.filenameFor(Component.PRIMARY_INDEX)), new File(link.filenameFor(Component.PRIMARY_INDEX))); - FileUtils.createHardLink(new File(descriptor.filenameFor(Component.DATA)), new File(link.filenameFor(Component.DATA))); - } - return link; - } - @SuppressWarnings("resource") public SSTableReader openEarly() { @@ -242,11 +242,10 @@ public class BigTableWriter extends SSTableWriter StatsMetadata stats = statsMetadata(); assert boundary.indexLength > 0 && boundary.dataLength > 0; - Descriptor link = makeTmpLinks(); - // open the reader early, giving it a FINAL descriptor type so that it is indistinguishable for other consumers - SegmentedFile ifile = iwriter.builder.complete(link.filenameFor(Component.PRIMARY_INDEX), boundary.indexLength); - SegmentedFile dfile = dbuilder.complete(link.filenameFor(Component.DATA), boundary.dataLength); - SSTableReader sstable = SSTableReader.internalOpen(descriptor.asType(Descriptor.Type.FINAL), + // open the reader early + SegmentedFile ifile = iwriter.builder.complete(descriptor.filenameFor(Component.PRIMARY_INDEX), boundary.indexLength); + SegmentedFile dfile = dbuilder.complete(descriptor.filenameFor(Component.DATA), boundary.dataLength); + SSTableReader sstable = SSTableReader.internalOpen(descriptor, components, metadata, partitioner, ifile, dfile, iwriter.summary.build(partitioner, boundary), @@ -263,7 +262,8 @@ public class BigTableWriter extends SSTableWriter // we must ensure the data is completely flushed to disk dataFile.sync(); iwriter.indexFile.sync(); - return openFinal(makeTmpLinks(), SSTableReader.OpenReason.EARLY); + + return openFinal(descriptor, SSTableReader.OpenReason.EARLY); } @SuppressWarnings("resource") @@ -276,7 +276,7 @@ public class BigTableWriter extends SSTableWriter // finalize in-memory state for the reader SegmentedFile ifile = iwriter.builder.complete(desc.filenameFor(Component.PRIMARY_INDEX)); SegmentedFile dfile = dbuilder.complete(desc.filenameFor(Component.DATA)); - SSTableReader sstable = SSTableReader.internalOpen(desc.asType(Descriptor.Type.FINAL), + SSTableReader sstable = SSTableReader.internalOpen(desc, components, this.metadata, partitioner, @@ -314,11 +314,8 @@ public class BigTableWriter extends SSTableWriter // save the table of components SSTable.appendTOC(descriptor, components); - // rename to final - rename(descriptor, components); - if (openResult) - finalReader = openFinal(descriptor.asType(Descriptor.Type.FINAL), SSTableReader.OpenReason.NORMAL); + finalReader = openFinal(descriptor, SSTableReader.OpenReason.NORMAL); } protected Throwable doCommit(Throwable accumulate) @@ -339,26 +336,6 @@ public class BigTableWriter extends SSTableWriter { accumulate = iwriter.abort(accumulate); accumulate = dataFile.abort(accumulate); - - accumulate = delete(descriptor, accumulate); - if (!openResult) - accumulate = delete(descriptor.asType(Descriptor.Type.FINAL), accumulate); - return accumulate; - } - - private Throwable delete(Descriptor desc, Throwable accumulate) - { - try - { - Set<Component> components = SSTable.discoverComponentsFor(desc); - if (!components.isEmpty()) - SSTable.delete(desc, components); - } - catch (Throwable t) - { - logger.error(String.format("Failed deleting temp components for %s", descriptor), t); - accumulate = merge(accumulate, t); - } return accumulate; } } @@ -366,7 +343,7 @@ public class BigTableWriter extends SSTableWriter private static void writeMetadata(Descriptor desc, Map<MetadataType, MetadataComponent> components) { File file = new File(desc.filenameFor(Component.STATS)); - try (SequentialWriter out = SequentialWriter.open(file);) + try (SequentialWriter out = SequentialWriter.open(file)) { desc.getMetadataSerializer().serialize(components, out.stream); out.setDescriptor(desc).finish(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/sstable/metadata/MetadataSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/metadata/MetadataSerializer.java b/src/java/org/apache/cassandra/io/sstable/metadata/MetadataSerializer.java index fcdf57a..9a5eae8 100644 --- a/src/java/org/apache/cassandra/io/sstable/metadata/MetadataSerializer.java +++ b/src/java/org/apache/cassandra/io/sstable/metadata/MetadataSerializer.java @@ -149,9 +149,8 @@ public class MetadataSerializer implements IMetadataSerializer private void rewriteSSTableMetadata(Descriptor descriptor, Map<MetadataType, MetadataComponent> currentComponents) throws IOException { - Descriptor tmpDescriptor = descriptor.asType(Descriptor.Type.TEMP); - - try (DataOutputStreamPlus out = new BufferedDataOutputStreamPlus(new FileOutputStream(tmpDescriptor.filenameFor(Component.STATS)))) + String filePath = descriptor.tmpFilenameFor(Component.STATS); + try (DataOutputStreamPlus out = new BufferedDataOutputStreamPlus(new FileOutputStream(filePath))) { serialize(currentComponents, out); out.flush(); @@ -159,7 +158,7 @@ public class MetadataSerializer implements IMetadataSerializer // we cant move a file on top of another file in windows: if (FBUtilities.isWindows()) FileUtils.delete(descriptor.filenameFor(Component.STATS)); - FileUtils.renameWithConfirm(tmpDescriptor.filenameFor(Component.STATS), descriptor.filenameFor(Component.STATS)); + FileUtils.renameWithConfirm(filePath, descriptor.filenameFor(Component.STATS)); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/util/FileUtils.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java index 480ecea..f415f2b 100644 --- a/src/java/org/apache/cassandra/io/util/FileUtils.java +++ b/src/java/org/apache/cassandra/io/util/FileUtils.java @@ -20,9 +20,11 @@ package org.apache.cassandra.io.util; import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.charset.Charset; import java.nio.file.*; import java.text.DecimalFormat; import java.util.Arrays; +import java.util.List; import org.apache.cassandra.config.Config; import sun.nio.ch.DirectBuffer; @@ -306,6 +308,29 @@ public class FileUtils } } + /** Return true if file is contained in folder */ + public static boolean isContained(File folder, File file) + { + String folderPath = getCanonicalPath(folder); + String filePath = getCanonicalPath(file); + + return filePath.startsWith(folderPath); + } + + /** Convert absolute path into a path relative to the base path */ + public static String getRelativePath(String basePath, String absolutePath) + { + try + { + return Paths.get(basePath).relativize(Paths.get(absolutePath)).toString(); + } + catch(Exception ex) + { + String absDataPath = FileUtils.getCanonicalPath(basePath); + return Paths.get(absDataPath).relativize(Paths.get(absolutePath)).toString(); + } + } + public static boolean isCleanerAvailable() { return canCleanDirectBuffers; @@ -555,4 +580,44 @@ public class FileUtils } return false; } + + public static void append(File file, String ... lines) + { + if (file.exists()) + write(file, StandardOpenOption.APPEND, lines); + else + write(file, StandardOpenOption.CREATE, lines); + } + + public static void replace(File file, String ... lines) + { + write(file, StandardOpenOption.TRUNCATE_EXISTING, lines); + } + + public static void write(File file, StandardOpenOption op, String ... lines) + { + try + { + Files.write(file.toPath(), + Arrays.asList(lines), + Charset.forName("utf-8"), + op); + } + catch (IOException ex) + { + throw new RuntimeException(ex); + } + } + + public static List<String> readLines(File file) + { + try + { + return Files.readAllLines(file.toPath(), Charset.forName("utf-8")); + } + catch (IOException ex) + { + throw new RuntimeException(ex); + } + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/io/util/SequentialWriter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/util/SequentialWriter.java b/src/java/org/apache/cassandra/io/util/SequentialWriter.java index ee6e5b4..90340ca 100644 --- a/src/java/org/apache/cassandra/io/util/SequentialWriter.java +++ b/src/java/org/apache/cassandra/io/util/SequentialWriter.java @@ -79,6 +79,8 @@ public class SequentialWriter extends OutputStream implements WritableByteChanne // due to lack of multiple-inheritance, we proxy our transactional implementation protected class TransactionalProxy extends AbstractTransactional { + private boolean deleteFile = true; + @Override protected Throwable doPreCleanup(Throwable accumulate) { @@ -118,7 +120,10 @@ public class SequentialWriter extends OutputStream implements WritableByteChanne protected Throwable doAbort(Throwable accumulate) { - return FileUtils.deleteWithConfirm(filePath, false, accumulate); + if (deleteFile) + return FileUtils.deleteWithConfirm(filePath, false, accumulate); + else + return accumulate; } } @@ -487,6 +492,11 @@ public class SequentialWriter extends OutputStream implements WritableByteChanne return new TransactionalProxy(); } + public void deleteFile(boolean val) + { + txnProxy.deleteFile = val; + } + public void releaseFileHandle() { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/service/CassandraDaemon.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index 8dadb91..548cbc7 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -169,7 +169,10 @@ public class CassandraDaemon try { - SystemKeyspace.snapshotOnVersionChange(); + if (SystemKeyspace.snapshotOnVersionChange()) + { + SystemKeyspace.migrateDataDirs(); + } } catch (IOException e) { @@ -218,17 +221,6 @@ public class CassandraDaemon // load schema from disk Schema.instance.loadFromDisk(); - // clean up compaction leftovers - Map<Pair<String, String>, Map<Integer, UUID>> unfinishedCompactions = SystemKeyspace.getUnfinishedCompactions(); - for (Pair<String, String> kscf : unfinishedCompactions.keySet()) - { - CFMetaData cfm = Schema.instance.getCFMetaData(kscf.left, kscf.right); - // CFMetaData can be null if CF is already dropped - if (cfm != null) - ColumnFamilyStore.removeUnfinishedCompactionLeftovers(cfm, unfinishedCompactions.get(kscf)); - } - SystemKeyspace.discardCompactionsInProgress(); - // clean up debris in the rest of the keyspaces for (String keyspaceName : Schema.instance.getKeyspaces()) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/service/GCInspector.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/GCInspector.java b/src/java/org/apache/cassandra/service/GCInspector.java index 4e03a49..fc7ff3d 100644 --- a/src/java/org/apache/cassandra/service/GCInspector.java +++ b/src/java/org/apache/cassandra/service/GCInspector.java @@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory; import com.sun.management.GarbageCollectionNotificationInfo; import com.sun.management.GcInfo; -import org.apache.cassandra.io.sstable.SSTableDeletingTask; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.utils.StatusLogger; public class GCInspector implements NotificationListener, GCInspectorMXBean @@ -193,10 +193,10 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean } /* - * Assume that a GC type is an old generation collection so SSTableDeletingTask.rescheduleFailedTasks() + * Assume that a GC type is an old generation collection so TransactionLogs.rescheduleFailedTasks() * should be invoked. * - * Defaults to not invoking SSTableDeletingTask.rescheduleFailedTasks() on unrecognized GC names + * Defaults to not invoking TransactionLogs.rescheduleFailedTasks() on unrecognized GC names */ private static boolean assumeGCIsOldGen(GarbageCollectorMXBean gc) { @@ -214,7 +214,7 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean return true; default: //Assume not old gen otherwise, don't call - //SSTableDeletingTask.rescheduleFailedTasks() + //TransactionLogs.rescheduleFailedTasks() return false; } } @@ -284,7 +284,7 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean // if we just finished an old gen collection and we're still using a lot of memory, try to reduce the pressure if (gcState.assumeGCIsOldGen) - SSTableDeletingTask.rescheduleFailedTasks(); + TransactionLogs.rescheduleFailedDeletions(); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/service/StartupChecks.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StartupChecks.java b/src/java/org/apache/cassandra/service/StartupChecks.java index 700fd1a..fee9789 100644 --- a/src/java/org/apache/cassandra/service/StartupChecks.java +++ b/src/java/org/apache/cassandra/service/StartupChecks.java @@ -218,7 +218,7 @@ public class StartupChecks { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (!file.toString().endsWith(".db")) + if (!Descriptor.isValidFile(file.getFileName().toString())) return FileVisitResult.CONTINUE; try @@ -236,7 +236,9 @@ public class StartupChecks public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { String name = dir.getFileName().toString(); - return (name.equals("snapshots") || name.equals("backups")) + return (name.equals(Directories.SNAPSHOT_SUBDIR) + || name.equals(Directories.BACKUPS_SUBDIR) + || name.equals(Directories.TRANSACTIONS_SUBDIR)) ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 2d434cb..da53bf7 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -70,6 +70,7 @@ import org.apache.cassandra.config.*; import org.apache.cassandra.db.*; import org.apache.cassandra.db.commitlog.CommitLog; import org.apache.cassandra.db.compaction.CompactionManager; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.dht.BootStrapper; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Range; @@ -93,7 +94,6 @@ import org.apache.cassandra.gms.IEndpointStateChangeSubscriber; import org.apache.cassandra.gms.IFailureDetector; import org.apache.cassandra.gms.TokenSerializer; import org.apache.cassandra.gms.VersionedValue; -import org.apache.cassandra.io.sstable.SSTableDeletingTask; import org.apache.cassandra.io.sstable.SSTableLoader; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.locator.AbstractReplicationStrategy; @@ -4216,7 +4216,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE public void rescheduleFailedDeletions() { - SSTableDeletingTask.rescheduleFailedTasks(); + TransactionLogs.rescheduleFailedDeletions(); } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/streaming/StreamLockfile.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/streaming/StreamLockfile.java b/src/java/org/apache/cassandra/streaming/StreamLockfile.java deleted file mode 100644 index 83ae5f0..0000000 --- a/src/java/org/apache/cassandra/streaming/StreamLockfile.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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.streaming; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import com.google.common.base.Charsets; -import org.apache.cassandra.io.sstable.format.SSTableWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.cassandra.io.sstable.Descriptor; -import org.apache.cassandra.io.sstable.SSTable; -import org.apache.cassandra.io.util.FileUtils; -import org.apache.cassandra.utils.JVMStabilityInspector; - -/** - * Encapsulates the behavior for 'locking' any streamed sttables to a node. - * If a process crashes while converting a set of SSTableWriters to SSTReaders - * (meaning, some subset of SSTWs were converted, but not the entire set), we want - * to disregard the entire set as we will surely have missing data (by definition). - * - * Basic behavior id to write out the names of all SSTWs to a file, one SSTW per line, - * and then delete the file when complete (normal behavior). This should happen before - * converting any SSTWs. Thus, the lockfile is created, some SSTWs are converted, - * and if the process crashes, on restart, we look for any existing lockfile, and delete - * any referenced SSTRs. - */ -public class StreamLockfile -{ - public static final String FILE_EXT = ".lockfile"; - private static final Logger logger = LoggerFactory.getLogger(StreamLockfile.class); - - private final File lockfile; - - public StreamLockfile(File directory, UUID uuid) - { - lockfile = new File(directory, uuid + FILE_EXT); - } - - public StreamLockfile(File lockfile) - { - assert lockfile != null; - this.lockfile = lockfile; - } - - public void create(Collection<SSTableWriter> sstables) - { - List<String> sstablePaths = new ArrayList<>(sstables.size()); - for (SSTableWriter writer : sstables) - { - /* write out the file names *without* the 'tmp-file' flag in the file name. - this class will not need to clean up tmp files (on restart), CassandraDaemon does that already, - just make sure we delete the fully-formed SSTRs. */ - sstablePaths.add(writer.descriptor.asType(Descriptor.Type.FINAL).baseFilename()); - } - - try - { - Files.write(lockfile.toPath(), sstablePaths, Charsets.UTF_8, - StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, StandardOpenOption.DSYNC); - } - catch (IOException e) - { - logger.warn(String.format("Could not create lockfile %s for stream session, nothing to worry too much about", lockfile), e); - } - } - - public void delete() - { - FileUtils.delete(lockfile); - } - - public void cleanup() - { - List<String> files = readLockfile(lockfile); - for (String file : files) - { - try - { - Descriptor desc = Descriptor.fromFilename(file, true); - SSTable.delete(desc, SSTable.componentsFor(desc)); - } - catch (Exception e) - { - JVMStabilityInspector.inspectThrowable(e); - logger.warn("failed to delete a potentially stale sstable {}", file); - } - } - } - - private List<String> readLockfile(File lockfile) - { - try - { - return Files.readAllLines(lockfile.toPath(), Charsets.UTF_8); - } - catch (IOException e) - { - logger.info("couldn't read lockfile {}, ignoring", lockfile.getAbsolutePath()); - return Collections.emptyList(); - } - } - -} http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/streaming/StreamReader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/streaming/StreamReader.java b/src/java/org/apache/cassandra/streaming/StreamReader.java index 132a095..61656b3 100644 --- a/src/java/org/apache/cassandra/streaming/StreamReader.java +++ b/src/java/org/apache/cassandra/streaming/StreamReader.java @@ -129,9 +129,9 @@ public class StreamReader Directories.DataDirectory localDir = cfs.directories.getWriteableLocation(totalSize); if (localDir == null) throw new IOException("Insufficient disk space to store " + totalSize + " bytes"); - desc = Descriptor.fromFilename(cfs.getTempSSTablePath(cfs.directories.getLocationForDisk(localDir), format)); + desc = Descriptor.fromFilename(cfs.getSSTablePath(cfs.directories.getLocationForDisk(localDir), format)); - return SSTableWriter.create(desc, estimatedKeys, repairedAt, sstableLevel, header.toHeader(cfs.metadata)); + return SSTableWriter.create(desc, estimatedKeys, repairedAt, sstableLevel, header.toHeader(cfs.metadata), session.getTransaction(cfId)); } protected void drain(InputStream dis, long bytesRead) throws IOException http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/streaming/StreamReceiveTask.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/streaming/StreamReceiveTask.java b/src/java/org/apache/cassandra/streaming/StreamReceiveTask.java index d4d49b3..b7db989 100644 --- a/src/java/org/apache/cassandra/streaming/StreamReceiveTask.java +++ b/src/java/org/apache/cassandra/streaming/StreamReceiveTask.java @@ -17,9 +17,6 @@ */ package org.apache.cassandra.streaming; -import java.io.File; -import java.io.IOError; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -31,6 +28,8 @@ import org.apache.cassandra.concurrent.NamedThreadFactory; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; +import org.apache.cassandra.db.compaction.OperationType; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.utils.Pair; @@ -49,6 +48,9 @@ public class StreamReceiveTask extends StreamTask // total size of files to receive private final long totalSize; + // Transaction tracking new files received + public final LifecycleTransaction txn; + // true if task is done (either completed or aborted) private boolean done = false; @@ -60,6 +62,9 @@ public class StreamReceiveTask extends StreamTask super(session, cfId); this.totalFiles = totalFiles; this.totalSize = totalSize; + // this is an "offline" transaction, as we currently manually expose the sstables once done; + // this should be revisited at a later date, so that LifecycleTransaction manages all sstable state changes + this.txn = LifecycleTransaction.offline(OperationType.STREAM, Schema.instance.getCFMetaData(cfId)); this.sstables = new ArrayList<>(totalFiles); } @@ -111,19 +116,15 @@ public class StreamReceiveTask extends StreamTask for (SSTableWriter writer : task.sstables) writer.abort(); task.sstables.clear(); + task.txn.abort(); return; } ColumnFamilyStore cfs = Keyspace.open(kscf.left).getColumnFamilyStore(kscf.right); - File lockfiledir = cfs.directories.getWriteableLocationAsFile(task.sstables.size() * 256L); - if (lockfiledir == null) - throw new IOError(new IOException("All disks full")); - StreamLockfile lockfile = new StreamLockfile(lockfiledir, UUID.randomUUID()); - lockfile.create(task.sstables); List<SSTableReader> readers = new ArrayList<>(); for (SSTableWriter writer : task.sstables) readers.add(writer.finish(true)); - lockfile.delete(); + task.txn.finish(); task.sstables.clear(); try (Refs<SSTableReader> refs = Refs.ref(readers)) @@ -151,6 +152,7 @@ public class StreamReceiveTask extends StreamTask done = true; for (SSTableWriter writer : sstables) writer.abort(); + txn.abort(); sstables.clear(); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/streaming/StreamSession.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/streaming/StreamSession.java b/src/java/org/apache/cassandra/streaming/StreamSession.java index c9ebdad..744a03a 100644 --- a/src/java/org/apache/cassandra/streaming/StreamSession.java +++ b/src/java/org/apache/cassandra/streaming/StreamSession.java @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import com.google.common.base.Function; import com.google.common.collect.*; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.db.lifecycle.View; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.slf4j.Logger; @@ -208,6 +209,12 @@ public class StreamSession implements IEndpointStateChangeSubscriber } + public LifecycleTransaction getTransaction(UUID cfId) + { + assert receivers.containsKey(cfId); + return receivers.get(cfId).txn; + } + /** * Bind this session to report to specific {@link StreamResultFuture} and * perform pre-streaming initialization. http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/tools/StandaloneLister.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/StandaloneLister.java b/src/java/org/apache/cassandra/tools/StandaloneLister.java new file mode 100644 index 0000000..71575c7 --- /dev/null +++ b/src/java/org/apache/cassandra/tools/StandaloneLister.java @@ -0,0 +1,214 @@ +/** + * 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.tools; + +import org.apache.cassandra.config.CFMetaData; +import org.apache.cassandra.config.Schema; +import org.apache.cassandra.db.Directories; +import org.apache.cassandra.db.lifecycle.LifecycleTransaction; +import org.apache.cassandra.utils.OutputHandler; +import org.apache.commons.cli.*; + +import java.io.File; + +import static org.apache.cassandra.tools.BulkLoader.CmdLineOptions; + +public class StandaloneLister +{ + private static final String TOOL_NAME = "sstablelister"; + private static final String TYPE_OPTION = "type"; + private static final String OP_LOG_OPTION = "oplog"; + private static final String VERBOSE_OPTION = "verbose"; + private static final String DEBUG_OPTION = "debug"; + private static final String HELP_OPTION = "help"; + + public static void main(String args[]) + { + Options options = Options.parseArgs(args); + try + { + // load keyspace descriptions. + Schema.instance.loadFromDisk(false); + + CFMetaData metadata = Schema.instance.getCFMetaData(options.keyspaceName, options.cfName); + if (metadata == null) + throw new IllegalArgumentException(String.format("Unknown keyspace/table %s.%s", + options.keyspaceName, + options.cfName)); + + OutputHandler handler = new OutputHandler.SystemOutput(options.verbose, options.debug); + + Directories directories = new Directories(metadata); + Directories.SSTableLister lister = directories.sstableLister(); + + if (options.type == Options.FileType.FINAL) + lister.skipTemporary(true); + else if (options.type == Options.FileType.TMP) + lister.onlyTemporary(true); + + for (File file : lister.listFiles()) + handler.output(file.getCanonicalPath()); + + if (options.oplogs) + { + for (File file : LifecycleTransaction.getLogFiles(metadata)) + { + handler.output(file.getCanonicalPath()); + } + } + + System.exit(0); + } + catch (Exception e) + { + System.err.println(e.getMessage()); + if (options.debug) + e.printStackTrace(System.err); + System.exit(1); + } + } + + private static class Options + { + public enum FileType + { + ALL("all", "list all files, final or temporary"), + TMP("tmp", "list temporary files only"), + FINAL("final", "list final files only"); + + public String option; + public String descr; + FileType(String option, String descr) + { + this.option = option; + this.descr = descr; + } + + static FileType fromOption(String option) + { + for (FileType fileType : FileType.values()) + { + if (fileType.option.equals(option)) + return fileType; + } + + return FileType.ALL; + } + + static String descr() + { + StringBuilder str = new StringBuilder(); + for (FileType fileType : FileType.values()) + { + str.append(fileType.option); + str.append(" ("); + str.append(fileType.descr); + str.append("), "); + } + return str.toString(); + } + } + + public final String keyspaceName; + public final String cfName; + + public boolean debug; + public boolean verbose; + public boolean oplogs; + public FileType type; + + private Options(String keyspaceName, String cfName) + { + this.keyspaceName = keyspaceName; + this.cfName = cfName; + } + + public static Options parseArgs(String cmdArgs[]) + { + CommandLineParser parser = new GnuParser(); + CmdLineOptions options = getCmdLineOptions(); + try + { + CommandLine cmd = parser.parse(options, cmdArgs, false); + + if (cmd.hasOption(HELP_OPTION)) + { + printUsage(options); + System.exit(0); + } + + String[] args = cmd.getArgs(); + if (args.length != 2) + { + String msg = args.length < 2 ? "Missing arguments" : "Too many arguments"; + System.err.println(msg); + printUsage(options); + System.exit(1); + } + + String keyspaceName = args[0]; + String cfName = args[1]; + + Options opts = new Options(keyspaceName, cfName); + + opts.debug = cmd.hasOption(DEBUG_OPTION); + opts.verbose = cmd.hasOption(VERBOSE_OPTION); + opts.type = FileType.fromOption(cmd.getOptionValue(TYPE_OPTION)); + opts.oplogs = cmd.hasOption(OP_LOG_OPTION); + + return opts; + } + catch (ParseException e) + { + errorMsg(e.getMessage(), options); + return null; + } + } + + private static void errorMsg(String msg, CmdLineOptions options) + { + System.err.println(msg); + printUsage(options); + System.exit(1); + } + + private static CmdLineOptions getCmdLineOptions() + { + CmdLineOptions options = new CmdLineOptions(); + options.addOption("d", DEBUG_OPTION, "display stack traces"); + options.addOption("h", HELP_OPTION, "display this help message"); + options.addOption("o", OP_LOG_OPTION, "include operation logs"); + options.addOption("t", TYPE_OPTION, true, FileType.descr()); + options.addOption("v", VERBOSE_OPTION, "verbose output"); + + return options; + } + + public static void printUsage(CmdLineOptions options) + { + String usage = String.format("%s [options] <keyspace> <column_family>", TOOL_NAME); + StringBuilder header = new StringBuilder(); + header.append("--\n"); + header.append("List sstable files for the provided table." ); + header.append("\n--\n"); + header.append("Options are:"); + new HelpFormatter().printHelp(usage, header.toString(), options, ""); + } + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/tools/StandaloneScrubber.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/StandaloneScrubber.java b/src/java/org/apache/cassandra/tools/StandaloneScrubber.java index be73cf7..c00d036 100644 --- a/src/java/org/apache/cassandra/tools/StandaloneScrubber.java +++ b/src/java/org/apache/cassandra/tools/StandaloneScrubber.java @@ -34,6 +34,7 @@ import org.apache.cassandra.db.Directories; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.compaction.*; import org.apache.cassandra.db.lifecycle.LifecycleTransaction; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.*; import org.apache.cassandra.utils.JVMStabilityInspector; @@ -120,7 +121,7 @@ public class StandaloneScrubber try (LifecycleTransaction txn = LifecycleTransaction.offline(OperationType.SCRUB, sstable)) { txn.obsoleteOriginals(); // make sure originals are deleted and avoid NPE if index is missing, CASSANDRA-9591 - try (Scrubber scrubber = new Scrubber(cfs, txn, options.skipCorrupted, handler, true, !options.noValidate)) + try (Scrubber scrubber = new Scrubber(cfs, txn, options.skipCorrupted, handler, true, !options.noValidate, false)) { scrubber.scrub(); } @@ -144,7 +145,7 @@ public class StandaloneScrubber // Check (and repair) manifests checkManifest(cfs.getCompactionStrategyManager(), cfs, sstables); CompactionManager.instance.finishCompactionsAndShutdown(5, TimeUnit.MINUTES); - SSTableDeletingTask.waitForDeletions(); + TransactionLogs.waitForDeletions(); System.exit(0); // We need that to stop non daemonized threads } catch (Exception e) http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/tools/StandaloneSplitter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/StandaloneSplitter.java b/src/java/org/apache/cassandra/tools/StandaloneSplitter.java index 4545ab6..5a0c43f 100644 --- a/src/java/org/apache/cassandra/tools/StandaloneSplitter.java +++ b/src/java/org/apache/cassandra/tools/StandaloneSplitter.java @@ -23,6 +23,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import org.apache.cassandra.config.Schema; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.commons.cli.*; @@ -154,8 +155,7 @@ public class StandaloneSplitter new SSTableSplitter(cfs, transaction, options.sizeInMB).split(); // Remove the sstable (it's been copied by split and snapshotted) - sstable.markObsolete(null); - sstable.selfRef().release(); + transaction.obsoleteOriginals(); } catch (Exception e) { @@ -163,9 +163,13 @@ public class StandaloneSplitter if (options.debug) e.printStackTrace(System.err); } + finally + { + sstable.selfRef().release(); + } } CompactionManager.instance.finishCompactionsAndShutdown(5, TimeUnit.MINUTES); - SSTableDeletingTask.waitForDeletions(); + TransactionLogs.waitForDeletions(); System.exit(0); // We need that to stop non daemonized threads } catch (Exception e) http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/tools/StandaloneUpgrader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/StandaloneUpgrader.java b/src/java/org/apache/cassandra/tools/StandaloneUpgrader.java index c5dfba0..0851d5b 100644 --- a/src/java/org/apache/cassandra/tools/StandaloneUpgrader.java +++ b/src/java/org/apache/cassandra/tools/StandaloneUpgrader.java @@ -20,6 +20,7 @@ package org.apache.cassandra.tools; import java.util.*; import java.util.concurrent.TimeUnit; +import org.apache.cassandra.db.lifecycle.TransactionLogs; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.commons.cli.*; @@ -103,15 +104,7 @@ public class StandaloneUpgrader try (LifecycleTransaction txn = LifecycleTransaction.offline(OperationType.UPGRADE_SSTABLES, sstable)) { Upgrader upgrader = new Upgrader(cfs, txn, handler); - upgrader.upgrade(); - - if (!options.keepSource) - { - // Remove the sstable (it's been copied by upgrade) - System.out.format("Deleting table %s.%n", sstable.descriptor.baseFilename()); - sstable.markObsolete(null); - sstable.selfRef().release(); - } + upgrader.upgrade(options.keepSource); } catch (Exception e) { @@ -119,9 +112,15 @@ public class StandaloneUpgrader if (options.debug) e.printStackTrace(System.err); } + finally + { + // we should have released this through commit of the LifecycleTransaction, + // but in case the upgrade failed (or something else went wrong) make sure we don't retain a reference + sstable.selfRef().ensureReleased(); + } } CompactionManager.instance.finishCompactionsAndShutdown(5, TimeUnit.MINUTES); - SSTableDeletingTask.waitForDeletions(); + TransactionLogs.waitForDeletions(); System.exit(0); } catch (Exception e) http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/src/java/org/apache/cassandra/utils/concurrent/Transactional.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/utils/concurrent/Transactional.java b/src/java/org/apache/cassandra/utils/concurrent/Transactional.java index 5b0eb8e..f79a795 100644 --- a/src/java/org/apache/cassandra/utils/concurrent/Transactional.java +++ b/src/java/org/apache/cassandra/utils/concurrent/Transactional.java @@ -18,10 +18,6 @@ */ package org.apache.cassandra.utils.concurrent; -import java.util.Set; - -import com.google.common.collect.ImmutableSet; - import static org.apache.cassandra.utils.Throwables.maybeFail; import static org.apache.cassandra.utils.Throwables.merge; @@ -45,14 +41,17 @@ import static org.apache.cassandra.utils.Throwables.merge; * If everything completes normally, then on exiting the try block the auto close method will invoke cleanup * to release any temporary state/resources * - * No exceptions should be thrown during commit; if they are, it is not at all clear what the correct behaviour + * All exceptions and assertions that may be thrown should be checked and ruled out during commit preparation. + * Commit should generally never throw an exception unless there is a real correctness-affecting exception that + * cannot be moved to prepareToCommit, in which case this operation MUST be executed before any other commit + * methods in the object graph. + * + * If exceptions are generated by commit after this initial moment, it is not at all clear what the correct behaviour * of the system should be, and so simply logging the exception is likely best (since it may have been an issue - * during cleanup, say), and rollback cannot now occur. As such all exceptions and assertions that may be thrown - * should be checked and ruled out during commit preparation. + * during cleanup, say), and rollback cannot now occur. */ public interface Transactional extends AutoCloseable { - /** * A simple abstract implementation of Transactional behaviour. * In general this should be used as the base class for any transactional implementations. @@ -60,9 +59,9 @@ public interface Transactional extends AutoCloseable * If the implementation wraps any internal Transactional objects, it must proxy every * commit() and abort() call onto each internal object to ensure correct behaviour */ - public static abstract class AbstractTransactional implements Transactional + abstract class AbstractTransactional implements Transactional { - public static enum State + public enum State { IN_PROGRESS, READY_TO_COMMIT, @@ -210,10 +209,10 @@ public interface Transactional extends AutoCloseable // but if it does generate one it should accumulate it in the parameter and return the result // IF a commit implementation has a real correctness affecting exception that cannot be moved to // prepareToCommit, it MUST be executed before any other commit methods in the object graph - public Throwable commit(Throwable accumulate); + Throwable commit(Throwable accumulate); // release any resources, then rollback all state changes (unless commit() has already been invoked) - public Throwable abort(Throwable accumulate); + Throwable abort(Throwable accumulate); - public void prepareToCommit(); + void prepareToCommit(); } http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-CompressionInfo.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-CompressionInfo.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-CompressionInfo.db new file mode 100644 index 0000000..f7a81f0 Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-CompressionInfo.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Data.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Data.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Data.db new file mode 100644 index 0000000..2d5e60a Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Data.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Digest.adler32 ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Digest.adler32 b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Digest.adler32 new file mode 100644 index 0000000..deffbd1 --- /dev/null +++ b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Digest.adler32 @@ -0,0 +1 @@ +2055934203 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Filter.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Filter.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Filter.db new file mode 100644 index 0000000..a749417 Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Filter.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Index.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Index.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Index.db new file mode 100644 index 0000000..d3923ab Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Index.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Statistics.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Statistics.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Statistics.db new file mode 100644 index 0000000..664bfa5 Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Statistics.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Summary.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Summary.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Summary.db new file mode 100644 index 0000000..a74f96f Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-Summary.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-TOC.txt ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-TOC.txt b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-TOC.txt new file mode 100644 index 0000000..92dc9fe --- /dev/null +++ b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/la-1-big-TOC.txt @@ -0,0 +1,8 @@ +Statistics.db +Summary.db +TOC.txt +Filter.db +Data.db +CompressionInfo.db +Digest.adler32 +Index.db http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Data.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Data.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Data.db new file mode 100644 index 0000000..2d5e60a Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Data.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Index.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Index.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Index.db new file mode 100644 index 0000000..d3923ab Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmp-la-2-big-Index.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Data.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Data.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Data.db new file mode 100644 index 0000000..2d5e60a Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Data.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Index.db ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Index.db b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Index.db new file mode 100644 index 0000000..d3923ab Binary files /dev/null and b/test/data/migration-sstables/2.2/keyspace1/test-dfcc85801bc811e5aa694b06169f4ffa/tmplink-la-2-big-Index.db differ http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435108403246-compactions_in_progress/manifest.json ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435108403246-compactions_in_progress/manifest.json b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435108403246-compactions_in_progress/manifest.json new file mode 100644 index 0000000..d5fdb4f --- /dev/null +++ b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435108403246-compactions_in_progress/manifest.json @@ -0,0 +1 @@ +{"files":[]} http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241281-upgrade-3.0.0-SNAPSHOT-2.2.0-rc1-SNAPSHOT/manifest.json ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241281-upgrade-3.0.0-SNAPSHOT-2.2.0-rc1-SNAPSHOT/manifest.json b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241281-upgrade-3.0.0-SNAPSHOT-2.2.0-rc1-SNAPSHOT/manifest.json new file mode 100644 index 0000000..d5fdb4f --- /dev/null +++ b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241281-upgrade-3.0.0-SNAPSHOT-2.2.0-rc1-SNAPSHOT/manifest.json @@ -0,0 +1 @@ +{"files":[]} http://git-wip-us.apache.org/repos/asf/cassandra/blob/b09e60f7/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241532-compactions_in_progress/manifest.json ---------------------------------------------------------------------- diff --git a/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241532-compactions_in_progress/manifest.json b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241532-compactions_in_progress/manifest.json new file mode 100644 index 0000000..d5fdb4f --- /dev/null +++ b/test/data/migration-sstables/2.2/system/compactions_in_progress-55080ab05d9c388690a4acb25fe1f77b/snapshots/1435298241532-compactions_in_progress/manifest.json @@ -0,0 +1 @@ +{"files":[]}
