You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2015/11/06 14:52:33 UTC
[2/3] cassandra git commit: Always update system keyspace to the most
up-to-date version
Always update system keyspace to the most up-to-date version
patch by slebresne; reviewed by carlyeks for CASSANDRA-10652
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6367987f
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6367987f
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6367987f
Branch: refs/heads/cassandra-3.0
Commit: 6367987f49a25512dbf715df9b6d564d53f27235
Parents: 801c50e
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Thu Nov 5 15:30:54 2015 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Fri Nov 6 14:42:31 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../cassandra/service/MigrationManager.java | 22 +++++++-
.../cassandra/service/StorageService.java | 56 ++++++++++++--------
3 files changed, 55 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/6367987f/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 538d5e4..7e969a5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
2.2.4
+ * Use most up-to-date version of schema for system tables (CASSANDRA-10652)
* Deprecate memory_allocator in cassandra.yaml (CASSANDRA-10581,10628)
* Expose phi values from failure detector via JMX and tweak debug
and trace logging (CASSANDRA-9526)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/6367987f/src/java/org/apache/cassandra/service/MigrationManager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/MigrationManager.java b/src/java/org/apache/cassandra/service/MigrationManager.java
index 9087672..ec7448a 100644
--- a/src/java/org/apache/cassandra/service/MigrationManager.java
+++ b/src/java/org/apache/cassandra/service/MigrationManager.java
@@ -277,12 +277,32 @@ public class MigrationManager
public static void announceNewColumnFamily(CFMetaData cfm, boolean announceLocally) throws ConfigurationException
{
+ announceNewColumnFamily(cfm, announceLocally, true);
+ }
+
+ /**
+ * Announces the table even if the definition is already know locally.
+ * This should generally be avoided but is used internally when we want to force the most up to date version of
+ * a system table schema (Note that we don't know if the schema we force _is_ the most recent version or not, we
+ * just rely on idempotency to basically ignore that announce if it's not. That's why we can't use announceUpdateColumnFamily,
+ * it would for instance delete new columns if this is not called with the most up-to-date version)
+ *
+ * Note that this is only safe for system tables where we know the cfId is fixed and will be the same whatever version
+ * of the definition is used.
+ */
+ public static void forceAnnounceNewColumnFamily(CFMetaData cfm) throws ConfigurationException
+ {
+ announceNewColumnFamily(cfm, false, false);
+ }
+
+ private static void announceNewColumnFamily(CFMetaData cfm, boolean announceLocally, boolean throwOnDuplicate) throws ConfigurationException
+ {
cfm.validate();
KSMetaData ksm = Schema.instance.getKSMetaData(cfm.ksName);
if (ksm == null)
throw new ConfigurationException(String.format("Cannot add table '%s' to non existing keyspace '%s'.", cfm.cfName, cfm.ksName));
- else if (ksm.cfMetaData().containsKey(cfm.cfName))
+ else if (throwOnDuplicate && ksm.cfMetaData().containsKey(cfm.cfName))
throw new AlreadyExistsException(cfm.ksName, cfm.cfName);
logger.info(String.format("Create new table: %s", cfm));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/6367987f/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 77483f2..ad209fc 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -950,11 +950,8 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
}
// if we don't have system_traces keyspace at this point, then create it manually
- if (Schema.instance.getKSMetaData(TraceKeyspace.NAME) == null)
- maybeAddKeyspace(TraceKeyspace.definition());
-
- if (Schema.instance.getKSMetaData(SystemDistributedKeyspace.NAME) == null)
- MigrationManager.announceNewKeyspace(SystemDistributedKeyspace.definition(), 0, false);
+ maybeAddOrUpdateKeyspace(TraceKeyspace.definition());
+ maybeAddOrUpdateKeyspace(SystemDistributedKeyspace.definition());
if (!isSurveyMode)
{
@@ -1020,24 +1017,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
private void doAuthSetup()
{
- try
- {
- // if we don't have system_auth keyspace at this point, then create it
- if (Schema.instance.getKSMetaData(AuthKeyspace.NAME) == null)
- maybeAddKeyspace(AuthKeyspace.definition());
- }
- catch (Exception e)
- {
- throw new AssertionError(e); // shouldn't ever happen.
- }
-
- // create any necessary tables as we may be upgrading in which case
- // the ks exists with the only the legacy tables defined.
- // Also, the addKeyspace above can be racy if multiple nodes are started
- // concurrently - see CASSANDRA-9201
- for (Map.Entry<String, CFMetaData> table : AuthKeyspace.definition().cfMetaData().entrySet())
- if (Schema.instance.getCFMetaData(AuthKeyspace.NAME, table.getKey()) == null)
- maybeAddTable(table.getValue());
+ maybeAddOrUpdateKeyspace(AuthKeyspace.definition());
DatabaseDescriptor.getRoleManager().setup();
DatabaseDescriptor.getAuthenticator().setup();
@@ -1069,6 +1049,36 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
}
}
+ /**
+ * Ensure the schema of a pseudo-system keyspace (a distributed system keyspace: traces, auth and the so-called distributedKeyspace),
+ * is up to date with what we expected (creating it if it doesn't exist and updating tables that may have been upgraded).
+ */
+ private void maybeAddOrUpdateKeyspace(KSMetaData expected)
+ {
+ // Note that want to deal with the keyspace and its table a bit differently: for the keyspace definition
+ // itself, we want to create it if it doesn't exist yet, but if it does exist, we don't want to modify it,
+ // because user can modify the definition to change the replication factor (#6016) and we don't want to
+ // override it. For the tables however, we have to deal with the fact that new version can add new columns
+ // (#8162 being an example), so even if the table definition exists, we still need to force the "current"
+ // version of the schema, the one the node will be expecting.
+
+ KSMetaData defined = Schema.instance.getKSMetaData(expected.name);
+ if (defined == null)
+ {
+ // The keyspace doesn't exist, create it
+ maybeAddKeyspace(expected);
+ return;
+ }
+
+ // While the keyspace exists, it might miss table or have outdated one
+ for (CFMetaData expectedTable : expected.cfMetaData().values())
+ {
+ CFMetaData definedTable = defined.cfMetaData().get(expectedTable.cfName);
+ if (definedTable == null || !definedTable.equals(expectedTable))
+ MigrationManager.forceAnnounceNewColumnFamily(expectedTable);
+ }
+ }
+
public boolean isJoined()
{
return joined && !isSurveyMode;