Add diagnostic events base classes patch by Stefan Podkowinski; reviewed by Mick Semb Wever for CASSANDRA-13457
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/2846b22a Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/2846b22a Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/2846b22a Branch: refs/heads/trunk Commit: 2846b22a70d48bae25203be945e02dd3b6cfda56 Parents: d3e6891 Author: Stefan Podkowinski <stefan.podkowin...@1und1.de> Authored: Thu Mar 16 12:50:52 2017 +0100 Committer: Stefan Podkowinski <stefan.podkowin...@1und1.de> Committed: Fri Aug 17 14:06:57 2018 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + conf/cassandra.yaml | 5 + .../org/apache/cassandra/config/Config.java | 3 + .../cassandra/config/DatabaseDescriptor.java | 11 + .../schema/AlterKeyspaceStatement.java | 5 + .../statements/schema/AlterTableStatement.java | 5 + .../statements/schema/AlterTypeStatement.java | 5 + .../statements/schema/AlterViewStatement.java | 5 + .../schema/CreateAggregateStatement.java | 5 + .../schema/CreateFunctionStatement.java | 5 + .../statements/schema/CreateIndexStatement.java | 5 + .../schema/CreateKeyspaceStatement.java | 5 + .../statements/schema/CreateTableStatement.java | 5 + .../schema/CreateTriggerStatement.java | 5 + .../statements/schema/CreateTypeStatement.java | 5 + .../statements/schema/CreateViewStatement.java | 5 + .../schema/DropAggregateStatement.java | 5 + .../schema/DropFunctionStatement.java | 5 + .../statements/schema/DropIndexStatement.java | 5 + .../schema/DropKeyspaceStatement.java | 5 + .../statements/schema/DropTableStatement.java | 5 + .../statements/schema/DropTriggerStatement.java | 5 + .../statements/schema/DropTypeStatement.java | 5 + .../statements/schema/DropViewStatement.java | 5 + .../org/apache/cassandra/dht/BootStrapper.java | 14 +- .../cassandra/dht/BootstrapDiagnostics.java | 80 +++++ .../apache/cassandra/dht/BootstrapEvent.java | 82 +++++ .../NoReplicationTokenAllocator.java | 4 + .../ReplicationAwareTokenAllocator.java | 7 +- .../TokenAllocatorDiagnostics.java | 195 ++++++++++++ .../dht/tokenallocator/TokenAllocatorEvent.java | 113 +++++++ .../tokenallocator/TokenAllocatorFactory.java | 8 +- .../apache/cassandra/diag/DiagnosticEvent.java | 50 +++ .../cassandra/diag/DiagnosticEventService.java | 291 +++++++++++++++++ src/java/org/apache/cassandra/gms/Gossiper.java | 46 ++- .../cassandra/gms/GossiperDiagnostics.java | 113 +++++++ .../org/apache/cassandra/gms/GossiperEvent.java | 111 +++++++ src/java/org/apache/cassandra/hints/Hint.java | 2 +- .../apache/cassandra/hints/HintDiagnostics.java | 85 +++++ .../org/apache/cassandra/hints/HintEvent.java | 102 ++++++ .../cassandra/hints/HintsDispatchExecutor.java | 10 + .../apache/cassandra/hints/HintsDispatcher.java | 52 +-- .../apache/cassandra/hints/HintsService.java | 12 +- .../hints/HintsServiceDiagnostics.java | 65 ++++ .../cassandra/hints/HintsServiceEvent.java | 71 +++++ .../apache/cassandra/locator/TokenMetadata.java | 2 + .../locator/TokenMetadataDiagnostics.java | 46 +++ .../cassandra/locator/TokenMetadataEvent.java | 62 ++++ src/java/org/apache/cassandra/schema/Diff.java | 5 + .../cassandra/schema/MigrationManager.java | 33 +- .../apache/cassandra/schema/MigrationTask.java | 5 + .../org/apache/cassandra/schema/Schema.java | 34 ++ .../schema/SchemaAnnouncementDiagnostics.java | 60 ++++ .../schema/SchemaAnnouncementEvent.java | 104 ++++++ .../cassandra/schema/SchemaDiagnostics.java | 178 +++++++++++ .../apache/cassandra/schema/SchemaEvent.java | 318 +++++++++++++++++++ .../schema/SchemaMigrationDiagnostics.java | 83 +++++ .../cassandra/schema/SchemaMigrationEvent.java | 114 +++++++ .../cassandra/schema/SchemaPushVerbHandler.java | 1 + .../service/PendingRangeCalculatorService.java | 23 +- ...endingRangeCalculatorServiceDiagnostics.java | 73 +++++ .../PendingRangeCalculatorServiceEvent.java | 69 ++++ .../diag/DiagnosticEventServiceTest.java | 244 ++++++++++++++ 63 files changed, 3047 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index d8aca56..ceba843 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0 + * Add base classes for diagnostic events (CASSANDRA-13457) * Clear view system metadata when dropping keyspace (CASSANDRA-14646) * Allocate ReentrantLock on-demand in java11 AtomicBTreePartitionerBase (CASSANDRA-14637) * Make all existing virtual tables use LocalPartitioner (CASSANDRA-14640) http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/conf/cassandra.yaml ---------------------------------------------------------------------- diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml index 663daaa..c7c2785 100644 --- a/conf/cassandra.yaml +++ b/conf/cassandra.yaml @@ -1217,3 +1217,8 @@ audit_logging_options: # validate tombstones on reads and compaction # can be either "disabled", "warn" or "exception" # corrupted_tombstone_strategy: disabled + +# Diagnostic Events # +# If enabled, diagnostic events can be helpful for troubleshooting operational issues. Emitted events contain details +# on internal state and temporal relationships across events, accessible by clients via JMX. +diagnostic_events_enabled: false http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/config/Config.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index 3a7ff0d..46dbc1c 100644 --- a/src/java/org/apache/cassandra/config/Config.java +++ b/src/java/org/apache/cassandra/config/Config.java @@ -386,6 +386,9 @@ public class Config public volatile AuditLogOptions audit_logging_options = new AuditLogOptions(); public CorruptedTombstoneStrategy corrupted_tombstone_strategy = CorruptedTombstoneStrategy.disabled; + + public volatile boolean diagnostic_events_enabled = false; + /** * @deprecated migrate to {@link DatabaseDescriptor#isClientInitialized()} */ http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 366dac7..65a34f0 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -2536,6 +2536,17 @@ public class DatabaseDescriptor return conf.back_pressure_enabled; } + public static boolean diagnosticEventsEnabled() + { + return conf.diagnostic_events_enabled; + } + + @VisibleForTesting + public static void setDiagnosticEventsEnabled(boolean enabled) + { + conf.diagnostic_events_enabled = enabled; + } + @VisibleForTesting public static void setBackPressureStrategy(BackPressureStrategy strategy) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java index c2d0e4c..12e73d0 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java @@ -95,6 +95,11 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.ALTER_KEYSPACE, keyspaceName); } + public String toString() + { + return String.format("%s (%s)", getClass().getSimpleName(), keyspaceName); + } + public static final class Raw extends CQLStatement.Raw { private final String keyspaceName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java index a081a2c..3ec75b2 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java @@ -81,6 +81,11 @@ public abstract class AlterTableStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.ALTER_TABLE, keyspaceName, tableName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, tableName); + } + abstract KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table); /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java index 50f09a0..6eab2ba 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java @@ -83,6 +83,11 @@ public abstract class AlterTypeStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.ALTER_TYPE, keyspaceName, typeName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, typeName); + } + private static final class AddField extends AlterTypeStatement { private final FieldIdentifier fieldName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java index 2ecc095..1931bb4 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java @@ -92,6 +92,11 @@ public final class AlterViewStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.ALTER_VIEW, keyspaceName, viewName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, viewName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java index cd9808a..462623d 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java @@ -271,6 +271,11 @@ public final class CreateAggregateStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_AGGREGATE, keyspaceName, aggregateName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, aggregateName); + } + private String stateFunctionString() { return format("%s(%s)", stateFunctionName, join(", ", transform(concat(singleton(rawStateType), rawArgumentTypes), Object::toString))); http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java index 13e173f..20c4ad9 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java @@ -198,6 +198,11 @@ public final class CreateFunctionStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_FUNCTION, keyspaceName, functionName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, functionName); + } + public static final class Raw extends CQLStatement.Raw { private final FunctionName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java index 0065a4c..df41358 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java @@ -194,6 +194,11 @@ public final class CreateIndexStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_INDEX, keyspaceName, indexName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, indexName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName tableName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java index ecd19ed..f85a4e9 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java @@ -94,6 +94,11 @@ public final class CreateKeyspaceStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_KEYSPACE, keyspaceName); } + public String toString() + { + return String.format("%s (%s)", getClass().getSimpleName(), keyspaceName); + } + public static final class Raw extends CQLStatement.Raw { public final String keyspaceName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java index ff26f0d..62fcafe 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java @@ -123,6 +123,11 @@ public final class CreateTableStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_TABLE, keyspaceName, tableName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, tableName); + } + public TableMetadata.Builder builder(Types types) { attrs.validate(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java index cb6d14e..e85ffd8 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java @@ -96,6 +96,11 @@ public final class CreateTriggerStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_TRIGGER, keyspaceName, triggerName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, triggerName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName tableName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java index c328eb7..7c1717e 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java @@ -115,6 +115,11 @@ public final class CreateTypeStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_TYPE, keyspaceName, typeName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, typeName); + } + public static final class Raw extends CQLStatement.Raw { private final UTName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java index f97b0fe..5f62001 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java @@ -341,6 +341,11 @@ public final class CreateViewStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.CREATE_VIEW, keyspaceName, viewName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, viewName); + } + public final static class Raw extends CQLStatement.Raw { private final QualifiedName tableName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java index 564f267..d24f77e 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java @@ -139,6 +139,11 @@ public final class DropAggregateStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_AGGREGATE, keyspaceName, aggregateName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, aggregateName); + } + private List<AbstractType<?>> prepareArgumentTypes(Types types) { return arguments.stream() http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java index 9433833..f7d7d4a 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java @@ -147,6 +147,11 @@ public final class DropFunctionStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_FUNCTION, keyspaceName, functionName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, functionName); + } + private List<AbstractType<?>> prepareArgumentTypes(Types types) { return arguments.stream() http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java index 6a6f8d9..2186470 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java @@ -90,6 +90,11 @@ public final class DropIndexStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_INDEX, keyspaceName, indexName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, indexName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java index ae5cf06..f2bd30b 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java @@ -64,6 +64,11 @@ public final class DropKeyspaceStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_KEYSPACE, keyspaceName); } + public String toString() + { + return String.format("%s (%s)", getClass().getSimpleName(), keyspaceName); + } + public static final class Raw extends CQLStatement.Raw { private final String keyspaceName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java index 9be59af..15c2a03 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java @@ -92,6 +92,11 @@ public final class DropTableStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_TABLE, keyspaceName, tableName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, tableName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java index 8de47c2..967e568 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java @@ -82,6 +82,11 @@ public final class DropTriggerStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_TRIGGER, keyspaceName, triggerName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, triggerName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName tableName; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java index d51954c..6cda7ba 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java @@ -129,6 +129,11 @@ public final class DropTypeStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_TYPE, keyspaceName, typeName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, typeName); + } + public static final class Raw extends CQLStatement.Raw { private final UTName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java index 807d03d..2c73717 100644 --- a/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java @@ -78,6 +78,11 @@ public final class DropViewStatement extends AlterSchemaStatement return new AuditLogContext(AuditLogEntryType.DROP_VIEW, keyspaceName, viewName); } + public String toString() + { + return String.format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, viewName); + } + public static final class Raw extends CQLStatement.Raw { private final QualifiedName name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/BootStrapper.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/BootStrapper.java b/src/java/org/apache/cassandra/dht/BootStrapper.java index 432586b..92bf8c8 100644 --- a/src/java/org/apache/cassandra/dht/BootStrapper.java +++ b/src/java/org/apache/cassandra/dht/BootStrapper.java @@ -168,7 +168,11 @@ public class BootStrapper extends ProgressEventNotifierSupport // if user specified tokens, use those if (initialTokens.size() > 0) - return getSpecifiedTokens(metadata, initialTokens); + { + Collection<Token> tokens = getSpecifiedTokens(metadata, initialTokens); + BootstrapDiagnostics.useSpecifiedTokens(address, allocationKeyspace, tokens, DatabaseDescriptor.getNumTokens()); + return tokens; + } int numTokens = DatabaseDescriptor.getNumTokens(); if (numTokens < 1) @@ -180,7 +184,9 @@ public class BootStrapper extends ProgressEventNotifierSupport if (numTokens == 1) logger.warn("Picking random token for a single vnode. You should probably add more vnodes and/or use the automatic token allocation mechanism."); - return getRandomTokens(metadata, numTokens); + Collection<Token> tokens = getRandomTokens(metadata, numTokens); + BootstrapDiagnostics.useRandomTokens(address, metadata, numTokens, tokens); + return tokens; } private static Collection<Token> getSpecifiedTokens(final TokenMetadata metadata, @@ -213,7 +219,9 @@ public class BootStrapper extends ProgressEventNotifierSupport throw new ConfigurationException("Problem opening token allocation keyspace " + allocationKeyspace); AbstractReplicationStrategy rs = ks.getReplicationStrategy(); - return TokenAllocation.allocateTokens(metadata, rs, address, numTokens); + Collection<Token> tokens = TokenAllocation.allocateTokens(metadata, rs, address, numTokens); + BootstrapDiagnostics.tokensAllocated(address, metadata, allocationKeyspace, numTokens, tokens); + return tokens; } public static Collection<Token> getRandomTokens(TokenMetadata metadata, int numTokens) http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/BootstrapDiagnostics.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/BootstrapDiagnostics.java b/src/java/org/apache/cassandra/dht/BootstrapDiagnostics.java new file mode 100644 index 0000000..5695532 --- /dev/null +++ b/src/java/org/apache/cassandra/dht/BootstrapDiagnostics.java @@ -0,0 +1,80 @@ +/* + * 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.dht; + +import java.util.Collection; +import com.google.common.collect.ImmutableList; + +import org.apache.cassandra.dht.BootstrapEvent.BootstrapEventType; +import org.apache.cassandra.diag.DiagnosticEventService; +import org.apache.cassandra.locator.InetAddressAndPort; +import org.apache.cassandra.locator.TokenMetadata; + +/** + * Utility methods for bootstrap related activities. + */ +final class BootstrapDiagnostics +{ + private static final DiagnosticEventService service = DiagnosticEventService.instance(); + + private BootstrapDiagnostics() + { + } + + static void useSpecifiedTokens(InetAddressAndPort address, String allocationKeyspace, Collection<Token> initialTokens, + int numTokens) + { + if (isEnabled(BootstrapEventType.BOOTSTRAP_USING_SPECIFIED_TOKENS)) + service.publish(new BootstrapEvent(BootstrapEventType.BOOTSTRAP_USING_SPECIFIED_TOKENS, + address, + null, + allocationKeyspace, + numTokens, + ImmutableList.copyOf(initialTokens))); + } + + static void useRandomTokens(InetAddressAndPort address, TokenMetadata metadata, int numTokens, Collection<Token> tokens) + { + if (isEnabled(BootstrapEventType.BOOTSTRAP_USING_RANDOM_TOKENS)) + service.publish(new BootstrapEvent(BootstrapEventType.BOOTSTRAP_USING_RANDOM_TOKENS, + address, + metadata.cloneOnlyTokenMap(), + null, + numTokens, + ImmutableList.copyOf(tokens))); + } + + static void tokensAllocated(InetAddressAndPort address, TokenMetadata metadata, + String allocationKeyspace, int numTokens, Collection<Token> tokens) + { + if (isEnabled(BootstrapEventType.TOKENS_ALLOCATED)) + service.publish(new BootstrapEvent(BootstrapEventType.TOKENS_ALLOCATED, + address, + metadata.cloneOnlyTokenMap(), + allocationKeyspace, + numTokens, + ImmutableList.copyOf(tokens))); + } + + private static boolean isEnabled(BootstrapEventType type) + { + return service.isEnabled(BootstrapEvent.class, type); + } + +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/BootstrapEvent.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/BootstrapEvent.java b/src/java/org/apache/cassandra/dht/BootstrapEvent.java new file mode 100644 index 0000000..5bad09a --- /dev/null +++ b/src/java/org/apache/cassandra/dht/BootstrapEvent.java @@ -0,0 +1,82 @@ +/* + * 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.dht; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableCollection; + +import org.apache.cassandra.diag.DiagnosticEvent; +import org.apache.cassandra.locator.InetAddressAndPort; +import org.apache.cassandra.locator.TokenMetadata; + +/** + * DiagnosticEvent implementation for bootstrap related activities. + */ +final class BootstrapEvent extends DiagnosticEvent +{ + + private final BootstrapEventType type; + @Nullable + private final TokenMetadata tokenMetadata; + private final InetAddressAndPort address; + @Nullable + private final String allocationKeyspace; + private final Integer numTokens; + private final Collection<Token> tokens; + + BootstrapEvent(BootstrapEventType type, InetAddressAndPort address, @Nullable TokenMetadata tokenMetadata, + @Nullable String allocationKeyspace, int numTokens, ImmutableCollection<Token> tokens) + { + this.type = type; + this.address = address; + this.tokenMetadata = tokenMetadata; + this.allocationKeyspace = allocationKeyspace; + this.numTokens = numTokens; + this.tokens = tokens; + } + + enum BootstrapEventType + { + BOOTSTRAP_USING_SPECIFIED_TOKENS, + BOOTSTRAP_USING_RANDOM_TOKENS, + TOKENS_ALLOCATED + } + + + public BootstrapEventType getType() + { + return type; + } + + public Map<String, Serializable> toMap() + { + // be extra defensive against nulls and bugs + HashMap<String, Serializable> ret = new HashMap<>(); + ret.put("tokenMetadata", String.valueOf(tokenMetadata)); + ret.put("allocationKeyspace", allocationKeyspace); + ret.put("numTokens", numTokens); + ret.put("tokens", String.valueOf(tokens)); + return ret; + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/tokenallocator/NoReplicationTokenAllocator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/tokenallocator/NoReplicationTokenAllocator.java b/src/java/org/apache/cassandra/dht/tokenallocator/NoReplicationTokenAllocator.java index 54d80dc..f6a1592 100644 --- a/src/java/org/apache/cassandra/dht/tokenallocator/NoReplicationTokenAllocator.java +++ b/src/java/org/apache/cassandra/dht/tokenallocator/NoReplicationTokenAllocator.java @@ -86,6 +86,7 @@ public class NoReplicationTokenAllocator<Unit> extends TokenAllocatorBase<Unit> sortedUnits.add(new Weighted<UnitInfo>(unitInfo.ownership, unitInfo)); } + TokenAllocatorDiagnostics.tokenInfosCreated(this, sortedUnits, sortedTokens, first); return first; } @@ -127,6 +128,7 @@ public class NoReplicationTokenAllocator<Unit> extends TokenAllocatorBase<Unit> } unitInfos.put(newUnit.unit, newUnit); createTokenInfos(unitInfos); + TokenAllocatorDiagnostics.randomTokensGenerated(this, numTokens, sortedUnits, sortedTokens, newUnit.unit, tokens); return tokens; } @@ -232,6 +234,7 @@ public class NoReplicationTokenAllocator<Unit> extends TokenAllocatorBase<Unit> } sortedUnits.add(new Weighted<>(newUnitInfo.ownership, newUnitInfo)); + TokenAllocatorDiagnostics.unitedAdded(this, numTokens, sortedUnits, sortedTokens, newTokens, newUnit); return newTokens; } @@ -257,6 +260,7 @@ public class NoReplicationTokenAllocator<Unit> extends TokenAllocatorBase<Unit> tokens.add(tokenInfo.value.token); } sortedTokens.keySet().removeAll(tokens); + TokenAllocatorDiagnostics.unitRemoved(this, n, sortedUnits, sortedTokens); } public int getReplicas() http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/tokenallocator/ReplicationAwareTokenAllocator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/tokenallocator/ReplicationAwareTokenAllocator.java b/src/java/org/apache/cassandra/dht/tokenallocator/ReplicationAwareTokenAllocator.java index 87dba59..efd2766 100644 --- a/src/java/org/apache/cassandra/dht/tokenallocator/ReplicationAwareTokenAllocator.java +++ b/src/java/org/apache/cassandra/dht/tokenallocator/ReplicationAwareTokenAllocator.java @@ -132,7 +132,9 @@ class ReplicationAwareTokenAllocator<Unit> extends TokenAllocatorBase<Unit> } } - return ImmutableList.copyOf(unitToTokens.get(newUnit)); + ImmutableList<Token> newTokens = ImmutableList.copyOf(unitToTokens.get(newUnit)); + TokenAllocatorDiagnostics.unitedAdded(this, numTokens, unitToTokens, sortedTokens, newTokens, newUnit); + return newTokens; } private Collection<Token> generateRandomTokens(Unit newUnit, int numTokens) @@ -148,6 +150,7 @@ class ReplicationAwareTokenAllocator<Unit> extends TokenAllocatorBase<Unit> unitToTokens.put(newUnit, token); } } + TokenAllocatorDiagnostics.randomTokensGenerated(this, numTokens, unitToTokens, sortedTokens, newUnit, tokens); return tokens; } @@ -176,6 +179,7 @@ class ReplicationAwareTokenAllocator<Unit> extends TokenAllocatorBase<Unit> curr = curr.next; } while (curr != first); + TokenAllocatorDiagnostics.tokenInfosCreated(this, unitToTokens, first); return first; } @@ -526,6 +530,7 @@ class ReplicationAwareTokenAllocator<Unit> extends TokenAllocatorBase<Unit> { Collection<Token> tokens = unitToTokens.removeAll(n); sortedTokens.keySet().removeAll(tokens); + TokenAllocatorDiagnostics.unitRemoved(this, n, unitToTokens, sortedTokens); } public int unitCount() http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorDiagnostics.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorDiagnostics.java b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorDiagnostics.java new file mode 100644 index 0000000..cc27a47 --- /dev/null +++ b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorDiagnostics.java @@ -0,0 +1,195 @@ +/* + * 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.dht.tokenallocator; + +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Queue; +import java.util.Set; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; + +import org.apache.cassandra.dht.Token; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.TokenInfo; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.UnitInfo; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.Weighted; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorEvent.TokenAllocatorEventType; +import org.apache.cassandra.diag.DiagnosticEventService; + +/** + * Utility methods for DiagnosticEvent around {@link TokenAllocator} activities. + */ +final class TokenAllocatorDiagnostics +{ + private static final DiagnosticEventService service = DiagnosticEventService.instance(); + + private TokenAllocatorDiagnostics() + { + } + + static <Unit> void noReplicationTokenAllocatorInstanciated(NoReplicationTokenAllocator<Unit> allocator) + { + if (isEnabled(TokenAllocatorEventType.NO_REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.NO_REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED, + allocator, null, null, null, null, null, null, null)); + } + + static <Unit> void replicationTokenAllocatorInstanciated(ReplicationAwareTokenAllocator<Unit> allocator) + { + if (isEnabled(TokenAllocatorEventType.REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED, + allocator, null, null, null,null, null, null, null)); + } + + static <Unit> void unitedAdded(TokenAllocatorBase<Unit> allocator, int numTokens, + Queue<Weighted<UnitInfo>> sortedUnits, NavigableMap<Token, Unit> sortedTokens, + List<Token> tokens, Unit unit) + { + if (isEnabled(TokenAllocatorEventType.UNIT_ADDED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.UNIT_ADDED, + allocator, + numTokens, + ImmutableList.copyOf(sortedUnits), + null, + ImmutableMap.copyOf(sortedTokens), + ImmutableList.copyOf(tokens), + unit, + null)); + } + + static <Unit> void unitedAdded(TokenAllocatorBase<Unit> allocator, int numTokens, + Multimap<Unit, Token> unitToTokens, NavigableMap<Token, Unit> sortedTokens, + List<Token> tokens, Unit unit) + { + if (isEnabled(TokenAllocatorEventType.UNIT_ADDED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.UNIT_ADDED, + allocator, + numTokens, + null, + ImmutableMap.copyOf(unitToTokens.asMap()), + ImmutableMap.copyOf(sortedTokens), + ImmutableList.copyOf(tokens), + unit, + null)); + } + + + static <Unit> void unitRemoved(TokenAllocatorBase<Unit> allocator, Unit unit, + Queue<Weighted<UnitInfo>> sortedUnits, Map<Token, Unit> sortedTokens) + { + if (isEnabled(TokenAllocatorEventType.UNIT_REMOVED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.UNIT_REMOVED, + allocator, + null, + ImmutableList.copyOf(sortedUnits), + null, + ImmutableMap.copyOf(sortedTokens), + null, + unit, + null)); + } + + static <Unit> void unitRemoved(TokenAllocatorBase<Unit> allocator, Unit unit, + Multimap<Unit, Token> unitToTokens, Map<Token, Unit> sortedTokens) + { + if (isEnabled(TokenAllocatorEventType.UNIT_REMOVED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.UNIT_REMOVED, + allocator, + null, + null, + ImmutableMap.copyOf(unitToTokens.asMap()), + ImmutableMap.copyOf(sortedTokens), + null, + unit, + null)); + } + + static <Unit> void tokenInfosCreated(TokenAllocatorBase<Unit> allocator, Queue<Weighted<UnitInfo>> sortedUnits, + Map<Token, Unit> sortedTokens, TokenInfo<Unit> tokenInfo) + { + if (isEnabled(TokenAllocatorEventType.TOKEN_INFOS_CREATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.TOKEN_INFOS_CREATED, + allocator, + null, + ImmutableList.copyOf(sortedUnits), + null, + ImmutableMap.copyOf(sortedTokens), + null, + null, + tokenInfo)); + } + + static <Unit> void tokenInfosCreated(TokenAllocatorBase<Unit> allocator, Multimap<Unit, Token> unitToTokens, + TokenInfo<Unit> tokenInfo) + { + if (isEnabled(TokenAllocatorEventType.TOKEN_INFOS_CREATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.TOKEN_INFOS_CREATED, + allocator, + null, + null, + ImmutableMap.copyOf(unitToTokens.asMap()), + null, + null, + null, + tokenInfo)); + } + + static <Unit> void randomTokensGenerated(TokenAllocatorBase<Unit> allocator, + int numTokens, Queue<Weighted<UnitInfo>> sortedUnits, + NavigableMap<Token, Unit> sortedTokens, Unit newUnit, + Set<Token> tokens) + { + if (isEnabled(TokenAllocatorEventType.RANDOM_TOKENS_GENERATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.RANDOM_TOKENS_GENERATED, + allocator, + numTokens, + ImmutableList.copyOf(sortedUnits), + null, + ImmutableMap.copyOf(sortedTokens), + ImmutableList.copyOf(tokens), + newUnit, + null)); + } + + static <Unit> void randomTokensGenerated(TokenAllocatorBase<Unit> allocator, + int numTokens, Multimap<Unit, Token> unitToTokens, + NavigableMap<Token, Unit> sortedTokens, Unit newUnit, + Set<Token> tokens) + { + if (isEnabled(TokenAllocatorEventType.RANDOM_TOKENS_GENERATED)) + service.publish(new TokenAllocatorEvent<>(TokenAllocatorEventType.RANDOM_TOKENS_GENERATED, + allocator, + numTokens, + null, + ImmutableMap.copyOf(unitToTokens.asMap()), + ImmutableMap.copyOf(sortedTokens), + ImmutableList.copyOf(tokens), + newUnit, + null)); + } + + private static boolean isEnabled(TokenAllocatorEventType type) + { + return service.isEnabled(TokenAllocatorEvent.class, type); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorEvent.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorEvent.java b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorEvent.java new file mode 100644 index 0000000..ca59938 --- /dev/null +++ b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorEvent.java @@ -0,0 +1,113 @@ +/* + * 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.dht.tokenallocator; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import org.apache.cassandra.dht.Token; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.TokenInfo; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.UnitInfo; +import org.apache.cassandra.dht.tokenallocator.TokenAllocatorBase.Weighted; +import org.apache.cassandra.diag.DiagnosticEvent; + +/** + * DiagnosticEvent implementation for {@link TokenAllocator} activities. + */ +final class TokenAllocatorEvent<Unit> extends DiagnosticEvent +{ + + private final TokenAllocatorEventType type; + private final TokenAllocatorBase<Unit> allocator; + private final int replicas; + @Nullable + private final Integer numTokens; + @Nullable + private final Collection<Weighted<UnitInfo>> sortedUnits; + @Nullable + private final Map<Unit, Collection<Token>> unitToTokens; + @Nullable + private final ImmutableMap<Token, Unit> sortedTokens; + @Nullable + private final List<Token> tokens; + @Nullable + private final Unit unit; + @Nullable + private final TokenInfo<Unit> tokenInfo; + + TokenAllocatorEvent(TokenAllocatorEventType type, TokenAllocatorBase<Unit> allocator, @Nullable Integer numTokens, + @Nullable ImmutableList<Weighted<UnitInfo>> sortedUnits, @Nullable ImmutableMap<Unit, Collection<Token>> unitToTokens, + @Nullable ImmutableMap<Token, Unit> sortedTokens, @Nullable ImmutableList<Token> tokens, Unit unit, + @Nullable TokenInfo<Unit> tokenInfo) + { + this.type = type; + this.allocator = allocator; + this.replicas = allocator.getReplicas(); + this.numTokens = numTokens; + this.sortedUnits = sortedUnits; + this.unitToTokens = unitToTokens; + this.sortedTokens = sortedTokens; + this.tokens = tokens; + this.unit = unit; + this.tokenInfo = tokenInfo; + } + + enum TokenAllocatorEventType + { + REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED, + NO_REPLICATION_AWARE_TOKEN_ALLOCATOR_INSTANCIATED, + UNIT_ADDED, + UNIT_REMOVED, + TOKEN_INFOS_CREATED, + RANDOM_TOKENS_GENERATED, + TOKENS_ALLOCATED + } + + public TokenAllocatorEventType getType() + { + return type; + } + + public HashMap<String, Serializable> toMap() + { + // be extra defensive against nulls and bugs + HashMap<String, Serializable> ret = new HashMap<>(); + if (allocator != null) + { + if (allocator.partitioner != null) ret.put("partitioner", allocator.partitioner.getClass().getSimpleName()); + if (allocator.strategy != null) ret.put("strategy", allocator.strategy.getClass().getSimpleName()); + } + ret.put("replicas", replicas); + ret.put("numTokens", this.numTokens); + ret.put("sortedUnits", String.valueOf(sortedUnits)); + ret.put("sortedTokens", String.valueOf(sortedTokens)); + ret.put("unitToTokens", String.valueOf(unitToTokens)); + ret.put("tokens", String.valueOf(tokens)); + ret.put("unit", String.valueOf(unit)); + ret.put("tokenInfo", String.valueOf(tokenInfo)); + return ret; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorFactory.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorFactory.java b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorFactory.java index 5fdba02..117fd09 100644 --- a/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorFactory.java +++ b/src/java/org/apache/cassandra/dht/tokenallocator/TokenAllocatorFactory.java @@ -37,9 +37,13 @@ public class TokenAllocatorFactory if(strategy.replicas() == 1) { logger.info("Using NoReplicationTokenAllocator."); - return new NoReplicationTokenAllocator<>(sortedTokens, strategy, partitioner); + NoReplicationTokenAllocator<InetAddressAndPort> allocator = new NoReplicationTokenAllocator<>(sortedTokens, strategy, partitioner); + TokenAllocatorDiagnostics.noReplicationTokenAllocatorInstanciated(allocator); + return allocator; } logger.info("Using ReplicationAwareTokenAllocator."); - return new ReplicationAwareTokenAllocator<>(sortedTokens, strategy, partitioner); + ReplicationAwareTokenAllocator<InetAddressAndPort> allocator = new ReplicationAwareTokenAllocator<>(sortedTokens, strategy, partitioner); + TokenAllocatorDiagnostics.replicationTokenAllocatorInstanciated(allocator); + return allocator; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/diag/DiagnosticEvent.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/diag/DiagnosticEvent.java b/src/java/org/apache/cassandra/diag/DiagnosticEvent.java new file mode 100644 index 0000000..5de703b --- /dev/null +++ b/src/java/org/apache/cassandra/diag/DiagnosticEvent.java @@ -0,0 +1,50 @@ +/* + * 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.diag; + +import java.io.Serializable; +import java.util.Map; + +/** + * Base class for internally emitted events used for diagnostics and testing. + */ +public abstract class DiagnosticEvent +{ + /** + * Event creation time. + */ + public final long timestamp = System.currentTimeMillis(); + + /** + * Name of allocating thread. + */ + public final String threadName = Thread.currentThread().getName(); + + /** + * Returns event type discriminator. This will usually be a enum value. + */ + public abstract Enum<?> getType(); + + /** + * Returns map of key-value pairs containing relevant event details. Values can be complex objects like other + * maps, but must be Serializable, as returned values may be consumed by external clients. It's strongly recommended + * to stick to standard Java classes to avoid distributing custom classes to clients and also prevent potential + * class versioning conflicts. + */ + public abstract Map<String, Serializable> toMap(); +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/diag/DiagnosticEventService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/diag/DiagnosticEventService.java b/src/java/org/apache/cassandra/diag/DiagnosticEventService.java new file mode 100644 index 0000000..577d0ba --- /dev/null +++ b/src/java/org/apache/cassandra/diag/DiagnosticEventService.java @@ -0,0 +1,291 @@ +/* + * 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.diag; + +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Iterables; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.cassandra.config.DatabaseDescriptor; + +/** + * Service for publishing and consuming {@link DiagnosticEvent}s. + */ +public final class DiagnosticEventService +{ + private static final Logger logger = LoggerFactory.getLogger(DiagnosticEventService.class); + + // Subscribers interested in consuming all kind of events + private ImmutableSet<Consumer<DiagnosticEvent>> subscribersAll = ImmutableSet.of(); + + // Subscribers for particular event class, e.g. BootstrapEvent + private ImmutableSetMultimap<Class<? extends DiagnosticEvent>, Consumer<DiagnosticEvent>> subscribersByClass = ImmutableSetMultimap.of(); + + // Subscribers for event class and type, e.g. BootstrapEvent#TOKENS_ALLOCATED + private ImmutableMap<Class, ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>>> subscribersByClassAndType = ImmutableMap.of(); + + private static final DiagnosticEventService instance = new DiagnosticEventService(); + + private DiagnosticEventService() + { + } + + /** + * Makes provided event available to all subscribers. + */ + public void publish(DiagnosticEvent event) + { + if (!DatabaseDescriptor.diagnosticEventsEnabled()) + return; + + logger.trace("Publishing: {}", event); + + // event class + type + ImmutableMultimap<Enum<?>, Consumer<DiagnosticEvent>> consumersByType = subscribersByClassAndType.get(event.getClass()); + if (consumersByType != null) + { + ImmutableCollection<Consumer<DiagnosticEvent>> consumers = consumersByType.get(event.getType()); + if (consumers != null) + { + for (Consumer<DiagnosticEvent> consumer : consumers) + consumer.accept(event); + } + } + + // event class + Set<Consumer<DiagnosticEvent>> consumersByEvents = subscribersByClass.get(event.getClass()); + if (consumersByEvents != null) + { + for (Consumer<DiagnosticEvent> consumer : consumersByEvents) + consumer.accept(event); + } + + // all events + for (Consumer<DiagnosticEvent> consumer : subscribersAll) + consumer.accept(event); + } + + /** + * Registers event handler for specified class of events. + * @param event DiagnosticEvent class implementation + * @param consumer Consumer for received events + */ + public synchronized <E extends DiagnosticEvent> void subscribe(Class<E> event, Consumer<E> consumer) + { + subscribersByClass = ImmutableSetMultimap.<Class<? extends DiagnosticEvent>, Consumer<DiagnosticEvent>>builder() + .putAll(subscribersByClass) + .put(event, new TypedConsumerWrapper<>(consumer)) + .build(); + } + + /** + * Registers event handler for specified class of events. + * @param event DiagnosticEvent class implementation + * @param consumer Consumer for received events + */ + public synchronized <E extends DiagnosticEvent, T extends Enum<T>> void subscribe(Class<E> event, + T eventType, + Consumer<E> consumer) + { + ImmutableSetMultimap.Builder<Enum<?>, Consumer<DiagnosticEvent>> byTypeBuilder = ImmutableSetMultimap.builder(); + if (subscribersByClassAndType.containsKey(event)) + byTypeBuilder.putAll(subscribersByClassAndType.get(event)); + byTypeBuilder.put(eventType, new TypedConsumerWrapper<>(consumer)); + + ImmutableMap.Builder<Class, ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>>> byClassBuilder = ImmutableMap.builder(); + for (Class clazz : subscribersByClassAndType.keySet()) + { + if (!clazz.equals(event)) + byClassBuilder.put(clazz, subscribersByClassAndType.get(clazz)); + } + + subscribersByClassAndType = byClassBuilder + .put(event, byTypeBuilder.build()) + .build(); + } + + /** + * Registers event handler for all DiagnosticEvents published from this point. + * @param consumer Consumer for received events + */ + public synchronized void subscribeAll(Consumer<DiagnosticEvent> consumer) + { + subscribersAll = ImmutableSet.<Consumer<DiagnosticEvent>>builder() + .addAll(subscribersAll) + .add(consumer) + .build(); + } + + /** + * De-registers event handler from receiving any further events. + * @param consumer Consumer registered for receiving events + */ + public synchronized <E extends DiagnosticEvent> void unsubscribe(Consumer<E> consumer) + { + // all events + subscribersAll = ImmutableSet.copyOf(Iterables.filter(subscribersAll, (c) -> c != consumer)); + + // event class + ImmutableSetMultimap.Builder<Class<? extends DiagnosticEvent>, Consumer<DiagnosticEvent>> byClassBuilder = ImmutableSetMultimap.builder(); + Collection<Map.Entry<Class<? extends DiagnosticEvent>, Consumer<DiagnosticEvent>>> entries = subscribersByClass.entries(); + for (Map.Entry<Class<? extends DiagnosticEvent>, Consumer<DiagnosticEvent>> entry : entries) + { + Consumer<DiagnosticEvent> subscriber = entry.getValue(); + if (subscriber instanceof TypedConsumerWrapper) + subscriber = ((TypedConsumerWrapper)subscriber).wrapped; + + if (subscriber != consumer) + { + byClassBuilder = byClassBuilder.put(entry); + } + } + subscribersByClass = byClassBuilder.build(); + + + // event class + type + ImmutableMap.Builder<Class, ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>>> byClassAndTypeBuilder = ImmutableMap.builder(); + for (Map.Entry<Class, ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>>> byClassEntry : subscribersByClassAndType.entrySet()) + { + ImmutableSetMultimap.Builder<Enum<?>, Consumer<DiagnosticEvent>> byTypeBuilder = ImmutableSetMultimap.builder(); + ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>> byTypeConsumers = byClassEntry.getValue(); + Iterables.filter(byTypeConsumers.entries(), (e) -> + { + if (e == null || e.getValue() == null) return false; + Consumer<DiagnosticEvent> subscriber = e.getValue(); + if (subscriber instanceof TypedConsumerWrapper) + subscriber = ((TypedConsumerWrapper) subscriber).wrapped; + return subscriber != consumer; + }).forEach(byTypeBuilder::put); + + ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>> byType = byTypeBuilder.build(); + if (!byType.isEmpty()) + byClassAndTypeBuilder.put(byClassEntry.getKey(), byType); + } + + subscribersByClassAndType = byClassAndTypeBuilder.build(); + } + + /** + * Indicates if any {@link Consumer} has been registered for the specified class of events. + * @param event DiagnosticEvent class implementation + */ + public <E extends DiagnosticEvent> boolean hasSubscribers(Class<E> event) + { + return !subscribersAll.isEmpty() || subscribersByClass.containsKey(event) || subscribersByClassAndType.containsKey(event); + } + + /** + * Indicates if any {@link Consumer} has been registered for the specified class of events. + * @param event DiagnosticEvent class implementation + * @param eventType Subscribed event type matched against {@link DiagnosticEvent#getType()} + */ + public <E extends DiagnosticEvent, T extends Enum<T>> boolean hasSubscribers(Class<E> event, T eventType) + { + if (!subscribersAll.isEmpty()) + return true; + + ImmutableSet<Consumer<DiagnosticEvent>> subscribers = subscribersByClass.get(event); + if (subscribers != null && !subscribers.isEmpty()) + return true; + + ImmutableSetMultimap<Enum<?>, Consumer<DiagnosticEvent>> byType = subscribersByClassAndType.get(event); + if (byType == null || byType.isEmpty()) return false; + + Set<Consumer<DiagnosticEvent>> consumers = byType.get(eventType); + return consumers != null && !consumers.isEmpty(); + } + + /** + * Indicates if events are enabled for specified event class based on {@link DatabaseDescriptor#diagnosticEventsEnabled()} + * and {@link #hasSubscribers(Class)}. + * @param event DiagnosticEvent class implementation + */ + public <E extends DiagnosticEvent> boolean isEnabled(Class<E> event) + { + return DatabaseDescriptor.diagnosticEventsEnabled() && hasSubscribers(event); + } + + /** + * Indicates if events are enabled for specified event class based on {@link DatabaseDescriptor#diagnosticEventsEnabled()} + * and {@link #hasSubscribers(Class, Enum)}. + * @param event DiagnosticEvent class implementation + * @param eventType Subscribed event type matched against {@link DiagnosticEvent#getType()} + */ + public <E extends DiagnosticEvent, T extends Enum<T>> boolean isEnabled(Class<E> event, T eventType) + { + return DatabaseDescriptor.diagnosticEventsEnabled() && hasSubscribers(event, eventType); + } + + public static DiagnosticEventService instance() + { + return instance; + } + + /** + * Removes all active subscribers. Should only be called from testing. + */ + public synchronized void cleanup() + { + subscribersByClass = ImmutableSetMultimap.of(); + subscribersAll = ImmutableSet.of(); + subscribersByClassAndType = ImmutableMap.of(); + } + + /** + * Wrapper class for supporting typed event handling for consumers. + */ + private static class TypedConsumerWrapper<E> implements Consumer<DiagnosticEvent> + { + private final Consumer<E> wrapped; + + private TypedConsumerWrapper(Consumer<E> wrapped) + { + this.wrapped = wrapped; + } + + public void accept(DiagnosticEvent e) + { + wrapped.accept((E)e); + } + + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TypedConsumerWrapper<?> that = (TypedConsumerWrapper<?>) o; + return Objects.equals(wrapped, that.wrapped); + } + + public int hashCode() + { + return Objects.hash(wrapped); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/gms/Gossiper.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 7bb2583..170843b 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -381,6 +381,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean { markDead(endpoint, epState); } + + GossiperDiagnostics.convicted(this, endpoint, phi); } /** @@ -398,6 +400,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean epState.getHeartBeatState().forceHighestPossibleVersionUnsafe(); markDead(endpoint, epState); FailureDetector.instance.forceConviction(endpoint); + GossiperDiagnostics.markedAsShutdown(this, endpoint); } /** @@ -428,6 +431,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean quarantineEndpoint(endpoint); if (logger.isDebugEnabled()) logger.debug("evicting {} from gossip", endpoint); + GossiperDiagnostics.evictedFromMembership(this, endpoint); } /** @@ -453,6 +457,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean MessagingService.instance().destroyConnectionPool(endpoint); if (logger.isDebugEnabled()) logger.debug("removing endpoint {}", endpoint); + GossiperDiagnostics.removedEndpoint(this, endpoint); } /** @@ -474,6 +479,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean private void quarantineEndpoint(InetAddressAndPort endpoint, long quarantineExpiration) { justRemovedEndpoints.put(endpoint, quarantineExpiration); + GossiperDiagnostics.quarantinedEndpoint(this, endpoint, quarantineExpiration); } /** @@ -485,6 +491,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean // remember, quarantineEndpoint will effectively already add QUARANTINE_DELAY, so this is 2x logger.debug(""); quarantineEndpoint(endpoint, System.currentTimeMillis() + QUARANTINE_DELAY); + GossiperDiagnostics.replacementQuarantine(this, endpoint); } /** @@ -498,6 +505,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean removeEndpoint(endpoint); evictFromMembership(endpoint); replacementQuarantine(endpoint); + GossiperDiagnostics.replacedEndpoint(this, endpoint); } /** @@ -688,7 +696,10 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean if (firstSynSendAt == 0) firstSynSendAt = System.nanoTime(); MessagingService.instance().sendOneWay(message, to); - return seeds.contains(to); + + boolean isSeed = seeds.contains(to); + GossiperDiagnostics.sendGossipDigestSyn(this, to); + return isSeed; } /* Sends a Gossip message to a live member and returns true if the recipient was a seed */ @@ -889,6 +900,31 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return endpointStateMap.size(); } + Map<InetAddressAndPort, EndpointState> getEndpointStateMap() + { + return ImmutableMap.copyOf(endpointStateMap); + } + + Map<InetAddressAndPort, Long> getJustRemovedEndpoints() + { + return ImmutableMap.copyOf(justRemovedEndpoints); + } + + Map<InetAddressAndPort, Long> getUnreachableEndpoints() + { + return ImmutableMap.copyOf(unreachableEndpoints); + } + + Set<InetAddressAndPort> getSeedsInShadowRound() + { + return ImmutableSet.copyOf(seedsInShadowRound); + } + + long getLastProcessedMessageAt() + { + return lastProcessedMessageAt; + } + public UUID getHostId(InetAddressAndPort endpoint) { return getHostId(endpoint, endpointStateMap); @@ -1028,6 +1064,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean }; MessagingService.instance().sendRR(echoMessage, addr, echoHandler); + + GossiperDiagnostics.markedAlive(this, addr, localState); } @VisibleForTesting @@ -1046,6 +1084,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean subscriber.onAlive(addr, localState); if (logger.isTraceEnabled()) logger.trace("Notified {}", subscribers); + + GossiperDiagnostics.realMarkedAlive(this, addr, localState); } @VisibleForTesting @@ -1061,6 +1101,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean subscriber.onDead(addr, localState); if (logger.isTraceEnabled()) logger.trace("Notified {}", subscribers); + + GossiperDiagnostics.markedDead(this, addr, localState); } /** @@ -1101,6 +1143,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean // check this at the end so nodes will learn about the endpoint if (isShutdown(ep)) markAsShutdown(ep); + + GossiperDiagnostics.majorStateChangeHandled(this, ep, epState); } public boolean isAlive(InetAddressAndPort endpoint) http://git-wip-us.apache.org/repos/asf/cassandra/blob/2846b22a/src/java/org/apache/cassandra/gms/GossiperDiagnostics.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/gms/GossiperDiagnostics.java b/src/java/org/apache/cassandra/gms/GossiperDiagnostics.java new file mode 100644 index 0000000..57552cc --- /dev/null +++ b/src/java/org/apache/cassandra/gms/GossiperDiagnostics.java @@ -0,0 +1,113 @@ +/* + * 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.gms; + + +import org.apache.cassandra.diag.DiagnosticEventService; +import org.apache.cassandra.gms.GossiperEvent.GossiperEventType; +import org.apache.cassandra.locator.InetAddressAndPort; + +/** + * Utility methods for DiagnosticEvent activities. + */ +final class GossiperDiagnostics +{ + private static final DiagnosticEventService service = DiagnosticEventService.instance(); + + private GossiperDiagnostics() + { + } + + static void markedAsShutdown(Gossiper gossiper, InetAddressAndPort endpoint) + { + if (isEnabled(GossiperEventType.MARKED_AS_SHUTDOWN)) + service.publish(new GossiperEvent(GossiperEventType.MARKED_AS_SHUTDOWN, gossiper, endpoint, null, null)); + } + + static void convicted(Gossiper gossiper, InetAddressAndPort endpoint, double phi) + { + if (isEnabled(GossiperEventType.CONVICTED)) + service.publish(new GossiperEvent(GossiperEventType.CONVICTED, gossiper, endpoint, null, null)); + } + + static void replacementQuarantine(Gossiper gossiper, InetAddressAndPort endpoint) + { + if (isEnabled(GossiperEventType.REPLACEMENT_QUARANTINE)) + service.publish(new GossiperEvent(GossiperEventType.REPLACEMENT_QUARANTINE, gossiper, endpoint, null, null)); + } + + static void replacedEndpoint(Gossiper gossiper, InetAddressAndPort endpoint) + { + if (isEnabled(GossiperEventType.REPLACED_ENDPOINT)) + service.publish(new GossiperEvent(GossiperEventType.REPLACED_ENDPOINT, gossiper, endpoint, null, null)); + } + + static void evictedFromMembership(Gossiper gossiper, InetAddressAndPort endpoint) + { + if (isEnabled(GossiperEventType.EVICTED_FROM_MEMBERSHIP)) + service.publish(new GossiperEvent(GossiperEventType.EVICTED_FROM_MEMBERSHIP, gossiper, endpoint, null, null)); + } + + static void removedEndpoint(Gossiper gossiper, InetAddressAndPort endpoint) + { + if (isEnabled(GossiperEventType.REMOVED_ENDPOINT)) + service.publish(new GossiperEvent(GossiperEventType.REMOVED_ENDPOINT, gossiper, endpoint, null, null)); + } + + static void quarantinedEndpoint(Gossiper gossiper, InetAddressAndPort endpoint, long quarantineExpiration) + { + if (isEnabled(GossiperEventType.QUARANTINED_ENDPOINT)) + service.publish(new GossiperEvent(GossiperEventType.QUARANTINED_ENDPOINT, gossiper, endpoint, quarantineExpiration, null)); + } + + static void markedAlive(Gossiper gossiper, InetAddressAndPort addr, EndpointState localState) + { + if (isEnabled(GossiperEventType.MARKED_ALIVE)) + service.publish(new GossiperEvent(GossiperEventType.MARKED_ALIVE, gossiper, addr, null, localState)); + } + + static void realMarkedAlive(Gossiper gossiper, InetAddressAndPort addr, EndpointState localState) + { + if (isEnabled(GossiperEventType.REAL_MARKED_ALIVE)) + service.publish(new GossiperEvent(GossiperEventType.REAL_MARKED_ALIVE, gossiper, addr, null, localState)); + } + + static void markedDead(Gossiper gossiper, InetAddressAndPort addr, EndpointState localState) + { + if (isEnabled(GossiperEventType.MARKED_DEAD)) + service.publish(new GossiperEvent(GossiperEventType.MARKED_DEAD, gossiper, addr, null, localState)); + } + + static void majorStateChangeHandled(Gossiper gossiper, InetAddressAndPort addr, EndpointState state) + { + if (isEnabled(GossiperEventType.MAJOR_STATE_CHANGE_HANDLED)) + service.publish(new GossiperEvent(GossiperEventType.MAJOR_STATE_CHANGE_HANDLED, gossiper, addr, null, state)); + } + + static void sendGossipDigestSyn(Gossiper gossiper, InetAddressAndPort to) + { + if (isEnabled(GossiperEventType.SEND_GOSSIP_DIGEST_SYN)) + service.publish(new GossiperEvent(GossiperEventType.SEND_GOSSIP_DIGEST_SYN, gossiper, to, null, null)); + } + + private static boolean isEnabled(GossiperEventType type) + { + return service.isEnabled(GossiperEvent.class, type); + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org