You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2010/08/27 22:19:44 UTC
svn commit: r990251 - in /cassandra/trunk: ./
src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/db/migration/
test/unit/org/apache/cassandra/db/
Author: jbellis
Date: Fri Aug 27 20:19:44 2010
New Revision: 990251
URL: http://svn.apache.org/viewvc?rev=990251&view=rev
Log:
replace CF graveyard with CFS.removeAllSSTables (which is recursive to handle 2ary index files); also handle 2ary indexes in renaming migrations.
patch by jbellis and gdusbabek for CASSANDRA-1406
Modified:
cassandra/trunk/CHANGES.txt
cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java
cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java
cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropColumnFamily.java
cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropKeyspace.java
cassandra/trunk/src/java/org/apache/cassandra/db/migration/Migration.java
cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameColumnFamily.java
cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameKeyspace.java
cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java
Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Fri Aug 27 20:19:44 2010
@@ -38,6 +38,7 @@ dev
* Add CfDef.default_validation_class (CASSANDRA-891)
* fix EstimatedHistogram.max (CASSANDRA-1413)
* handle zero-length (or missing) rows during HH paging (CASSANDRA-1432)
+ * include secondary indexes during schema migrations (CASSANDRA-1406)
0.7-beta1
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Fri Aug 27 20:19:44 2010
@@ -767,6 +767,15 @@ public class ColumnFamilyStore implement
ssTables.replace(sstables, replacements);
}
+ public void removeAllSSTables()
+ {
+ ssTables.replace(ssTables.getSSTables(), Collections.<SSTableReader>emptyList());
+ for (ColumnFamilyStore indexedCfs : indexedColumns.values())
+ {
+ indexedCfs.removeAllSSTables();
+ }
+ }
+
/**
* submits flush sort on the flushSorter executor, which will in turn submit to flushWriter when sorted.
* TODO because our executors use CallerRunsPolicy, when flushSorter fills up, no writes will proceed
@@ -1547,6 +1556,33 @@ public class ColumnFamilyStore implement
return postFlushExecutor.submit(runnable);
}
+ // if this errors out, we are in a world of hurt.
+ public void renameSSTables(String newCfName) throws IOException
+ {
+ // complete as much of the job as possible. Don't let errors long the way prevent as much renaming as possible
+ // from happening.
+ IOException mostRecentProblem = null;
+ for (File existing : DefsTable.getFiles(table, columnFamily))
+ {
+ try
+ {
+ String newFileName = existing.getName().replaceFirst("\\w+-", newCfName + "-");
+ FileUtils.renameWithConfirm(existing, new File(existing.getParent(), newFileName));
+ }
+ catch (IOException ex)
+ {
+ mostRecentProblem = ex;
+ }
+ }
+ if (mostRecentProblem != null)
+ throw new IOException("One or more IOExceptions encountered while renaming files. Most recent problem is included.", mostRecentProblem);
+
+ for (ColumnFamilyStore indexedCfs : indexedColumns.values())
+ {
+ indexedCfs.renameSSTables(indexedCfs.columnFamily.replace(columnFamily, newCfName));
+ }
+ }
+
public static Future<?> submitPostFlush(Runnable runnable)
{
return postFlushExecutor.submit(runnable);
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java Fri Aug 27 20:19:44 2010
@@ -76,53 +76,6 @@ public class CompactionManager implement
private CompactionExecutor executor = new CompactionExecutor();
private Map<ColumnFamilyStore, Integer> estimatedCompactions = new NonBlockingHashMap<ColumnFamilyStore, Integer>();
-
- /** cleans up data files for CFs that have been dropped. */
- public Future submitGraveyardCleanup()
- {
- Callable c = new Callable()
- {
- public Object call() throws Exception
- {
- logger.debug("Cleaning up abandoned column families...");
- ColumnFamily dropped = SystemTable.getDroppedCFs();
- if (dropped == null)
- // there is nothing that needs to be cleaned up.
- return null;
- Collection<IColumn> successes = new ArrayList<IColumn>();
- for (IColumn col : dropped.getSortedColumns())
- {
- if (!col.isMarkedForDelete())
- {
- final String[] parts = new String(col.name()).split("-");
- // table-cfname-cfid
- for (String dataDir : DatabaseDescriptor.getAllDataFileLocationsForTable(parts[0]))
- {
- File dir = new File(dataDir);
- if (dir.exists())
- {
- File[] dbFiles = dir.listFiles(new FileFilter()
- {
- public boolean accept(File pathname)
- {
- return pathname.getName().startsWith(parts[1] + "-") && pathname.exists();
- }
- });
- for (File f : dbFiles)
- {
- FileUtils.deleteWithConfirm(f);
- }
- }
- }
- successes.add(col);
- }
- }
- SystemTable.deleteDroppedCfMarkers(successes);
- return null;
- }
- };
- return executor.submit(c);
- }
/**
* Call this whenever a compaction might be needed on the given columnfamily.
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java Fri Aug 27 20:19:44 2010
@@ -51,7 +51,6 @@ public class SystemTable
public static final String STATUS_CF = "LocationInfo"; // keep the old CF string for backwards-compatibility
private static final byte[] LOCATION_KEY = "L".getBytes(UTF_8);
private static final byte[] BOOTSTRAP_KEY = "Bootstrap".getBytes(UTF_8);
- private static final byte[] GRAVEYARD_KEY = "Graveyard".getBytes(UTF_8);
private static final byte[] COOKIE_KEY = "Cookies".getBytes(UTF_8);
private static final byte[] BOOTSTRAP = "B".getBytes(UTF_8);
private static final byte[] TOKEN = "Token".getBytes(UTF_8);
@@ -337,38 +336,6 @@ public class SystemTable
}
}
- public static ColumnFamily getDroppedCFs() throws IOException
- {
- ColumnFamilyStore cfs = Table.open(Table.SYSTEM_TABLE).getColumnFamilyStore(SystemTable.STATUS_CF);
- return cfs.getColumnFamily(QueryFilter.getSliceFilter(decorate(GRAVEYARD_KEY), new QueryPath(STATUS_CF), "".getBytes(), "".getBytes(), false, 100));
- }
-
- public static void deleteDroppedCfMarkers(Collection<IColumn> cols) throws IOException
- {
- RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, GRAVEYARD_KEY);
- long now = System.currentTimeMillis();
- for (IColumn col : cols)
- rm.delete(new QueryPath(STATUS_CF, null, col.name()), new TimestampClock(now));
- rm.apply();
- }
-
- /** when a cf is dropped, it needs to be marked so its files get deleted at some point. */
- public static void markForRemoval(CFMetaData cfm)
- {
- ColumnFamily cf = ColumnFamily.create(Table.SYSTEM_TABLE, STATUS_CF);
- cf.addColumn(new Column((cfm.tableName + "-" + cfm.cfName + "-" + cfm.cfId).getBytes(), ArrayUtils.EMPTY_BYTE_ARRAY, new TimestampClock(System.currentTimeMillis())));
- RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, GRAVEYARD_KEY);
- rm.add(cf);
- try
- {
- rm.apply();
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
public static class StorageMetadata
{
private Token token;
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Fri Aug 27 20:19:44 2010
@@ -19,7 +19,6 @@
package org.apache.cassandra.db;
import java.io.IOError;
-import java.lang.management.ManagementFactory;
import java.util.*;
import java.io.IOException;
import java.io.File;
@@ -37,9 +36,6 @@ import org.apache.cassandra.io.sstable.S
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.io.util.FileUtils;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import org.apache.commons.lang.ArrayUtils;
import org.apache.cassandra.service.StorageService;
@@ -251,10 +247,7 @@ public class Table
}
for (CFMetaData cfm : new ArrayList<CFMetaData>(DatabaseDescriptor.getTableDefinition(table).cfMetaData().values()))
- {
- ColumnFamilyStore cfs = ColumnFamilyStore.createColumnFamilyStore(table, cfm.cfName);
- columnFamilyStores.put(cfm.cfId, cfs);
- }
+ initCf(cfm.cfId, cfm.cfName);
// check 10x as often as the lifetime, so we can exceed lifetime by 10% at most
int checkMs = DatabaseDescriptor.getMemtableLifetimeMS() / 10;
@@ -271,28 +264,33 @@ public class Table
flushTimer.schedule(flushTask, checkMs, checkMs);
}
- /** removes a cf from internal structures (doesn't change disk files). */
public void dropCf(Integer cfId) throws IOException
{
assert columnFamilyStores.containsKey(cfId);
ColumnFamilyStore cfs = columnFamilyStores.remove(cfId);
- if (cfs != null)
+ if (cfs == null)
+ return;
+
+ unloadCf(cfs);
+ cfs.removeAllSSTables();
+ }
+
+ // disassociate a cfs from this table instance.
+ private void unloadCf(ColumnFamilyStore cfs) throws IOException
+ {
+ try
{
- try
- {
- cfs.forceBlockingFlush();
- }
- catch (ExecutionException e)
- {
- throw new IOException(e);
- }
- catch (InterruptedException e)
- {
- throw new IOException(e);
- }
-
- cfs.unregisterMBean();
+ cfs.forceBlockingFlush();
}
+ catch (ExecutionException e)
+ {
+ throw new IOException(e);
+ }
+ catch (InterruptedException e)
+ {
+ throw new IOException(e);
+ }
+ cfs.unregisterMBean();
}
/** adds a cf to internal structures, ends up creating disk files). */
@@ -306,7 +304,10 @@ public class Table
/** basically a combined drop and add */
public void renameCf(Integer cfId, String newName) throws IOException
{
- dropCf(cfId);
+ assert columnFamilyStores.containsKey(cfId);
+ ColumnFamilyStore cfs = columnFamilyStores.remove(cfId);
+ unloadCf(cfs);
+ cfs.renameSSTables(newName);
initCf(cfId, newName);
}
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropColumnFamily.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropColumnFamily.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropColumnFamily.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropColumnFamily.java Fri Aug 27 20:19:44 2010
@@ -92,14 +92,8 @@ public class DropColumnFamily extends Mi
if (!clientMode)
{
Table.open(ksm.name).dropCf(cfm.cfId);
-
- // indicate that some files need to be deleted (eventually)
- SystemTable.markForRemoval(cfm);
-
// we don't really need a new segment, but let's force it to be consistent with other operations.
CommitLog.instance().forceNewSegment();
-
- Migration.cleanupDeadFiles(blockOnFileDeletion);
}
}
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropKeyspace.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropKeyspace.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropKeyspace.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/migration/DropKeyspace.java Fri Aug 27 20:19:44 2010
@@ -73,7 +73,6 @@ public class DropKeyspace extends Migrat
if (!clientMode)
{
table.dropCf(cfm.cfId);
- SystemTable.markForRemoval(cfm);
}
}
@@ -83,8 +82,6 @@ public class DropKeyspace extends Migrat
if (!clientMode)
{
CommitLog.instance().forceNewSegment();
- Migration.cleanupDeadFiles(blockOnFileDeletion);
-
// clear up any local hinted data for this keyspace.
HintedHandOffManager.renameHints(name, null);
}
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/migration/Migration.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/migration/Migration.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/migration/Migration.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/migration/Migration.java Fri Aug 27 20:19:44 2010
@@ -227,28 +227,7 @@ public abstract class Migration
now);
return rm;
}
-
- static void cleanupDeadFiles(boolean wait)
- {
- Future cleanup = CompactionManager.instance.submitGraveyardCleanup();
- if (wait)
- {
- // notify the compaction manager that it needs to clean up the dropped cf files.
- try
- {
- cleanup.get();
- }
- catch (InterruptedException e)
- {
- throw new RuntimeException(e);
- }
- catch (ExecutionException e)
- {
- throw new RuntimeException(e);
- }
- }
- }
-
+
public byte[] serialize() throws IOException
{
// super deflate
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameColumnFamily.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameColumnFamily.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameColumnFamily.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameColumnFamily.java Fri Aug 27 20:19:44 2010
@@ -87,8 +87,6 @@ public class RenameColumnFamily extends
{
// leave it up to operators to ensure there are no writes going on durng the file rename. Just know that
// attempting row mutations on oldcfName right now would be really bad.
- if (!clientMode)
- renameCfStorageFiles(tableName, oldName, newName);
// reset defs.
KSMetaData oldKsm = DatabaseDescriptor.getTableDefinition(tableName);
@@ -113,28 +111,6 @@ public class RenameColumnFamily extends
}
}
- // if this errors out, we are in a world of hurt.
- private static void renameCfStorageFiles(String table, String oldCfName, String newCfName) throws IOException
- {
- // complete as much of the job as possible. Don't let errors long the way prevent as much renaming as possible
- // from happening.
- IOException mostRecentProblem = null;
- for (File existing : DefsTable.getFiles(table, oldCfName))
- {
- try
- {
- String newFileName = existing.getName().replaceFirst("\\w+-", newCfName + "-");
- FileUtils.renameWithConfirm(existing, new File(existing.getParent(), newFileName));
- }
- catch (IOException ex)
- {
- mostRecentProblem = ex;
- }
- }
- if (mostRecentProblem != null)
- throw new IOException("One or more IOExceptions encountered while renaming files. Most recent problem is included.", mostRecentProblem);
- }
-
public void subdeflate(org.apache.cassandra.db.migration.avro.Migration mi)
{
org.apache.cassandra.db.migration.avro.RenameColumnFamily rcf = new org.apache.cassandra.db.migration.avro.RenameColumnFamily();
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameKeyspace.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameKeyspace.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameKeyspace.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/migration/RenameKeyspace.java Fri Aug 27 20:19:44 2010
@@ -36,6 +36,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import org.apache.commons.lang.StringUtils;
+
public class RenameKeyspace extends Migration
{
private String oldName;
@@ -119,26 +121,17 @@ public class RenameKeyspace extends Migr
private static void renameKsStorageFiles(String oldKs, String newKs) throws IOException
{
- IOException mostRecentProblem = null;
- Set<String> cfNames = DatabaseDescriptor.getTableDefinition(oldKs).cfMetaData().keySet();
- for (String cfName : cfNames)
+ ArrayList<File> failed = new ArrayList<File>();
+ for (String dataDir : DatabaseDescriptor.getAllDataFileLocations())
{
- for (File existing : DefsTable.getFiles(oldKs, cfName))
- {
- try
- {
- File newParent = new File(existing.getParentFile().getParent(), newKs);
- newParent.mkdirs();
- FileUtils.renameWithConfirm(existing, new File(newParent, existing.getName()));
- }
- catch (IOException ex)
- {
- mostRecentProblem = ex;
- }
- }
+ File ksDir = new File(dataDir, oldKs);
+ if (ksDir.exists())
+ if (!ksDir.renameTo(new File(dataDir, newKs)))
+ failed.add(ksDir);
}
- if (mostRecentProblem != null)
- throw new IOException("One or more IOExceptions encountered while renaming files. Most recent problem is included.", mostRecentProblem);
+
+ if (!failed.isEmpty())
+ throw new IOException("One or more problems encountered while renaming " + StringUtils.join(failed, ","));
}
public void subdeflate(org.apache.cassandra.db.migration.avro.Migration mi)
Modified: cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java?rev=990251&r1=990250&r2=990251&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java Fri Aug 27 20:19:44 2010
@@ -18,10 +18,12 @@
package org.apache.cassandra.db;
+import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
+import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.apache.cassandra.CleanupHelper;
@@ -218,8 +220,12 @@ public class DefsTest extends CleanupHel
assert !success : "This mutation should have failed since the CF no longer exists.";
// verify that the files are gone.
- assert DefsTable.getFiles(cfm.tableName, cfm.cfName).size() == 0;
- }
+ for (File file : DefsTable.getFiles(cfm.tableName, cfm.cfName))
+ {
+ if (file.getPath().endsWith("Data.db") && !new File(file.getPath().replace("Data.db", "Compacted")).exists())
+ throw new AssertionError("undeleted file " + file);
+ }
+ }
@Test
public void renameCf() throws ConfigurationException, IOException, ExecutionException, InterruptedException
@@ -373,7 +379,6 @@ public class DefsTest extends CleanupHel
assert newKs.cfMetaData().containsKey(cfName);
assert newKs.cfMetaData().get(cfName).tableName.equals(newKsName);
assert DefsTable.getFiles(newKs.name, cfName).size() > 0;
- assert DefsTable.getFiles(oldKs.name, cfName).size() == 0;
// read on old should fail.
try