You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sa...@apache.org on 2023/11/23 19:05:33 UTC
(cassandra) branch cep-21-tcm updated (ece8e960e3 -> c6a6822a66)
This is an automated email from the ASF dual-hosted git repository.
samt pushed a change to branch cep-21-tcm
in repository https://gitbox.apache.org/repos/asf/cassandra.git
omit ece8e960e3 [CEP-21] Add initial notes to NEWS.txt
omit 30da332407 [CEP-21] Improve setup and initialisation of LocalLog
omit 500b47ed46 Fix long compactions test: since we are waiting on futures, we should rely on executor metrics instead of “estimate” that is used for metrics.
omit ad3435ec7f [CEP-21] Don't notify subscribers if a registered but unjoined node is DOWN
omit 72f6eb488b [CEP-21] Fix EphemeralSnapshotTest
omit 5948077037 [CEP-21] Fix CQLSSTableWriterConcurrencyTest
omit 9d2e9f2e50 [CEP-21] Rebase fix ControllerTest
omit 150c04901d [CEP-21] Fix DescribeStatementTest
omit 3243c841bd [CEP-21] Ignore schema push/pull messages
omit 81017dfdc5 [CEP-21] Add system_ prefix to cluster_metadata log
omit 15a6718c92 [CEP-21] Create initial CM with the same RF on all replicas
omit 8dce7af795 [CEP-21] Don't replayPersisted during normal catchup
omit e5a4f3011b squash with [CEP-21] Scrub data dirs earlier in process startup
omit e53b972467 [CEP-21] Actually merge endpoint states during gossip upgrade
omit de1ad09269 [CEP-21] If we can't gossip with anyone, populate initial CM from system tables on upgrade
omit 58dfb0a281 Use _write_ contacts for read repair, but use _original read_ contacts for selector.
omit 14f5124565 Split TransientRangeMovementTest in two.
omit 12949c928e [CEP-21] Update tests to handle new gossip shutdown
omit 72b151e7b5 Fix InternodeEncryptionEnforcementTest#testOutboundConnectionsAreInterruptedWhenAuthFails
omit da4c68378c [CEP-21] Scrub data dirs earlier in process startup
omit bd4c8ebec8 [CEP-21] Slightly relax ALTER restrictions on table with indexes
omit 5c62ca0041 [CEP-21] Schema alterations should only operate on metadata
omit 91dafcc6b3 [CEP-21] Don't add log listeners until local replay is complete
omit f15196d91a [CEP-21] Break circular metadata dependency during view creation
omit 62ad94d797 [CEP-21] Fail fast if attempting to replace a live peer
omit 966c1822f0 [CEP-21] Fixes for aborting failed bootstrap
omit badec8d5c1 [CEP-21] Remove specialized replica plan for read repair
omit 3141b967d3 [CEP-21] Minor cleanup to BatchlogManager
omit 2dc48debd3 [CEP-21] Write survey mode should halt before MID step
omit 22f232fdac Fix InternodeEncryptionEnforcementTest
omit 2dfafd13d1 [CEP-21] Fix jvm upgrade dtests
omit 046b6a1e2a [CEP-21] Fix GossipShutdownTest
omit 57760e976b set localdc
omit 5f40af00ad [CEP-21] fix ColumnFamilyStoreClientModeTest
omit d798370e93 [CEP-21] fix CompactionStressTest
omit f9635c6de8 Fix AlterTest
omit 4a26753273 [CEP-21] fix LongStreamingTest
omit 7cf6f20aac [CEP-21] fix DynamicEndpointSnitchLongTest
omit 0230ef6c52 Fix CommitLogSegmentManagerCDCTest
omit 8bb481b858 fix FailureDetectorTest
omit 0b5c3b2327 Re-fix tests after rebase
omit 00e5668fc2 Fix consistent bootstrap test
omit 6da22893b7 Remove a duplicate resumable bootstrap test
omit aa15552cad Fix BootstrapTest
omit c61c724e25 Fix BootstrapTest
omit 67a65f221e Improve a fix for DecommissionTest
omit 47ff21e2bb Fix auth dtest
omit 75cb7fd949 fix DropRecreateAndRestoreTest
omit 6b51dd00c1 fix StorageServiceDrainTest
omit 2d73a09005 fix GuardrailTablesTest
omit ede37e2666 ignore PendingRangesTest for now
omit 6415d95006 fix guardrailstest
omit ccac77ae77 Fix read command serialization after rebase
omit b5c3c0df3e Fix DecomissionTest tests
omit 680d54630b Fix DecomissionTest tests
omit df808a75d2 Fix StorageServiceTest tests
omit e0abb22f7a [CEP-21] Add since to new deprecation annotations
omit 9731d5d5be [CEP-21] Fix ReplicaPlan.ForFullRangeRead after rebase
omit 0b8794e6a8 [CEP-21] Remove unused GlobalPlacementDelta class
omit 4e88a3e1f7 [CEP-21] Simplify scope-local retries using Entry.Id
omit 2ab5bb6291 [CEP-21] Use epoch-based table ids by default
omit 4b244dc566 [CEP-21] Rationalise method order in MultiStepOperation & impls
omit 81bf4b9512 [CEP-21] Clean up InProgressSequences keys
omit 10479d5a50 [CEP-21] Move Kind from InProgressSequences to MultiStepOperation
omit 804ed4100c [CEP-21] Rename InProgressSequence to MultiStepOperation
omit a3c765af8c [CEP-21] Refactor multi step operations
omit 6c9cc05557 [CEP-21] Add a way to reject a transformation by throwing a special kind of exception.
omit 3f606b62c6 [CEP-21] Make RackInferringSnitch work with ClusterMetadata
omit 9523b4673b [CEP-21] DC and Rack startup checks cannot be disabled
omit 7d8d3669ad [CEP-21] PropertyFileSnitch is responsible for local node location only
omit 42c0d08b3e [CEP-21] Improve Comments
omit facd50d492 [CEP-21] Allow unknown nodes during discovery
omit 3d9bdf2ba5 [CEP-21] Split logic previously contained in SS across corresponding classes.
omit 6e5821bea0 [CEP-21] Test Assigning the same token to several nodes
omit 2c9449ad6e [CEP-21] Improve CMS handoff and configuration
omit bc87aea05a Use pinned Harry version
omit 370badc21d Add implementation overview doc
omit 8841c544e0 [CEP-21] fix GossiperTest - this test now matches trunk
omit d97879983d [CEP-21] CASSANDRA-18816 rebase fixes
omit 45d2f19e11 update dtest repo for cci
omit 5c68f8de5d [CEP-21] fix cqlshlib tests
omit 5afd598d35 [CEP-21] remove authsetup
omit 7d4d72d447 [CEP-21] serialize MemtableParams when writing TableParams
omit 8d2e89b1aa [CEP-21] Upgrading a one node cluster to TCM fails attempting Gossip shadow round
omit 1fe86bfd3e [CEP-21] Implement replacement with same address
omit 5629c8c3b1 [CEP-21] fix nodetool bootstrap resume
omit b188c32041 [CEP-21] Remove LEFT peers from system tables and exclude them during startup
omit 6aeb59eb73 [CEP-21] Fix flaky distributed log test. While it fails very infrequently on CI, it consistently fails locally.
omit 46889005e8 [CEP-21] Retry indefinitely for STARTUP messages.
omit de2ad6ff2a [CEP-21] Implement versioning for ranges
omit 8154008a8d [CEP-21] Handle case where removenode requires no streaming to restore RF
omit 00f5bd960a [CEP-21] Remove redundant Keyspaces arg from SchemaTransformation::apply
omit f60db8972a [CEP-21] Don't trigger client warnings or guardrails when executing AlterSchema transformations
omit d68c705763 [CEP-21] Validate schema alterations on coordinator
omit 0c70500150 [CEP-21] Add a script for simulation running
omit 8cdbbe2ed2 [CEP-21] Add nextId to Directory serialization and make it possible to bump metadata serialization version
omit 23f652ec39 [CEP-21] Add metric for CMS membership
omit d08744c664 [CEP-21] Reenable starting without joining (-Dcassandra.join_ring=false)
omit 58565908ed [CEP-21] Preparing DDL statements should capture the CQL string
omit 3a621821be rebase
omit b2d16f0a34 [CEP-21] Work with Storage Compatiblility Mode
omit bda6415113 storage_compat_mode: none
omit f1d552ff8c [CEP-21] Update tests which require the local node not to be joined by default
omit 441a95906a more test fixes
omit 5f6266e382 fix UnifiedCompactionStrategyTest
omit cfe1350594 rebase fix
omit 9d7381fe7f Fix ByteBuddyExamplesTest
omit 6847903df8 rebase fixes
omit 07240e891c [CEP-21] Evict replaced endpoint from gossip
omit 79ae0bcdb7 [CEP-21] Avoid gossip deadlock by grabbing taskLock before runInGossipStageBlocking
omit ccfaf364d4 [CEP-21] Python dtest fixes * maybe fix hintedhandoff test
omit 30e9e9061a [CEP-21] More in-jvm dtest fixes
omit f181d35876 [CEP-21] Use harry for generating data for coordinator path test
omit e2de6a40de [CEP-21] Various JVM Dtest fixes
omit 2bd9030720 [CEP-21] Fix flaky consistentleave test
omit 1be09fdf6f [CEP-21] Fix assassinate dtests
omit 2a022c5c2c [CEP-21] Fix MoveTest
omit 04538052b1 [CEP-21] Fix paxos self execution tests
omit 753bf106fe [CEP-21] Fix IPMembershipTest
omit 1065d4519d [CEP-21] Fix reprepare tests
omit 69e48a97db [CEP-21] Reduce number of data harry writes to reduce flakiness
omit 7fc1d7b02f [CEP-21] Fix replacement tests
omit 50c891a1a5 [CEP-21] Fix o.a.c.dht.BootstrapperTest
omit b4d078ba18 [CEP-21] Fix o.a.c.service.BootstrapTransientTest
omit a936c8e1a7 [CEP-21] Fix o.a.c.db.StreamRequestTest
omit 53f203aa51 [CEP-21] Fix o.a.c.streaming.StreamRateLimiterTest
omit 3d8a943db0 [CEP-21] Fix o.a.c.tools.TopPartitionsTest
omit 47e4375642 [CEP-21] Fix o.a.c.io.sstable.format.RangeAwareSSTableWriterTest
omit e993a29238 [CEP-21] Disable auto metadata snapshots during tests
omit b9e4917398 [CEP-21] Fix o.a.c.tcm.ownership.DeltaMapTest
omit 644d5c9f23 [CEP-21] Syncronize processing of LocalLog in test code
omit 5d5abbaec7 [CEP-21] Fix MockSchema to use supplied keyspace name
omit 1b31759702 [CEP-21] Fix o.a.c.db.view.ViewUtilsTest
omit 680f99dbcf [CEP-21] Fix o.a.c.service.reads.repair.[BlockingReadRepairTest|DiagEventsBlockingReadRepairTest]
omit 51b6ee5670 [CEP-21] Restore previous behaviour when fetching effective ownership for a local system keyspace
omit b2d2b11631 [CEP-21] Fix o.a.c.db.CleanupTest
omit 27f827a86e [CEP-21] Fix o.a.c.tcm.RemoteProcessorTest
omit 96f7a04c3e [CEP-21] Remove obsolete o.a.c.locator.ReplicationStrategyEndpointCacheTest
omit a828f9c3aa [CEP-21] Fix o.a.c.locator.DynamicEndpointSnitchTest
omit 5646810eec [CEP-21] Fix o.a.c.locator.ReplicaPlansTest
omit fd20741986 [CEP-21] Fix o.a.c.tcm.transformations.EventsMetadataTest
omit 974ee12234 [CEP-21] Fix o.a.c.tcm.transformations.PrepareLeaveTest
omit d3a4d9a6ee [CEP-21] Fix o.a.c.cql3.KeyCacheCqlTest
omit 66d65511f4 [CEP-21] Remove o.a.c.gms.ExpireEndpointTest.java (CMS updates now remove from gossip)
omit 2e75f99c2e [CEP-21] Remove o.a.c.gms.PendingRangeCalculatorServiceTest
omit c0c7e9aa3b [CEP-21] Fix o.a.c.db.CleanupTransientTest
omit cecd76f9d5 [CEP-21] Fix o.a.c.db.ColumnFamilyMetricTest
omit 1766da3c98 [CEP-21] Fix o.a.c.db.VerifyTest
omit a001dd386a [CEP-21] Fix o.a.c.db.compaction.writers.CompactionAwareWriterTest
omit a64278c1d1 [CEP-21] Remove o.a.c.schema.RemoveWithoutDroppingTest
omit ebf57e45b3 [CEP-21] Fix o.a.c.schema.SchemaKeyspaceTest
omit 64e429bd6a [CEP-21] Rewrite o.a.c.service.StorageServiceServerTest
omit 36157a3832 [CEP-21] Fix o.a.c.gms.GossiperTest
omit f46d97f150 [CEP-21] Fix o.a.c.tcm.ClusterMetadataTransformationTest
omit 1ce7e50cc0 [CEP-21] Fix o.a.c.tcm.RemoteProcessorTest
omit 62b89405be [CEP-21] Fix o.a.c.service.StorageProxyTest
omit a185a953c6 [CEP-21] Additional tests which no longer need to manually create system_auth
omit d9dea379bf [CEP-21] Fix o.a.c.service.StorageServiceServerM3PTest
omit 734572a3d9 [CEP-21] Fix o.a.c.service.PartitionDenylistTest
omit 460619376f [CEP-21] Fix o.a.c.service.JoinTokenRingTest
omit c350847940 [CEP-21] Adjust test for GossipInfo now STATUS is removed
omit 65c670dccd [CEP-21] Tests no longer need to manually create system_auth
omit fedf1784db [CEP-21] Fix o.a.c.tools.StandaloneSplitterWithCQLTesterTest
omit cf7082d141 [CEP-21] Fix o.a.c.tools.JMXCompatibilityTest
omit 6f3407291f [CEP-21] Fix o.a.c.service.reads.range.TokenUpdater
omit 681b0949eb [CEP-21] Fix o.a.c.service.LegacyAuthFailTest
omit ce05431ad5 [CEP-21] Fix o.a.c.db.virtual.StreamingVirtualTableTest
omit 254a329e5d [CEP-21] Fix o.a.c.db.virtual.LocalRepairTablesTest
omit f65d97d4bd [CEP-21] Fix o.a.c.db.virtual.JmxPermissionsCacheKeysTableTest
omit b825bcecdd [CEP-21] fix o.a.c.db.rows.ThrottledUnfilteredIteratorTest
omit db18fd3605 [CEP-21] Fix o.a.c.db.compaction.CompactionStrategyManagerBoundaryReloadTest
omit 1ed20fc175 [CEP-21] Fix o.a.c.db.TopPartitionTrackerTest
omit d013fc4322 [CEP-21] Fix o.a.c.db.KeyspaceTest
omit 7bcf2c0ae3 [CEP-21] Fix o.a.c.db.DiskBoundaryManagerTest
omit 6e38192bc4 [CEP-21] Fix o.a.c.cql3.validation.operations.DropRecreateAndRestoreTest
omit a09c15f13e [CEP-21] Fix o.a.c.cql3.validation.operations.AlterNTSTest
omit 6f7ee008a4 [CEP-21] Fix o.a.c.cql3.validation.entities.SecondaryIndexTest
omit 2387ba79ff [CEP-21] Fix o.a.c.cql3.statements.DescribeStatementTest
omit 3916f51482 [CEP-21] Fix o.a.c.cql3.OutOfSpaceTest
omit 4bb169cb45 [CEP-21] Fix o.a.c.cql3.Memtable*Test
omit fe435a18d8 [CEP-21] Adjust to new Register checks
omit f7cfa7ba6b [CEP-21] Fix o.a.c.cql3.BatchTest
omit 2822f3ea7f [CEP-21] Remove superseded join/move/leave/remove unit tests
omit d4c2daee7f [CEP-21] Move CQLTester initialisation from static block to @BeforeClass
omit 41244023b6 [CEP-21] Move local node registration from CQLTester -> ServerTestUtils
omit 1ae6f215c1 [CEP-21] Fix nodetool cache invalidation tests
omit 996ac90ec5 [CEP-21] Update tests which require the local node not to be joined by default
omit da94e0cf0b [CEP-21] Fix/remove fixture setup in several CQLTester subclasses
omit d811409819 [CEP-21] Fix o.a.c.db.compaction.CompactionIteratorTest
omit 279adab583 [CEP-21] Fix o.a.c.locator.ReplicationFactorTest
omit 34eeae8bd2 [CEP-21] Fix o.a.c.locator.NetworkTopologyStrategyTest
omit 27d6547740 [CEP-21] Fix third party snitch tests
omit 0f7bf6e746 [CEP-21] fix o.a.c.tools.SSTableExportSchemaLoadingTest
omit a61f04aa70 [CEP-21] fix o.a.c.dht.tokenallocator.TokenAllocationTest
omit afebbb5e12 [CEP-21] Bring back (most of) ring/BootstrapTest
omit 1ccb947498 [CEP-21] Remove redundant or outdated tests
omit 12ff38c435 [CEP-21] make ColumnFamilyStoreClientModeTest build
omit 7cc3030dfc [CEP-21] fix MutualTls tests
omit 1e60f5868f [CEP-21] Escape infinite local log loop on replica mis-configuration
omit bb67eb22c8 [CEP-21] Fix issue when catching up from snapshot and the pending log is non-consecutive
omit 6ae65d7b91 [CEP-21] Multi cms simulation, Deadlines for local processor, reworked retries for local and remote processor
omit ab5e83e62f [CEP-21] Fix batchlog consistency errors during epoch bumps
omit f08681e695 [CEP-21] Add keyspace to read and write recompute
omit 33492b377c [CEP-21] Avoid using batches in distributed metadata log keyspace
omit e192051984 [CEP-21] Exclude meta keyspace from TableMetrics::totalNonSystemTablesSize
omit 4fc7f88344 [CEP-21] Don't warn about new system tables in StartupCheck
omit 794165687d [CEP-21] Simplistic schema metadata diff
omit 176ade37e7 [CEP-21] Fix table metadata serialization
omit dc759e16ff [CEP-21] Issues found during upgrade testing
omit 3f39823186 [CEP-21] Extend nodetool describecms output (#3507)
omit 8740da1532 [CEP-21] add more metrics
omit ea97f99769 [CEP-21] Simulator harry integration
omit f4b7753eff [CEP-21] getHostIdForEndpoint return null if unknown endpoint
omit cff48ee5a1 [CEP-21] Add nodetool command to remove from CMS
omit 76679d5c66 [CEP-21] Transfer CMS membership before replacement (#3498)
omit 3a3c4fd801 [CEP-21] Update system.local host id on upgrades, and bounces to fix current broken cluster (#3496)
omit a0ed4a08b8 [CEP-21] Support catching up from peers
omit 7fdbc41af4 [CEP-21] Require Paxos V2 for cluster metadata log operations
omit b6ace02924 [CEP-21] Mark successful migration as complete on nodes which did not initiate it
omit a5dd204129 [CEP-21] Disaster recovery
omit 719a087378 [CEP-21] Reenable write survey mode
omit 7ebf4ce89e [CEP-21] Switch nodeId from uuid to int
omit 97a036930f [CEP-21] Make CQLSSTableWriter exclusively a client utility
omit 4cbe13089e [CEP-21] When deserializing partition update, allow if current epoch >= serialized epoch
omit 9962dbacb0 [CEP-21] ClusterMetadata::writePlacementAllSettled handles bootstrapping nodes correctly
omit 111cd559cc [CEP-21] Allow Schema.instance to be initialized empty for client apps
omit 298ec6c53a [CEP-21] Update bootstrap log messages to match trunk
omit 9743924eb3 [CEP-21] Support nodetool assasinate
omit 8aa3a2c75a [CEP-21] avoid npe when replaying from snapshot and endpoint shows up first time as LEFT (#3499)
omit 438437ea05 [CEP-21] Don't invalidate prepared stmt cache on every schema change
omit 17b3125b20 [CEP-21] In progress sequence updates
omit cc550edb14 [CEP-21] Simplify check for whether DROP COMPACT STORAGE is permitted
omit 1b30682139 [CEP-21] Enforce data ownership checks
omit 8f96670369 [CEP-21] Gossip fixes
omit dc30995c10 [CEP-21] DC and RF aware acknowledgments for multistep operations
omit 65172939b9 [CEP-21] Re-enable startup checks on non-test initialization
omit 5e53087e33 [CEP-21] Unify streaming: make all operations use explicit ranges for streaming
omit 7cf8aedc22 [CEP-21] Add vtable for metadata log
omit 1cf25fe7eb [CEP-21] Add exception code to commit result if rejected
omit 9502d945d8 [CEP-21] Simulate NTS
omit b0803a9ed2 [CEP-21] Fix eclipse warning
omit 8fe5b1a5a5 [CEP-21] Don't include system_distributed in initial schema
omit 3ee48f86cf [CEP-21] Make cleanup safe to run during range movements
omit 1499d2c6e6 [CEP-21] Remove some of the remaining vestiges of schema pulling
omit 7c0fce2958 [CEP-21] ReplicaPlan recomputation and stillAppliesTo implementation for Paxos
omit 1f4a604dbc [CEP-21] Update index status fixes post-rebase
omit da5cb363a4 [CEP-21] Create new auth tables, remove cidr constants for column names
omit b79ce02e13 Circle config
omit 3e82c5b26c [CEP-21] Reinstate client notifications for joining/leaving/moving nodes
omit ffaca079cb [CEP-21] Fix tools tests
omit 9c9ad75e06 [CEP-21] Avoid NPE when getting dc/rack for not yet registered endpoints
omit f688ad31a1 [CEP-21] Ensure that ClusterMetadata::forceEpoch keeps component epochs consistent
omit 90cef91726 [CEP-21] Rewrite o.a.c.distributed.test.SchemaTest
omit 9fed3f0d21 [CEP-21] During startup, don't open SSTables until local metadata log replay is complete
omit 4bdf93b788 [CEP-21] Ensure that SchemaTransformation impls correctly set TableMetadata epoch
omit f4a58f2460 [CEP-21] During startup request replay from CMS asynchronously
omit 6db4fe98e7 [CEP-21] Implement multi-dc placement simulator for NTS
omit 86a1120b3f [CEP-21] Fix (re)building MVs
omit 6c4979f4c5 [CEP-21] Add invalid routing exception
omit 4de7b54f6d [CEP-21] Improve support for start/end tokens in nodetool rebuild
omit ccec909638 [CEP-21] Implement retries for log replay on CMS members
omit f67014df78 [CEP-21] Remove paranoid check during SRPP
omit c491b8d1b1 [CEP-21] Always use Paxos.v2 for global log reads/writes
omit 5af7c0c042 [CEP-21] Various fixes to in-jvm dtests
omit 4398452452 [CEP-21] Improve seedlist inspection at startup
omit 349de29162 [CEP-21] Always populate local gossip state at startup
omit 9520b9cb28 [CEP-21] Add debounce to log replay
omit 84b25332e6 [CEP-21] During multi step operations, defer token map update until completion of final step
omit 523abe8dfa [CEP-21] Dereference TableMetadata in simple partition builder
omit 47b13e5ef1 [CEP-21] Ensure that global log replication factor is maintained after decommission
omit 9cdf39ab28 [CEP-21] Re-enable stdout/sterr redirection at startup
omit fe0f81c714 [CEP-21] Secondary indexes should not be rebuilt on restart
omit 272ebd8efe [CEP-21] Fix nodetool ring and effective ownership
omit e4e4cbd86e [CEP-21] Correctly represent bootstrapping nodes in StorageService
omit d2606ce6fe TMP - use bundled version of harry
omit 898816a478 [CEP-21] Bulk update of unit and dtests
omit 2c2eb6206d [CEP-21] Test / build config changes
omit 0209f563d9 [CEP-21] Modify CassandraDaemon
omit 44f5f19fa4 [CEP-21] Update snitches to use Directory
omit 0342efb0e0 [CEP-21] Upgrade support
omit 2a02032a4d [CEP-21] Option to record thread creation stacktrace
omit 7f7deb77f9 [CEP-21] Add missing implementations to concurrent utils
omit 8f38d93813 [CEP-21] New nodetool commands
omit 856b681a90 [CEP-21] Restore operation mode reporting (7/7)
omit 97d22f307e [CEP-21] Remove TokenMetadata (6/7)
omit 49c4753bbe [CEP-21] Fix misc compilation errors (5/7)
omit e59258a360 [CEP-21] Update ColumnFamilyStore (4/7)
omit e0d3352345 [CEP-21] Consistent read/write path (3/7)
omit 9a335c3e1a [CEP-21] Placement and ownership related changes (2/7)
omit d4772dd982 [CEP-21] Major changes to StorageService to remove TMD and Gossip (1/7)
omit f8d925bb41 [CEP-21] Replace fake initial implementation of CMS membership
omit 0f5063439d [CEP-21] Start to remove and deprecate gossip functionality
omit a25b137146 [CEP-21] Initial transforms for modifying ownership
omit 09c97548c2 [CEP-21] Produce placements equivalent to current replication strategies
omit 14b7a9454a [CEP-21] Add basics of ownership and data placement
omit 69dd053715 [CEP-21] Add rudimentary cluster membership to TCM
omit 22c0f439ac [CEP-21] Include current epoch in internode header
omit fbd39b5d28 [CEP-21] Move schema management to TCM
omit 3c7eefaa88 [CEP-21] Add distributed metadata log
add c26f2a3d69 Fix SAI unindexed contexts not considering CONTAINS KEY
add 06dabb8b3a Merge branch 'cassandra-5.0' into trunk
add 9c6e671434 Fixed bug where UnifiedCompactionTask constructor was calling the wrong base constructor of CompactionTask
add 360128b3eb Merge branch 'cassandra-5.0' into trunk
new c6a6822a66 Implementation of Transactional Cluster Metadata as described in CEP-21
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (ece8e960e3)
\
N -- N -- N refs/heads/cep-21-tcm (c6a6822a66)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
CHANGES.txt | 2 +
.../org/apache/cassandra/db/ColumnFamilyStore.java | 4 +-
.../cassandra/db/compaction/ShardManager.java | 3 +-
.../compaction/unified/UnifiedCompactionTask.java | 2 +-
.../cassandra/index/sai/plan/QueryController.java | 4 +-
.../org/apache/cassandra/tcm/TCM_implementation.md | 18 +++
.../cassandra/tcm/TransactionalClusterMetadata.md | 77 +++++++++
.../cassandra/distributed/test/MoveTest.java | 1 -
.../distributed/test/RepairErrorsTest.java | 12 +-
.../distributed/test/log/BounceGossipTest.java | 1 +
.../distributed/test/log/GossipDeadlockTest.java | 1 +
.../unit/org/apache/cassandra/ServerTestUtils.java | 11 +-
test/unit/org/apache/cassandra/db/ColumnsTest.java | 4 +-
.../apache/cassandra/db/RepairedDataInfoTest.java | 4 +-
.../db/compaction/CompactionControllerTest.java | 179 ++++++++++++++++++++-
.../compaction/UnifiedCompactionStrategyTest.java | 6 +-
.../apache/cassandra/db/lifecycle/HelpersTest.java | 5 +-
.../apache/cassandra/db/lifecycle/TrackerTest.java | 3 +-
.../apache/cassandra/db/lifecycle/ViewTest.java | 5 +-
.../index/sai/cql/CollectionIndexingTest.java | 40 ++++-
.../org/apache/cassandra/tcm/LogStateTest.java | 4 +-
.../org/apache/cassandra/tcm/log/LocalLogTest.java | 2 +-
.../tcm/log/LocalStorageLogStateTest.java | 2 +-
.../concurrent/AbstractTransactionalTest.java | 5 +-
24 files changed, 356 insertions(+), 39 deletions(-)
create mode 100644 src/java/org/apache/cassandra/tcm/TransactionalClusterMetadata.md
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org
(cassandra) 01/01: Implementation of Transactional Cluster Metadata as described in CEP-21
Posted by sa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
samt pushed a commit to branch cep-21-tcm
in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit c6a6822a662020ad68277f4355fae6091cf232c2
Author: Sam Tunnicliffe <sa...@apache.org>
AuthorDate: Thu Nov 23 18:39:11 2023 +0000
Implementation of Transactional Cluster Metadata as described in CEP-21
An overview of the core components can be found in the included
TransactionalClusterMetadata.md
patch by Alex Petrov, Marcus Eriksson and Sam Tunnicliffe; reviewed by
Alex Petrov, Marcus Eriksson and Sam Tunnicliffe for CASSANDRA-18330
Co-authored-by: Marcus Eriksson <ma...@apache.org>
Co-authored-by: Alex Petrov <ol...@gmail.com>
Co-authored-by: Sam Tunnicliffe <sa...@apache.org>
---
.build/build-resolver.xml | 6 +-
.build/cassandra-build-deps-template.xml | 4 +
.build/parent-pom-template.xml | 10 +-
.circleci/config.yml | 626 ++--
.gitignore | 1 +
NEWS.txt | 59 +
build.xml | 2 +-
ci/harry_simulation.sh | 96 +
conf/cassandra.yaml | 14 +-
conf/harry-example.yaml | 95 +
lib/harry-core-0.0.2-CASSANDRA-18768.jar | Bin 0 -> 458194 bytes
pylib/cqlshlib/cql3handling.py | 4 +-
pylib/cqlshlib/test/test_cqlsh_completion.py | 7 +-
.../org/apache/cassandra/auth/AuthKeyspace.java | 91 +-
.../cassandra/auth/CIDRGroupsMappingLoader.java | 2 +-
.../cassandra/auth/CIDRGroupsMappingManager.java | 24 +-
.../cassandra/auth/CIDRPermissionsManager.java | 22 +-
.../cassandra/auth/CassandraRoleManager.java | 26 +-
.../org/apache/cassandra/auth/DCPermissions.java | 3 +-
.../org/apache/cassandra/auth/IRoleManager.java | 13 +-
.../apache/cassandra/batchlog/BatchlogManager.java | 41 +-
.../apache/cassandra/cache/AutoSavingCache.java | 10 +-
.../cassandra/concurrent/NamedThreadFactory.java | 38 +-
.../org/apache/cassandra/concurrent/Stage.java | 2 +
.../config/CassandraRelevantProperties.java | 35 +-
src/java/org/apache/cassandra/config/Config.java | 27 +-
.../cassandra/config/DatabaseDescriptor.java | 257 +-
.../org/apache/cassandra/cql3/QueryProcessor.java | 101 +-
.../cassandra/cql3/functions/UDAggregate.java | 75 +
.../cassandra/cql3/functions/UDFunction.java | 73 +
.../cql3/functions/masking/ColumnMask.java | 79 +
.../cql3/restrictions/StatementRestrictions.java | 5 +-
.../cql3/statements/DescribeStatement.java | 14 +-
.../cql3/statements/PropertyDefinitions.java | 2 +-
.../statements/schema/AlterKeyspaceStatement.java | 88 +-
.../statements/schema/AlterSchemaStatement.java | 77 +-
.../statements/schema/AlterTableStatement.java | 171 +-
.../cql3/statements/schema/AlterTypeStatement.java | 5 +-
.../cql3/statements/schema/AlterViewStatement.java | 5 +-
.../schema/CreateAggregateStatement.java | 5 +-
.../statements/schema/CreateFunctionStatement.java | 4 +-
.../statements/schema/CreateIndexStatement.java | 8 +-
.../statements/schema/CreateKeyspaceStatement.java | 16 +-
.../statements/schema/CreateTableStatement.java | 20 +-
.../statements/schema/CreateTriggerStatement.java | 5 +-
.../statements/schema/CreateTypeStatement.java | 4 +-
.../statements/schema/CreateViewStatement.java | 9 +-
.../statements/schema/DropAggregateStatement.java | 4 +-
.../statements/schema/DropFunctionStatement.java | 5 +-
.../cql3/statements/schema/DropIndexStatement.java | 5 +-
.../statements/schema/DropKeyspaceStatement.java | 5 +-
.../cql3/statements/schema/DropTableStatement.java | 4 +-
.../statements/schema/DropTriggerStatement.java | 5 +-
.../cql3/statements/schema/DropTypeStatement.java | 5 +-
.../cql3/statements/schema/DropViewStatement.java | 5 +-
.../cql3/statements/schema/TableAttributes.java | 4 +-
.../cassandra/db/AbstractMutationVerbHandler.java | 185 +
.../org/apache/cassandra/db/ColumnFamilyStore.java | 105 +-
.../cassandra/db/CounterMutationVerbHandler.java | 8 +-
.../org/apache/cassandra/db/DiskBoundaries.java | 23 +-
.../apache/cassandra/db/DiskBoundaryManager.java | 84 +-
src/java/org/apache/cassandra/db/Keyspace.java | 132 +-
.../apache/cassandra/db/MutationVerbHandler.java | 9 +-
.../cassandra/db/PartitionRangeReadCommand.java | 65 +-
src/java/org/apache/cassandra/db/ReadCommand.java | 72 +-
.../cassandra/db/ReadCommandVerbHandler.java | 144 +-
.../apache/cassandra/db/ReadRepairVerbHandler.java | 8 +-
src/java/org/apache/cassandra/db/ReadResponse.java | 7 +
.../cassandra/db/SinglePartitionReadCommand.java | 54 +-
.../apache/cassandra/db/SizeEstimatesRecorder.java | 43 +-
.../org/apache/cassandra/db/SystemKeyspace.java | 274 +-
.../commitlog/AbstractCommitLogSegmentManager.java | 7 +-
.../cassandra/db/compaction/CompactionManager.java | 31 +-
.../db/compaction/CompactionStrategyManager.java | 6 +
.../db/compaction/ShardManagerNoDisks.java | 4 +-
.../db/compaction/UnifiedCompactionStrategy.java | 7 +-
.../org/apache/cassandra/db/filter/RowFilter.java | 1 +
.../apache/cassandra/db/guardrails/Guardrail.java | 2 +-
.../org/apache/cassandra/db/lifecycle/Tracker.java | 10 +-
.../cassandra/db/memtable/ShardBoundaries.java | 13 +-
.../cassandra/db/partitions/PartitionUpdate.java | 81 +-
.../streaming/CassandraCompressedStreamReader.java | 2 +-
.../db/streaming/CassandraStreamReader.java | 80 +-
.../org/apache/cassandra/db/view/TableViews.java | 47 +-
.../org/apache/cassandra/db/view/ViewBuilder.java | 4 +-
.../apache/cassandra/db/view/ViewBuilderTask.java | 2 +-
.../org/apache/cassandra/db/view/ViewManager.java | 35 +-
.../org/apache/cassandra/db/view/ViewUtils.java | 17 +-
.../db/virtual/ClusterMetadataLogTable.java | 87 +
.../apache/cassandra/db/virtual/LocalTable.java | 145 +
.../apache/cassandra/db/virtual/PeersTable.java | 200 ++
.../cassandra/db/virtual/SystemViewsKeyspace.java | 3 +
.../org/apache/cassandra/dht/AbstractBounds.java | 2 +-
.../org/apache/cassandra/dht/BootStrapper.java | 108 +-
.../apache/cassandra/dht/BootstrapDiagnostics.java | 15 +-
.../org/apache/cassandra/dht/BootstrapEvent.java | 10 +-
.../cassandra/dht/ComparableObjectToken.java | 2 +-
src/java/org/apache/cassandra/dht/Datacenters.java | 16 +-
.../org/apache/cassandra/dht/IPartitioner.java | 4 +-
.../org/apache/cassandra/dht/LocalPartitioner.java | 4 +-
.../cassandra/dht/OrderPreservingPartitioner.java | 24 +
src/java/org/apache/cassandra/dht/OwnedRanges.java | 139 +
src/java/org/apache/cassandra/dht/Range.java | 28 +
.../org/apache/cassandra/dht/RangeStreamer.java | 296 +-
src/java/org/apache/cassandra/dht/Token.java | 27 +
.../dht/tokenallocator/OfflineTokenAllocator.java | 9 +-
.../dht/tokenallocator/TokenAllocation.java | 80 +-
.../exceptions/CoordinatorBehindException.java | 32 +
.../exceptions/InvalidRoutingException.java | 62 +
.../cassandra/exceptions/RequestFailureReason.java | 17 +-
.../cassandra/exceptions/UnavailableException.java | 3 +-
.../exceptions/WriteTimeoutException.java | 3 +-
.../org/apache/cassandra/gms/ApplicationState.java | 24 +-
.../org/apache/cassandra/gms/EndpointState.java | 16 +-
.../org/apache/cassandra/gms/FailureDetector.java | 17 +-
.../org/apache/cassandra/gms/GossipDigestAck.java | 2 +-
.../cassandra/gms/GossipDigestAckVerbHandler.java | 11 +-
.../cassandra/gms/GossipDigestSynVerbHandler.java | 5 +-
src/java/org/apache/cassandra/gms/Gossiper.java | 1059 ++----
.../org/apache/cassandra/gms/GossiperEvent.java | 7 +-
.../org/apache/cassandra/gms/GossiperMBean.java | 2 +
src/java/org/apache/cassandra/gms/NewGossiper.java | 178 +
.../org/apache/cassandra/gms/VersionedValue.java | 93 +-
.../apache/cassandra/hints/HintVerbHandler.java | 12 +-
.../org/apache/cassandra/hints/HintsCatalog.java | 4 +
.../cassandra/hints/HintsDispatchExecutor.java | 7 +-
.../cassandra/hints/HintsDispatchTrigger.java | 2 +-
.../org/apache/cassandra/hints/HintsReader.java | 7 +-
.../cassandra/index/SecondaryIndexManager.java | 7 +-
.../org/apache/cassandra/index/TargetParser.java | 8 +
.../cassandra/index/internal/CassandraIndex.java | 11 +-
.../index/sai/virtual/ColumnIndexesSystemView.java | 9 +-
.../sai/virtual/SSTableIndexesSystemView.java | 7 +-
.../index/sai/virtual/SegmentsSystemView.java | 5 +-
.../cassandra/io/sstable/CQLSSTableWriter.java | 28 +-
.../io/sstable/SSTableSimpleIterator.java | 26 +
.../cassandra/io/sstable/format/SSTableReader.java | 5 +-
.../format/SSTableReaderLoadingBuilder.java | 2 +-
.../io/sstable/format/big/BigTableWriter.java | 1 -
.../AbstractCloudMetadataServiceSnitch.java | 32 +-
.../locator/AbstractReplicaCollection.java | 40 +-
.../locator/AbstractReplicationStrategy.java | 265 +-
.../cassandra/locator/CMSPlacementStrategy.java | 155 +
.../org/apache/cassandra/locator/Endpoints.java | 5 +
.../cassandra/locator/EndpointsByReplica.java | 64 +
.../cassandra/locator/EndpointsForRange.java | 7 +-
.../cassandra/locator/EndpointsForToken.java | 32 +-
.../locator/GossipingPropertyFileSnitch.java | 59 +-
.../cassandra/locator/InetAddressAndPort.java | 32 +
.../apache/cassandra/locator/LocalStrategy.java | 57 +-
.../org/apache/cassandra/locator/MetaStrategy.java | 87 +
.../cassandra/locator/NetworkTopologyStrategy.java | 137 +-
.../apache/cassandra/locator/PendingRangeMaps.java | 212 --
.../cassandra/locator/PropertyFileSnitch.java | 248 +-
.../cassandra/locator/RackInferringSnitch.java | 38 +-
.../apache/cassandra/locator/RangesByEndpoint.java | 75 +
src/java/org/apache/cassandra/locator/Replica.java | 40 +-
.../apache/cassandra/locator/ReplicaLayout.java | 83 +-
.../org/apache/cassandra/locator/ReplicaPlan.java | 227 +-
.../org/apache/cassandra/locator/ReplicaPlans.java | 394 +-
.../apache/cassandra/locator/SimpleStrategy.java | 66 +-
.../apache/cassandra/locator/SystemStrategy.java | 53 +
.../apache/cassandra/locator/TokenMetadata.java | 1611 ---------
.../locator/TokenMetadataDiagnostics.java | 46 -
.../cassandra/locator/TokenMetadataEvent.java | 62 -
.../apache/cassandra/metrics/KeyspaceMetrics.java | 10 +
.../org/apache/cassandra/metrics/PaxosMetrics.java | 3 +
.../apache/cassandra/metrics/StorageMetrics.java | 2 +
.../org/apache/cassandra/metrics/TCMMetrics.java | 154 +
.../org/apache/cassandra/metrics/TableMetrics.java | 2 +
.../cassandra/net/InboundMessageHandler.java | 6 +-
src/java/org/apache/cassandra/net/InboundSink.java | 31 +-
src/java/org/apache/cassandra/net/Message.java | 127 +-
.../org/apache/cassandra/net/MessageDelivery.java | 44 +
.../org/apache/cassandra/net/MessagingService.java | 50 +-
.../apache/cassandra/net/OutboundConnection.java | 10 +-
.../apache/cassandra/net/ResponseVerbHandler.java | 65 +-
src/java/org/apache/cassandra/net/Verb.java | 40 +
.../apache/cassandra/repair/RepairCoordinator.java | 4 +-
.../org/apache/cassandra/repair/RepairJob.java | 8 +-
.../cassandra/repair/RepairMessageVerbHandler.java | 23 +
.../repair/RepairOutOfTokenRangeException.java | 32 +
.../org/apache/cassandra/repair/RepairSession.java | 2 +-
.../apache/cassandra/schema/ColumnMetadata.java | 61 +
.../schema/DefaultSchemaUpdateHandler.java | 356 --
.../schema/DefaultSchemaUpdateHandlerFactory.java | 36 -
.../schema/DistributedMetadataLogKeyspace.java | 284 ++
.../apache/cassandra/schema/DistributedSchema.java | 281 +-
.../org/apache/cassandra/schema/DroppedColumn.java | 34 +
.../org/apache/cassandra/schema/IndexMetadata.java | 41 +
src/java/org/apache/cassandra/schema/Indexes.java | 36 +
.../apache/cassandra/schema/KeyspaceMetadata.java | 77 +-
.../apache/cassandra/schema/KeyspaceParams.java | 35 +-
.../org/apache/cassandra/schema/Keyspaces.java | 142 +-
.../cassandra/schema/MigrationCoordinator.java | 761 ----
.../schema/OfflineSchemaUpdateHandler.java | 96 -
.../apache/cassandra/schema/PartitionDenylist.java | 17 +-
.../apache/cassandra/schema/ReplicationParams.java | 187 +-
src/java/org/apache/cassandra/schema/Schema.java | 770 +---
.../apache/cassandra/schema/SchemaConstants.java | 3 +-
.../apache/cassandra/schema/SchemaDiagnostics.java | 44 +-
.../org/apache/cassandra/schema/SchemaEvent.java | 9 +-
.../apache/cassandra/schema/SchemaKeyspace.java | 55 +-
.../apache/cassandra/schema/SchemaProvider.java | 188 +-
.../cassandra/schema/SchemaPullVerbHandler.java | 20 +-
.../cassandra/schema/SchemaPushVerbHandler.java | 21 +-
.../cassandra/schema/SchemaTransformation.java | 97 +-
.../cassandra/schema/SchemaTransformations.java | 29 +-
.../cassandra/schema/SchemaUpdateHandler.java | 78 -
.../schema/SchemaUpdateHandlerFactory.java | 35 -
.../schema/SchemaUpdateHandlerFactoryProvider.java | 65 -
.../schema/SystemDistributedKeyspace.java | 155 +-
src/java/org/apache/cassandra/schema/TableId.java | 35 +-
.../org/apache/cassandra/schema/TableMetadata.java | 171 +-
.../apache/cassandra/schema/TableMetadataRef.java | 131 +-
.../cassandra/schema/TableMetadataRefCache.java | 152 -
.../org/apache/cassandra/schema/TableParams.java | 144 +
src/java/org/apache/cassandra/schema/Tables.java | 38 +
.../apache/cassandra/schema/TriggerMetadata.java | 32 +
src/java/org/apache/cassandra/schema/Triggers.java | 39 +
src/java/org/apache/cassandra/schema/Types.java | 66 +
.../org/apache/cassandra/schema/UserFunctions.java | 64 +
.../org/apache/cassandra/schema/ViewMetadata.java | 52 +
src/java/org/apache/cassandra/schema/Views.java | 38 +
.../service/AbstractWriteResponseHandler.java | 4 +
.../cassandra/service/ActiveRepairService.java | 118 +-
.../apache/cassandra/service/CassandraDaemon.java | 244 +-
.../org/apache/cassandra/service/ClientState.java | 21 +
.../org/apache/cassandra/service/ClientWarn.java | 22 +-
.../apache/cassandra/service/EchoVerbHandler.java | 3 +-
.../service/PendingRangeCalculatorService.java | 98 -
.../PendingRangeCalculatorServiceDiagnostics.java | 66 -
.../PendingRangeCalculatorServiceEvent.java | 75 -
.../apache/cassandra/service/RangeRelocator.java | 323 --
src/java/org/apache/cassandra/service/Rebuild.java | 253 ++
.../apache/cassandra/service/StartupChecks.java | 64 +-
.../org/apache/cassandra/service/StorageProxy.java | 145 +-
.../apache/cassandra/service/StorageService.java | 3797 +++++---------------
.../cassandra/service/StorageServiceMBean.java | 7 +-
.../cassandra/service/WriteResponseHandler.java | 2 +
.../service/disk/usage/DiskUsageBroadcaster.java | 1 +
.../org/apache/cassandra/service/paxos/Paxos.java | 88 +-
.../cassandra/service/paxos/PaxosPrepare.java | 14 +-
.../cassandra/service/paxos/PaxosRepair.java | 39 +-
.../service/paxos/cleanup/PaxosCleanup.java | 18 +-
.../service/paxos/cleanup/PaxosCleanupRequest.java | 5 +
.../paxos/cleanup/PaxosStartPrepareCleanup.java | 3 -
.../service/paxos/uncommitted/PaxosRows.java | 2 +-
.../paxos/uncommitted/UncommittedTableData.java | 4 +-
.../service/paxos/v1/AbstractPaxosVerbHandler.java | 73 +
.../service/paxos/v1/PrepareVerbHandler.java | 6 +-
.../service/paxos/v1/ProposeVerbHandler.java | 6 +-
.../service/reads/AbstractReadExecutor.java | 11 +-
.../cassandra/service/reads/ReadCallback.java | 33 +-
.../service/reads/ReplicaFilteringProtection.java | 3 +-
.../cassandra/service/reads/ResponseResolver.java | 1 -
.../service/reads/range/ReplicaPlanIterator.java | 8 +-
.../reads/repair/BlockingPartitionRepair.java | 54 +-
.../service/reads/repair/BlockingReadRepair.java | 7 +
.../reads/repair/RowIteratorMergeListener.java | 20 +-
.../apache/cassandra/streaming/DataMovement.java | 111 +
.../streaming/DataMovementVerbHandler.java | 112 +
.../StreamReceivedOutOfTokenRangeException.java | 49 +
.../StreamRequestOutOfTokenRangeException.java | 36 +
.../apache/cassandra/streaming/StreamSession.java | 68 +-
.../cassandra/tcm/AbstractLocalProcessor.java | 202 ++
.../cassandra/tcm/AtomicLongBackedProcessor.java | 182 +
.../org/apache/cassandra/tcm/CMSOperations.java | 199 +
.../apache/cassandra/tcm/CMSOperationsMBean.java | 45 +
.../org/apache/cassandra/tcm/ClusterMetadata.java | 945 +++++
.../cassandra/tcm/ClusterMetadataService.java | 860 +++++
src/java/org/apache/cassandra/tcm/Commit.java | 407 +++
.../cassandra/tcm/CurrentEpochRequestHandler.java | 42 +
src/java/org/apache/cassandra/tcm/Discovery.java | 260 ++
src/java/org/apache/cassandra/tcm/Epoch.java | 202 ++
.../apache/cassandra/tcm/EpochAwareDebounce.java | 82 +
src/java/org/apache/cassandra/tcm/FetchCMSLog.java | 121 +
.../org/apache/cassandra/tcm/FetchPeerLog.java | 90 +
src/java/org/apache/cassandra/tcm/MetadataKey.java | 81 +
.../org/apache/cassandra/tcm/MetadataKeys.java | 55 +
.../apache/cassandra/tcm/MetadataSnapshots.java | 121 +
.../org/apache/cassandra/tcm/MetadataValue.java | 25 +
.../apache/cassandra/tcm/MultiStepOperation.java | 187 +
.../org/apache/cassandra/tcm/NotCMSException.java | 27 +
.../apache/cassandra/tcm/PaxosBackedProcessor.java | 219 ++
.../org/apache/cassandra/tcm/PeerLogFetcher.java | 108 +
src/java/org/apache/cassandra/tcm/Period.java | 207 ++
src/java/org/apache/cassandra/tcm/Processor.java | 73 +
.../cassandra/tcm/RecentlySealedPeriods.java | 140 +
.../org/apache/cassandra/tcm/RemoteProcessor.java | 341 ++
src/java/org/apache/cassandra/tcm/Retry.java | 202 ++
src/java/org/apache/cassandra/tcm/Sealed.java | 128 +
src/java/org/apache/cassandra/tcm/Startup.java | 500 +++
.../cassandra/tcm/StubClusterMetadataService.java | 124 +
.../org/apache/cassandra/tcm/TCM_implementation.md | 75 +
.../cassandra/tcm/TransactionalClusterMetadata.md | 77 +
.../org/apache/cassandra/tcm/Transformation.java | 320 ++
.../cassandra/tcm/compatibility/GossipHelper.java | 392 ++
.../tcm/compatibility/TokenRingUtils.java | 222 ++
.../tcm/extensions/AbstractExtensionValue.java | 80 +
.../cassandra/tcm/extensions/EpochValue.java | 54 +
.../cassandra/tcm/extensions/ExtensionKey.java | 71 +
.../cassandra/tcm/extensions/ExtensionValue.java | 36 +
.../apache/cassandra/tcm/extensions/IntValue.java | 54 +
.../cassandra/tcm/extensions/StringValue.java | 54 +
.../cassandra/tcm/listeners/ChangeListener.java | 42 +
.../tcm/listeners/ClientNotificationListener.java | 128 +
.../tcm/listeners/InitializationListener.java | 36 +
.../tcm/listeners/LegacyStateListener.java | 164 +
.../cassandra/tcm/listeners/LogListener.java | 33 +
.../tcm/listeners/MetadataSnapshotListener.java | 51 +
.../tcm/listeners/PlacementsChangeListener.java | 52 +
.../cassandra/tcm/listeners/SchemaListener.java | 57 +
.../tcm/listeners/UpgradeMigrationListener.java | 39 +
src/java/org/apache/cassandra/tcm/log/Entry.java | 189 +
.../org/apache/cassandra/tcm/log/LocalLog.java | 858 +++++
.../org/apache/cassandra/tcm/log/LogReader.java | 33 +
.../org/apache/cassandra/tcm/log/LogState.java | 267 ++
.../org/apache/cassandra/tcm/log/LogStorage.java | 55 +
.../org/apache/cassandra/tcm/log/Replication.java | 260 ++
.../cassandra/tcm/log/SystemKeyspaceStorage.java | 162 +
.../apache/cassandra/tcm/membership/Directory.java | 757 ++++
.../apache/cassandra/tcm/membership/Location.java | 83 +
.../cassandra/tcm/membership/NodeAddresses.java | 145 +
.../apache/cassandra/tcm/membership/NodeId.java | 126 +
.../apache/cassandra/tcm/membership/NodeState.java | 46 +
.../cassandra/tcm/membership/NodeVersion.java | 137 +
.../tcm/migration/ClusterMetadataHolder.java | 95 +
.../apache/cassandra/tcm/migration/Election.java | 264 ++
.../cassandra/tcm/migration/GossipCMSListener.java | 80 +
.../cassandra/tcm/migration/GossipProcessor.java | 42 +
.../cassandra/tcm/ownership/DataPlacement.java | 206 ++
.../cassandra/tcm/ownership/DataPlacements.java | 277 ++
.../org/apache/cassandra/tcm/ownership/Delta.java | 138 +
.../cassandra/tcm/ownership/EntireRange.java | 50 +
.../cassandra/tcm/ownership/MovementMap.java | 165 +
.../cassandra/tcm/ownership/PlacementDeltas.java | 245 ++
.../cassandra/tcm/ownership/PlacementForRange.java | 437 +++
.../cassandra/tcm/ownership/PlacementProvider.java | 54 +
.../tcm/ownership/PlacementTransitionPlan.java | 128 +
.../tcm/ownership/PrimaryRangeComparator.java | 51 +
.../cassandra/tcm/ownership/ReplicationMap.java | 106 +
.../apache/cassandra/tcm/ownership/TokenMap.java | 290 ++
.../tcm/ownership/UniformRangePlacement.java | 349 ++
.../tcm/ownership/VersionedEndpoints.java | 210 ++
.../apache/cassandra/tcm/sequences/AddToCMS.java | 208 ++
.../cassandra/tcm/sequences/BootstrapAndJoin.java | 523 +++
.../tcm/sequences/BootstrapAndReplace.java | 500 +++
.../tcm/sequences/CancelCMSReconfiguration.java | 105 +
.../cassandra/tcm/sequences/DataMovements.java | 143 +
.../tcm/sequences/InProgressSequences.java | 304 ++
.../cassandra/tcm/sequences/LeaveStreams.java | 47 +
.../cassandra/tcm/sequences/LockedRanges.java | 451 +++
.../org/apache/cassandra/tcm/sequences/Move.java | 586 +++
.../cassandra/tcm/sequences/ProgressBarrier.java | 575 +++
.../cassandra/tcm/sequences/ReconfigureCMS.java | 367 ++
.../cassandra/tcm/sequences/RemoveNodeStreams.java | 165 +
.../tcm/sequences/ReplaceSameAddress.java | 99 +
.../cassandra/tcm/sequences/SequenceState.java | 124 +
.../tcm/sequences/SingleNodeSequences.java | 168 +
.../tcm/sequences/UnbootstrapAndLeave.java | 367 ++
.../tcm/sequences/UnbootstrapStreams.java | 233 ++
.../AsymmetricMetadataSerializer.java | 53 +
.../tcm/serialization/MessageSerializers.java | 87 +
.../tcm/serialization/MetadataSerializer.java | 22 +
.../PartitionerAwareMetadataSerializer.java | 56 +
.../UDTAndFunctionsAwareMetadataSerializer.java | 63 +
.../serialization/UDTAwareMetadataSerializer.java | 61 +
.../serialization/VerboseMetadataSerializer.java | 53 +
.../cassandra/tcm/serialization/Version.java | 97 +
.../cassandra/tcm/transformations/AlterSchema.java | 280 ++
.../tcm/transformations/ApplyPlacementDeltas.java | 148 +
.../cassandra/tcm/transformations/Assassinate.java | 133 +
.../transformations/CancelInProgressSequence.java | 97 +
.../tcm/transformations/CustomTransformation.java | 264 ++
.../tcm/transformations/ForceSnapshot.java | 81 +
.../cassandra/tcm/transformations/PrepareJoin.java | 355 ++
.../tcm/transformations/PrepareLeave.java | 320 ++
.../cassandra/tcm/transformations/PrepareMove.java | 300 ++
.../tcm/transformations/PrepareReplace.java | 386 ++
.../cassandra/tcm/transformations/Register.java | 216 ++
.../cassandra/tcm/transformations/SealPeriod.java | 100 +
.../cassandra/tcm/transformations/Startup.java | 157 +
.../cassandra/tcm/transformations/Unregister.java | 104 +
.../cassandra/tcm/transformations/UnsafeJoin.java | 107 +
.../cms/AdvanceCMSReconfiguration.java | 393 ++
.../cms/BaseMembershipTransformation.java | 95 +
.../tcm/transformations/cms/FinishAddToCMS.java | 111 +
.../tcm/transformations/cms/Initialize.java | 92 +
.../tcm/transformations/cms/PreInitialize.java | 135 +
.../cms/PrepareCMSReconfiguration.java | 289 ++
.../tcm/transformations/cms/RemoveFromCMS.java | 175 +
.../tcm/transformations/cms/StartAddToCMS.java | 121 +
src/java/org/apache/cassandra/tools/NodeProbe.java | 28 +-
src/java/org/apache/cassandra/tools/NodeTool.java | 5 +
.../cassandra/tools/SSTableExpiredBlockers.java | 4 +-
.../org/apache/cassandra/tools/SSTableExport.java | 1 +
.../cassandra/tools/SSTableLevelResetter.java | 8 +-
.../cassandra/tools/SSTableOfflineRelevel.java | 6 +-
.../cassandra/tools/StandaloneSSTableUtil.java | 7 +-
.../apache/cassandra/tools/StandaloneScrubber.java | 5 +-
.../apache/cassandra/tools/StandaloneSplitter.java | 6 +-
.../apache/cassandra/tools/StandaloneUpgrader.java | 8 +-
.../apache/cassandra/tools/StandaloneVerifier.java | 8 +-
.../tools/TransformClusterMetadataHelper.java | 95 +
src/java/org/apache/cassandra/tools/Util.java | 2 +-
.../cassandra/tools/nodetool/AbortBootstrap.java | 48 +
.../cassandra/tools/nodetool/DescribeCMS.java | 44 +
.../cassandra/tools/nodetool/InitializeCMS.java | 39 +
.../org/apache/cassandra/tools/nodetool/Join.java | 2 -
.../cassandra/tools/nodetool/ReconfigureCMS.java | 122 +
.../cassandra/tools/nodetool/RemoveNode.java | 21 +-
.../cassandra/tools/nodetool/SealPeriod.java | 33 +
.../apache/cassandra/tracing/TraceKeyspace.java | 65 +-
.../org/apache/cassandra/utils/BiMultiValMap.java | 16 +
.../apache/cassandra/utils/CassandraVersion.java | 1 +
src/java/org/apache/cassandra/utils/CounterId.java | 4 +-
.../org/apache/cassandra/utils/FBUtilities.java | 29 +-
.../org/apache/cassandra/utils/NativeLibrary.java | 5 +
.../cassandra/utils/RecomputingSupplier.java | 125 -
.../cassandra/utils/btree/AbstractBTreeMap.java | 157 +
.../apache/cassandra/utils/btree/BTreeBiMap.java | 102 +
.../org/apache/cassandra/utils/btree/BTreeMap.java | 232 ++
.../cassandra/utils/btree/BTreeMultimap.java | 214 ++
.../org/apache/cassandra/utils/btree/BTreeSet.java | 45 +-
.../cassandra/utils/concurrent/AbstractFuture.java | 33 +
.../cassandra/utils/concurrent/AsyncFuture.java | 11 +
.../apache/cassandra/utils/concurrent/Future.java | 10 +
.../cassandra/utils/concurrent/LoadingMap.java | 7 +
.../cassandra/utils/concurrent/SyncFuture.java | 11 +
.../cassandra/utils/concurrent/WaitQueue.java | 1 +
test/conf/logback-dtest.xml | 5 +-
test/conf/logback-simulator.xml | 1 -
.../org/apache/cassandra/distributed/Cluster.java | 41 +-
.../apache/cassandra/distributed/Constants.java | 4 +
.../cassandra/distributed/action/GossipHelper.java | 282 +-
.../cassandra/distributed/api/ICoordinator.java | 22 +
.../ConcurrentQuiescentCheckerIntegrationTest.java | 123 +
.../cassandra/distributed/fuzz/HarryHelper.java | 67 +-
.../fuzz/InJVMTokenAwareVisitorExecutor.java | 111 +
.../cassandra/distributed/fuzz/InJvmSut.java | 43 +-
.../cassandra/distributed/fuzz/InJvmSutBase.java | 43 +-
.../cassandra/distributed/harry/ClusterState.java | 24 +
.../distributed/harry/ExistingClusterSUT.java | 96 +
.../cassandra/distributed/harry/FlaggedRunner.java | 85 +
.../distributed/impl/AbstractCluster.java | 49 +-
.../distributed/impl/DistributedTestSnitch.java | 2 +-
.../cassandra/distributed/impl/Instance.java | 452 +--
.../apache/cassandra/distributed/impl/Listen.java | 7 -
.../apache/cassandra/distributed/impl/Query.java | 7 -
.../distributed/impl/TestChangeListener.java | 119 +
.../distributed/impl/UnsafeGossipHelper.java | 8 +-
.../mock/nodetool/InternalNodeProbe.java | 2 +
.../cassandra/distributed/shared/ClusterUtils.java | 469 ++-
.../distributed/shared/PreventSystemExit.java | 44 +
.../cassandra/distributed/test/AlterTest.java | 12 -
.../cassandra/distributed/test/AuthTest.java | 77 +-
.../distributed/test/ByteBuddyExamplesTest.java | 15 +-
.../cassandra/distributed/test/CASAddTest.java | 18 +-
.../distributed/test/CASContentionTest.java | 6 +
.../cassandra/distributed/test/CASMultiDCTest.java | 6 +
.../apache/cassandra/distributed/test/CASTest.java | 6 +
.../cassandra/distributed/test/CASTestBase.java | 24 +-
.../distributed/test/CompactionDiskSpaceTest.java | 2 +-
.../test/CreateTableNonDeterministicTest.java | 89 +
.../distributed/test/DecommissionTest.java | 71 +-
.../distributed/test/FailureLoggingTest.java | 19 -
.../cassandra/distributed/test/FrozenUDTTest.java | 5 +-
.../cassandra/distributed/test/GossipTest.java | 287 +-
.../test/HintedHandoffAddRemoveNodesTest.java | 80 +-
.../distributed/test/IPMembershipTest.java | 11 +-
.../test/InternodeEncryptionEnforcementTest.java | 128 +-
.../cassandra/distributed/test/JVMDTestTest.java | 8 +-
.../distributed/test/MigrationCoordinatorTest.java | 123 -
.../distributed/test/MixedModeFuzzTest.java | 5 +-
.../cassandra/distributed/test/MoveTest.java | 5 +-
.../distributed/test/PartitionDenylistTest.java | 1 -
.../distributed/test/PaxosRepair2Test.java | 5 +-
.../distributed/test/PaxosRepairTest.java | 38 +-
.../test/PaxosUncommittedIndexTest.java | 2 +-
.../cassandra/distributed/test/ReadRepairTest.java | 61 +-
.../cassandra/distributed/test/RemoveNodeTest.java | 99 +
.../distributed/test/RepairCoordinatorFast.java | 22 +-
.../test/RepairCoordinatorNeighbourDown.java | 24 +-
.../distributed/test/RepairDigestTrackingTest.java | 54 +-
.../distributed/test/RepairErrorsTest.java | 12 +-
.../distributed/test/SSTableIdGenerationTest.java | 6 +
.../cassandra/distributed/test/SchemaTest.java | 161 +-
.../distributed/test/SecondaryIndexTest.java | 2 +-
.../cassandra/distributed/test/TestBaseImpl.java | 31 +-
.../test/TransientRangeMovement2Test.java | 134 +
.../test/TransientRangeMovementTest.java | 272 ++
.../test/UpdateSystemAuthAfterDCExpansionTest.java | 33 +-
.../test/guardrails/GuardrailDiskUsageTest.java | 26 +-
...rdrailItemsPerCollectionOnSSTableWriteTest.java | 9 +-
.../hostreplacement/AssassinatedEmptyNodeTest.java | 11 +-
.../test/hostreplacement/BaseAssassinatedCase.java | 8 +-
.../test/hostreplacement/FailedBootstrapTest.java | 48 +-
.../HostReplacementOfDownedClusterTest.java | 57 +-
.../test/hostreplacement/HostReplacementTest.java | 18 +-
...AsHibernatingNodeWithoutReplaceAddressTest.java | 16 +-
.../distributed/test/jmx/JMXGetterCheckTest.java | 9 +-
.../distributed/test/log/BootWithMetadataTest.java | 140 +
.../distributed/test/log/BounceGossipTest.java | 247 ++
.../test/log/BounceIndexRebuildTest.java | 52 +
.../test/log/BounceResetHostIdTest.java | 52 +
.../test/log/CMSMembershipMetricsTest.java | 119 +
.../distributed/test/log/CMSTestBase.java | 131 +
.../test/log/ClusterMetadataTestHelper.java | 1078 ++++++
.../test/log/ConflictingAddressRestartTest.java | 85 +
.../distributed/test/log/ConsistentLeaveTest.java | 154 +
.../distributed/test/log/ConsistentMoveTest.java | 163 +
.../distributed/test/log/CoordinatorPathTest.java | 260 ++
.../test/log/CoordinatorPathTestBase.java | 1152 ++++++
.../distributed/test/log/DiscoverCMSTest.java | 84 +
.../distributed/test/log/DistributedLogTest.java | 200 ++
.../distributed/test/log/FailedLeaveTest.java | 174 +
.../test/log/FetchLogFromPeersTest.java | 367 ++
.../distributed/test/log/ForceSnapshotTest.java | 157 +
.../distributed/test/log/FuzzTestBase.java | 142 +
.../distributed/test/log/GossipDeadlockTest.java | 147 +
.../log/InProgressSequenceCoordinationTest.java | 406 +++
.../test/log/MetadataChangeSimulationTest.java | 763 ++++
.../distributed/test/log/ModelChecker.java | 307 ++
.../cassandra/distributed/test/log/ModelState.java | 364 ++
.../test/log/OperationalEquivalenceTest.java | 204 ++
.../distributed/test/log/PauseCommitsTest.java | 56 +
.../distributed/test/log/PlacementSimulator.java | 1789 +++++++++
.../test/log/PlacementSimulatorTest.java | 379 ++
.../test/log/QuorumIntersectionSimulatorTest.java | 142 +
.../distributed/test/log/ReconfigureCMSTest.java | 141 +
.../distributed/test/log/RegisterTest.java | 169 +
.../test/log/RequestCurrentEpochTest.java | 102 +
.../distributed/test/log/ResumableStartupTest.java | 150 +
.../cassandra/distributed/test/log/RngUtils.java | 106 +
.../distributed/test/log/SimulatedOperation.java | 562 +++
.../distributed/test/log/SnapshotTest.java | 244 ++
.../test/log/SystemKeyspaceStorageTest.java | 235 ++
.../distributed/test/log/TestProcessor.java | 137 +
.../test/log/TriggeredReconfigureCMSTest.java | 151 +
.../ring/AssignSameTokenToMultipleNodesTest.java | 52 +
.../test/ring/BootstrapResetProgressTest.java | 156 +
.../distributed/test/ring/BootstrapTest.java | 193 +-
.../distributed/test/ring/CMSMembershipTest.java | 185 +
.../test/ring/CleanupDuringRangeMovementTest.java | 145 +
.../distributed/test/ring/CleanupFailureTest.java | 112 -
.../ring/CommunicationDuringDecommissionTest.java | 18 +-
.../test/ring/ConsistentBootstrapTest.java | 251 ++
.../distributed/test/ring/DecommissionTest.java | 209 ++
.../distributed/test/ring/NodeNotInRingTest.java | 3 +-
.../distributed/test/ring/PendingWritesTest.java | 109 -
.../distributed/test/ring/RangeVersioningTest.java | 72 +
.../test/ring/ReadsDuringBootstrapTest.java | 115 -
.../test/ring/StopProcessingExceptionTest.java | 78 +
.../test/streaming/StreamCloseInMiddleTest.java | 22 +-
.../test/tcm/LogReplicationSmokeTest.java | 101 +
.../test/topology/DecommissionAvoidTimeouts.java | 23 +-
.../distributed/upgrade/BatchUpgradeTest.java | 2 +
.../upgrade/ClusterMetadataUpgradeHarryTest.java | 143 +
.../upgrade/ClusterMetadataUpgradeTest.java | 223 ++
.../upgrade/CompactStorageColumnDeleteTest.java | 2 +
.../upgrade/CompactStorageHiddenColumnTest.java | 2 +
...CompactStorageImplicitNullInClusteringTest.java | 2 +
.../upgrade/CompactStoragePagingTest.java | 2 +
.../CompactionHistorySystemTableUpgradeTest.java | 2 +
.../upgrade/DropCompactStorageTest.java | 1 +
.../upgrade/MixedModeBatchTestBase.java | 2 +
.../upgrade/MixedModeConsistencyV30Test.java | 4 +-
.../upgrade/MixedModeFrom3ReplicationTest.java | 2 +
.../upgrade/MixedModeIndexTestBase.java | 4 +-
.../distributed/upgrade/MixedModeRepairTest.java | 2 +-
.../upgrade/MixedModeTTLOverflowUpgradeTest.java | 2 +
.../upgrade/MixedModeWritetimeOrTTLTest.java | 2 +
.../upgrade/Pre40MessageFilterTest.java | 2 +-
.../distributed/upgrade/UpgradeTestBase.java | 39 +-
.../util/byterewrite/StatusChangeListener.java | 133 -
.../org/apache/cassandra/cql3/CorruptionTest.java | 15 +-
.../db/commitlog/CommitLogStressTest.java | 2 +-
.../db/compaction/LongCompactionsTest.java | 2 +-
.../LongLeveledCompactionStrategyCQLTest.java | 3 +-
.../LongLeveledCompactionStrategyTest.java | 29 +-
.../io/sstable/CQLSSTableWriterLongTest.java | 10 -
.../locator/DynamicEndpointSnitchLongTest.java | 2 +
.../cassandra/streaming/LongStreamingTest.java | 5 +-
.../cassandra/test/microbench/MutationBench.java | 22 +-
.../test/microbench/PendingRangesBench.java | 115 -
.../simulator/asm/GlobalMethodTransformer.java | 8 +-
.../cassandra/simulator/asm/InterceptAgent.java | 6 +-
.../systems/InterceptorOfSystemMethods.java | 13 +-
.../org/apache/cassandra/simulator/ActionList.java | 12 +
.../org/apache/cassandra/simulator/Actions.java | 6 +-
.../cassandra/simulator/ClusterSimulation.java | 76 +-
.../main/org/apache/cassandra/simulator/Debug.java | 12 +-
.../org/apache/cassandra/simulator/Ordered.java | 4 +-
.../cassandra/simulator/SimulationRunner.java | 2 -
.../apache/cassandra/simulator/SimulatorUtils.java | 9 +
.../simulator/cluster/ClusterActions.java | 57 +-
.../simulator/cluster/KeyspaceActions.java | 216 +-
.../simulator/cluster/OnClusterChangeRf.java | 5 +-
.../simulator/cluster/OnClusterChangeTopology.java | 5 +-
.../cassandra/simulator/cluster/OnClusterJoin.java | 88 +-
.../simulator/cluster/OnClusterLeave.java | 96 +-
.../simulator/cluster/OnClusterReplace.java | 161 +-
.../cluster/OnClusterSyncPendingRanges.java | 29 -
.../simulator/cluster/OnClusterUpdateGossip.java | 64 -
.../simulator/cluster/OnInstanceBootstrap.java | 54 -
.../simulator/cluster/OnInstanceGossipWith.java | 50 -
.../simulator/cluster/OnInstanceGossipWithAll.java | 38 -
.../simulator/cluster/OnInstanceMarkShutdown.java | 29 -
.../simulator/cluster/OnInstanceRepair.java | 8 +-
.../cluster/OnInstanceSendShutdownToAll.java | 33 -
.../cluster/OnInstanceSetBootstrapReplacing.java | 31 -
.../cluster/OnInstanceSetBootstrapping.java | 29 -
.../simulator/cluster/OnInstanceSetLeaving.java | 29 -
.../simulator/cluster/OnInstanceSetLeft.java | 29 -
.../simulator/cluster/OnInstanceSetNormal.java | 36 -
.../cluster/OnInstanceSyncPendingRanges.java | 42 -
.../cluster/OnInstanceSyncSchemaForBootstrap.java | 37 -
.../cassandra/simulator/cluster/Quiesce.java | 55 +
.../apache/cassandra/simulator/cluster/Utils.java | 23 +-
.../simulator/harry/HarryValidatingQuery.java | 147 +
.../simulator/systems/InterceptingAwaitable.java | 6 +-
.../simulator/systems/InterceptingExecutor.java | 3 +-
.../systems/InterceptingGlobalMethods.java | 3 +
.../simulator/systems/InterceptingMonitors.java | 5 +-
.../simulator/systems/SimulatedAction.java | 26 +-
.../simulator/systems/SimulatedActionCallable.java | 4 +-
.../simulator/systems/SimulatedActionTask.java | 8 +
.../systems/SimulatedFailureDetector.java | 6 +
.../simulator/systems/SimulatedSnitch.java | 7 +
.../simulator/systems/SimulatedSystems.java | 12 +-
.../test/AlwaysDeliverNetworkScheduler.java | 77 +
.../simulator/test/FixedLossNetworkScheduler.java | 158 +
.../simulator/test/HarrySimulatorTest.java | 797 ++++
.../simulator/test/ShortPaxosSimulationTest.java | 68 +
.../simulator/test/SimulatedVisitExectuor.java | 182 +
.../simulator/test/SimulationTestBase.java | 122 +-
.../simulator/test/TrivialSimulationTest.java | 1 +
test/unit/org/apache/cassandra/SchemaLoader.java | 37 +-
.../unit/org/apache/cassandra/ServerTestUtils.java | 166 +-
test/unit/org/apache/cassandra/Util.java | 106 +-
.../cassandra/auth/AllowAllCIDRAuthorizerTest.java | 3 -
.../cassandra/auth/CassandraAuthorizerTest.java | 3 +-
.../CassandraCIDRAuthorizerEnforceModeTest.java | 2 -
.../CassandraCIDRAuthorizerMonitorModeTest.java | 2 -
.../auth/CassandraNetworkAuthorizerTest.java | 1 -
.../cassandra/auth/CassandraRoleManagerTest.java | 9 +-
.../cassandra/auth/CreateAndAlterRoleTest.java | 6 +-
.../apache/cassandra/auth/GrantAndRevokeTest.java | 3 +-
.../cassandra/auth/MutualTlsAuthenticatorTest.java | 5 +-
.../auth/MutualTlsInternodeAuthenticatorTest.java | 5 +-
...alTlsWithPasswordFallbackAuthenticatorTest.java | 4 +-
.../cassandra/auth/PasswordAuthenticatorTest.java | 6 +-
.../org/apache/cassandra/auth/RoleOptionsTest.java | 2 +-
.../cassandra/batchlog/BatchlogManagerTest.java | 31 +-
.../cassandra/cql3/AlterSchemaStatementTest.java | 67 +
test/unit/org/apache/cassandra/cql3/BatchTest.java | 2 +-
.../apache/cassandra/cql3/CDCStatementTest.java | 3 +-
test/unit/org/apache/cassandra/cql3/CQLTester.java | 97 +-
.../cassandra/cql3/CustomNowInSecondsTest.java | 6 +-
.../org/apache/cassandra/cql3/KeyCacheCqlTest.java | 10 +-
.../org/apache/cassandra/cql3/OutOfSpaceTest.java | 25 +-
.../unit/org/apache/cassandra/cql3/PagingTest.java | 16 +-
.../apache/cassandra/cql3/RandomSchemaTest.java | 29 +
test/unit/org/apache/cassandra/cql3/ViewTest.java | 4 +-
.../cql3/functions/masking/ColumnMaskTester.java | 1 -
.../masking/SelectMaskedPermissionTest.java | 1 -
.../functions/masking/UnmaskPermissionTest.java | 1 -
.../cql3/selection/SelectionColumnMappingTest.java | 6 +-
.../cql3/statements/DescribeStatementTest.java | 12 +-
.../validation/entities/FrozenCollectionsTest.java | 5 +-
.../cql3/validation/entities/JsonTest.java | 10 +-
.../validation/entities/SecondaryIndexTest.java | 9 +-
.../cql3/validation/entities/UserTypesTest.java | 7 +-
.../cql3/validation/entities/VirtualTableTest.java | 6 +-
.../cql3/validation/operations/AlterNTSTest.java | 37 +-
.../cql3/validation/operations/AlterTest.java | 219 +-
.../operations/CompactStorageSplit2Test.java | 1 -
.../cql3/validation/operations/CreateTest.java | 96 +-
.../operations/DropRecreateAndRestoreTest.java | 3 +
.../InsertUpdateIfConditionCollectionsTest.java | 11 +-
.../InsertUpdateIfConditionStaticsTest.java | 11 +-
.../operations/InsertUpdateIfConditionTest.java | 35 +-
.../validation/operations/SelectLimitTest.java | 9 +-
.../unit/org/apache/cassandra/db/CellSpecTest.java | 1 +
test/unit/org/apache/cassandra/db/CleanupTest.java | 86 +-
.../apache/cassandra/db/CleanupTransientTest.java | 29 +-
.../db/ColumnFamilyStoreClientModeTest.java | 21 +-
test/unit/org/apache/cassandra/db/ColumnsTest.java | 4 +-
.../org/apache/cassandra/db/CounterCacheTest.java | 24 +-
.../CounterMutationVerbHandlerOutOfRangeTest.java | 192 +
.../cassandra/db/DiskBoundaryManagerTest.java | 32 +-
test/unit/org/apache/cassandra/db/ImportTest.java | 104 +-
.../unit/org/apache/cassandra/db/KeyspaceTest.java | 21 +-
.../db/MutationVerbHandlerOutOfRangeTest.java | 221 ++
.../org/apache/cassandra/db/ReadCommandTest.java | 5 +-
.../db/ReadCommandVerbHandlerOutOfRangeTest.java | 272 ++
.../cassandra/db/ReadCommandVerbHandlerTest.java | 30 +-
.../org/apache/cassandra/db/ReadResponseTest.java | 14 +-
.../cassandra/db/RecoveryManagerFlushedTest.java | 23 +-
.../apache/cassandra/db/RepairedDataInfoTest.java | 4 +-
.../unit/org/apache/cassandra/db/RowCacheTest.java | 35 +-
.../apache/cassandra/db/SchemaCQLHelperTest.java | 8 -
.../apache/cassandra/db/SecondaryIndexTest.java | 13 +-
.../db/SinglePartitionSliceCommandTest.java | 2 +-
.../apache/cassandra/db/SystemKeyspaceTest.java | 14 +-
.../cassandra/db/TopPartitionTrackerTest.java | 22 +-
.../commitlog/CommitLogSegmentManagerCDCTest.java | 2 +-
.../cassandra/db/commitlog/CommitLogTest.java | 57 +-
.../db/commitlog/CommitLogUpgradeTest.java | 22 +-
.../db/compaction/CompactionControllerTest.java | 3 +-
.../db/compaction/CompactionIteratorTest.java | 32 +-
...ompactionStrategyManagerBoundaryReloadTest.java | 32 +-
.../compaction/CompactionStrategyManagerTest.java | 9 +-
.../db/compaction/LeveledGenerationsTest.java | 1 -
.../cassandra/db/compaction/NeverPurgeTest.java | 6 +-
.../db/compaction/PartialCompactionsTest.java | 6 +-
.../cassandra/db/compaction/ShardManagerTest.java | 11 +-
.../TimeWindowCompactionStrategyTest.java | 6 +-
.../compaction/UnifiedCompactionStrategyTest.java | 6 +-
.../db/compaction/unified/ControllerTest.java | 7 +-
.../unified/ShardedCompactionWriterTest.java | 16 +-
.../compaction/unified/ShardedMultiWriterTest.java | 1 -
.../writers/CompactionAwareWriterTest.java | 6 +-
.../cassandra/db/context/CounterContextTest.java | 7 +
.../cassandra/db/filter/ColumnFilterTest.java | 16 +-
.../apache/cassandra/db/filter/RowFilterTest.java | 1 +
.../db/guardrails/GuardrailKeyspacesTest.java | 10 -
.../GuardrailMaximumReplicationFactorTest.java | 6 +-
.../GuardrailMinimumReplicationFactorTest.java | 7 +-
.../db/guardrails/GuardrailTablesTest.java | 3 +-
.../cassandra/db/guardrails/GuardrailTester.java | 9 +-
.../apache/cassandra/db/lifecycle/HelpersTest.java | 5 +-
.../db/lifecycle/LifecycleTransactionTest.java | 4 +-
.../db/lifecycle/RealTransactionsTest.java | 5 +-
.../apache/cassandra/db/lifecycle/TrackerTest.java | 3 +-
.../apache/cassandra/db/lifecycle/ViewTest.java | 5 +-
.../cassandra/db/memtable/MemtableQuickTest.java | 4 +-
.../db/memtable/MemtableSizeTestBase.java | 1 -
.../cassandra/db/partitions/PurgeFunctionTest.java | 1 +
.../repair/AbstractPendingAntiCompactionTest.java | 14 +-
.../rows/PartitionSerializationExceptionTest.java | 5 +-
.../apache/cassandra/db/rows/RowsMergingTest.java | 3 +-
.../db/rows/ThrottledUnfilteredIteratorTest.java | 14 +-
.../db/rows/UnfilteredRowIteratorsTest.java | 1 +
.../cassandra/db/streaming/StreamRequestTest.java | 3 +
.../db/transform/RTTransformationsTest.java | 2 +
.../cassandra/db/view/ViewBuilderTaskTest.java | 2 +-
.../apache/cassandra/db/view/ViewUtilsTest.java | 68 +-
.../db/virtual/BatchMetricsTableTest.java | 7 -
.../db/virtual/CIDRFilteringMetricsTableTest.java | 2 -
.../cassandra/db/virtual/CQLMetricsTableTest.java | 7 -
.../cassandra/db/virtual/ClientsTableTest.java | 7 -
.../db/virtual/CredentialsCacheKeysTableTest.java | 4 +-
.../cassandra/db/virtual/GossipInfoTableTest.java | 7 -
.../virtual/JmxPermissionsCacheKeysTableTest.java | 3 +-
.../db/virtual/LocalRepairTablesTest.java | 2 -
.../cassandra/db/virtual/LogMessagesTableTest.java | 7 -
.../NetworkPermissionsCacheKeysTableTest.java | 3 +-
.../db/virtual/PermissionsCacheKeysTableTest.java | 3 +-
.../db/virtual/RolesCacheKeysTableTest.java | 3 +-
.../db/virtual/SSTableTasksTableTest.java | 3 +-
.../cassandra/db/virtual/SettingsTableTest.java | 7 -
.../db/virtual/StreamingVirtualTableTest.java | 1 -
.../db/virtual/SystemPropertiesTableTest.java | 7 -
.../org/apache/cassandra/dht/BootStrapperTest.java | 101 +-
.../apache/cassandra/dht/LengthPartitioner.java | 2 +-
.../dht/tokenallocator/TokenAllocationTest.java | 129 +-
.../apache/cassandra/gms/ExpireEndpointTest.java | 65 -
.../apache/cassandra/gms/FailureDetectorTest.java | 26 +-
.../apache/cassandra/gms/GossipShutdownTest.java | 6 +-
.../org/apache/cassandra/gms/GossiperTest.java | 96 +-
.../org/apache/cassandra/gms/NewGossiperTest.java | 154 +
.../gms/PendingRangeCalculatorServiceTest.java | 134 -
.../apache/cassandra/gms/SerializationsTest.java | 28 +-
.../org/apache/cassandra/gms/ShadowRoundTest.java | 218 --
.../org/apache/cassandra/hints/AlteredHints.java | 2 +-
.../apache/cassandra/hints/DTestSerializer.java | 6 +-
.../apache/cassandra/hints/HintMessageTest.java | 2 +-
test/unit/org/apache/cassandra/hints/HintTest.java | 41 +-
.../apache/cassandra/hints/HintsReaderTest.java | 6 +-
.../org/apache/cassandra/hints/HintsStoreTest.java | 2 +-
.../index/internal/CustomCassandraIndex.java | 37 +-
.../index/sai/memory/VectorMemoryIndexTest.java | 26 +-
.../index/sai/virtual/IndexesSystemViewTest.java | 3 -
.../index/sai/virtual/SSTablesSystemViewTest.java | 3 -
.../index/sasi/disk/PerSSTableIndexWriterTest.java | 3 +-
.../cassandra/index/sasi/plan/OperationTest.java | 3 +-
.../cassandra/io/compress/CQLCompressionTest.java | 4 +-
.../io/sstable/CQLSSTableWriterClientTest.java | 22 +-
.../sstable/CQLSSTableWriterConcurrencyTest.java | 7 -
.../cassandra/io/sstable/CQLSSTableWriterTest.java | 2 +
.../cassandra/io/sstable/LegacySSTableTest.java | 5 +-
.../io/sstable/RangeAwareSSTableWriterTest.java | 7 +-
.../cassandra/io/sstable/SSTableLoaderTest.java | 8 +-
.../io/sstable/SSTableWriterTestBase.java | 4 +-
.../apache/cassandra/io/sstable/VerifyTest.java | 20 +-
.../locator/AbstractReplicationStrategyTest.java | 45 -
.../cassandra/locator/AlibabaCloudSnitchTest.java | 34 +-
.../locator/AssureSufficientLiveNodesTest.java | 20 +-
.../cassandra/locator/CloudstackSnitchTest.java | 42 +-
.../locator/DynamicEndpointSnitchTest.java | 20 +
.../apache/cassandra/locator/Ec2SnitchTest.java | 34 +-
.../cassandra/locator/GoogleCloudSnitchTest.java | 34 +-
.../apache/cassandra/locator/MetaStrategyTest.java | 161 +
.../locator/NetworkTopologyStrategyTest.java | 261 +-
.../cassandra/locator/PendingRangeMapsTest.java | 108 -
.../cassandra/locator/PendingRangesTest.java | 273 +-
.../cassandra/locator/PropertyFileSnitchTest.java | 338 +-
.../apache/cassandra/locator/ReplicaPlansTest.java | 18 +-
.../cassandra/locator/ReplicationFactorTest.java | 4 +-
.../ReplicationStrategyEndpointCacheTest.java | 107 -
.../cassandra/locator/SimpleStrategyTest.java | 176 +-
.../cassandra/locator/TokenMetadataTest.java | 399 --
.../apache/cassandra/locator/WithPartitioner.java | 46 +
.../cassandra/metrics/TrieMemtableMetricsTest.java | 2 -
.../org/apache/cassandra/net/ConnectionTest.java | 45 +-
.../unit/org/apache/cassandra/net/FramingTest.java | 2 +
.../org/apache/cassandra/net/HandshakeTest.java | 26 +-
.../net/MessageSerializationPropertyTest.java | 2 +
.../unit/org/apache/cassandra/net/MessageTest.java | 15 +-
.../apache/cassandra/net/MessagingServiceTest.java | 2 +
.../cassandra/net/MockMessagingServiceTest.java | 4 +-
.../cassandra/net/OutboundConnectionsTest.java | 2 +
.../cassandra/net/OutboundMessageQueueTest.java | 2 +
.../cassandra/net/ProxyHandlerConnectionsTest.java | 2 +
.../net/StartupClusterConnectivityCheckerTest.java | 4 +
.../org/apache/cassandra/repair/FuzzTestBase.java | 41 +-
.../org/apache/cassandra/repair/RepairJobTest.java | 4 +
.../RepairMessageVerbHandlerOutOfRangeTest.java | 273 ++
.../consistent/CoordinatorMessagingTest.java | 2 +-
.../repair/consistent/CoordinatorSessionTest.java | 8 +-
.../repair/consistent/CoordinatorSessionsTest.java | 2 +-
.../repair/consistent/LocalSessionTest.java | 2 +-
.../messages/RepairMessageSerializationsTest.java | 2 +
.../repair/messages/RepairMessageTest.java | 6 +-
.../org/apache/cassandra/schema/DropKSTest.java | 108 +
.../cassandra/schema/MigrationCoordinatorTest.java | 443 ---
.../schema/MigrationManagerDropKSTest.java | 108 -
.../cassandra/schema/MigrationManagerTest.java | 574 ---
.../org/apache/cassandra/schema/MockSchema.java | 166 +-
.../schema/RemoveWithoutDroppingTest.java | 125 -
.../SchemaChangeDuringRangeMovementTest.java | 254 ++
.../apache/cassandra/schema/SchemaChangesTest.java | 578 +++
.../cassandra/schema/SchemaKeyspaceTest.java | 80 +-
.../org/apache/cassandra/schema/SchemaTest.java | 319 +-
.../apache/cassandra/schema/SchemaTestUtil.java | 57 +-
.../cassandra/schema/TableMetadataSerDeTest.java | 187 +
.../apache/cassandra/schema/TableMetadataTest.java | 8 +
.../cassandra/service/ActiveRepairServiceTest.java | 92 +-
.../cassandra/service/BootstrapTransientTest.java | 174 +-
.../apache/cassandra/service/ClientStateTest.java | 11 +-
.../service/DefaultFSErrorHandlerTest.java | 2 +
.../cassandra/service/DiskFailurePolicyTest.java | 2 +
.../cassandra/service/JoinTokenRingTest.java | 24 +-
.../cassandra/service/LeaveAndBootstrapTest.java | 739 ----
.../cassandra/service/LegacyAuthFailTest.java | 7 -
.../org/apache/cassandra/service/MoveTest.java | 1102 ------
.../cassandra/service/MoveTransientTest.java | 705 ----
.../cassandra/service/PartitionDenylistTest.java | 56 +-
.../org/apache/cassandra/service/RemoveTest.java | 92 +-
.../cassandra/service/SerializationsTest.java | 3 +
.../apache/cassandra/service/StorageProxyTest.java | 18 +-
.../cassandra/service/StorageServiceAccessor.java | 29 -
.../cassandra/service/StorageServiceDrainTest.java | 10 +-
.../service/StorageServiceServerM3PTest.java | 12 +-
.../service/StorageServiceServerTest.java | 572 ++-
.../cassandra/service/StorageServiceTest.java | 133 +-
.../service/WriteResponseHandlerTest.java | 18 +-
.../service/WriteResponseHandlerTransientTest.java | 33 +-
.../paxos/PaxosVerbHandlerOutOfRangeTest.java | 195 +
.../service/reads/AbstractReadResponseTest.java | 7 +-
.../cassandra/service/reads/DataResolverTest.java | 38 +-
.../service/reads/DigestResolverTest.java | 3 +-
.../cassandra/service/reads/ReadExecutorTest.java | 5 +-
.../service/reads/range/ReplicaPlanMergerTest.java | 14 +
.../service/reads/range/TokenUpdater.java | 48 +-
.../reads/repair/AbstractReadRepairTest.java | 48 +-
.../reads/repair/BlockingReadRepairTest.java | 4 +-
.../repair/DiagEventsBlockingReadRepairTest.java | 4 +-
.../reads/repair/RepairedDataVerifierTest.java | 3 +-
.../service/snapshot/MetadataSnapshotsTest.java | 224 ++
.../service/snapshot/SnapshotManagerTest.java | 224 --
.../cassandra/streaming/StreamRateLimiterTest.java | 8 +-
.../cassandra/streaming/StreamReaderTest.java | 547 +++
.../streaming/StreamSessionOwnedRangesTest.java | 221 ++
.../cassandra/streaming/StreamSessionTest.java | 2 +-
.../apache/cassandra/tcm/BootWithMetadataTest.java | 184 +
.../apache/cassandra/tcm/ClusterMetadataTest.java | 110 +
.../tcm/ClusterMetadataTransformationTest.java | 316 ++
.../cassandra/tcm/DiscoverySimulationTest.java | 186 +
.../org/apache/cassandra/tcm/LogStateTest.java | 102 +
.../cassandra/tcm/RecentlySealedPeriodsTest.java | 112 +
.../apache/cassandra/tcm/RemoteProcessorTest.java | 110 +
.../tcm/compatibility/GossipHelperTest.java | 233 ++
.../listeners/ClientNotificationListenerTest.java | 63 +
.../cassandra/tcm/log/DistributedLogStateTest.java | 157 +
.../org/apache/cassandra/tcm/log/LocalLogTest.java | 256 ++
.../tcm/log/LocalStorageLogStateTest.java | 138 +
.../tcm/log/LogListenerNotificationTest.java | 138 +
.../apache/cassandra/tcm/log/LogStateTestBase.java | 273 ++
.../cassandra/tcm/membership/MembershipUtils.java | 60 +
.../cassandra/tcm/ownership/DeltaMapTest.java | 217 ++
.../cassandra/tcm/ownership/OwnershipUtils.java | 242 ++
.../tcm/ownership/PrimaryRangeComparatorTest.java | 107 +
.../UniformRangePlacementIntegrationTest.java | 100 +
.../tcm/ownership/UniformRangePlacementTest.java | 320 ++
.../InProgressSequenceCancellationTest.java | 344 ++
.../tcm/sequences/ProgressBarrierTest.java | 351 ++
.../cassandra/tcm/sequences/SequencesUtils.java | 172 +
.../tcm/transformations/EventsMetadataTest.java | 191 +
.../tcm/transformations/PrepareLeaveTest.java | 177 +
.../cassandra/tools/JMXCompatabilityTest.java | 38 +-
.../tools/StandaloneSplitterWithCQLTesterTest.java | 20 +
.../tools/StandaloneVerifierOnSSTablesTest.java | 3 +-
.../cassandra/tools/SystemExitException.java | 3 +
.../apache/cassandra/tools/TopPartitionsTest.java | 7 +-
.../tools/nodetool/CIDRFilteringStatsTest.java | 3 -
.../tools/nodetool/DropCIDRGroupTest.java | 4 -
.../tools/nodetool/GetAuthCacheConfigTest.java | 1 -
.../tools/nodetool/GetCIDRGroupsOfIPTest.java | 4 -
.../cassandra/tools/nodetool/GossipInfoTest.java | 1 -
.../InvalidateCIDRPermissionsCacheTest.java | 3 -
.../nodetool/InvalidateCredentialsCacheTest.java | 4 -
.../InvalidateJmxPermissionsCacheTest.java | 19 +-
.../InvalidateNetworkPermissionsCacheTest.java | 3 -
.../nodetool/InvalidatePermissionsCacheTest.java | 41 +-
.../tools/nodetool/InvalidateRolesCacheTest.java | 3 -
.../tools/nodetool/ListCIDRGroupTest.java | 6 +-
.../tools/nodetool/ReloadCIDRGroupsCacheTest.java | 3 -
.../tools/nodetool/SetAuthCacheConfigTest.java | 1 -
.../tools/nodetool/TableHistogramsTest.java | 3 +-
.../cassandra/tools/nodetool/TableStatsTest.java | 4 +-
.../tools/nodetool/UpdateCIDRGroupTest.java | 3 -
.../cassandra/tools/nodetool/VerifyTest.java | 1 -
.../cassandra/triggers/TriggersSchemaTest.java | 8 +-
.../apache/cassandra/triggers/TriggersTest.java | 2 +-
.../cassandra/utils/RecomputingSupplierTest.java | 157 -
.../cassandra/utils/btree/BTreeBiMapGuavaTest.java | 78 +
.../cassandra/utils/btree/BTreeBiMapTest.java | 132 +
.../cassandra/utils/btree/BTreeMapGuavaTest.java | 128 +
.../apache/cassandra/utils/btree/BTreeMapTest.java | 133 +
.../cassandra/utils/btree/BTreeMultimapTest.java | 118 +
.../cassandra/utils/btree/BTreeSetGuavaTest.java | 121 +
.../concurrent/AbstractTransactionalTest.java | 5 +-
tools/bin/addtocmstool | 49 +
.../io/sstable/StressCQLSSTableWriter.java | 25 +-
.../apache/cassandra/stress/CompactionStress.java | 18 +-
948 files changed, 67491 insertions(+), 22993 deletions(-)
diff --git a/.build/build-resolver.xml b/.build/build-resolver.xml
index c95dc1eb78..889dc11bde 100644
--- a/.build/build-resolver.xml
+++ b/.build/build-resolver.xml
@@ -59,7 +59,7 @@
<remoterepo id="resolver-central" url="${artifact.remoteRepository.central}"/>
<remoterepo id="resolver-apache" url="${artifact.remoteRepository.apache}"/>
<!-- Snapshots are not allowed, but for feature branches they may be needed, so uncomment the below to allow snapshots to work -->
- <!-- <remoterepo id="resolver-apache-snapshot" url="https://repository.apache.org/content/repositories/snapshots" releases="false" snapshots="true" updates="always" checksums="fail" /> -->
+ <remoterepo id="resolver-apache-snapshot" url="https://repository.apache.org/content/repositories/snapshots" releases="false" snapshots="true" updates="always" checksums="fail" />
</resolver:remoterepos>
<macrodef name="resolve">
@@ -267,6 +267,10 @@
<delete file="${build.lib}/netty-tcnative-boringssl-static-2.0.61.Final-windows-x86_64.jar" failonerror="false"/>
<delete file="${build.dir.lib}/jars/netty-tcnative-boringssl-static-2.0.61.Final-windows-x86_64.jar" failonerror="false"/>
+
+ <copy todir="${test.lib}/jars" quiet="false">
+ <file file="${build.lib}/harry-core-0.0.2-CASSANDRA-18768.jar"/>
+ </copy>
</target>
<target name="_resolver-dist-lib_get_files">
diff --git a/.build/cassandra-build-deps-template.xml b/.build/cassandra-build-deps-template.xml
index 357325f8be..b620cda8f5 100644
--- a/.build/cassandra-build-deps-template.xml
+++ b/.build/cassandra-build-deps-template.xml
@@ -70,6 +70,10 @@
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava-testlib</artifactId>
+ </dependency>
<dependency>
<groupId>org.quicktheories</groupId>
<artifactId>quicktheories</artifactId>
diff --git a/.build/parent-pom-template.xml b/.build/parent-pom-template.xml
index 3991bc5fde..39766937ca 100644
--- a/.build/parent-pom-template.xml
+++ b/.build/parent-pom-template.xml
@@ -330,6 +330,11 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava-testlib</artifactId>
+ <version>27.0-jre</version>
+ </dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
@@ -511,8 +516,9 @@
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>harry-core</artifactId>
- <version>0.0.1</version>
- <scope>test</scope>
+ <version>harry-core-0.0.2-CASSANDRA-18768</version>
+ <scope>system</scope>
+ <systemPath>${test.lib}/harry-core-0.0.2-CASSANDRA-18768.jar</systemPath>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 145afaa557..038c22578d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -24,7 +24,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -75,8 +75,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -111,10 +111,10 @@ jobs:
j17_dtests:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -182,8 +182,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -246,8 +246,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -281,10 +281,10 @@ jobs:
j17_cqlsh_dtests_py311_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -354,8 +354,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -392,7 +392,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -443,8 +443,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -481,7 +481,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -532,8 +532,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -597,8 +597,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -633,10 +633,10 @@ jobs:
j17_cqlsh_dtests_py3_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -706,8 +706,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -744,7 +744,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -823,8 +823,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -858,10 +858,10 @@ jobs:
j17_cqlsh_dtests_py38_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -931,8 +931,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -966,10 +966,10 @@ jobs:
j17_dtests_vnode_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1085,8 +1085,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1120,10 +1120,10 @@ jobs:
j17_dtests_offheap_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1217,8 +1217,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1252,10 +1252,10 @@ jobs:
j11_dtests_vnode_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1349,8 +1349,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1388,7 +1388,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1467,8 +1467,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1503,10 +1503,10 @@ jobs:
j17_cqlsh_dtests_py3:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -1576,8 +1576,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1614,7 +1614,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1665,8 +1665,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1704,7 +1704,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1783,8 +1783,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1821,7 +1821,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -1872,8 +1872,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -1907,10 +1907,10 @@ jobs:
j11_cqlsh_dtests_py311:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -1980,8 +1980,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2016,10 +2016,10 @@ jobs:
j17_dtests_large_vnode_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2113,8 +2113,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2148,10 +2148,10 @@ jobs:
j17_dtests_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2267,8 +2267,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2305,7 +2305,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2384,8 +2384,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2420,10 +2420,10 @@ jobs:
j17_cqlsh_dtests_py311:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -2493,8 +2493,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2528,10 +2528,10 @@ jobs:
j11_cqlsh_dtests_py38:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -2601,8 +2601,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2640,7 +2640,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2691,8 +2691,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2729,7 +2729,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2780,8 +2780,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2819,7 +2819,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -2898,8 +2898,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -2936,7 +2936,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3093,8 +3093,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3129,7 +3129,7 @@ jobs:
j11_dtests_large_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
@@ -3178,8 +3178,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3214,10 +3214,10 @@ jobs:
j11_dtests_large_vnode_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3311,8 +3311,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3350,7 +3350,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3429,8 +3429,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3464,10 +3464,10 @@ jobs:
j11_cqlsh_dtests_py38_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -3537,8 +3537,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3573,7 +3573,7 @@ jobs:
j11_dtests_large:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
@@ -3622,8 +3622,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3661,7 +3661,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3712,8 +3712,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3751,7 +3751,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3830,8 +3830,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -3866,10 +3866,10 @@ jobs:
j11_upgrade_dtests_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -3963,8 +3963,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4002,7 +4002,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 1
+ parallelism: 10
steps:
- attach_workspace:
at: /home/cassandra
@@ -4081,8 +4081,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4119,7 +4119,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -4276,8 +4276,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4311,10 +4311,10 @@ jobs:
j11_cqlsh_dtests_py3:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -4384,8 +4384,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4491,8 +4491,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4529,7 +4529,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -4608,8 +4608,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4647,7 +4647,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -4698,8 +4698,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4769,8 +4769,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4805,10 +4805,10 @@ jobs:
j11_dtests_offheap_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -4902,8 +4902,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -4941,7 +4941,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 1
+ parallelism: 10
steps:
- attach_workspace:
at: /home/cassandra
@@ -5020,8 +5020,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5124,8 +5124,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5196,8 +5196,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5235,7 +5235,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -5286,8 +5286,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5399,8 +5399,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5438,7 +5438,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 1
+ parallelism: 4
steps:
- attach_workspace:
at: /home/cassandra
@@ -5517,8 +5517,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5589,8 +5589,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5628,7 +5628,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -5679,8 +5679,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5715,10 +5715,10 @@ jobs:
j17_dtests_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -5786,8 +5786,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5821,10 +5821,10 @@ jobs:
j11_dtests_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -5918,8 +5918,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -5957,7 +5957,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -6036,8 +6036,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6075,7 +6075,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -6126,8 +6126,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6161,10 +6161,10 @@ jobs:
j11_cqlsh_dtests_py3_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -6234,8 +6234,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6270,10 +6270,10 @@ jobs:
j11_cqlsh_dtests_py311_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -6343,8 +6343,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6382,7 +6382,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -6461,8 +6461,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6497,10 +6497,10 @@ jobs:
j11_upgrade_dtests:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@@ -6546,8 +6546,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6582,10 +6582,10 @@ jobs:
j11_dtests_large_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -6679,8 +6679,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6718,7 +6718,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -6769,8 +6769,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6804,10 +6804,10 @@ jobs:
j11_cqlsh_dtests_py3_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -6877,8 +6877,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6949,8 +6949,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -6984,7 +6984,7 @@ jobs:
j17_dtests_large_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
@@ -7033,8 +7033,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7068,10 +7068,10 @@ jobs:
j11_dtests_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -7117,8 +7117,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7153,10 +7153,10 @@ jobs:
j11_cqlsh_dtests_py38_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -7226,8 +7226,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7265,7 +7265,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -7316,8 +7316,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7355,7 +7355,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -7406,8 +7406,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7445,7 +7445,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -7496,8 +7496,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7532,10 +7532,10 @@ jobs:
j17_cqlsh_dtests_py38_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -7605,8 +7605,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7668,8 +7668,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7703,10 +7703,10 @@ jobs:
j11_cqlsh_dtests_py311_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -7776,8 +7776,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7815,7 +7815,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -7894,8 +7894,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -7929,10 +7929,10 @@ jobs:
j17_cqlsh_dtests_py3_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -8002,8 +8002,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8037,10 +8037,10 @@ jobs:
j17_cqlsh_dtests_py311_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -8110,8 +8110,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8148,7 +8148,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 1
+ parallelism: 10
steps:
- attach_workspace:
at: /home/cassandra
@@ -8227,8 +8227,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8299,8 +8299,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8337,7 +8337,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -8388,8 +8388,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8495,8 +8495,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8534,7 +8534,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -8585,8 +8585,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8649,8 +8649,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8685,10 +8685,10 @@ jobs:
j11_dtests:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -8734,8 +8734,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8773,7 +8773,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 1
+ parallelism: 10
steps:
- attach_workspace:
at: /home/cassandra
@@ -8852,8 +8852,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8887,10 +8887,10 @@ jobs:
j17_cqlsh_dtests_py38:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -8960,8 +8960,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -8998,7 +8998,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9077,8 +9077,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9115,7 +9115,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9166,8 +9166,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9201,7 +9201,7 @@ jobs:
j17_dtests_large:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
@@ -9250,8 +9250,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9288,7 +9288,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9339,8 +9339,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9411,8 +9411,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9449,7 +9449,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9500,8 +9500,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9535,10 +9535,10 @@ jobs:
j11_dtests_vnode:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11-w-dependencies:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -9584,8 +9584,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9623,7 +9623,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9674,8 +9674,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9709,10 +9709,10 @@ jobs:
j17_dtests_offheap:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 50
steps:
- attach_workspace:
at: /home/cassandra
@@ -9780,8 +9780,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9815,10 +9815,10 @@ jobs:
j17_dtests_large_repeat:
docker:
- image: apache/cassandra-testing-ubuntu2004-java11:latest
- resource_class: medium
+ resource_class: large
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -9912,8 +9912,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -9950,7 +9950,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -10001,8 +10001,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
@@ -10039,7 +10039,7 @@ jobs:
resource_class: medium
working_directory: ~/
shell: /bin/bash -eo pipefail -l
- parallelism: 4
+ parallelism: 25
steps:
- attach_workspace:
at: /home/cassandra
@@ -10090,8 +10090,8 @@ jobs:
- CASS_DRIVER_NO_EXTENSIONS: true
- CASS_DRIVER_NO_CYTHON: true
- CASSANDRA_SKIP_SYNC: true
- - DTEST_REPO: https://github.com/apache/cassandra-dtest.git
- - DTEST_BRANCH: trunk
+ - DTEST_REPO: https://github.com/krummas/cassandra-dtest.git
+ - DTEST_BRANCH: cep-21-tcm
- CCM_MAX_HEAP_SIZE: 1024M
- CCM_HEAP_NEWSIZE: 256M
- REPEATED_TESTS_STOP_ON_FAILURE: false
diff --git a/.gitignore b/.gitignore
index aa9e76c932..16cc10a5ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ pylib/src/
pylib/cqlshlib/serverversion.py
!lib/cassandra-driver-internal-only-*.zip
!lib/puresasl-*.zip
+!lib/harry-0.0.2-internal-20221121.14211-2.jar
# C* debs
build-stamp
diff --git a/NEWS.txt b/NEWS.txt
index c6b7e75ee3..37c3c93928 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -71,11 +71,70 @@ using the provided 'sstableupgrade' tool.
New features
------------
+ [The following is a placeholder, to be revised asap]
+ - CEP-21 Transactional Cluster Metadata introduces a distributed log for linearizing modifications to cluster
+ metadata. In the first instance, this encompasses cluster membership, token ownership and schema metadata. See
+ https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-21%3A+Transactional+Cluster+Metadata for more detail on
+ the motivation and design, and see "Upgrading" below for specific instructions on migrating clusters to this system.
+ More updates and documentation to follow.
- New Guardrails added:
- Whether bulk loading of SSTables is allowed.
Upgrading
---------
+ [The following is a placeholder, to be revised asap]
+ - Upgrading to 5.1 is currently only supported from 4.0, 4.1 or 5.0. Clusters running earlier releases must first
+ upgrade to at least the latest 4.0 release. When a cluster is upgraded to 5.1 there is an additional step for
+ operators to perform. The upgrade is not considered complete until:
+ 1. All UP nodes are running 5.1
+ 2. The Cluster Metadata Service (CMS) has been enabled
+ The first step is just a regular upgrade, there are no changes to external APIs, SSTable formats to consider.
+ Step 2 requires an operator to run a new nodetool subcommand, intializecms, on one node in the cluster.
+ - > nodetool initializecms
+ Doing so creates the CMS with the local node as its only member. The initializecms command cannot be executed until
+ step 1 is complete and all nodes are running 5.1 as migrating metadata management over to the new TCM system
+ requires all nodes to be in agreement over the current state of the cluster. Essentially this means agreement on
+ schema and topology. Once the upgrade has started, but before initializecms is run, metadata-changing operations are
+ not permitted and if attempted from an upgraded node will be rejected.
+ Prohibited operations include:
+ - schema changes
+ - node replacement
+ - bootstrap
+ - decommission
+ - move
+ - assasinate
+ For the time being there is no mechanism in place to prevent these operations being executed by a node still running
+ a previous version, though this is planned before release. Any automation which can trigger these operations should
+ be disabled for the cluster prior to starting the upgrade.
+ Should any of the prohibited operations be executed (i.e. on a node that is still running a pre-5.1 version) before
+ the CMS migration, nodes which are DOWN or which have been upgraded will not process the metadata changes. However,
+ nodes still UP and running the old version will. This will eventually cause the migration to fail, as the cluster
+ will not be in agreement.
+ - > nodetool initializecms
+ Got mismatching cluster metadatas from [/x.x.x.x:7000] aborting migration
+ See 'nodetool help' or 'nodetool help <command>'.
+ If the initializecms command fails, it will indicate which nodes’ current metadata does not agree with the node
+ where the command was executed. To mitigate this situation, bring any mismatching nodes DOWN and rerun the
+ initializecms command with the additional —ignore flag.
+ - nodetool intializecms -ignore x.x.x.x
+ Once the command has run successfully the ignored nodes can be restarted but any metadata changes that they
+ accepted/and or applied whilst the cluster was in mixed mode will be lost. We plan to improve this before beta, but
+ in the meantime operators should ensure no schema or membership/ownership changes are performed during the upgrade.
+ Although the restrictions on metadata-changing operations will be removed as soon as the initial CMS migration is
+ complete, at that point the CMS will only contain a single member, which is not suitable for real clusters. To
+ modify the membership of the CMS a second nodetool subcommand, reconfigurecms, should be run. This command allows
+ the number of required number of CMS members to be specified for each datacenter. Consensus for metadata operations
+ by the CMS is obtained via Paxos, operating at SERIAL/QUORUM consistency, so the minimum safe size for the CMS is 3
+ nodes. In multi-DC deployments, the CMS members may be distributed across DCs to ensure resilience in the case of a
+ DC outage. It is not recommended to make every node a member of the CMS. Redundancy is the primary concern here, not
+ locality or latency, so between 3 and 7 nodes per DC depending on the size of the cluster should be the goal.
+ Deploying to a fresh cluster is more straightforward. As the cluster comes up, at least one node will automatically
+ nominate itself as the first CMS node. A simple election mechanism ensures that only one node will be chosen if
+ multiple peers attempt to nominate themselves. As soon as the election is complete, metadata modifications are
+ supported. Typically, this takes only a few seconds and is likely to complete before all nodes are fully UP. Nodes
+ which come up during or after an election will learn of the elected first CMS node and direct metadata updates to
+ it. It is important to remember that at the completion of the election, the CMS still only comprises a single
+ member. Just as in the upgrade case, operators should add further members as soon as possible.
Deprecation
-----------
diff --git a/build.xml b/build.xml
index 04b742ad51..a3beed1f17 100644
--- a/build.xml
+++ b/build.xml
@@ -403,7 +403,7 @@
<target name="realclean" depends="clean" description="Remove the entire build directory and all downloaded artifacts">
<delete>
- <fileset dir="${build.lib}" excludes="cassandra-driver-internal-only-*,puresasl-internal-only-*"/>
+ <fileset dir="${build.lib}" excludes="cassandra-driver-internal-only-*,puresasl-internal-only-*,harry-*"/>
</delete>
<delete dir="${build.dir}" />
<delete dir="${doc.dir}/build" />
diff --git a/ci/harry_simulation.sh b/ci/harry_simulation.sh
new file mode 100755
index 0000000000..8af018cecd
--- /dev/null
+++ b/ci/harry_simulation.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+# 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.
+
+set -x
+set -o errexit
+set -o nounset
+set -o pipefail
+
+rm -f build/test/lib/jars/guava-18.0.jar
+current_dir=$(dirname "$(readlink -f "$0")")
+
+common=(-Dstorage-config=$current_dir/../test/conf
+ -Djava.awt.headless=true
+ -ea
+ -XX:SoftRefLRUPolicyMSPerMB=0
+ -XX:HeapDumpPath=build/test
+ -Dcassandra.test.driver.connection_timeout_ms=10000
+ -Dcassandra.test.driver.read_timeout_ms=24000
+ -Dcassandra.memtable_row_overhead_computation_step=100
+ -Dcassandra.test.use_prepared=true
+ -Dcassandra.test.sstableformatdevelopment=true
+ -Djava.security.egd=file:/dev/urandom
+ -Dcassandra.testtag=.jdk11
+ -Dstorage-config=$current_dir/../test/conf
+ -Djava.awt.headless=true
+ -Dcassandra.keepBriefBrief=true
+ -Dcassandra.allow_simplestrategy=true
+ -Dcassandra.strict.runtime.checks=true
+ -Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true
+ -Dcassandra.test.flush_local_schema_changes=false
+ -Dcassandra.test.messagingService.nonGracefulShutdown=true
+ -Dcassandra.use_nix_recursive_delete=true
+ -Dcie-cassandra.disable_schema_drop_log=true
+ -Dcassandra.ring_delay_ms=10000
+ -Dcassandra.tolerate_sstable_size=true
+ -Dcassandra.skip_sync=true
+ -Dcassandra.debugrefcount=false
+ -Dcassandra.test.simulator.determinismcheck=strict
+ -Dcassandra.test.simulator.print_asm=none
+ -Dlog4j2.disableJmx=true
+ -Dlog4j2.disable.jmx=true
+ -Dlog4j.shutdownHookEnabled=false
+ -Dcassandra.test.logConfigPath=$current_dir/../test/conf/log4j2-dtest-simulator.xml
+ -Dcassandra.test.logConfigProperty=log4j.configurationFile
+ -Dlog4j2.configurationFile=$current_dir/../test/conf/log4j2-dtest-simulator.xml
+ -javaagent:$current_dir/../lib/jamm-0.3.2.jar
+ -javaagent:$current_dir/../build/test/lib/jars/simulator-asm.jar
+ -Xbootclasspath/a:$current_dir/../build/test/lib/jars/simulator-bootstrap.jar
+ -XX:ActiveProcessorCount=4
+ -XX:-TieredCompilation
+ -XX:-BackgroundCompilation
+ -XX:CICompilerCount=1
+ -XX:Tier4CompileThreshold=1000
+ -XX:ReservedCodeCacheSize=256M
+ -Xmx16G
+ -Xmx4G
+ -Xss384k
+ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
+ --add-exports java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-exports java.base/sun.nio.ch=ALL-UNNAMED
+ --add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
+ --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
+ --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED
+ --add-exports java.sql/java.sql=ALL-UNNAMED
+ --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
+ --add-opens java.base/java.lang.module=ALL-UNNAMED
+ --add-opens java.base/java.net=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.ref=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.math=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.module=ALL-UNNAMED
+ --add-opens java.base/jdk.internal.util.jar=ALL-UNNAMED
+ --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
+ --add-opens jdk.management.jfr/jdk.management.jfr=ALL-UNNAMED
+ --add-opens java.desktop/com.sun.beans.introspect=ALL-UNNAMED
+ -classpath $current_dir/../build/classes/main/:$current_dir/../build/test/classes/:$current_dir/../build/test/lib/jars/*:$current_dir/../build/lib/jars/*
+
+ )
+
+
+java "${common[@]}" org.apache.cassandra.simulator.test.HarrySimulatorTest
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index 4fb3bde86d..1663357bee 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1201,16 +1201,16 @@ range_request_timeout: 10000ms
# How long the coordinator should wait for writes to complete.
# Lowest acceptable value is 10 ms.
# Min unit: ms
-write_request_timeout: 2000ms
+write_request_timeout: 10000ms
# How long the coordinator should wait for counter writes to complete.
# Lowest acceptable value is 10 ms.
# Min unit: ms
-counter_write_request_timeout: 5000ms
+counter_write_request_timeout: 1000ms
# How long a coordinator should continue to retry a CAS operation
# that contends with other proposals for the same row.
# Lowest acceptable value is 10 ms.
# Min unit: ms
-cas_contention_timeout: 1000ms
+cas_contention_timeout: 5000ms
# How long the coordinator should wait for truncates to complete
# (This can be much longer, because unless auto_snapshot is disabled
# we need to flush first so we can snapshot before removing the data.)
@@ -2088,12 +2088,6 @@ drop_compact_storage_enabled: false
# enabled: false
# ownership_token: "sometoken" # (overriden by "CassandraOwnershipToken" system property)
# ownership_filename: ".cassandra_fs_ownership" # (overriden by "cassandra.fs_ownership_filename")
-# Prevents a node from starting if snitch's data center differs from previous data center.
-# check_dc:
-# enabled: true # (overriden by cassandra.ignore_dc system property)
-# Prevents a node from starting if snitch's rack differs from previous rack.
-# check_rack:
-# enabled: true # (overriden by cassandra.ignore_rack system property)
# Enable this property to fail startup if the node is down for longer than gc_grace_seconds, to potentially
# prevent data resurrection on tables with deletes. By default, this will run against all keyspaces and tables
# except the ones specified on excluded_keyspaces and excluded_tables.
@@ -2129,4 +2123,4 @@ drop_compact_storage_enabled: false
# - Do a rolling restart with all nodes starting with NONE. This sheds the extra cost of checking nodes versions and ensures
# a stable cluster. If a node from a previous version was started by accident we won't any longer toggle behaviors as when UPGRADING.
#
-storage_compatibility_mode: CASSANDRA_4
+storage_compatibility_mode: NONE
diff --git a/conf/harry-example.yaml b/conf/harry-example.yaml
new file mode 100644
index 0000000000..1868ad9959
--- /dev/null
+++ b/conf/harry-example.yaml
@@ -0,0 +1,95 @@
+# 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.
+
+seed: 1596731732524
+
+# Default schema provider generates random schema
+schema_provider:
+ fixed:
+ keyspace: harry
+ table: test_table
+ partition_keys:
+ pk1: bigint
+ pk2: ascii
+ clustering_keys:
+ ck1: ascii
+ ck2: bigint
+ regular_columns:
+ v1: ascii
+ v2: bigint
+ v3: ascii
+ v4: bigint
+ static_keys:
+ s1: ascii
+ s2: bigint
+ s3: ascii
+ s4: bigint
+
+# Clock is a component responsible for mapping _logical_ timestamps to _real-time_ ones.
+#
+# When reproducing test failures, and for validation purposes, a snapshot of such clock can
+# be taken to map a real-time timestamp from the value retrieved from the database in order
+# to map it back to the logical timestamp of the operation that wrote this value.
+clock:
+ offset:
+ offset: 1000
+
+drop_schema: false
+create_schema: true
+truncate_table: true
+
+# Partition descriptor selector controls how partitions is selected based on the current logical
+# timestamp. Default implementation is a sliding window of partition descriptors that will visit
+# one partition after the other in the window `slide_after_repeats` times. After that will
+# retire one partition descriptor, and pick one instead of it.
+partition_descriptor_selector:
+ default:
+ window_size: 10
+ slide_after_repeats: 100
+
+# Clustering descriptor selector controls how clusterings are picked within the partition:
+# how many rows there can be in a partition, how many rows will be visited for a logical timestamp,
+# how many operations there will be in batch, what kind of operations there will and how often
+# each kind of operation is going to occur.
+clustering_descriptor_selector:
+ default:
+ modifications_per_lts:
+ type: "constant"
+ constant: 2
+ rows_per_modification:
+ type: "constant"
+ constant: 2
+ operation_kind_weights:
+ DELETE_RANGE: 0
+ DELETE_SLICE: 0
+ DELETE_ROW: 0
+ DELETE_COLUMN: 0
+ DELETE_PARTITION: 0
+ DELETE_COLUMN_WITH_STATICS: 0
+ INSERT_WITH_STATICS: 50
+ INSERT: 50
+ UPDATE_WITH_STATICS: 50
+ UPDATE: 50
+ column_mask_bitsets: null
+ max_partition_size: 1000
+
+metric_reporter:
+ no_op: {}
+
+data_tracker:
+ locking:
+ max_seen_lts: -1
+ max_complete_lts: -1
diff --git a/lib/harry-core-0.0.2-CASSANDRA-18768.jar b/lib/harry-core-0.0.2-CASSANDRA-18768.jar
new file mode 100644
index 0000000000..292db01f06
Binary files /dev/null and b/lib/harry-core-0.0.2-CASSANDRA-18768.jar differ
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 861ebee7e4..252ebabe30 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,8 +34,8 @@ class UnexpectedTableStructure(UserWarning):
SYSTEM_KEYSPACES = ('system', 'system_schema', 'system_traces', 'system_auth', 'system_distributed', 'system_views',
- 'system_virtual_schema')
-NONALTERBALE_KEYSPACES = ('system', 'system_schema', 'system_views', 'system_virtual_schema')
+ 'system_virtual_schema', 'system_cluster_metadata')
+NONALTERBALE_KEYSPACES = ('system', 'system_schema', 'system_views', 'system_virtual_schema', 'system_cluster_metadata')
class Cql3ParsingRuleSet(CqlParsingRuleSet):
diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py
index 8e079c8e36..c2a99dc7b5 100644
--- a/pylib/cqlshlib/test/test_cqlsh_completion.py
+++ b/pylib/cqlshlib/test/test_cqlsh_completion.py
@@ -589,7 +589,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
def test_complete_in_drop_type(self):
self.trycompletions('DROP TYPE ', choices=['IF', 'system_views.',
- 'tags', 'system_traces.', 'system_distributed.',
+ 'tags', 'system_traces.', 'system_distributed.', 'system_cluster_metadata.',
'phone_number', 'quote_udt', 'band_info_type', 'address', 'system.', 'system_schema.',
'system_auth.', 'system_virtual_schema.', self.cqlsh.keyspace + '.'
])
@@ -897,7 +897,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
self.trycompletions('US', immediate='E ')
self.trycompletions('USE ', choices=[self.cqlsh.keyspace, 'system', 'system_auth',
'system_distributed', 'system_schema', 'system_traces', 'system_views',
- 'system_virtual_schema' ])
+ 'system_virtual_schema', 'system_cluster_metadata' ])
def test_complete_in_create_index(self):
self.trycompletions('CREATE I', immediate='NDEX ')
@@ -994,6 +994,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
'system_traces.', 'songs', 'system_views.',
'system_virtual_schema.',
'system_schema.', 'system_distributed.',
+ 'system_cluster_metadata.',
self.cqlsh.keyspace + '.'])
self.trycompletions('ALTER TABLE IF EXISTS new_table ADD ', choices=['<new_column_name>', 'IF'])
self.trycompletions('ALTER TABLE IF EXISTS new_table ADD IF NOT EXISTS ', choices=['<new_column_name>'])
@@ -1021,7 +1022,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
self.trycompletions('ALTER TYPE ', choices=['IF', 'system_views.',
'tags', 'system_traces.', 'system_distributed.',
'phone_number', 'quote_udt', 'band_info_type', 'address', 'system.', 'system_schema.',
- 'system_auth.', 'system_virtual_schema.', self.cqlsh.keyspace + '.'
+ 'system_auth.', 'system_virtual_schema.', 'system_cluster_metadata.', self.cqlsh.keyspace + '.'
])
self.trycompletions('ALTER TYPE IF EXISTS new_type ADD ', choices=['<new_field_name>', 'IF'])
self.trycompletions('ALTER TYPE IF EXISTS new_type ADD IF NOT EXISTS ', choices=['<new_field_name>'])
diff --git a/src/java/org/apache/cassandra/auth/AuthKeyspace.java b/src/java/org/apache/cassandra/auth/AuthKeyspace.java
index b495c90419..e973f5f455 100644
--- a/src/java/org/apache/cassandra/auth/AuthKeyspace.java
+++ b/src/java/org/apache/cassandra/auth/AuthKeyspace.java
@@ -41,7 +41,7 @@ public final class AuthKeyspace
{
}
- private static final int DEFAULT_RF = CassandraRelevantProperties.SYSTEM_AUTH_DEFAULT_RF.getInt();
+ public static final int DEFAULT_RF = CassandraRelevantProperties.SYSTEM_AUTH_DEFAULT_RF.getInt();
/**
* Generation is used as a timestamp for automatic table creation on startup.
@@ -68,79 +68,85 @@ public final class AuthKeyspace
public static final long SUPERUSER_SETUP_DELAY = SUPERUSER_SETUP_DELAY_MS.getLong();
+ public static String ROLES_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "role text,"
+ + "is_superuser boolean,"
+ + "can_login boolean,"
+ + "salted_hash text,"
+ + "member_of set<text>,"
+ + "PRIMARY KEY(role))";
private static final TableMetadata Roles =
parse(ROLES,
"role definitions",
- "CREATE TABLE %s ("
- + "role text,"
- + "is_superuser boolean,"
- + "can_login boolean,"
- + "salted_hash text,"
- + "member_of set<text>,"
- + "PRIMARY KEY(role))");
+ ROLES_CQL);
+
+ public static String IDENTITY_TO_ROLES_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "identity text," // opaque identity string for use by role authenticators
+ + "role text,"
+ + "PRIMARY KEY(identity))";
private static final TableMetadata IdentityToRoles =
parse(IDENTITY_TO_ROLES,
"mtls authorized identities lookup table",
- "CREATE TABLE %s ("
- + "identity text," // opaque identity string for use by role authenticators
- + "role text,"
- + "PRIMARY KEY(identity))"
+ IDENTITY_TO_ROLES_CQL
);
+ public static String ROLE_MEMBERS_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "role text,"
+ + "member text,"
+ + "PRIMARY KEY(role, member))";
private static final TableMetadata RoleMembers =
parse(ROLE_MEMBERS,
"role memberships lookup table",
- "CREATE TABLE %s ("
- + "role text,"
- + "member text,"
- + "PRIMARY KEY(role, member))");
+ ROLE_MEMBERS_CQL);
+ public static String ROLE_PERMISSIONS_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "role text,"
+ + "resource text,"
+ + "permissions set<text>,"
+ + "PRIMARY KEY(role, resource))";
private static final TableMetadata RolePermissions =
parse(ROLE_PERMISSIONS,
"permissions granted to db roles",
- "CREATE TABLE %s ("
- + "role text,"
- + "resource text,"
- + "permissions set<text>,"
- + "PRIMARY KEY(role, resource))");
+ ROLE_PERMISSIONS_CQL);
+ public static String RESOURCE_ROLE_INDEX_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "resource text,"
+ + "role text,"
+ + "PRIMARY KEY(resource, role))";
private static final TableMetadata ResourceRoleIndex =
parse(RESOURCE_ROLE_INDEX,
"index of db roles with permissions granted on a resource",
- "CREATE TABLE %s ("
- + "resource text,"
- + "role text,"
- + "PRIMARY KEY(resource, role))");
+ RESOURCE_ROLE_INDEX_CQL);
+ public static String NETWORK_PERMISSIONS_CQL = "CREATE TABLE IF NOT EXISTS %s ("
+ + "role text, "
+ + "dcs frozen<set<text>>, "
+ + "PRIMARY KEY(role))";
private static final TableMetadata NetworkPermissions =
parse(NETWORK_PERMISSIONS,
"user network permissions",
- "CREATE TABLE %s ("
- + "role text, "
- + "dcs frozen<set<text>>, "
- + "PRIMARY KEY(role))");
+ NETWORK_PERMISSIONS_CQL);
+
+ public static String CIDR_PERMISSIONS_CQL = "CREATE TABLE %s ("
+ + "role text, "
+ + "cidr_groups frozen<set<text>>, "
+ + "PRIMARY KEY(role))";
- public static final String CIDR_PERMISSIONS_TBL_ROLE_COL_NAME = "role";
- public static final String CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME = "cidr_groups";
private static final TableMetadata CIDRPermissions =
parse(CIDR_PERMISSIONS,
"user cidr permissions",
- "CREATE TABLE %s ("
- + CIDR_PERMISSIONS_TBL_ROLE_COL_NAME + " text, "
- + CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME + " frozen<set<text>>, "
- + "PRIMARY KEY(" + CIDR_PERMISSIONS_TBL_ROLE_COL_NAME + "))"
+ CIDR_PERMISSIONS_CQL
);
- public static final String CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME = "cidr_group";
- public static final String CIDR_GROUPS_TBL_CIDRS_COL_NAME = "cidrs";
+ public static String CIDR_GROUPS_CQL = "CREATE TABLE %s ("
+ + "cidr_group text, "
+ + "cidrs frozen<set<tuple<inet, smallint>>>, "
+ + "PRIMARY KEY(cidr_group))";
private static final TableMetadata CIDRGroups =
parse(CIDR_GROUPS,
"cidr groups to cidrs mapping",
- "CREATE TABLE %s ("
- + CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME + " text, "
- + CIDR_GROUPS_TBL_CIDRS_COL_NAME + " frozen<set<tuple<inet, smallint>>>, "
- + "PRIMARY KEY(" + CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME + "))"
+ CIDR_GROUPS_CQL
);
private static TableMetadata parse(String name, String description, String cql)
@@ -158,7 +164,6 @@ public final class AuthKeyspace
KeyspaceParams.simple(Math.max(DEFAULT_RF, DatabaseDescriptor.getDefaultKeyspaceRF())),
Tables.of(Roles, RoleMembers, RolePermissions,
ResourceRoleIndex, NetworkPermissions,
- CIDRPermissions, CIDRGroups,
- IdentityToRoles));
+ CIDRPermissions, CIDRGroups, IdentityToRoles));
}
}
diff --git a/src/java/org/apache/cassandra/auth/CIDRGroupsMappingLoader.java b/src/java/org/apache/cassandra/auth/CIDRGroupsMappingLoader.java
index 42ba904b28..925ff39da5 100644
--- a/src/java/org/apache/cassandra/auth/CIDRGroupsMappingLoader.java
+++ b/src/java/org/apache/cassandra/auth/CIDRGroupsMappingLoader.java
@@ -58,7 +58,7 @@ public class CIDRGroupsMappingLoader
UntypedResultSet rows = cidrGroupsMappingManager.getCidrGroupsTableEntries();
for (UntypedResultSet.Row row : rows)
{
- String cidrGroupName = row.getString(AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME);
+ String cidrGroupName = row.getString("cidr_group");
Set<Pair<InetAddress, Short>> cidrs = cidrGroupsMappingManager.retrieveCidrsFromRow(row);
for (Pair<InetAddress, Short> cidr : cidrs)
diff --git a/src/java/org/apache/cassandra/auth/CIDRGroupsMappingManager.java b/src/java/org/apache/cassandra/auth/CIDRGroupsMappingManager.java
index 6659bdcc15..c3788dfc96 100644
--- a/src/java/org/apache/cassandra/auth/CIDRGroupsMappingManager.java
+++ b/src/java/org/apache/cassandra/auth/CIDRGroupsMappingManager.java
@@ -70,18 +70,15 @@ public class CIDRGroupsMappingManager implements CIDRGroupsMappingManagerMBean
if (!MBeanWrapper.instance.isRegistered(MBEAN_NAME))
MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
- String getCidrGroupsQuery = String.format("SELECT %s FROM %s.%s",
- AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME,
+ String getCidrGroupsQuery = String.format("SELECT cidr_group FROM %s.%s",
SchemaConstants.AUTH_KEYSPACE_NAME,
AuthKeyspace.CIDR_GROUPS);
getCidrGroupsStatement = (SelectStatement) QueryProcessor.getStatement(getCidrGroupsQuery,
ClientState.forInternalCalls());
- String getCidrsForCidrGroupQuery = String.format("SELECT %s FROM %s.%s where %s = ?",
- AuthKeyspace.CIDR_GROUPS_TBL_CIDRS_COL_NAME,
+ String getCidrsForCidrGroupQuery = String.format("SELECT cidrs FROM %s.%s where cidr_group = ?",
SchemaConstants.AUTH_KEYSPACE_NAME,
- AuthKeyspace.CIDR_GROUPS,
- AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME);
+ AuthKeyspace.CIDR_GROUPS);
getCidrsForCidrGroupStatement = (SelectStatement) QueryProcessor.getStatement(getCidrsForCidrGroupQuery,
ClientState.forInternalCalls());
}
@@ -125,11 +122,11 @@ public class CIDRGroupsMappingManager implements CIDRGroupsMappingManagerMBean
for (UntypedResultSet.Row row : result)
{
- if (!row.has(AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME))
+ if (!row.has("cidr_group"))
throw new IllegalStateException("Invalid row " + row + " in table: " +
SchemaConstants.AUTH_KEYSPACE_NAME + '.' + AuthKeyspace.CIDR_GROUPS);
- availableCidrGroups.add(row.getString(AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME));
+ availableCidrGroups.add(row.getString("cidr_group"));
}
return availableCidrGroups;
@@ -137,14 +134,13 @@ public class CIDRGroupsMappingManager implements CIDRGroupsMappingManagerMBean
public Set<Pair<InetAddress, Short>> retrieveCidrsFromRow(UntypedResultSet.Row row)
{
- if (!row.has(AuthKeyspace.CIDR_GROUPS_TBL_CIDRS_COL_NAME))
- throw new RuntimeException("Invalid row, doesn't have column " +
- AuthKeyspace.CIDR_GROUPS_TBL_CIDRS_COL_NAME);
+ if (!row.has("cidrs"))
+ throw new RuntimeException("Invalid row, doesn't have column cidrs");
Set<Pair<InetAddress, Short>> cidrs = new HashSet<>();
TupleType tupleType = new TupleType(Arrays.asList(InetAddressType.instance, ShortType.instance));
- Set<ByteBuffer> cidrAsTuples = row.getFrozenSet(AuthKeyspace.CIDR_GROUPS_TBL_CIDRS_COL_NAME, tupleType);
+ Set<ByteBuffer> cidrAsTuples = row.getFrozenSet("cidrs", tupleType);
for (ByteBuffer cidrAsTuple : cidrAsTuples)
{
ByteBuffer[] splits = tupleType.split(ByteBufferAccessor.instance, cidrAsTuple);
@@ -182,12 +178,10 @@ public class CIDRGroupsMappingManager implements CIDRGroupsMappingManagerMBean
validCidrs.add(CIDR.getInstance(cidr));
}
- String query = String.format("UPDATE %s.%s SET %s = %s WHERE %s = '%s'",
+ String query = String.format("UPDATE %s.%s SET cidrs = %s WHERE cidr_group = '%s'",
SchemaConstants.AUTH_KEYSPACE_NAME,
AuthKeyspace.CIDR_GROUPS,
- AuthKeyspace.CIDR_GROUPS_TBL_CIDRS_COL_NAME,
getCidrTuplesSetString(validCidrs),
- AuthKeyspace.CIDR_GROUPS_TBL_CIDR_GROUP_COL_NAME,
cidrGroupName);
process(query, CassandraAuthorizer.authWriteConsistencyLevel());
diff --git a/src/java/org/apache/cassandra/auth/CIDRPermissionsManager.java b/src/java/org/apache/cassandra/auth/CIDRPermissionsManager.java
index 459d845bee..9c44c676d3 100644
--- a/src/java/org/apache/cassandra/auth/CIDRPermissionsManager.java
+++ b/src/java/org/apache/cassandra/auth/CIDRPermissionsManager.java
@@ -64,11 +64,9 @@ public class CIDRPermissionsManager implements CIDRPermissionsManagerMBean, Auth
if (!MBeanWrapper.instance.isRegistered(MBEAN_NAME))
MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
- String getCidrPermissionsOfUserQuery = String.format("SELECT %s FROM %s.%s WHERE %s = ?",
- AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME,
+ String getCidrPermissionsOfUserQuery = String.format("SELECT cidr_groups FROM %s.%s WHERE role = ?",
SchemaConstants.AUTH_KEYSPACE_NAME,
- AuthKeyspace.CIDR_PERMISSIONS,
- AuthKeyspace.CIDR_PERMISSIONS_TBL_ROLE_COL_NAME);
+ AuthKeyspace.CIDR_PERMISSIONS);
getCidrPermissionsOfUserStatement = (SelectStatement) QueryProcessor.getStatement(getCidrPermissionsOfUserQuery,
ClientState.forInternalCalls());
}
@@ -92,9 +90,9 @@ public class CIDRPermissionsManager implements CIDRPermissionsManagerMBean, Auth
ResultMessage.Rows rows = select(getCidrPermissionsOfUserStatement, options);
UntypedResultSet result = UntypedResultSet.create(rows.result);
- if (!result.isEmpty() && result.one().has(AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME))
+ if (!result.isEmpty() && result.one().has("cidr_groups"))
{
- return result.one().getFrozenSet(AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME, UTF8Type.instance);
+ return result.one().getFrozenSet("cidr_groups", UTF8Type.instance);
}
return Collections.emptySet();
@@ -145,12 +143,10 @@ public class CIDRPermissionsManager implements CIDRPermissionsManagerMBean, Auth
*/
public void setCidrGroupsForRole(RoleResource role, CIDRPermissions cidrPermissions)
{
- String query = String.format("UPDATE %s.%s SET %s = %s WHERE %s = '%s'",
+ String query = String.format("UPDATE %s.%s SET cidr_groups = %s WHERE role = '%s'",
SchemaConstants.AUTH_KEYSPACE_NAME,
AuthKeyspace.CIDR_PERMISSIONS,
- AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME,
getCidrPermissionsSetString(cidrPermissions),
- AuthKeyspace.CIDR_PERMISSIONS_TBL_ROLE_COL_NAME,
role.getRoleName());
process(query, CassandraAuthorizer.authWriteConsistencyLevel());
@@ -191,18 +187,16 @@ public class CIDRPermissionsManager implements CIDRPermissionsManagerMBean, Auth
logger.info("Pre-warming CIDR permissions cache from cidr_permissions table");
Map<RoleResource, CIDRPermissions> entries = new HashMap<>();
- UntypedResultSet rows = process(String.format("SELECT %s, %s FROM %s.%s",
- AuthKeyspace.CIDR_PERMISSIONS_TBL_ROLE_COL_NAME,
- AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME,
+ UntypedResultSet rows = process(String.format("SELECT role, cidr_groups FROM %s.%s",
SchemaConstants.AUTH_KEYSPACE_NAME,
AuthKeyspace.CIDR_PERMISSIONS),
CassandraAuthorizer.authReadConsistencyLevel());
for (UntypedResultSet.Row row : rows)
{
- RoleResource role = RoleResource.role(row.getString(AuthKeyspace.CIDR_PERMISSIONS_TBL_ROLE_COL_NAME));
+ RoleResource role = RoleResource.role(row.getString("role"));
CIDRPermissions.Builder builder = new CIDRPermissions.Builder();
- Set<String> cidrGroups = row.getFrozenSet(AuthKeyspace.CIDR_PERMISSIONS_TBL_CIDR_GROUPS_COL_NAME,
+ Set<String> cidrGroups = row.getFrozenSet("cidr_groups",
UTF8Type.instance);
for (String cidrGroup : cidrGroups)
builder.add(cidrGroup);
diff --git a/src/java/org/apache/cassandra/auth/CassandraRoleManager.java b/src/java/org/apache/cassandra/auth/CassandraRoleManager.java
index 3221c85184..921a45dcb2 100644
--- a/src/java/org/apache/cassandra/auth/CassandraRoleManager.java
+++ b/src/java/org/apache/cassandra/auth/CassandraRoleManager.java
@@ -36,18 +36,19 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.concurrent.ScheduledExecutors;
import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.cql3.statements.SelectStatement;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.exceptions.*;
+import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.StorageProxy;
-import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.messages.ResultMessage;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.NoSpamLogger;
+import org.apache.cassandra.utils.FBUtilities;
import org.mindrot.jbcrypt.BCrypt;
import static org.apache.cassandra.config.CassandraRelevantProperties.AUTH_BCRYPT_GENSALT_LOG2_ROUNDS;
@@ -144,14 +145,21 @@ public class CassandraRoleManager implements IRoleManager
}
@Override
- public void setup()
+ public void setup(boolean asyncRoleSetup)
{
loadRoleStatement();
loadIdentityStatement();
- scheduleSetupTask(() -> {
+ if (asyncRoleSetup)
+ {
+ scheduleSetupTask(() -> {
+ setupDefaultRole();
+ return null;
+ });
+ }
+ else
+ {
setupDefaultRole();
- return null;
- });
+ }
}
@Override
@@ -417,7 +425,7 @@ public class CassandraRoleManager implements IRoleManager
*/
private static void setupDefaultRole()
{
- if (StorageService.instance.getTokenMetadata().sortedTokens().isEmpty())
+ if (ClusterMetadata.current().tokenMap.tokens().isEmpty())
throw new IllegalStateException("CassandraRoleManager skipped default role setup: no known tokens in ring");
try
@@ -461,7 +469,7 @@ public class CassandraRoleManager implements IRoleManager
{
// The delay is to give the node a chance to see its peers before attempting the operation
ScheduledExecutors.optionalTasks.scheduleSelfRecurring(() -> {
- if (!StorageProxy.isSafeToPerformRead())
+ if (!StorageProxy.hasJoined())
{
logger.trace("Setup task may not run due to it not being safe to perform reads... rescheduling");
scheduleSetupTask(setupTask);
@@ -487,7 +495,7 @@ public class CassandraRoleManager implements IRoleManager
}
catch (RequestValidationException e)
{
- throw new AssertionError(e); // not supposed to happen
+ throw new AssertionError(e + " " + FBUtilities.getJustLocalAddress()); // not supposed to happen
}
}
diff --git a/src/java/org/apache/cassandra/auth/DCPermissions.java b/src/java/org/apache/cassandra/auth/DCPermissions.java
index d04242dd7e..c8a7716f45 100644
--- a/src/java/org/apache/cassandra/auth/DCPermissions.java
+++ b/src/java/org/apache/cassandra/auth/DCPermissions.java
@@ -28,6 +28,7 @@ import com.google.common.collect.Sets;
import org.apache.cassandra.dht.Datacenters;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.tcm.ClusterMetadata;
public abstract class DCPermissions
{
@@ -93,7 +94,7 @@ public abstract class DCPermissions
public void validate()
{
- Set<String> unknownDcs = Sets.difference(subset, Datacenters.getValidDatacenters());
+ Set<String> unknownDcs = Sets.difference(subset, Datacenters.getValidDatacenters(ClusterMetadata.current()));
if (!unknownDcs.isEmpty())
{
throw new InvalidRequestException(String.format("Invalid value(s) for DATACENTERS '%s'," +
diff --git a/src/java/org/apache/cassandra/auth/IRoleManager.java b/src/java/org/apache/cassandra/auth/IRoleManager.java
index 460bf1a16f..0479913846 100644
--- a/src/java/org/apache/cassandra/auth/IRoleManager.java
+++ b/src/java/org/apache/cassandra/auth/IRoleManager.java
@@ -22,6 +22,8 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
+import com.google.common.annotations.VisibleForTesting;
+
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.RequestExecutionException;
import org.apache.cassandra.exceptions.RequestValidationException;
@@ -226,7 +228,16 @@ public interface IRoleManager extends AuthCache.BulkLoader<RoleResource, Set<Rol
*
* For example, use this method to create any required keyspaces/column families.
*/
- void setup();
+ default void setup()
+ {
+ setup(true);
+ }
+
+ /**
+ * Like the method above, but allows to disable async role setup, making it synchronous.
+ */
+ @VisibleForTesting
+ void setup(boolean asyncRoleSetup);
/**
* Each valid identity is associated with a role in the identity_to_role table, this method returns role
diff --git a/src/java/org/apache/cassandra/batchlog/BatchlogManager.java b/src/java/org/apache/cassandra/batchlog/BatchlogManager.java
index b7b25cb7b2..a7ca258183 100644
--- a/src/java/org/apache/cassandra/batchlog/BatchlogManager.java
+++ b/src/java/org/apache/cassandra/batchlog/BatchlogManager.java
@@ -36,6 +36,8 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.RateLimiter;
import org.apache.cassandra.concurrent.ScheduledExecutorPlus;
+import org.apache.cassandra.schema.KeyspaceMetadata;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.utils.TimeUUID;
import org.apache.cassandra.utils.concurrent.Future;
import org.slf4j.Logger;
@@ -203,7 +205,7 @@ public class BatchlogManager implements BatchlogManagerMBean
// rate limit is in bytes per second. Uses Double.MAX_VALUE if disabled (set to 0 in cassandra.yaml).
// max rate is scaled by the number of nodes in the cluster (same as for HHOM - see CASSANDRA-5272).
- int endpointsCount = StorageService.instance.getTokenMetadata().getSizeOfAllEndpoints();
+ int endpointsCount = ClusterMetadata.current().directory.allJoinedEndpoints().size();
if (endpointsCount <= 0)
{
logger.trace("Replay cancelled as there are no peers in the ring.");
@@ -234,7 +236,7 @@ public class BatchlogManager implements BatchlogManagerMBean
*/
public void setRate(final int throttleInKB)
{
- int endpointsCount = StorageService.instance.getTokenMetadata().getSizeOfAllEndpoints();
+ int endpointsCount = ClusterMetadata.current().directory.allAddresses().size();
if (endpointsCount > 0)
{
int endpointThrottleInKiB = throttleInKB / endpointsCount;
@@ -471,29 +473,27 @@ public class BatchlogManager implements BatchlogManagerMBean
Set<UUID> hintedNodes)
{
String ks = mutation.getKeyspaceName();
- Keyspace keyspace = Keyspace.open(ks);
Token tk = mutation.key().getToken();
+ ClusterMetadata metadata = ClusterMetadata.current();
+ KeyspaceMetadata keyspaceMetadata = metadata.schema.getKeyspaceMetadata(ks);
// TODO: this logic could do with revisiting at some point, as it is unclear what its rationale is
// we perform a local write, ignoring errors and inline in this thread (potentially slowing replay down)
// effectively bumping CL for locally owned writes and also potentially stalling log replay if an error occurs
// once we decide how it should work, it can also probably be simplified, and avoid constructing a ReplicaPlan directly
- ReplicaLayout.ForTokenWrite liveAndDown = ReplicaLayout.forTokenWriteLiveAndDown(keyspace, tk);
- Replicas.temporaryAssertFull(liveAndDown.all()); // TODO in CASSANDRA-14549
+ ReplicaLayout.ForTokenWrite allReplias = ReplicaLayout.forTokenWriteLiveAndDown(metadata, keyspaceMetadata, tk);
+ ReplicaPlan.ForWrite replicaPlan = forReplayMutation(metadata, Keyspace.open(ks), tk);
- Replica selfReplica = liveAndDown.all().selfIfPresent();
+ Replica selfReplica = allReplias.all().selfIfPresent();
if (selfReplica != null)
mutation.apply();
- ReplicaLayout.ForTokenWrite liveRemoteOnly = liveAndDown.filter(
- r -> FailureDetector.isReplicaAlive.test(r) && r != selfReplica);
-
- for (Replica replica : liveAndDown.all())
+ for (Replica replica : allReplias.all())
{
- if (replica == selfReplica || liveRemoteOnly.all().contains(replica))
+ if (replica == selfReplica || replicaPlan.liveAndDown().contains(replica))
continue;
- UUID hostId = StorageService.instance.getHostIdForEndpoint(replica.endpoint());
+ UUID hostId = metadata.directory.peerId(replica.endpoint()).toUUID();
if (null != hostId)
{
HintsService.instance.write(hostId, Hint.create(mutation, writtenAt));
@@ -501,15 +501,26 @@ public class BatchlogManager implements BatchlogManagerMBean
}
}
- ReplicaPlan.ForWrite replicaPlan = new ReplicaPlan.ForWrite(keyspace, liveAndDown.replicationStrategy(),
- ConsistencyLevel.ONE, liveRemoteOnly.pending(), liveRemoteOnly.all(), liveRemoteOnly.all(), liveRemoteOnly.all());
ReplayWriteResponseHandler<Mutation> handler = new ReplayWriteResponseHandler<>(replicaPlan, mutation, nanoTime());
Message<Mutation> message = Message.outWithFlag(MUTATION_REQ, mutation, MessageFlag.CALL_BACK_ON_FAILURE);
- for (Replica replica : liveRemoteOnly.all())
+ for (Replica replica : replicaPlan.liveAndDown())
MessagingService.instance().sendWriteWithCallback(message, replica, handler);
return handler;
}
+ public static ReplicaPlan.ForWrite forReplayMutation(ClusterMetadata metadata, Keyspace keyspace, Token token)
+ {
+ ReplicaLayout.ForTokenWrite liveAndDown = ReplicaLayout.forTokenWriteLiveAndDown(metadata, keyspace.getMetadata(), token);
+ Replicas.temporaryAssertFull(liveAndDown.all()); // TODO in CASSANDRA-14549
+
+ Replica selfReplica = liveAndDown.all().selfIfPresent();
+ ReplicaLayout.ForTokenWrite liveRemoteOnly = liveAndDown.filter(r -> FailureDetector.isReplicaAlive.test(r) && r != selfReplica);
+
+ return new ReplicaPlan.ForWrite(keyspace, liveAndDown.replicationStrategy(),
+ ConsistencyLevel.ONE, liveRemoteOnly.pending(), liveRemoteOnly.all(), liveRemoteOnly.all(), liveRemoteOnly.all(),
+ (cm) -> forReplayMutation(cm, keyspace, token),
+ metadata.epoch);
+ }
private static int gcgs(Collection<Mutation> mutations)
{
int gcgs = Integer.MAX_VALUE;
diff --git a/src/java/org/apache/cassandra/cache/AutoSavingCache.java b/src/java/org/apache/cassandra/cache/AutoSavingCache.java
index 3826eb412e..0cfea0817d 100644
--- a/src/java/org/apache/cassandra/cache/AutoSavingCache.java
+++ b/src/java/org/apache/cassandra/cache/AutoSavingCache.java
@@ -60,6 +60,7 @@ import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.CacheService;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.concurrent.Future;
@@ -219,12 +220,13 @@ public class AutoSavingCache<K extends CacheKey, V> extends InstrumentingCache<K
in = streamFactory.getInputStream(dataPath, crcPath);
//Check the schema has not changed since CFs are looked up by name which is ambiguous
- UUID schemaVersion = new UUID(in.readLong(), in.readLong());
- if (!schemaVersion.equals(Schema.instance.getVersion()))
+ UUID expected = new UUID(in.readLong(), in.readLong());
+ UUID actual = ClusterMetadata.current().schema.getVersion();
+ if (!expected.equals(actual))
throw new RuntimeException("Cache schema version "
- + schemaVersion
+ + expected
+ " does not match current schema version "
- + Schema.instance.getVersion());
+ + actual);
ArrayDeque<Future<Pair<K, V>>> futures = new ArrayDeque<>();
long loadByNanos = start + TimeUnit.SECONDS.toNanos(DatabaseDescriptor.getCacheLoadTimeout());
diff --git a/src/java/org/apache/cassandra/concurrent/NamedThreadFactory.java b/src/java/org/apache/cassandra/concurrent/NamedThreadFactory.java
index 9816649424..e732729299 100644
--- a/src/java/org/apache/cassandra/concurrent/NamedThreadFactory.java
+++ b/src/java/org/apache/cassandra/concurrent/NamedThreadFactory.java
@@ -17,12 +17,14 @@
*/
package org.apache.cassandra.concurrent;
+import java.util.Arrays;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.annotations.VisibleForTesting;
import io.netty.util.concurrent.FastThreadLocalThread;
+import org.apache.cassandra.config.CassandraRelevantProperties;
import org.apache.cassandra.utils.JVMStabilityInspector;
/**
@@ -33,6 +35,8 @@ import org.apache.cassandra.utils.JVMStabilityInspector;
public class NamedThreadFactory implements ThreadFactory
{
+ public static final Boolean PRESERVE_THREAD_CREATION_STACKTRACE = CassandraRelevantProperties.TEST_PRESERVE_THREAD_CREATION_STACKTRACE.getBoolean();
+
private static final AtomicInteger anonymousCounter = new AtomicInteger();
private static volatile String globalPrefix;
@@ -159,11 +163,43 @@ public class NamedThreadFactory implements ThreadFactory
public static Thread createThread(ThreadGroup threadGroup, Runnable runnable, String name, boolean daemon)
{
String prefix = globalPrefix;
- Thread thread = new FastThreadLocalThread(threadGroup, runnable, prefix != null ? prefix + name : name);
+ Thread thread;
+ String threadName = prefix != null ? prefix + name : name;
+ if (PRESERVE_THREAD_CREATION_STACKTRACE)
+ thread = new InspectableFastThreadLocalThread(threadGroup, runnable, threadName);
+ else
+ thread = new FastThreadLocalThread(threadGroup, runnable, threadName);
thread.setDaemon(daemon);
return thread;
}
+ public static class InspectableFastThreadLocalThread extends FastThreadLocalThread
+ {
+ public StackTraceElement[] creationTrace;
+
+ private void setStack()
+ {
+ creationTrace = Thread.currentThread().getStackTrace();
+ creationTrace = Arrays.copyOfRange(creationTrace, 2, creationTrace.length);
+ }
+
+ public InspectableFastThreadLocalThread() { super(); setStack(); }
+
+ public InspectableFastThreadLocalThread(Runnable target) { super(target); setStack(); }
+
+ public InspectableFastThreadLocalThread(ThreadGroup group, Runnable target) { super(group, target); setStack(); }
+
+ public InspectableFastThreadLocalThread(String name) { super(name); setStack(); }
+
+ public InspectableFastThreadLocalThread(ThreadGroup group, String name) { super(group, name); setStack(); }
+
+ public InspectableFastThreadLocalThread(Runnable target, String name) { super(target, name); setStack(); }
+
+ public InspectableFastThreadLocalThread(ThreadGroup group, Runnable target, String name) { super(group, target, name); setStack(); }
+
+ public InspectableFastThreadLocalThread(ThreadGroup group, Runnable target, String name, long stackSize) { super(group, target, name, stackSize); setStack(); }
+
+ }
public static <T extends Thread> T setupThread(T thread, int priority, ClassLoader contextClassLoader, Thread.UncaughtExceptionHandler uncaughtExceptionHandler)
{
thread.setPriority(priority);
diff --git a/src/java/org/apache/cassandra/concurrent/Stage.java b/src/java/org/apache/cassandra/concurrent/Stage.java
index 05b6c612fa..4def177422 100644
--- a/src/java/org/apache/cassandra/concurrent/Stage.java
+++ b/src/java/org/apache/cassandra/concurrent/Stage.java
@@ -55,6 +55,8 @@ public enum Stage
INTERNAL_RESPONSE (false, "InternalResponseStage", "internal", FBUtilities::getAvailableProcessors, null, Stage::multiThreadedStage),
IMMEDIATE (false, "ImmediateStage", "internal", () -> 0, null, Stage::immediateExecutor),
PAXOS_REPAIR (false, "PaxosRepairStage", "internal", FBUtilities::getAvailableProcessors, null, Stage::multiThreadedStage),
+ INTERNAL_METADATA (false, "InternalMetadataStage", "internal", FBUtilities::getAvailableProcessors, null, Stage::multiThreadedStage),
+ FETCH_LOG (false, "MetadataFetchLogStage", "internal", () -> 1, null, Stage::singleThreadedStage)
;
public final String jmxName;
diff --git a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
index a850e99342..a38da0e22f 100644
--- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
+++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
@@ -353,7 +353,7 @@ public enum CassandraRelevantProperties
MEMTABLE_OVERHEAD_SIZE("cassandra.memtable.row_overhead_size", "-1"),
MEMTABLE_SHARD_COUNT("cassandra.memtable.shard.count"),
MEMTABLE_TRIE_SIZE_LIMIT("cassandra.trie_size_limit_mb"),
- MIGRATION_DELAY("cassandra.migration_delay_ms", "60000"),
+ METRICS_REPORTER_CONFIG_FILE("cassandra.metricsReporterConfigFile"),
/** Defines the maximum number of unique timed out queries that will be reported in the logs. Use a negative number to remove any limit. */
MONITORING_MAX_OPERATIONS("cassandra.monitoring_max_operations", "50"),
/** Defines the interval for reporting any operations that have timed out. */
@@ -468,7 +468,6 @@ public enum CassandraRelevantProperties
*/
SAI_VECTOR_SEARCH_ORDER_CHUNK_SIZE("cassandra.sai.vector_search.order_chunk_size", "100000"),
- SCHEMA_PULL_INTERVAL_MS("cassandra.schema_pull_interval_ms", "60000"),
SCHEMA_UPDATE_HANDLER_FACTORY_CLASS("cassandra.schema.update_handler_factory.class"),
SEARCH_CONCURRENCY_FACTOR("cassandra.search_concurrency_factor", "1"),
@@ -482,6 +481,7 @@ public enum CassandraRelevantProperties
SET_SEP_THREAD_NAME("cassandra.set_sep_thread_name", "true"),
SHUTDOWN_ANNOUNCE_DELAY_IN_MS("cassandra.shutdown_announce_in_ms", "2000"),
SIZE_RECORDER_INTERVAL("cassandra.size_recorder_interval", "300"),
+ SKIP_GC_INSPECTOR("cassandra.skip_gc_inspector", "false"),
SKIP_PAXOS_REPAIR_ON_TOPOLOGY_CHANGE("cassandra.skip_paxos_repair_on_topology_change"),
/** If necessary for operational purposes, permit certain keyspaces to be ignored for paxos topology repairs. */
SKIP_PAXOS_REPAIR_ON_TOPOLOGY_CHANGE_KEYSPACES("cassandra.skip_paxos_repair_on_topology_change_keyspaces"),
@@ -518,6 +518,30 @@ public enum CassandraRelevantProperties
SYSTEM_AUTH_DEFAULT_RF("cassandra.system_auth.default_rf", "1"),
SYSTEM_DISTRIBUTED_DEFAULT_RF("cassandra.system_distributed.default_rf", "3"),
SYSTEM_TRACES_DEFAULT_RF("cassandra.system_traces.default_rf", "2"),
+
+ // transactional cluster metadata relevant properties
+ // TODO: not a fan of being forced to prefix these to satisfy the alphabetic ordering constraint
+ // but it makes sense to group logically related properties together
+
+ TCM_ALLOW_TRANSFORMATIONS_DURING_UPGRADES("cassandra.allow_transformations_during_upgrades", "false"),
+ /**
+ * for obtaining acknowlegement from peers to make progress in multi-step operations
+ */
+ TCM_PROGRESS_BARRIER_BACKOFF_MILLIS("cassandra.progress_barrier_backoff_ms", "1000"),
+ TCM_PROGRESS_BARRIER_TIMEOUT_MILLIS("cassandra.progress_barrier_timeout_ms", "3600000"),
+ /**
+ * size of in-memory index of max epoch -> sealed period
+ */
+ TCM_RECENTLY_SEALED_PERIOD_INDEX_SIZE("cassandra.recently_sealed_period_index_size", "10"),
+
+ /**
+ * should replica groups in data placements be sorted to ensure the primary replica is first in the list
+ */
+ TCM_SORT_REPLICA_GROUPS("cassandra.sorted_replica_groups_enabled", "true"),
+ TCM_UNSAFE_BOOT_WITH_CLUSTERMETADATA("cassandra.unsafe_boot_with_clustermetadata", null),
+ TCM_USE_ATOMIC_LONG_PROCESSOR("cassandra.test.use_atomic_long_processor", "false"),
+ TCM_USE_NO_OP_REPLICATOR("cassandra.test.use_no_op_replicator", "false"),
+
TEST_BBFAILHELPER_ENABLED("test.bbfailhelper.enabled"),
TEST_BLOB_SHARED_SEED("cassandra.test.blob.shared.seed"),
TEST_BYTEMAN_TRANSFORMATIONS_DEBUG("cassandra.test.byteman.transformations.debug"),
@@ -543,13 +567,16 @@ public enum CassandraRelevantProperties
TEST_IGNORE_SIGAR("cassandra.test.ignore_sigar"),
TEST_INVALID_LEGACY_SSTABLE_ROOT("invalid-legacy-sstable-root"),
TEST_JVM_DTEST_DISABLE_SSL("cassandra.test.disable_ssl"),
+ TEST_JVM_SHUTDOWN_MESSAGING_GRACEFULLY("cassandra.test.messagingService.gracefulShutdown", "false"),
TEST_LEGACY_SSTABLE_ROOT("legacy-sstable-root"),
TEST_ORG_CAFFINITAS_OHC_SEGMENTCOUNT("org.caffinitas.ohc.segmentCount"),
+ TEST_PRESERVE_THREAD_CREATION_STACKTRACE("cassandra.test.preserve_thread_creation_stacktrace", "false"),
TEST_RANDOM_SEED("cassandra.test.random.seed"),
TEST_READ_ITERATION_DELAY_MS("cassandra.test.read_iteration_delay_ms", "0"),
TEST_REUSE_PREPARED("cassandra.test.reuse_prepared", "true"),
TEST_ROW_CACHE_SIZE("cassandra.test.row_cache_size"),
TEST_SERIALIZATION_WRITES("cassandra.test-serialization-writes"),
+ TEST_SIGAR_NATIVE_LOGGING("sigar.nativeLogging", "true"),
TEST_SIMULATOR_DEBUG("cassandra.test.simulator.debug"),
TEST_SIMULATOR_DETERMINISM_CHECK("cassandra.test.simulator.determinismcheck", "none"),
TEST_SIMULATOR_LIVENESS_CHECK("cassandra.test.simulator.livenesscheck", "true"),
@@ -590,7 +617,9 @@ public enum CassandraRelevantProperties
USE_NIX_RECURSIVE_DELETE("cassandra.use_nix_recursive_delete"),
/** Gossiper compute expiration timeout. Default value 3 days. */
VERY_LONG_TIME_MS("cassandra.very_long_time_ms", "259200000"),
- WAIT_FOR_TRACING_EVENTS_TIMEOUT_SECS("cassandra.wait_for_tracing_events_timeout_secs", "0");
+ WAIT_FOR_TRACING_EVENTS_TIMEOUT_SECS("cassandra.wait_for_tracing_events_timeout_secs", "0"),
+ ;
+
static
{
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 6fdcdd5a49..a898ec5cc6 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -171,6 +171,15 @@ public class Config
public volatile DurationSpec.LongMillisecondsBound stream_transfer_task_timeout = new DurationSpec.LongMillisecondsBound("12h");
+ public volatile DurationSpec.LongMillisecondsBound cms_await_timeout = new DurationSpec.LongMillisecondsBound("120000ms");
+ public volatile int cms_default_max_retries = 10;
+ public volatile DurationSpec.IntMillisecondsBound cms_default_retry_backoff = new DurationSpec.IntMillisecondsBound("50ms");
+ /**
+ * How often we should snapshot the cluster metadata.
+ */
+ public volatile int metadata_snapshot_frequency = 100;
+
+
public volatile double phi_convict_threshold = 8.0;
public int concurrent_reads = 32;
@@ -1243,5 +1252,21 @@ public class Config
public double severity_during_decommission = 0;
- public StorageCompatibilityMode storage_compatibility_mode = StorageCompatibilityMode.CASSANDRA_4;
+ // TODO Revisit MessagingService::current_version
+ public StorageCompatibilityMode storage_compatibility_mode = StorageCompatibilityMode.NONE;
+
+ /**
+ * For the purposes of progress barrier we only support ALL, EACH_QUORUM, QUORUM, LOCAL_QUORUM, ANY, and ONE.
+ *
+ * We will still try all consistency levels above the lowest acceptable, and only fall back to it if we can not
+ * collect enough nodes.
+ */
+ public volatile ConsistencyLevel progress_barrier_min_consistency_level = ConsistencyLevel.EACH_QUORUM;
+ public volatile boolean log_out_of_token_range_requests = true;
+ public volatile boolean reject_out_of_token_range_requests = true;
+ public volatile ConsistencyLevel progress_barrier_default_consistency_level = ConsistencyLevel.EACH_QUORUM;
+
+ public volatile DurationSpec.LongMillisecondsBound progress_barrier_timeout = new DurationSpec.LongMillisecondsBound("3600000ms");
+ public volatile DurationSpec.LongMillisecondsBound progress_barrier_backoff = new DurationSpec.LongMillisecondsBound("1000ms");
+ public boolean unsafe_tcm_mode = false;
}
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index ddf9c0d872..9d0cdc61e8 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -29,10 +29,12 @@ import java.net.UnknownHostException;
import java.nio.file.FileStore;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -84,6 +86,7 @@ import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.fql.FullQueryLoggerOptions;
import org.apache.cassandra.gms.IFailureDetector;
+import org.apache.cassandra.gms.VersionedValue;
import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.io.sstable.format.SSTableFormat;
import org.apache.cassandra.io.sstable.format.big.BigFormat;
@@ -104,6 +107,7 @@ import org.apache.cassandra.security.EncryptionContext;
import org.apache.cassandra.security.JREProvider;
import org.apache.cassandra.security.SSLFactory;
import org.apache.cassandra.service.CacheService.CacheType;
+import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.service.paxos.Paxos;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.StorageCompatibilityMode;
@@ -135,6 +139,7 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.UNSAFE_SYS
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.BYTES_PER_SECOND;
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES;
+import static org.apache.cassandra.db.ConsistencyLevel.*;
import static org.apache.cassandra.io.util.FileUtils.ONE_GIB;
import static org.apache.cassandra.io.util.FileUtils.ONE_MIB;
import static org.apache.cassandra.utils.Clock.Global.logInitializationOutcome;
@@ -592,12 +597,12 @@ public class DatabaseDescriptor
if (conf.repair_session_space.toMebibytes() < 1)
throw new ConfigurationException("repair_session_space must be > 0, but was " + conf.repair_session_space);
else if (conf.repair_session_space.toMebibytes() > (int) (Runtime.getRuntime().maxMemory() / (4 * 1048576)))
- logger.warn("A repair_session_space of " + conf.repair_session_space+ " mebibytes is likely to cause heap pressure");
+ logger.warn("A repair_session_space of " + conf.repair_session_space + " mebibytes is likely to cause heap pressure");
checkForLowestAcceptedTimeouts(conf);
long valueInBytes = conf.native_transport_max_frame_size.toBytes();
- if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE-1)
+ if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE - 1)
{
throw new ConfigurationException(String.format("native_transport_max_frame_size must be positive value < %dB, but was %dB",
Integer.MAX_VALUE,
@@ -770,8 +775,8 @@ public class DatabaseDescriptor
{
// if prepared_statements_cache_size option was set to "auto" then size of the cache should be "max(1/256 of Heap (in MiB), 10MiB)"
preparedStatementsCacheSizeInMiB = (conf.prepared_statements_cache_size == null)
- ? Math.max(10, (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024 / 256))
- : conf.prepared_statements_cache_size.toMebibytes();
+ ? Math.max(10, (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024 / 256))
+ : conf.prepared_statements_cache_size.toMebibytes();
if (preparedStatementsCacheSizeInMiB == 0)
throw new NumberFormatException(); // to escape duplicating error message
@@ -789,8 +794,8 @@ public class DatabaseDescriptor
{
// if key_cache_size option was set to "auto" then size of the cache should be "min(5% of Heap (in MiB), 100MiB)
keyCacheSizeInMiB = (conf.key_cache_size == null)
- ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.05 / 1024 / 1024)), 100)
- : conf.key_cache_size.toMebibytes();
+ ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.05 / 1024 / 1024)), 100)
+ : conf.key_cache_size.toMebibytes();
if (keyCacheSizeInMiB < 0)
throw new NumberFormatException(); // to escape duplicating error message
@@ -808,8 +813,8 @@ public class DatabaseDescriptor
{
// if counter_cache_size option was set to "auto" then size of the cache should be "min(2.5% of Heap (in MiB), 50MiB)
counterCacheSizeInMiB = (conf.counter_cache_size == null)
- ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.025 / 1024 / 1024)), 50)
- : conf.counter_cache_size.toMebibytes();
+ ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.025 / 1024 / 1024)), 50)
+ : conf.counter_cache_size.toMebibytes();
if (counterCacheSizeInMiB < 0)
throw new NumberFormatException(); // to escape duplicating error message
@@ -817,15 +822,15 @@ public class DatabaseDescriptor
catch (NumberFormatException e)
{
throw new ConfigurationException("counter_cache_size option was set incorrectly to '"
- + (conf.counter_cache_size !=null ?conf.counter_cache_size.toString() : null) + "', supported values are <integer> >= 0.", false);
+ + (conf.counter_cache_size != null ? conf.counter_cache_size.toString() : null) + "', supported values are <integer> >= 0.", false);
}
try
{
// if paxosCacheSizeInMiB option was set to "auto" then size of the cache should be "min(1% of Heap (in MB), 50MB)
paxosCacheSizeInMiB = (conf.paxos_cache_size == null)
- ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.01 / 1024 / 1024)), 50)
- : conf.paxos_cache_size.toMebibytes();
+ ? Math.min(Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.01 / 1024 / 1024)), 50)
+ : conf.paxos_cache_size.toMebibytes();
if (paxosCacheSizeInMiB < 0)
throw new NumberFormatException(); // to escape duplicating error message
@@ -833,7 +838,7 @@ public class DatabaseDescriptor
catch (NumberFormatException e)
{
throw new ConfigurationException("paxos_cache_size option was set incorrectly to '"
- + conf.paxos_cache_size + "', supported values are <integer> >= 0.", false);
+ + conf.paxos_cache_size + "', supported values are <integer> >= 0.", false);
}
// we need this assignment for the Settings virtual table - CASSANDRA-17735
@@ -841,8 +846,8 @@ public class DatabaseDescriptor
// if set to empty/"auto" then use 5% of Heap size
indexSummaryCapacityInMiB = (conf.index_summary_capacity == null)
- ? Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.05 / 1024 / 1024))
- : conf.index_summary_capacity.toMebibytes();
+ ? Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.05 / 1024 / 1024))
+ : conf.index_summary_capacity.toMebibytes();
if (indexSummaryCapacityInMiB < 0)
throw new ConfigurationException("index_summary_capacity option was set incorrectly to '"
@@ -860,7 +865,7 @@ public class DatabaseDescriptor
if (conf.allow_extra_insecure_udfs)
logger.warn("Allowing java.lang.System.* access in UDFs is dangerous and not recommended. Set allow_extra_insecure_udfs: false to disable.");
- if(conf.scripted_user_defined_functions_enabled)
+ if (conf.scripted_user_defined_functions_enabled)
throw new ConfigurationException("JavaScript user-defined functions were removed in CASSANDRA-18252. " +
"Hooks are planned to be introduced as part of CASSANDRA-17280");
@@ -896,7 +901,7 @@ public class DatabaseDescriptor
throw new ConfigurationException("max_value_size must be positive", false);
else if (conf.max_value_size.toMebibytes() >= 2048)
throw new ConfigurationException("max_value_size must be smaller than 2048, but was "
- + conf.max_value_size.toString(), false);
+ + conf.max_value_size.toString(), false);
switch (conf.disk_optimization_strategy)
{
@@ -968,6 +973,20 @@ public class DatabaseDescriptor
throw new ConfigurationException(String.format("Invalid configuration. Heap dump is enabled but cannot create heap dump output path: %s.", conf.heap_dump_path != null ? conf.heap_dump_path : "null"));
conf.sai_options.validate();
+
+ List<ConsistencyLevel> progressBarrierCLsArr = Arrays.asList(ALL, EACH_QUORUM, LOCAL_QUORUM, QUORUM, ONE, NODE_LOCAL);
+ Set<ConsistencyLevel> progressBarrierCls = new HashSet<>(progressBarrierCLsArr);
+ if (!progressBarrierCls.contains(conf.progress_barrier_min_consistency_level))
+ {
+ throw new ConfigurationException(String.format("Invalid value for progress_barrier_min_consistency_level %s. Allowed values: %s",
+ conf.progress_barrier_min_consistency_level, progressBarrierCLsArr));
+ }
+
+ if (!progressBarrierCls.contains(conf.progress_barrier_default_consistency_level))
+ {
+ throw new ConfigurationException(String.format("Invalid value for.progress_barrier_default_consistency_level %s. Allowed values: %s",
+ conf.progress_barrier_default_consistency_level, progressBarrierCLsArr));
+ }
}
@VisibleForTesting
@@ -1264,7 +1283,7 @@ public class DatabaseDescriptor
try
{
Class<?> seedProviderClass = Class.forName(conf.seed_provider.class_name);
- seedProvider = (SeedProvider)seedProviderClass.getConstructor(Map.class).newInstance(conf.seed_provider.parameters);
+ seedProvider = (SeedProvider) seedProviderClass.getConstructor(Map.class).newInstance(conf.seed_provider.parameters);
}
// there are about 5 checked exceptions that could be thrown here.
catch (Exception e)
@@ -1278,42 +1297,42 @@ public class DatabaseDescriptor
@VisibleForTesting
static void checkForLowestAcceptedTimeouts(Config conf)
{
- if(conf.read_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.read_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("read_request_timeout", conf.read_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.read_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.range_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.range_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("range_request_timeout", conf.range_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.range_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("request_timeout", conf.request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.write_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.write_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("write_request_timeout", conf.write_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.write_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.cas_contention_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.cas_contention_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("cas_contention_timeout", conf.cas_contention_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.cas_contention_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.counter_write_request_timeout.toMilliseconds()< LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.counter_write_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("counter_write_request_timeout", conf.counter_write_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.counter_write_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
- if(conf.truncate_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
+ if (conf.truncate_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("truncate_request_timeout", conf.truncate_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.truncate_request_timeout = LOWEST_ACCEPTED_TIMEOUT;
@@ -1518,7 +1537,9 @@ public class DatabaseDescriptor
private static long tryGetSpace(String dir, PathUtils.IOToLongFunction<FileStore> getSpace)
{
- return PathUtils.tryGetSpace(new File(dir).toPath(), getSpace, e -> { throw new ConfigurationException("Unable check disk space in '" + dir + "'. Perhaps the Cassandra user does not have the necessary permissions"); });
+ return PathUtils.tryGetSpace(new File(dir).toPath(), getSpace, e -> {
+ throw new ConfigurationException("Unable check disk space in '" + dir + "'. Perhaps the Cassandra user does not have the necessary permissions");
+ });
}
public static IEndpointSnitch createEndpointSnitch(boolean dynamic, String snitchClassName) throws ConfigurationException
@@ -1546,6 +1567,7 @@ public class DatabaseDescriptor
{
DatabaseDescriptor.cryptoProvider = cryptoProvider;
}
+
public static IAuthenticator getAuthenticator()
{
return authenticator;
@@ -1618,7 +1640,7 @@ public class DatabaseDescriptor
{
int defaultCidrGroupsCacheRefreshInterval = 5; // mins
- if (conf.cidr_authorizer == null || conf.cidr_authorizer.parameters == null)
+ if (conf.cidr_authorizer == null || conf.cidr_authorizer.parameters == null)
return defaultCidrGroupsCacheRefreshInterval;
String cidrGroupsCacheRefreshInterval = conf.cidr_authorizer.parameters.get("cidr_groups_cache_refresh_interval");
@@ -1632,7 +1654,7 @@ public class DatabaseDescriptor
{
int defaultIpCacheMaxSize = 100;
- if (conf.cidr_authorizer == null || conf.cidr_authorizer.parameters == null)
+ if (conf.cidr_authorizer == null || conf.cidr_authorizer.parameters == null)
return defaultIpCacheMaxSize;
String ipCacheMaxSize = conf.cidr_authorizer.parameters.get("ip_cache_max_size");
@@ -1675,8 +1697,8 @@ public class DatabaseDescriptor
public static int getPermissionsUpdateInterval()
{
return conf.permissions_update_interval == null
- ? conf.permissions_validity.toMilliseconds()
- : conf.permissions_update_interval.toMilliseconds();
+ ? conf.permissions_validity.toMilliseconds()
+ : conf.permissions_update_interval.toMilliseconds();
}
public static void setPermissionsUpdateInterval(int updateInterval)
@@ -1720,8 +1742,8 @@ public class DatabaseDescriptor
public static int getRolesUpdateInterval()
{
return conf.roles_update_interval == null
- ? conf.roles_validity.toMilliseconds()
- : conf.roles_update_interval.toMilliseconds();
+ ? conf.roles_validity.toMilliseconds()
+ : conf.roles_update_interval.toMilliseconds();
}
public static void setRolesCacheActiveUpdate(boolean update)
@@ -1852,7 +1874,7 @@ public class DatabaseDescriptor
}
catch (ConfigurationException e)
{
- throw new IllegalArgumentException("Bad configuration; unable to start server: "+e.getMessage());
+ throw new IllegalArgumentException("Bad configuration; unable to start server: " + e.getMessage());
}
catch (FSWriteError e)
{
@@ -1872,6 +1894,13 @@ public class DatabaseDescriptor
/* For tests ONLY, don't use otherwise or all hell will break loose. Tests should restore value at the end. */
public static IPartitioner setPartitionerUnsafe(IPartitioner newPartitioner)
+ {
+ IPartitioner old = setOnlyPartitionerUnsafe(newPartitioner);
+ StorageService.instance.valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
+ return old;
+ }
+
+ public static IPartitioner setOnlyPartitionerUnsafe(IPartitioner newPartitioner)
{
IPartitioner old = partitioner;
partitioner = newPartitioner;
@@ -1882,6 +1911,7 @@ public class DatabaseDescriptor
{
return snitch;
}
+
public static void setEndpointSnitch(IEndpointSnitch eps)
{
snitch = eps;
@@ -1909,7 +1939,7 @@ public class DatabaseDescriptor
public static void setColumnIndexSizeInKiB(int val)
{
- conf.column_index_size = val != -1 ? createIntKibibyteBoundAndEnsureItIsValidForByteConversion(val,"column_index_size") : null;
+ conf.column_index_size = val != -1 ? createIntKibibyteBoundAndEnsureItIsValidForByteConversion(val, "column_index_size") : null;
}
public static int getColumnIndexCacheSize()
@@ -1924,7 +1954,7 @@ public class DatabaseDescriptor
public static void setColumnIndexCacheSize(int val)
{
- conf.column_index_cache_size = createIntKibibyteBoundAndEnsureItIsValidForByteConversion(val,"column_index_cache_size");
+ conf.column_index_cache_size = createIntKibibyteBoundAndEnsureItIsValidForByteConversion(val, "column_index_cache_size");
}
public static int getBatchSizeWarnThreshold()
@@ -1954,7 +1984,7 @@ public class DatabaseDescriptor
public static void setBatchSizeWarnThresholdInKiB(int threshold)
{
- conf.batch_size_warn_threshold = createIntKibibyteBoundAndEnsureItIsValidForByteConversion(threshold,"batch_size_warn_threshold");
+ conf.batch_size_warn_threshold = createIntKibibyteBoundAndEnsureItIsValidForByteConversion(threshold, "batch_size_warn_threshold");
}
public static void setBatchSizeFailThresholdInKiB(int threshold)
@@ -2021,7 +2051,8 @@ public class DatabaseDescriptor
try
{
return UUID.fromString(REPLACE_NODE.getString());
- } catch (NullPointerException e)
+ }
+ catch (NullPointerException e)
{
return null;
}
@@ -2378,7 +2409,7 @@ public class DatabaseDescriptor
public static void setStreamThroughputOutboundMebibytesPerSecAsInt(int value)
{
if (MEBIBYTES_PER_SECOND.toMegabitsPerSecond(value) >= Integer.MAX_VALUE)
- throw new IllegalArgumentException("stream_throughput_outbound: " + value +
+ throw new IllegalArgumentException("stream_throughput_outbound: " + value +
" is too large; it should be less than " +
Integer.MAX_VALUE + " in megabits/s");
@@ -2502,10 +2533,10 @@ public class DatabaseDescriptor
public static String[] getLocalSystemKeyspacesDataFileLocations()
{
if (useSpecificLocationForLocalSystemData())
- return new String[] {conf.local_system_data_file_directory};
+ return new String[]{ conf.local_system_data_file_directory };
- return conf.data_file_directories.length == 0 ? conf.data_file_directories
- : new String[] {conf.data_file_directories[0]};
+ return conf.data_file_directories.length == 0 ? conf.data_file_directories
+ : new String[]{ conf.data_file_directories[0] };
}
/**
@@ -2562,11 +2593,11 @@ public class DatabaseDescriptor
conf.flush_compression = compression;
}
- /**
- * Maximum number of buffers in the compression pool. The default value is 3, it should not be set lower than that
- * (one segment in compression, one written to, one in reserve); delays in compression may cause the log to use
- * more, depending on how soon the sync policy stops all writing threads.
- */
+ /**
+ * Maximum number of buffers in the compression pool. The default value is 3, it should not be set lower than that
+ * (one segment in compression, one written to, one in reserve); delays in compression may cause the log to use
+ * more, depending on how soon the sync policy stops all writing threads.
+ */
public static int getCommitLogMaxCompressionBuffersInPool()
{
return conf.commitlog_max_compression_buffers_in_pool;
@@ -2634,6 +2665,7 @@ public class DatabaseDescriptor
* Update commitlog_segment_size in the tests.
* {@link CommitLogSegmentManagerCDC} uses the CommitLogSegmentSize to estimate the file size on allocation.
* It is important to keep the value unchanged for the estimation to be correct.
+ *
* @param sizeMebibytes
*/
@VisibleForTesting /* Only for testing */
@@ -2729,7 +2761,7 @@ public class DatabaseDescriptor
* refer to it as native address although some places still call it RPC address. It's not thrift RPC anymore
* so native is more appropriate. The address alone is not enough to uniquely identify this instance because
* multiple instances might use the same interface with different ports.
- *
+ * <p>
* May be null, please use {@link FBUtilities#getBroadcastNativeAddressAndPort()} instead.
*/
public static InetAddress getBroadcastRpcAddress()
@@ -2829,8 +2861,8 @@ public class DatabaseDescriptor
}
/**
- * This is the port used with RPC address for the native protocol to communicate with clients. Now that thrift RPC
- * is no longer in use there is no RPC port.
+ * This is the port used with RPC address for the native protocol to communicate with clients. Now that thrift RPC
+ * is no longer in use there is no RPC port.
*/
public static int getNativeTransportPort()
{
@@ -2872,7 +2904,7 @@ public class DatabaseDescriptor
/**
* If this value is set to <= 0 it will move auth requests to the standard request pool regardless of the current
* size of the {@link org.apache.cassandra.transport.Dispatcher#authExecutor}'s active size.
- *
+ * <p>
* see {@link org.apache.cassandra.transport.Dispatcher#dispatch} for executor selection
*/
public static void setNativeTransportMaxAuthThreads(int threads)
@@ -3122,7 +3154,7 @@ public class DatabaseDescriptor
{
DurationSpec.IntMillisecondsBound blockMillis = conf.periodic_commitlog_sync_lag_block;
return blockMillis == null
- ? (long)(getCommitLogSyncPeriod() * 1.5)
+ ? (long) (getCommitLogSyncPeriod() * 1.5)
: blockMillis.toMilliseconds();
}
@@ -3211,6 +3243,7 @@ public class DatabaseDescriptor
{
conf.auto_snapshot = autoSnapshot;
}
+
@VisibleForTesting
public static boolean getAutoSnapshot()
{
@@ -3314,7 +3347,7 @@ public class DatabaseDescriptor
public static File getSerializedCachePath(CacheType cacheType, String version, String extension)
{
String name = cacheType.toString()
- + (version == null ? "" : '-' + version + '.' + extension);
+ + (version == null ? "" : '-' + version + '.' + extension);
return new File(conf.saved_caches_directory, name);
}
@@ -3322,6 +3355,7 @@ public class DatabaseDescriptor
{
return conf.dynamic_snitch_update_interval.toMilliseconds();
}
+
public static void setDynamicUpdateInterval(int dynamicUpdateInterval)
{
conf.dynamic_snitch_update_interval = new DurationSpec.IntMillisecondsBound(dynamicUpdateInterval);
@@ -3331,6 +3365,7 @@ public class DatabaseDescriptor
{
return conf.dynamic_snitch_reset_interval.toMilliseconds();
}
+
public static void setDynamicResetInterval(int dynamicResetInterval)
{
conf.dynamic_snitch_reset_interval = new DurationSpec.IntMillisecondsBound(dynamicResetInterval);
@@ -3399,7 +3434,7 @@ public class DatabaseDescriptor
public static long getMaxHintsFileSize()
{
- return conf.max_hints_file_size.toBytesInLong();
+ return conf.max_hints_file_size.toBytesInLong();
}
public static ParameterizedClass getHintsCompression()
@@ -3513,7 +3548,9 @@ public class DatabaseDescriptor
conf.key_cache_migrate_during_compaction = migrateCacheEntry;
}
- /** This method can return negative number for disabled */
+ /**
+ * This method can return negative number for disabled
+ */
public static int getSSTablePreemptiveOpenIntervalInMiB()
{
if (conf.sstable_preemptive_open_interval == null)
@@ -3521,7 +3558,9 @@ public class DatabaseDescriptor
return conf.sstable_preemptive_open_interval.toMebibytes();
}
- /** Negative number for disabled */
+ /**
+ * Negative number for disabled
+ */
public static void setSSTablePreemptiveOpenIntervalInMiB(int mib)
{
if (mib < 0)
@@ -3809,8 +3848,10 @@ public class DatabaseDescriptor
{
switch (datamodel)
{
- case "64": return true;
- case "32": return false;
+ case "64":
+ return true;
+ case "32":
+ return false;
}
}
String arch = OS_ARCH.getString();
@@ -4073,7 +4114,7 @@ public class DatabaseDescriptor
public static FullQueryLoggerOptions getFullQueryLogOptions()
{
- return conf.full_query_logging_options;
+ return conf.full_query_logging_options;
}
public static void setFullQueryLogOptions(FullQueryLoggerOptions options)
@@ -4572,7 +4613,10 @@ public class DatabaseDescriptor
conf.row_index_read_size_fail_threshold = value;
}
- public static int getDefaultKeyspaceRF() { return conf.default_keyspace_rf; }
+ public static int getDefaultKeyspaceRF()
+ {
+ return conf.default_keyspace_rf;
+ }
public static void setDefaultKeyspaceRF(int value) throws IllegalArgumentException
{
@@ -4665,11 +4709,13 @@ public class DatabaseDescriptor
}
}
- public static DurationSpec.IntSecondsBound getStreamingSlowEventsLogTimeout() {
+ public static DurationSpec.IntSecondsBound getStreamingSlowEventsLogTimeout()
+ {
return conf.streaming_slow_events_log_timeout;
}
- public static void setStreamingSlowEventsLogTimeout(String value) {
+ public static void setStreamingSlowEventsLogTimeout(String value)
+ {
DurationSpec.IntSecondsBound next = new DurationSpec.IntSecondsBound(value);
if (!conf.streaming_slow_events_log_timeout.equals(next))
{
@@ -4785,6 +4831,7 @@ public class DatabaseDescriptor
* both the more evolved cassandra.yaml approach but also the -XX param to override it on a one-off basis so you don't
* have to change the full config of a node or a cluster in order to get a heap dump from a single node that's
* misbehaving.
+ *
* @return the absolute path of the -XX param if provided, else the heap_dump_path in cassandra.yaml
*/
public static Path getHeapDumpPath()
@@ -4911,4 +4958,94 @@ public class DatabaseDescriptor
{
return conf == null ? new RepairRetrySpec() : conf.repair.retries;
}
+
+ public static int getCmsDefaultRetryMaxTries()
+ {
+ return conf.cms_default_max_retries;
+ }
+
+ public static void setCmsDefaultRetryMaxTries(int value)
+ {
+ conf.cms_default_max_retries = value;
+ }
+
+ public static DurationSpec getDefaultRetryBackoff()
+ {
+ return conf.cms_default_retry_backoff;
+ }
+
+ public static DurationSpec getCmsAwaitTimeout()
+ {
+ return conf.cms_await_timeout;
+ }
+
+ public static int getMetadataSnapshotFrequency()
+ {
+ return conf.metadata_snapshot_frequency;
+ }
+
+ public static void setMetadataSnapshotFrequency(int frequency)
+ {
+ conf.metadata_snapshot_frequency = frequency;
+ }
+
+ public static ConsistencyLevel getProgressBarrierMinConsistencyLevel()
+ {
+ return conf.progress_barrier_min_consistency_level;
+ }
+
+ public static void setProgressBarrierMinConsistencyLevel(ConsistencyLevel newLevel)
+ {
+ conf.progress_barrier_min_consistency_level = newLevel;
+ }
+
+ public static boolean getLogOutOfTokenRangeRequests()
+ {
+ return conf.log_out_of_token_range_requests;
+ }
+
+ public static void setLogOutOfTokenRangeRequests(boolean enabled)
+ {
+ conf.log_out_of_token_range_requests = enabled;
+ }
+
+ public static boolean getRejectOutOfTokenRangeRequests()
+ {
+ return conf.reject_out_of_token_range_requests;
+ }
+
+ public static void setRejectOutOfTokenRangeRequests(boolean enabled)
+ {
+ conf.reject_out_of_token_range_requests = enabled;
+ }
+
+ public static ConsistencyLevel getProgressBarrierDefaultConsistencyLevel()
+ {
+ return conf.progress_barrier_default_consistency_level;
+ }
+
+ public static long getProgressBarrierTimeout(TimeUnit unit)
+ {
+ return conf.progress_barrier_timeout.to(unit);
+ }
+
+ public static long getProgressBarrierBackoff(TimeUnit unit)
+ {
+ return conf.progress_barrier_backoff.to(unit);
+ }
+
+ public static void setProgressBarrierTimeout(long timeOutInMillis)
+ {
+ conf.progress_barrier_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis);
+ }
+
+ public static void setProgressBarrierBackoff(long timeOutInMillis)
+ {
+ conf.progress_barrier_backoff = new DurationSpec.LongMillisecondsBound(timeOutInMillis);
+ }
+
+ public static boolean getUnsafeTCMMode()
+ {
+ return conf.unsafe_tcm_mode;
+ }
}
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index fba424d7d9..c879845266 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -18,28 +18,63 @@
package org.apache.cassandra.cql3;
import java.nio.ByteBuffer;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
-import com.github.benmanes.caffeine.cache.Cache;
-import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
-import com.google.common.collect.*;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
import com.google.common.primitives.Ints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.antlr.runtime.*;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.antlr.runtime.RecognitionException;
import org.apache.cassandra.concurrent.ImmediateExecutor;
import org.apache.cassandra.concurrent.ScheduledExecutors;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.functions.Function;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.UDAggregate;
+import org.apache.cassandra.cql3.functions.UDFunction;
+import org.apache.cassandra.cql3.selection.ResultSetBuilder;
+import org.apache.cassandra.cql3.statements.BatchStatement;
+import org.apache.cassandra.cql3.statements.ModificationStatement;
+import org.apache.cassandra.cql3.statements.QualifiedStatement;
+import org.apache.cassandra.cql3.statements.SelectStatement;
+import org.apache.cassandra.cql3.statements.schema.AlterSchemaStatement;
+import org.apache.cassandra.db.ConsistencyLevel;
+import org.apache.cassandra.db.DecoratedKey;
+import org.apache.cassandra.db.ReadCommand;
+import org.apache.cassandra.db.ReadQuery;
+import org.apache.cassandra.db.ReadResponse;
+import org.apache.cassandra.db.SinglePartitionReadQuery;
+import org.apache.cassandra.db.SystemKeyspace;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.partitions.PartitionIterator;
+import org.apache.cassandra.db.partitions.PartitionIterators;
import org.apache.cassandra.db.partitions.UnfilteredPartitionIterators;
+import org.apache.cassandra.db.rows.Row;
+import org.apache.cassandra.db.rows.RowIterator;
+import org.apache.cassandra.exceptions.CassandraException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.IsBootstrappingException;
+import org.apache.cassandra.exceptions.RequestExecutionException;
+import org.apache.cassandra.exceptions.RequestValidationException;
+import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.locator.InetAddressAndPort;
+import org.apache.cassandra.metrics.CQLMetrics;
import org.apache.cassandra.metrics.ClientRequestMetrics;
import org.apache.cassandra.metrics.ClientRequestsMetricsHolder;
import org.apache.cassandra.net.Message;
@@ -49,27 +84,20 @@ import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.SchemaChangeListener;
import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.cql3.functions.UDAggregate;
-import org.apache.cassandra.cql3.functions.UDFunction;
-import org.apache.cassandra.cql3.functions.Function;
-import org.apache.cassandra.cql3.functions.FunctionName;
-import org.apache.cassandra.cql3.selection.ResultSetBuilder;
-import org.apache.cassandra.cql3.statements.*;
-import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.rows.Row;
-import org.apache.cassandra.db.rows.RowIterator;
-import org.apache.cassandra.db.partitions.PartitionIterator;
-import org.apache.cassandra.db.partitions.PartitionIterators;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.exceptions.*;
-import org.apache.cassandra.gms.Gossiper;
-import org.apache.cassandra.metrics.CQLMetrics;
-import org.apache.cassandra.service.*;
+import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.service.QueryState;
+import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.service.pager.QueryPager;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.*;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.CassandraVersion;
+import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.JVMStabilityInspector;
+import org.apache.cassandra.utils.MD5Digest;
+import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.Future;
import org.apache.cassandra.utils.concurrent.FutureCombiner;
@@ -206,7 +234,6 @@ public class QueryProcessor implements QueryHandler
private QueryProcessor()
{
- Schema.instance.registerListener(new StatementInvalidatingListener());
}
@VisibleForTesting
@@ -273,7 +300,7 @@ public class QueryProcessor implements QueryHandler
private ResultMessage processNodeLocalWrite(CQLStatement statement, QueryState queryState, QueryOptions options)
{
- ClientRequestMetrics levelMetrics = ClientRequestsMetricsHolder.writeMetricsForLevel(ConsistencyLevel.NODE_LOCAL);
+ ClientRequestMetrics levelMetrics = ClientRequestsMetricsHolder.writeMetricsForLevel(ConsistencyLevel.NODE_LOCAL);
ClientRequestMetrics globalMetrics = ClientRequestsMetricsHolder.writeMetrics;
long startTime = nanoTime();
@@ -428,11 +455,16 @@ public class QueryProcessor implements QueryHandler
qualifiedStatement.setKeyspace(clientState);
keyspace = qualifiedStatement.keyspace();
}
-
// Note: if 2 threads prepare the same query, we'll live so don't bother synchronizing
CQLStatement statement = raw.prepare(clientState);
statement.validate(clientState);
+ // Set CQL string for AlterSchemaStatement as this is used to serialize the transformation
+ // in the cluster metadata log
+ if (statement instanceof AlterSchemaStatement)
+ ((AlterSchemaStatement)statement).setCql(query);
+
+
if (isInternal)
return new Prepared(statement, "", fullyQualified, keyspace);
else
@@ -641,7 +673,7 @@ public class QueryProcessor implements QueryHandler
synchronized (this)
{
- CassandraVersion minVersion = Gossiper.instance.getMinVersion(DatabaseDescriptor.getWriteRpcTimeout(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
+ CassandraVersion minVersion = ClusterMetadata.current().directory.clusterMinVersion.cassandraVersion;
if (minVersion != null && minVersion.compareTo(NEW_PREPARED_STATEMENT_BEHAVIOUR_SINCE_40, true) >= 0)
{
logger.info("Fully upgraded to at least {}", minVersion);
@@ -854,7 +886,13 @@ public class QueryProcessor implements QueryHandler
((QualifiedStatement) statement).setKeyspace(clientState);
Tracing.trace("Preparing statement");
- return statement.prepare(clientState);
+ CQLStatement prepared = statement.prepare(clientState);
+ // Set CQL string for AlterSchemaStatement as this is used to serialize the transformation
+ // in the cluster metadata log
+ if (prepared instanceof AlterSchemaStatement)
+ ((AlterSchemaStatement) prepared).setCql(queryStr);
+
+ return prepared;
}
public static <T extends CQLStatement.Raw> T parseStatement(String queryStr, Class<T> klass, String type) throws SyntaxException
@@ -917,6 +955,11 @@ public class QueryProcessor implements QueryHandler
preparedStatements.asMap().clear();
}
+ public static void registerStatementInvalidatingListener()
+ {
+ Schema.instance.registerListener(new StatementInvalidatingListener());
+ }
+
private static class StatementInvalidatingListener implements SchemaChangeListener
{
private static void removeInvalidPreparedStatements(String ksName, String cfName)
@@ -1019,7 +1062,7 @@ public class QueryProcessor implements QueryHandler
{
// in case there are other overloads, we have to remove all overloads since argument type
// matching may change (due to type casting)
- if (Schema.instance.getKeyspaceMetadata(ksName).userFunctions.get(new FunctionName(ksName, functionName)).size() > 1)
+ if (!Schema.instance.getKeyspaceMetadata(ksName).userFunctions.get(new FunctionName(ksName, functionName)).isEmpty())
removeInvalidPreparedStatementsForFunction(ksName, functionName);
}
@@ -1077,4 +1120,4 @@ public class QueryProcessor implements QueryHandler
removeInvalidPreparedStatementsForFunction(aggregate.name().keyspace, aggregate.name().name);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
index 2b15c8d935..161ac8e353 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDAggregate.java
@@ -17,6 +17,7 @@
*/
package org.apache.cassandra.cql3.functions;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
@@ -30,13 +31,20 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.io.util.DataInputPlus;
+import org.apache.cassandra.io.util.DataOutputPlus;
+import org.apache.cassandra.tcm.serialization.Version;
+import org.apache.cassandra.schema.CQLTypeParser;
import org.apache.cassandra.schema.Difference;
import org.apache.cassandra.schema.UserFunctions;
+import org.apache.cassandra.schema.Types;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.transport.ProtocolVersion;
+import org.apache.cassandra.utils.ByteBufferUtil;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.transform;
+import static org.apache.cassandra.db.TypeSizes.sizeof;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
/**
@@ -44,6 +52,8 @@ import static org.apache.cassandra.utils.Clock.Global.nanoTime;
*/
public class UDAggregate extends UserFunction implements AggregateFunction
{
+ public static final Serializer serializer = new Serializer();
+
protected static final Logger logger = LoggerFactory.getLogger(UDAggregate.class);
private final UDFDataType stateType;
@@ -375,4 +385,69 @@ public class UDAggregate extends UserFunction implements AggregateFunction
return builder.append(";")
.toString();
}
+
+ // Not quite a MetadataSerializer, or even a UDTAwareMetadataSerializer, as it needs the collection of UDFs during deserialization.
+ public static class Serializer
+ {
+ public void serialize(UDAggregate t, DataOutputPlus out, Version version) throws IOException
+ {
+ out.writeUTF(t.name().keyspace);
+ out.writeUTF(t.name().name);
+ out.writeInt(t.argumentsList().size());
+ for (String arg : t.argumentsList())
+ out.writeUTF(arg);
+ out.writeUTF(t.returnType().asCQL3Type().toString());
+ out.writeUTF(t.stateFunction.name().name);
+ out.writeUTF(t.stateType.toAbstractType().asCQL3Type().toString());
+ out.writeBoolean(t.finalFunction() != null);
+ if (t.finalFunction() != null)
+ out.writeUTF(t.finalFunction().name().name);
+ out.writeBoolean(t.initialCondition() != null);
+ if (t.initialCondition() != null)
+ ByteBufferUtil.writeWithShortLength(t.initialCondition(), out);
+ }
+
+ public UDAggregate deserialize(DataInputPlus in, Types types, Collection<UDFunction> functions, Version version) throws IOException
+ {
+ String ks = in.readUTF();
+ String name = in.readUTF();
+ FunctionName fn = new FunctionName(ks, name);
+ int argCount = in.readInt();
+ List<AbstractType<?>> argList = new ArrayList<>(argCount);
+ for (int i = 0; i < argCount; i++)
+ argList.add(CQLTypeParser.parse(ks, in.readUTF(), types).udfType());
+ AbstractType<?> returnType = CQLTypeParser.parse(ks, in.readUTF(), types).udfType();
+ FunctionName stateFunction = new FunctionName(ks, in.readUTF());
+ AbstractType<?> stateType = CQLTypeParser.parse(ks, in.readUTF(), types).udfType();
+ boolean hasFinalFunction = in.readBoolean();
+ FunctionName finalFunction = null;
+ if (hasFinalFunction)
+ finalFunction = new FunctionName(ks, in.readUTF());
+ boolean hasInitialCondition = in.readBoolean();
+ ByteBuffer initCond = null;
+ if (hasInitialCondition)
+ initCond = ByteBufferUtil.readWithShortLength(in);
+ return UDAggregate.create(functions, fn, argList, returnType, stateFunction, finalFunction, stateType, initCond);
+ }
+
+ public long serializedSize(UDAggregate t, Version version)
+ {
+ long size = sizeof(t.name().keyspace) + sizeof(t.name().name);
+
+ size += sizeof(t.argumentsList().size());
+ for (String arg : t.argumentsList())
+ size += sizeof(arg);
+
+ size += sizeof(t.returnType().asCQL3Type().toString());
+ size += sizeof(t.stateFunction.name().name);
+ size += sizeof(t.stateType.toAbstractType().asCQL3Type().toString());
+ size += sizeof(t.finalFunction() != null);
+ if (t.finalFunction() != null)
+ size += sizeof(t.finalFunction().name().name);
+ size += sizeof(t.initialCondition() != null);
+ if (t.initialCondition() != null)
+ size += ByteBufferUtil.serializedSizeWithShortLength(t.initialCondition());
+ return size;
+ }
+ }
}
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
index 538d80e992..ce660acdef 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
@@ -17,11 +17,13 @@
*/
package org.apache.cassandra.cql3.functions;
+import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress;
import java.net.URL;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
@@ -34,6 +36,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
@@ -50,6 +53,10 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.exceptions.FunctionExecutionException;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.io.util.DataInputPlus;
+import org.apache.cassandra.io.util.DataOutputPlus;
+import org.apache.cassandra.tcm.serialization.UDTAwareMetadataSerializer;
+import org.apache.cassandra.tcm.serialization.Version;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.service.ClientWarn;
import org.apache.cassandra.tracing.Tracing;
@@ -59,6 +66,8 @@ import org.apache.cassandra.utils.concurrent.UncheckedInterruptedException;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.transform;
+import static org.apache.cassandra.db.TypeSizes.*;
+import static org.apache.cassandra.schema.SchemaKeyspace.bbToString;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
/**
@@ -66,6 +75,8 @@ import static org.apache.cassandra.utils.Clock.Global.nanoTime;
*/
public abstract class UDFunction extends UserFunction implements ScalarFunction
{
+ public static final Serializer serializer = new Serializer();
+
protected static final Logger logger = LoggerFactory.getLogger(UDFunction.class);
static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
@@ -732,4 +743,66 @@ public abstract class UDFunction extends UserFunction implements ScalarFunction
return super.loadClass(name);
}
}
+
+ public static class Serializer implements UDTAwareMetadataSerializer<UDFunction>
+ {
+ public void serialize(UDFunction t, DataOutputPlus out, Version version) throws IOException
+ {
+ out.writeUTF(t.name().keyspace);
+ out.writeUTF(t.name().name);
+ out.writeUTF(t.body());
+ out.writeUTF(t.language());
+ out.writeUTF(t.returnType().asCQL3Type().toString());
+ out.writeBoolean(t.isCalledOnNullInput());
+ List<String> arguments = t.argNames().stream().map(c -> bbToString(c.bytes)).collect(Collectors.toList());
+ out.writeInt(arguments.size());
+ for (String argument : arguments)
+ out.writeUTF(argument);
+
+ out.writeInt(t.argumentsList().size());
+ for (String type : t.argumentsList())
+ out.writeUTF(type);
+ }
+
+ public UDFunction deserialize(DataInputPlus in, Types types, Version version) throws IOException
+ {
+ String keyspace = in.readUTF();
+ String name = in.readUTF();
+ FunctionName fn = new FunctionName(keyspace, name);
+ String body = in.readUTF();
+ String language = in.readUTF();
+ AbstractType<?> returnType = CQLTypeParser.parse(keyspace, in.readUTF(), types).udfType();
+ boolean isCalledOnNullInput = in.readBoolean();
+ int argumentCount = in.readInt();
+ List<ColumnIdentifier> arguments = new ArrayList<>(argumentCount);
+ for (int i = 0; i < argumentCount; i++)
+ arguments.add(new ColumnIdentifier(in.readUTF(), true));
+
+ int argumentTypeCount = in.readInt();
+ List<AbstractType<?>> argTypes = new ArrayList<>(argumentTypeCount);
+ for (int i = 0; i < argumentTypeCount; i++)
+ argTypes.add(CQLTypeParser.parse(keyspace, in.readUTF(), types).udfType());
+
+ return UDFunction.create(fn, arguments, argTypes, returnType, isCalledOnNullInput, language, body);
+ }
+
+ public long serializedSize(UDFunction t, Version version)
+ {
+ long size = sizeof(t.name().keyspace);
+ size += sizeof(t.name().name);
+ size += sizeof(t.body());
+ size += sizeof(t.language());
+ size += sizeof(t.returnType().asCQL3Type().toString());
+ size += sizeof(t.isCalledOnNullInput());
+ List<String> arguments = t.argNames().stream().map(c -> bbToString(c.bytes)).collect(Collectors.toList());
+ size += sizeof(arguments.size());
+ for (String argument : arguments)
+ size += sizeof(argument);
+
+ size += sizeof(t.argumentsList().size());
+ for (String type : t.argumentsList())
+ size += sizeof(type);
+ return size;
+ }
+ }
}
diff --git a/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java b/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java
index e8b7931718..de05aa58e2 100644
--- a/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java
+++ b/src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.cql3.functions.masking;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -40,10 +41,19 @@ import org.apache.cassandra.cql3.functions.Function;
import org.apache.cassandra.cql3.functions.FunctionName;
import org.apache.cassandra.cql3.functions.FunctionResolver;
import org.apache.cassandra.cql3.functions.ScalarFunction;
+import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.ReversedType;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.io.util.DataInputPlus;
+import org.apache.cassandra.io.util.DataOutputPlus;
+import org.apache.cassandra.schema.CQLTypeParser;
+import org.apache.cassandra.schema.Types;
+import org.apache.cassandra.schema.UserFunctions;
+import org.apache.cassandra.tcm.serialization.Version;
import org.apache.cassandra.transport.ProtocolVersion;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.vint.VIntCoding;
import static java.lang.String.format;
import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
@@ -67,6 +77,7 @@ import static org.apache.cassandra.cql3.statements.RequestValidations.invalidReq
*/
public class ColumnMask
{
+ public static Serializer serializer = new Serializer();
public static final String DISABLED_ERROR_MESSAGE = "Cannot mask columns because dynamic data masking is not " +
"enabled. You can enable it with the " +
"dynamic_data_masking_enabled property on cassandra.yaml";
@@ -268,4 +279,72 @@ public class ColumnMask
return format("%s(%s)", name, StringUtils.join(rawPartialArguments, ", "));
}
}
+
+ public static class Serializer
+ {
+ public void serialize(ColumnMask columnMask, DataOutputPlus out, Version version) throws IOException
+ {
+ out.writeUTF(columnMask.function.name().keyspace);
+ out.writeUTF(columnMask.function.name().name);
+ List<AbstractType<?>> argTypes = columnMask.partialArgumentTypes();
+ int numArgs = argTypes.size();
+ out.writeUnsignedVInt32(numArgs);
+ for (int i = 0; i < numArgs; i++)
+ {
+ out.writeUTF(argTypes.get(i).asCQL3Type().toString());
+ ByteBuffer value = columnMask.partialArgumentValues[i];
+ out.writeBoolean(value != null);
+ if (value != null)
+ ByteBufferUtil.writeWithVIntLength(value, out);
+ }
+ }
+
+ public ColumnMask deserialize(DataInputPlus in, String keyspace, AbstractType<?> columnType, Types types, UserFunctions functions, Version version) throws IOException
+ {
+ FunctionName functionName = new FunctionName(in.readUTF(), in.readUTF());
+
+ int numArgs = in.readUnsignedVInt32();
+ List<AbstractType<?>> argTypes = new ArrayList<>(numArgs + 1);
+ argTypes.set(0, columnType);
+ ByteBuffer[] partialArgValues = new ByteBuffer[numArgs];
+ for (int i = 0; i < numArgs; i++)
+ {
+ AbstractType<?> argType = CQLTypeParser.parse(keyspace, in.readUTF(), types);
+ argTypes.set(i + 1, argType);
+ boolean valuePresent = in.readBoolean();
+ partialArgValues[i] = valuePresent ? null : ByteBufferUtil.readWithVIntLength(in);
+ }
+
+ Function function = FunctionResolver.get(keyspace, functionName, argTypes, null, null, null, functions);
+ if (function == null)
+ {
+ throw new AssertionError(format("Unable to find masking function %s(%s)", functionName, argTypes));
+ }
+ else if (!(function instanceof ScalarFunction))
+ {
+ throw new AssertionError(format("Function %s is not a scalar masking function", function));
+ }
+ return new ColumnMask((ScalarFunction) function, partialArgValues);
+ }
+
+ public long serializedSize(ColumnMask columnMask, Version version)
+ {
+ List<AbstractType<?>> argTypes = columnMask.partialArgumentTypes();
+ int numArgs = argTypes.size();
+ long size = TypeSizes.sizeof(columnMask.function.name().keyspace) +
+ TypeSizes.sizeof(columnMask.function.name().name) +
+ VIntCoding.computeUnsignedVIntSize(numArgs);
+
+ for (int i = 0; i < numArgs; i++)
+ {
+ size += TypeSizes.sizeof(argTypes.get(i).asCQL3Type().toString());
+ size += TypeSizes.BOOL_SIZE;
+ ByteBuffer value = columnMask.partialArgumentValues[i];
+ if (value != null)
+ size += ByteBufferUtil.serializedSizeWithVIntLength(value);
+ }
+ return size;
+ }
+ }
+
}
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index dc9324e03a..f7261e6768 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@ -177,8 +177,9 @@ public final class StatementRestrictions
{
this(type, table, allowFiltering);
- final IndexRegistry indexRegistry = type.allowUseOfSecondaryIndices() ? IndexRegistry.obtain(table) : null;
-
+ final IndexRegistry indexRegistry = type.allowUseOfSecondaryIndices() && allowUseOfSecondaryIndices
+ ? IndexRegistry.obtain(table)
+ : null;
/*
* WHERE clause. For a given entity, rules are:
* - EQ relation conflicts with anything else (including a 2nd EQ)
diff --git a/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java b/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
index 90382dfe57..30e039e6b4 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DescribeStatement.java
@@ -132,13 +132,9 @@ public abstract class DescribeStatement<T> extends CQLStatement.Raw implements C
@Override
public ResultMessage executeLocally(QueryState state, QueryOptions options)
{
- DistributedSchema schema = Schema.instance.getDistributedSchemaBlocking();
-
- Keyspaces keyspaces = Keyspaces.builder()
- .add(schema.getKeyspaces())
- .add(Schema.instance.getLocalKeyspaces())
- .add(VirtualKeyspaceRegistry.instance.virtualKeyspacesMetadata())
- .build();
+ Keyspaces keyspaces = Schema.instance.distributedAndLocalKeyspaces();
+ UUID schemaVersion = Schema.instance.getVersion();
+ keyspaces = keyspaces.with(VirtualKeyspaceRegistry.instance.virtualKeyspacesMetadata());
PagingState pagingState = options.getPagingState();
@@ -156,7 +152,7 @@ public abstract class DescribeStatement<T> extends CQLStatement.Raw implements C
// (vint bytes) serialized schema hash (currently the result of Keyspaces.hashCode())
//
- long offset = getOffset(pagingState, schema.getVersion());
+ long offset = getOffset(pagingState, schemaVersion);
int pageSize = options.getPageSize();
Stream<? extends T> stream = describe(state.getClientState(), keyspaces);
@@ -173,7 +169,7 @@ public abstract class DescribeStatement<T> extends CQLStatement.Raw implements C
ResultSet result = new ResultSet(resultMetadata, rows);
if (pageSize > 0 && rows.size() == pageSize)
- result.metadata.setHasMorePages(getPagingState(offset + pageSize, schema.getVersion()));
+ result.metadata.setHasMorePages(getPagingState(offset + pageSize, schemaVersion));
return new ResultMessage.Rows(result);
}
diff --git a/src/java/org/apache/cassandra/cql3/statements/PropertyDefinitions.java b/src/java/org/apache/cassandra/cql3/statements/PropertyDefinitions.java
index 65ec8fca67..a80e9ae693 100644
--- a/src/java/org/apache/cassandra/cql3/statements/PropertyDefinitions.java
+++ b/src/java/org/apache/cassandra/cql3/statements/PropertyDefinitions.java
@@ -82,7 +82,7 @@ public class PropertyDefinitions
return properties.containsKey(name);
}
- protected String getString(String name) throws SyntaxException
+ public String getString(String name) throws SyntaxException
{
Object val = properties.get(name);
if (val == null)
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 b8a27af3ba..14bdef0f68 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
@@ -18,21 +18,19 @@
package org.apache.cassandra.cql3.statements.schema;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.apache.cassandra.audit.AuditLogContext;
import org.apache.cassandra.audit.AuditLogEntryType;
import org.apache.cassandra.auth.Permission;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQLStatement;
-import org.apache.cassandra.db.ColumnFamilyStore;
-import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.locator.AbstractReplicationStrategy;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.locator.LocalStrategy;
@@ -42,7 +40,11 @@ import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.schema.KeyspaceMetadata.KeyspaceDiff;
import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
+import org.apache.cassandra.schema.SchemaConstants;
+import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.membership.NodeId;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.utils.FBUtilities;
@@ -52,9 +54,10 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.ALLOW_UNSA
public final class AlterKeyspaceStatement extends AlterSchemaStatement
{
+ private static final Logger logger = LoggerFactory.getLogger(AlterKeyspaceStatement.class);
+
private static final boolean allow_alter_rf_during_range_movement = ALLOW_ALTER_RF_DURING_RANGE_MOVEMENT.getBoolean();
private static final boolean allow_unsafe_transient_changes = ALLOW_UNSAFE_TRANSIENT_CHANGES.getBoolean();
- private final HashSet<String> clientWarnings = new HashSet<>();
private final KeyspaceAttributes attrs;
private final boolean ifExists;
@@ -66,10 +69,11 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
attrs.validate();
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
{
@@ -83,17 +87,29 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement
if (attrs.getReplicationStrategyClass() != null && attrs.getReplicationStrategyClass().equals(SimpleStrategy.class.getSimpleName()))
Guardrails.simpleStrategyEnabled.ensureEnabled(state);
+ if (keyspace.params.replication.isMeta() && !keyspace.name.equals(SchemaConstants.METADATA_KEYSPACE_NAME))
+ throw ire("Can not alter a keyspace to use MetaReplicationStrategy");
+
if (newKeyspace.params.replication.klass.equals(LocalStrategy.class))
throw ire("Unable to use given strategy class: LocalStrategy is reserved for internal use.");
- newKeyspace.params.validate(keyspaceName, state);
+ newKeyspace.params.validate(keyspaceName, state, metadata);
+ newKeyspace.replicationStrategy.validate(metadata);
validateNoRangeMovements();
- validateTransientReplication(keyspace.createReplicationStrategy(), newKeyspace.createReplicationStrategy());
+ validateTransientReplication(keyspace, newKeyspace);
- Keyspaces res = schema.withAddedOrUpdated(newKeyspace);
+ // Because we used to not properly validate unrecognized options, we only log a warning if we find one.
+ try
+ {
+ newKeyspace.replicationStrategy.validateExpectedOptions(metadata);
+ }
+ catch (ConfigurationException e)
+ {
+ logger.warn("Ignoring {}", e.getMessage());
+ }
- return res;
+ return schema.withAddedOrUpdated(newKeyspace);
}
SchemaChange schemaChangeEvent(KeyspacesDiff diff)
@@ -109,13 +125,14 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement
@Override
Set<String> clientWarnings(KeyspacesDiff diff)
{
+ HashSet<String> clientWarnings = new HashSet<>();
if (diff.isEmpty())
return clientWarnings;
KeyspaceDiff keyspaceDiff = diff.altered.get(0);
- AbstractReplicationStrategy before = keyspaceDiff.before.createReplicationStrategy();
- AbstractReplicationStrategy after = keyspaceDiff.after.createReplicationStrategy();
+ AbstractReplicationStrategy before = keyspaceDiff.before.replicationStrategy;
+ AbstractReplicationStrategy after = keyspaceDiff.after.replicationStrategy;
if (before.getReplicationFactor().fullReplicas < after.getReplicationFactor().fullReplicas)
clientWarnings.add("When increasing replication factor you need to run a full (-full) repair to distribute the data.");
@@ -128,29 +145,36 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement
if (allow_alter_rf_during_range_movement)
return;
- Stream<InetAddressAndPort> unreachableNotAdministrativelyInactive =
- Gossiper.instance.getUnreachableMembers().stream().filter(endpoint -> !FBUtilities.getBroadcastAddressAndPort().equals(endpoint) &&
- !Gossiper.instance.isAdministrativelyInactiveState(endpoint));
- Stream<InetAddressAndPort> endpoints = Stream.concat(Gossiper.instance.getLiveMembers().stream(),
- unreachableNotAdministrativelyInactive);
- List<InetAddressAndPort> notNormalEndpoints = endpoints.filter(endpoint -> !FBUtilities.getBroadcastAddressAndPort().equals(endpoint) &&
- !Gossiper.instance.getEndpointStateForEndpoint(endpoint).isNormalState())
- .collect(Collectors.toList());
+ ClusterMetadata metadata = ClusterMetadata.current();
+ NodeId nodeId = metadata.directory.peerId(FBUtilities.getBroadcastAddressAndPort());
+ Set<InetAddressAndPort> notNormalEndpoints = metadata.directory.states.entrySet().stream().filter(e -> !e.getKey().equals(nodeId)).filter(e -> {
+ switch (e.getValue())
+ {
+ case BOOTSTRAPPING:
+ case LEAVING:
+ case MOVING:
+ return true;
+ default:
+ return false;
+ }
+
+ }).map(e -> metadata.directory.endpoint(e.getKey())).collect(Collectors.toSet());
+
if (!notNormalEndpoints.isEmpty())
{
throw new ConfigurationException("Cannot alter RF while some endpoints are not in normal state (no range movements): " + notNormalEndpoints);
}
}
- private void validateTransientReplication(AbstractReplicationStrategy oldStrategy, AbstractReplicationStrategy newStrategy)
+ private void validateTransientReplication(KeyspaceMetadata current, KeyspaceMetadata proposed)
{
//If there is no read traffic there are some extra alterations you can safely make, but this is so atypical
//that a good default is to not allow unsafe changes
if (allow_unsafe_transient_changes)
return;
- ReplicationFactor oldRF = oldStrategy.getReplicationFactor();
- ReplicationFactor newRF = newStrategy.getReplicationFactor();
+ ReplicationFactor oldRF = current.replicationStrategy.getReplicationFactor();
+ ReplicationFactor newRF = proposed.replicationStrategy.getReplicationFactor();
int oldTrans = oldRF.transientReplicas();
int oldFull = oldRF.fullReplicas;
@@ -162,19 +186,13 @@ public final class AlterKeyspaceStatement extends AlterSchemaStatement
if (DatabaseDescriptor.getNumTokens() > 1)
throw new ConfigurationException(String.format("Transient replication is not supported with vnodes yet"));
- Keyspace ks = Keyspace.open(keyspaceName);
- for (ColumnFamilyStore cfs : ks.getColumnFamilyStores())
- {
- if (cfs.viewManager.hasViews())
- {
- throw new ConfigurationException("Cannot use transient replication on keyspaces using materialized views");
- }
- if (cfs.indexManager.hasIndexes())
- {
+ if (!current.views.isEmpty())
+ throw new ConfigurationException("Cannot use transient replication on keyspaces using materialized views");
+
+ for (TableMetadata table : current.tables)
+ if (!table.indexes.isEmpty())
throw new ConfigurationException("Cannot use transient replication on keyspaces using secondary indexes");
- }
- }
}
//This is true right now because the transition from transient -> full lacks the pending state
diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/AlterSchemaStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/AlterSchemaStatement.java
index a539ea74e8..8907a93f8f 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterSchemaStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterSchemaStatement.java
@@ -34,6 +34,7 @@ import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.ClientWarn;
import org.apache.cassandra.service.QueryState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.messages.ResultMessage;
@@ -41,12 +42,46 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
{
protected final String keyspaceName; // name of the keyspace affected by the statement
protected ClientState state;
+ // TODO: not sure if this is going to stay the same, or will be replaced by more efficient serialization/sanitation means
+ // or just `toString` for every statement
+ private String cql;
protected AlterSchemaStatement(String keyspaceName)
{
this.keyspaceName = keyspaceName;
}
+ public void setCql(String cql)
+ {
+ this.cql = cql;
+ }
+
+ @Override
+ public String cql()
+ {
+ assert cql != null;
+ return cql;
+ }
+
+ @Override
+ public void enterExecution()
+ {
+ ClientWarn.instance.pauseCapture();
+ ClientState localState = state;
+ if (localState != null)
+ localState.pauseGuardrails();
+ }
+
+ @Override
+ public void exitExecution()
+ {
+ ClientWarn.instance.resumeCapture();
+ ClientState localState = state;
+ if (localState != null)
+ localState.resumeGuardrails();
+ }
+
+ // TODO: validation should be performed during application
public void validate(ClientState state)
{
// validation is performed while executing the statement, in apply()
@@ -57,7 +92,7 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
public ResultMessage execute(QueryState state, QueryOptions options, long queryStartNanoTime)
{
- return execute(state, false);
+ return execute(state);
}
@Override
@@ -68,7 +103,7 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
public ResultMessage executeLocally(QueryState state, QueryOptions options)
{
- return execute(state, true);
+ return execute(state);
}
/**
@@ -100,7 +135,7 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
return ImmutableSet.of();
}
- public ResultMessage execute(QueryState state, boolean locally)
+ public ResultMessage execute(QueryState state)
{
if (SchemaConstants.isLocalSystemKeyspace(keyspaceName))
throw ire("System keyspace '%s' is not user-modifiable", keyspaceName);
@@ -110,12 +145,24 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
throw ire("Virtual keyspace '%s' is not user-modifiable", keyspaceName);
validateKeyspaceName();
-
- SchemaTransformationResult result = Schema.instance.transform(this, locally);
-
- clientWarnings(result.diff).forEach(ClientWarn.instance::warn);
-
- if (result.diff.isEmpty())
+ // Perform a 'dry-run' attempt to apply the transformation locally before submitting to the CMS. This can save a
+ // round trip to the CMS for things syntax errors, but also fail fast for things like configuration errors.
+ // Such failures may be dependent on the specific node's config (for things like guardrails/memtable
+ // config/etc), but executing a schema change which has already been committed by the CMS should always succeed
+ // or else the node cannot make progress on any subsequent metadata changes. For this reason, validation errors
+ // during execution are trapped and the node will fall back to safe default config wherever possible. Attempting
+ // to apply the SchemaTransformation at this point will catch any such error which occurs locally before
+ // submission to the CMS, but it can't guarantee that the statement can be applied as-is on every node in the
+ // cluster, as config can be heterogenous falling back to safe defaults may occur on some nodes.
+ ClusterMetadata metadata = ClusterMetadata.current();
+ apply(metadata);
+
+ ClusterMetadata result = Schema.instance.submit(this);
+
+ KeyspacesDiff diff = Keyspaces.diff(metadata.schema.getKeyspaces(), result.schema.getKeyspaces());
+ clientWarnings(diff).forEach(ClientWarn.instance::warn);
+
+ if (diff.isEmpty())
return new ResultMessage.Void();
/*
@@ -127,9 +174,9 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
*/
AuthenticatedUser user = state.getClientState().getUser();
if (null != user && !user.isAnonymous())
- createdResources(result.diff).forEach(r -> grantPermissionsOnResource(r, user));
+ createdResources(diff).forEach(r -> grantPermissionsOnResource(r, user));
- return new ResultMessage.SchemaChange(schemaChangeEvent(result.diff));
+ return new ResultMessage.SchemaChange(schemaChangeEvent(diff));
}
private void validateKeyspaceName()
@@ -170,4 +217,12 @@ abstract public class AlterSchemaStatement implements CQLStatement.SingleKeyspac
{
return new InvalidRequestException(String.format(format, args));
}
+
+ public String toString()
+ {
+ return "AlterSchemaStatement{" +
+ "keyspaceName='" + keyspaceName + '\'' +
+ ", cql='" + cql() + '\'' +
+ '}';
+ }
}
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 fc0b4cffe6..24f9535d9f 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java
@@ -24,14 +24,15 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,38 +45,38 @@ import org.apache.cassandra.cql3.CQLStatement;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.QualifiedName;
import org.apache.cassandra.cql3.functions.masking.ColumnMask;
-import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.db.marshal.AbstractType;
-
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.gms.ApplicationState;
import org.apache.cassandra.gms.Gossiper;
+import org.apache.cassandra.index.TargetParser;
import org.apache.cassandra.locator.InetAddressAndPort;
-import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.schema.IndexMetadata;
import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
+import org.apache.cassandra.schema.MemtableParams;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.schema.TableParams;
import org.apache.cassandra.schema.ViewMetadata;
import org.apache.cassandra.schema.Views;
import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.service.reads.repair.ReadRepairStrategy;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
+import org.apache.cassandra.tcm.membership.Directory;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
+import org.apache.cassandra.utils.CassandraVersion;
import org.apache.cassandra.utils.NoSpamLogger;
+import org.apache.cassandra.utils.Pair;
+import static com.google.common.collect.Iterables.isEmpty;
import static java.lang.String.format;
import static java.lang.String.join;
-
-import static com.google.common.collect.Iterables.isEmpty;
-import static com.google.common.collect.Iterables.transform;
-
import static org.apache.cassandra.schema.TableMetadata.Flag;
public abstract class AlterTableStatement extends AlterSchemaStatement
@@ -100,8 +101,9 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
this.state = state;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
TableMetadata table = null == keyspace
@@ -118,7 +120,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
if (table.isView())
throw ire("Cannot use ALTER TABLE on a materialized view; use ALTER MATERIALIZED VIEW instead");
- return schema.withAddedOrUpdated(apply(keyspace, table));
+ return schema.withAddedOrUpdated(apply(metadata.nextEpoch(), keyspace, table));
}
SchemaChange schemaChangeEvent(KeyspacesDiff diff)
@@ -142,7 +144,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
return format("%s (%s, %s)", getClass().getSimpleName(), keyspaceName, tableName);
}
- abstract KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table);
+ abstract KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table);
/**
* {@code ALTER TABLE [IF EXISTS] <table> ALTER <column> TYPE <newtype>;}
@@ -156,7 +158,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
super(keyspaceName, tableName, ifTableExists);
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
throw ire("Altering column types is no longer supported");
}
@@ -196,7 +198,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
}
@Override
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
ColumnMetadata column = table.getColumn(columnName);
@@ -214,7 +216,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
if (Objects.equals(oldMask, newMask))
return keyspace;
- TableMetadata.Builder tableBuilder = table.unbuild();
+ TableMetadata.Builder tableBuilder = table.unbuild().epoch(epoch);
tableBuilder.alterColumnMask(columnName, newMask);
TableMetadata newTable = tableBuilder.build();
newTable.validate();
@@ -274,10 +276,10 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
newColumns.forEach(c -> c.type.validate(state, "Column " + c.name));
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
Guardrails.alterTableEnabled.ensureEnabled("ALTER TABLE changing columns", state);
- TableMetadata.Builder tableBuilder = table.unbuild();
+ TableMetadata.Builder tableBuilder = table.unbuild().epoch(epoch);
Views.Builder viewsBuilder = keyspace.views.unbuild();
newColumns.forEach(c -> addColumn(keyspace, table, c, ifColumnNotExists, tableBuilder, viewsBuilder));
@@ -360,6 +362,38 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
}
}
+ private static void validateIndexesForColumnModification(TableMetadata table,
+ ColumnIdentifier colId,
+ boolean isRename)
+ {
+ ColumnMetadata column = table.getColumn(colId);
+ Set<String> dependentIndexes = new HashSet<>();
+ for (IndexMetadata index : table.indexes)
+ {
+ Optional<Pair<ColumnMetadata, IndexTarget.Type>> target = TargetParser.tryParse(table, index);
+ if (target.isEmpty())
+ {
+ // The target column(s) of this index is not trivially discernible from its metadata.
+ // This implies an external custom index implementation and without instantiating the
+ // index itself we cannot be sure that the column metadata is safe to modify.
+ dependentIndexes.add(index.name);
+ }
+ else if (target.get().left.equals(column))
+ {
+ // The index metadata declares an explicit dependency on the column being modified, so
+ // the mutation must be rejected.
+ dependentIndexes.add(index.name);
+ }
+ }
+ if (!dependentIndexes.isEmpty())
+ {
+ throw ire("Cannot %s column %s because it has dependent secondary indexes (%s)",
+ isRename ? "rename" : "drop",
+ colId,
+ join(", ", dependentIndexes));
+ }
+ }
+
/**
* {@code ALTER TABLE [IF EXISTS] <table> DROP [IF EXISTS] <column>}
* {@code ALTER TABLE [IF EXISTS] <table> DROP [IF EXISTS] ( <column>, <column1>, ... <columnn>)}
@@ -379,7 +413,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
this.timestamp = timestamp;
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
Guardrails.alterTableEnabled.ensureEnabled("ALTER TABLE changing columns", state);
TableMetadata.Builder builder = table.unbuild();
@@ -407,14 +441,8 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
if (currentColumn.type.isUDT() && currentColumn.type.isMultiCell())
throw ire("Cannot drop non-frozen column %s of user type %s", column, currentColumn.type.asCQL3Type());
- // TODO: some day try and find a way to not rely on Keyspace/IndexManager/Index to find dependent indexes
- Set<IndexMetadata> dependentIndexes = Keyspace.openAndGetStore(table).indexManager.getDependentIndexes(currentColumn);
- if (!dependentIndexes.isEmpty())
- {
- throw ire("Cannot drop column %s because it has dependent secondary indexes (%s)",
- currentColumn,
- join(", ", transform(dependentIndexes, i -> i.name)));
- }
+ if (!table.indexes.isEmpty())
+ AlterTableStatement.validateIndexesForColumnModification(table, column, false);
if (!isEmpty(keyspace.views.forTable(table.id)))
throw ire("Cannot drop column %s on base table %s with materialized views", currentColumn, table.name);
@@ -447,10 +475,10 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
this.ifColumnsExists = ifColumnsExists;
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
Guardrails.alterTableEnabled.ensureEnabled("ALTER TABLE changing columns", state);
- TableMetadata.Builder tableBuilder = table.unbuild();
+ TableMetadata.Builder tableBuilder = table.unbuild().epoch(epoch);
Views.Builder viewsBuilder = keyspace.views.unbuild();
renamedColumns.forEach((o, n) -> renameColumn(keyspace, table, o, n, ifColumnsExists, tableBuilder, viewsBuilder));
@@ -485,14 +513,8 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
table);
}
- // TODO: some day try and find a way to not rely on Keyspace/IndexManager/Index to find dependent indexes
- Set<IndexMetadata> dependentIndexes = Keyspace.openAndGetStore(table).indexManager.getDependentIndexes(column);
- if (!dependentIndexes.isEmpty())
- {
- throw ire("Can't rename column %s because it has dependent secondary indexes (%s)",
- oldName,
- join(", ", transform(dependentIndexes, i -> i.name)));
- }
+ if (!table.indexes.isEmpty())
+ AlterTableStatement.validateIndexesForColumnModification(table, oldName, true);
for (ViewMetadata view : keyspace.views.forTable(table.id))
{
@@ -523,13 +545,15 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
public void validate(ClientState state)
{
super.validate(state);
-
+ // If a memtable configuration is specified, validate it against config
+ if (attrs.hasOption(TableParams.Option.MEMTABLE))
+ MemtableParams.get(attrs.getString(TableParams.Option.MEMTABLE.toString()));
Guardrails.tableProperties.guard(attrs.updatedProperties(), attrs::removeProperty, state);
validateDefaultTimeToLive(attrs.asNewTableParams());
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
attrs.validate();
@@ -547,7 +571,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
"before being replayed.");
}
- if (keyspace.createReplicationStrategy().hasTransientReplicas()
+ if (keyspace.replicationStrategy.hasTransientReplicas()
&& params.readRepair != ReadRepairStrategy.NONE)
{
throw ire("read_repair must be set to 'NONE' for transiently replicated keyspaces");
@@ -573,7 +597,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
super(keyspaceName, tableName, ifTableExists);
}
- public KeyspaceMetadata apply(KeyspaceMetadata keyspace, TableMetadata table)
+ public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table)
{
if (!DatabaseDescriptor.enableDropCompactStorage())
throw new InvalidRequestException("DROP COMPACT STORAGE is disabled. Enable in cassandra.yaml to use.");
@@ -587,7 +611,7 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
? ImmutableSet.of(Flag.COMPOUND, Flag.COUNTER)
: ImmutableSet.of(Flag.COMPOUND);
- return keyspace.withSwapped(keyspace.tables.withSwapped(table.withSwapped(flags)));
+ return keyspace.withSwapped(keyspace.tables.withSwapped(table.unbuild().flags(flags).build()));
}
/**
@@ -608,40 +632,45 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
Set<InetAddressAndPort> preC15897nodes = new HashSet<>();
Set<InetAddressAndPort> with2xSStables = new HashSet<>();
Splitter onComma = Splitter.on(',').omitEmptyStrings().trimResults();
- for (InetAddressAndPort node : StorageService.instance.getTokenMetadata().getAllEndpoints())
+ Directory directory = ClusterMetadata.current().directory;
+ for (InetAddressAndPort node : directory.allAddresses())
{
- if (MessagingService.instance().versions.knows(node) &&
- MessagingService.instance().versions.getRaw(node) < MessagingService.VERSION_40)
- {
- before4.add(node);
- continue;
- }
- String sstableVersionsString = Gossiper.instance.getApplicationState(node, ApplicationState.SSTABLE_VERSIONS);
- if (sstableVersionsString == null)
- {
- preC15897nodes.add(node);
- continue;
- }
+ CassandraVersion version = directory.version(directory.peerId(node)).cassandraVersion;
- try
+ if (version.compareTo(CassandraVersion.CASSANDRA_4_0) < 0)
{
- boolean has2xSStables = onComma.splitToList(sstableVersionsString)
- .stream()
- .anyMatch(v -> v.compareTo("big-ma")<=0);
- if (has2xSStables)
- with2xSStables.add(node);
+ // if the cluster contains any pre-4.0 nodes (which really shouldn't be the case), reject this
+ // operation as we can't be certain all peers can support it.
+ before4.add(node);
}
- catch (IllegalArgumentException e)
+ else
{
- // Means VersionType::fromString didn't parse a version correctly. Which shouldn't happen, we shouldn't
- // have garbage in Gossip. But crashing the request is not ideal, so we log the error but ignore the
- // node otherwise.
- noSpamLogger.error("Unexpected error parsing sstable versions from gossip for {} (gossiped value " +
- "is '{}'). This is a bug and should be reported. Cannot ensure that {} has no " +
- "non-upgraded 2.x sstables anymore. If after this DROP COMPACT STORAGE some old " +
- "sstables cannot be read anymore, please use `upgradesstables` with the " +
- "`--force-compact-storage-on` option.", node, sstableVersionsString, node);
+ // any peer on a version greater than 4.0.0 must include CASSANDRA-15897, so just check that
+ // its min sstable version. Note: this app state may be empty/unset if the full StorageService
+ // initialisation hasn't been done, i.e. in tests.
+ String sstableVersionsString = Gossiper.instance.getApplicationState(node, ApplicationState.SSTABLE_VERSIONS);
+ if (Strings.isNullOrEmpty(sstableVersionsString))
+ continue;
+ try
+ {
+ boolean has2xSStables = onComma.splitToList(sstableVersionsString)
+ .stream()
+ .anyMatch(v -> v.compareTo("big-ma")<=0);
+ if (has2xSStables)
+ with2xSStables.add(node);
+ }
+ catch (IllegalArgumentException e)
+ {
+ // Means VersionType::fromString didn't parse a version correctly. Which shouldn't happen, we shouldn't
+ // have garbage in Gossip. But crashing the request is not ideal, so we log the error but ignore the
+ // node otherwise.
+ noSpamLogger.error("Unexpected error parsing sstable versions from gossip for {} (gossiped value " +
+ "is '{}'). This is a bug and should be reported. Cannot ensure that {} has no " +
+ "non-upgraded 2.x sstables anymore. If after this DROP COMPACT STORAGE some old " +
+ "sstables cannot be read anymore, please use `upgradesstables` with the " +
+ "`--force-compact-storage-on` option.", node, sstableVersionsString, node);
+ }
}
}
@@ -649,10 +678,6 @@ public abstract class AlterTableStatement extends AlterSchemaStatement
throw new InvalidRequestException(format("Cannot DROP COMPACT STORAGE as some nodes in the cluster (%s) " +
"are not on 4.0+ yet. Please upgrade those nodes and run " +
"`upgradesstables` before retrying.", before4));
- if (!preC15897nodes.isEmpty())
- throw new InvalidRequestException(format("Cannot guarantee that DROP COMPACT STORAGE is safe as some nodes " +
- "in the cluster (%s) do not have https://issues.apache.org/jira/browse/CASSANDRA-15897. " +
- "Please upgrade those nodes and retry.", preC15897nodes));
if (!with2xSStables.isEmpty())
throw new InvalidRequestException(format("Cannot DROP COMPACT STORAGE as some nodes in the cluster (%s) " +
"has some non-upgraded 2.x sstables. Please run `upgradesstables` " +
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 40bca4aac9..fefe70e1c6 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java
@@ -34,6 +34,7 @@ import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -69,8 +70,10 @@ public abstract class AlterTypeStatement extends AlterSchemaStatement
return new SchemaChange(Change.UPDATED, Target.TYPE, keyspaceName, typeName);
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
UserType type = null == keyspace
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 7e707f476b..831e46b0ca 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java
@@ -26,6 +26,7 @@ import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -54,8 +55,10 @@ public final class AlterViewStatement extends AlterSchemaStatement
this.state = state;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
ViewMetadata view = null == keyspace
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 eb9f33a949..8950f67d9a 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java
@@ -44,6 +44,7 @@ import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -89,7 +90,8 @@ public final class CreateAggregateStatement extends AlterSchemaStatement
this.ifNotExists = ifNotExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
if (ifNotExists && orReplace)
throw ire("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");
@@ -105,6 +107,7 @@ public final class CreateAggregateStatement extends AlterSchemaStatement
if (!rawStateType.isImplicitlyFrozen() && rawStateType.isFrozen())
throw ire("State type '%s' cannot be frozen; remove frozen<> modifier from '%s'", rawStateType, rawStateType);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
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 f04ae37cd5..20923687ff 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java
@@ -40,6 +40,7 @@ import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -82,7 +83,7 @@ public final class CreateFunctionStatement extends AlterSchemaStatement
}
// TODO: replace affected aggregates !!
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
if (ifNotExists && orReplace)
throw ire("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");
@@ -103,6 +104,7 @@ public final class CreateFunctionStatement extends AlterSchemaStatement
if (!rawReturnType.isImplicitlyFrozen() && rawReturnType.isFrozen())
throw ire("Return type '%s' cannot be frozen; remove frozen<> modifier from '%s'", rawReturnType, rawReturnType);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
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 b53e066f90..c1626d0f09 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
@@ -31,7 +31,6 @@ import org.apache.cassandra.cql3.CQLStatement;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.QualifiedName;
import org.apache.cassandra.cql3.statements.schema.IndexTarget.Type;
-import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.exceptions.InvalidRequestException;
@@ -40,6 +39,7 @@ import org.apache.cassandra.index.sasi.SASIIndex;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -112,7 +112,8 @@ public final class CreateIndexStatement extends AlterSchemaStatement
this.state = state;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
attrs.validate();
@@ -121,6 +122,7 @@ public final class CreateIndexStatement extends AlterSchemaStatement
if (attrs.isCustom && attrs.customClass.equals(SASIIndex.class.getName()) && !DatabaseDescriptor.getSASIIndexesEnabled())
throw new InvalidRequestException(SASI_INDEX_DISABLED);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire(KEYSPACE_DOES_NOT_EXIST, keyspaceName);
@@ -143,7 +145,7 @@ public final class CreateIndexStatement extends AlterSchemaStatement
if (table.isView())
throw ire(MATERIALIZED_VIEWS_NOT_SUPPORTED);
- if (Keyspace.open(table.keyspace).getReplicationStrategy().hasTransientReplicas())
+ if (keyspace.replicationStrategy.hasTransientReplicas())
throw new InvalidRequestException(TRANSIENTLY_REPLICATED_KEYSPACE_NOT_SUPPORTED);
// guardrails to limit number of secondary indexes per table.
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 13d52b1e15..16a117c890 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.cql3.statements.schema;
-import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
@@ -36,12 +35,11 @@ import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.exceptions.AlreadyExistsException;
import org.apache.cassandra.locator.LocalStrategy;
import org.apache.cassandra.locator.SimpleStrategy;
-import org.apache.cassandra.schema.KeyspaceMetadata;
+import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.KeyspaceParams.Option;
-import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
-import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -51,7 +49,6 @@ public final class CreateKeyspaceStatement extends AlterSchemaStatement
private final KeyspaceAttributes attrs;
private final boolean ifNotExists;
- private final HashSet<String> clientWarnings = new HashSet<>();
public CreateKeyspaceStatement(String keyspaceName, KeyspaceAttributes attrs, boolean ifNotExists)
{
@@ -60,7 +57,7 @@ public final class CreateKeyspaceStatement extends AlterSchemaStatement
this.ifNotExists = ifNotExists;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
attrs.validate();
@@ -70,6 +67,7 @@ public final class CreateKeyspaceStatement extends AlterSchemaStatement
if (attrs.getReplicationStrategyClass() != null && attrs.getReplicationStrategyClass().equals(SimpleStrategy.class.getSimpleName()))
Guardrails.simpleStrategyEnabled.ensureEnabled("SimpleStrategy", state);
+ Keyspaces schema = metadata.schema.getKeyspaces();
if (schema.containsKeyspace(keyspaceName))
{
if (ifNotExists)
@@ -83,7 +81,11 @@ public final class CreateKeyspaceStatement extends AlterSchemaStatement
if (keyspace.params.replication.klass.equals(LocalStrategy.class))
throw ire("Unable to use given strategy class: LocalStrategy is reserved for internal use.");
- keyspace.params.validate(keyspaceName, state);
+ if (keyspace.params.replication.isMeta())
+ throw ire("Can not create a keyspace with MetaReplicationStrategy");
+
+ keyspace.params.validate(keyspaceName, state, metadata);
+ keyspace.replicationStrategy.validateExpectedOptions(metadata);
return schema.withAddedOrUpdated(keyspace);
}
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 747837f305..b606a96d99 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java
@@ -34,15 +34,16 @@ import org.apache.cassandra.audit.AuditLogEntryType;
import org.apache.cassandra.auth.DataResource;
import org.apache.cassandra.auth.IResource;
import org.apache.cassandra.auth.Permission;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.cql3.functions.masking.ColumnMask;
-import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.exceptions.AlreadyExistsException;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.service.reads.repair.ReadRepairStrategy;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -94,8 +95,9 @@ public final class CreateTableStatement extends AlterSchemaStatement
this.useCompactStorage = useCompactStorage;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
@@ -108,10 +110,13 @@ public final class CreateTableStatement extends AlterSchemaStatement
throw new AlreadyExistsException(keyspaceName, tableName);
}
- TableMetadata table = builder(keyspace.types).build();
+ TableMetadata.Builder builder = builder(keyspace.types).epoch(metadata.nextEpoch());
+ if (!builder.hasId() && !DatabaseDescriptor.useDeterministicTableID())
+ builder.id(TableId.get(metadata));
+ TableMetadata table = builder.build();
table.validate();
- if (keyspace.createReplicationStrategy().hasTransientReplicas()
+ if (keyspace.replicationStrategy.hasTransientReplicas()
&& table.params.readRepair != ReadRepairStrategy.NONE)
{
throw ire("read_repair must be set to 'NONE' for transiently replicated keyspaces");
@@ -128,6 +133,10 @@ public final class CreateTableStatement extends AlterSchemaStatement
{
super.validate(state);
+ // If a memtable configuration is specified, validate it against config
+ if (attrs.hasOption(TableParams.Option.MEMTABLE))
+ MemtableParams.get(attrs.getString(TableParams.Option.MEMTABLE.toString()));
+
// Guardrail on table properties
Guardrails.tableProperties.guard(attrs.updatedProperties(), attrs::removeProperty, state);
@@ -139,8 +148,7 @@ public final class CreateTableStatement extends AlterSchemaStatement
{
int totalUserTables = Schema.instance.getUserKeyspaces()
.stream()
- .map(Keyspace::open)
- .mapToInt(keyspace -> keyspace.getColumnFamilyStores().size())
+ .mapToInt(ksm -> ksm.tables.size())
.sum();
Guardrails.tables.guard(totalUserTables + 1, tableName, false, state);
}
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 e85ffd80ae..392996b2f3 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTriggerStatement.java
@@ -24,6 +24,7 @@ import org.apache.cassandra.cql3.QualifiedName;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.triggers.TriggerExecutor;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -45,8 +46,10 @@ public final class CreateTriggerStatement extends AlterSchemaStatement
this.ifNotExists = ifNotExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
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 d76c8089f6..bd63310f18 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateTypeStatement.java
@@ -34,6 +34,7 @@ import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.schema.Types;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -75,8 +76,9 @@ public final class CreateTypeStatement extends AlterSchemaStatement
}
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
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 05629e00fd..a4a8ddcfbe 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java
@@ -41,6 +41,7 @@ import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -110,7 +111,8 @@ public final class CreateViewStatement extends AlterSchemaStatement
this.state = state;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
if (!DatabaseDescriptor.getMaterializedViewsEnabled())
throw ire("Materialized views are disabled. Enable in cassandra.yaml to use.");
@@ -119,11 +121,12 @@ public final class CreateViewStatement extends AlterSchemaStatement
* Basic dependency validations
*/
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
- if (keyspace.createReplicationStrategy().hasTransientReplicas())
+ if (keyspace.replicationStrategy.hasTransientReplicas())
throw new InvalidRequestException("Materialized views are not supported on transiently replicated keyspaces");
TableMetadata table = keyspace.tables.getNullable(tableName);
@@ -324,6 +327,8 @@ public final class CreateViewStatement extends AlterSchemaStatement
if (attrs.hasProperty(TableAttributes.ID))
builder.id(attrs.getId());
+ else if (!builder.hasId() && !DatabaseDescriptor.useDeterministicTableID())
+ builder.id(TableId.get(metadata));
builder.params(attrs.asNewTableParams())
.kind(TableMetadata.Kind.VIEW);
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 d83fbbf97f..e61332ee12 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropAggregateStatement.java
@@ -35,6 +35,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -64,13 +65,14 @@ public final class DropAggregateStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
String name =
argumentsSpeficied
? format("%s.%s(%s)", keyspaceName, aggregateName, join(", ", transform(arguments, CQL3Type.Raw::toString)))
: format("%s.%s", keyspaceName, aggregateName);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
{
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 af82206322..0353964683 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java
@@ -35,6 +35,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -65,13 +66,15 @@ public final class DropFunctionStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
String name =
argumentsSpeficied
? format("%s.%s(%s)", keyspaceName, functionName, join(", ", transform(arguments, CQL3Type.Raw::toString)))
: format("%s.%s", keyspaceName, functionName);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
{
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 24b372d8c3..06cbc4be99 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropIndexStatement.java
@@ -26,6 +26,7 @@ import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.KeyspaceMetadata.KeyspaceDiff;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -42,8 +43,10 @@ public final class DropIndexStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
TableMetadata table = null == keyspace
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 47e514a527..e074da54a3 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropKeyspaceStatement.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
@@ -38,10 +39,12 @@ public final class DropKeyspaceStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
Guardrails.dropKeyspaceEnabled.ensureEnabled(state);
+ Keyspaces schema = metadata.schema.getKeyspaces();
if (schema.containsKeyspace(keyspaceName))
return schema.without(keyspaceName);
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 78c98be3a7..56848a8c22 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTableStatement.java
@@ -26,6 +26,7 @@ import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -47,10 +48,11 @@ public final class DropTableStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ public Keyspaces apply(ClusterMetadata metadata)
{
Guardrails.dropTruncateTableEnabled.ensureEnabled(state);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
TableMetadata table = null == keyspace
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 967e56834f..15007c3b1e 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTriggerStatement.java
@@ -24,6 +24,7 @@ import org.apache.cassandra.cql3.QualifiedName;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -42,8 +43,10 @@ public final class DropTriggerStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
TableMetadata table = null == keyspace
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 97830c882a..105c8f5db8 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropTypeStatement.java
@@ -31,6 +31,7 @@ import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.schema.Keyspaces;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
import org.apache.cassandra.transport.Event.SchemaChange;
@@ -55,10 +56,12 @@ public final class DropTypeStatement extends AlterSchemaStatement
}
// TODO: expand types into tuples in all dropped columns of all tables
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
ByteBuffer name = bytes(typeName);
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
UserType type = null == keyspace
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 2c73717546..121575503c 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/DropViewStatement.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.cql3.QualifiedName;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.transport.Event.SchemaChange;
import org.apache.cassandra.transport.Event.SchemaChange.Change;
import org.apache.cassandra.transport.Event.SchemaChange.Target;
@@ -41,8 +42,10 @@ public final class DropViewStatement extends AlterSchemaStatement
this.ifExists = ifExists;
}
- public Keyspaces apply(Keyspaces schema)
+ @Override
+ public Keyspaces apply(ClusterMetadata metadata)
{
+ Keyspaces schema = metadata.schema.getKeyspaces();
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
ViewMetadata view = null == keyspace
diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/TableAttributes.java b/src/java/org/apache/cassandra/cql3/statements/schema/TableAttributes.java
index 93d477c847..87af6b840b 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/TableAttributes.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/TableAttributes.java
@@ -115,8 +115,8 @@ public final class TableAttributes extends PropertyDefinitions
if (hasOption(COMPRESSION))
builder.compression(CompressionParams.fromMap(getMap(COMPRESSION)));
- if (hasOption(MEMTABLE))
- builder.memtable(MemtableParams.get(getString(MEMTABLE)));
+ if (hasOption(Option.MEMTABLE))
+ builder.memtable(MemtableParams.getWithFallback(getString(Option.MEMTABLE)));
if (hasOption(DEFAULT_TIME_TO_LIVE))
builder.defaultTimeToLive(getInt(DEFAULT_TIME_TO_LIVE));
diff --git a/src/java/org/apache/cassandra/db/AbstractMutationVerbHandler.java b/src/java/org/apache/cassandra/db/AbstractMutationVerbHandler.java
new file mode 100644
index 0000000000..cfea7eb45c
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/AbstractMutationVerbHandler.java
@@ -0,0 +1,185 @@
+/*
+ * 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.db;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.cassandra.db.partitions.PartitionUpdate;
+import org.apache.cassandra.exceptions.CoordinatorBehindException;
+import org.apache.cassandra.exceptions.InvalidRoutingException;
+import org.apache.cassandra.locator.InetAddressAndPort;
+import org.apache.cassandra.metrics.TCMMetrics;
+import org.apache.cassandra.net.IVerbHandler;
+import org.apache.cassandra.net.Message;
+import org.apache.cassandra.schema.SchemaConstants;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.ClusterMetadataService;
+import org.apache.cassandra.tcm.Epoch;
+import org.apache.cassandra.tcm.ownership.VersionedEndpoints;
+import org.apache.cassandra.utils.NoSpamLogger;
+
+public abstract class AbstractMutationVerbHandler<T extends IMutation> implements IVerbHandler<T>
+{
+ private static final Logger logger = LoggerFactory.getLogger(AbstractMutationVerbHandler.class);
+ private static final String logMessageTemplate = "Received mutation from {} for token {} outside valid range for keyspace {}";
+
+ public void doVerb(Message<T> message) throws IOException
+ {
+ processMessage(message, message.respondTo());
+ }
+
+ protected void processMessage(Message<T> message, InetAddressAndPort respondTo)
+ {
+ if (message.epoch().isAfter(Epoch.EMPTY))
+ {
+ ClusterMetadata metadata = ClusterMetadata.current();
+ metadata = checkTokenOwnership(metadata, message);
+ metadata = checkSchemaVersion(metadata, message);
+ }
+ applyMutation(message, respondTo);
+ }
+
+ abstract void applyMutation(Message<T> message, InetAddressAndPort respondToAddress);
+
+ private ClusterMetadata checkTokenOwnership(ClusterMetadata metadata, Message<T> message)
+ {
+ String keyspace = message.payload.getKeyspaceName();
+ DecoratedKey key = message.payload.key();
+
+ VersionedEndpoints.ForToken forToken = writePlacements(metadata, keyspace, key);
+
+ if (message.epoch().isAfter(metadata.epoch))
+ {
+ // If replica detects that coordinator has made an out-of-range request, it has to catch up blockingly,
+ // since coordinator's routing may be more recent.
+ if (!forToken.get().containsSelf())
+ {
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ forToken = writePlacements(metadata, keyspace, key);
+ }
+ // Otherwise, coordinator and the replica agree about the placement of the givent token, so catch-up can be async
+ else
+ {
+ ClusterMetadataService.instance().fetchLogFromPeerOrCMSAsync(metadata, message.from(), message.epoch());
+ }
+ }
+
+ if (!forToken.get().containsSelf())
+ {
+ StorageService.instance.incOutOfRangeOperationCount();
+ Keyspace.open(message.payload.getKeyspaceName()).metric.outOfRangeTokenWrites.inc();
+ NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, 1, TimeUnit.SECONDS, logMessageTemplate, message.from(), key.getToken(), message.payload.getKeyspaceName());
+ throw InvalidRoutingException.forWrite(message.from(), key.getToken(), metadata.epoch, message.payload);
+ }
+
+ if (forToken.lastModified().isAfter(message.epoch()))
+ {
+ TCMMetrics.instance.coordinatorBehindPlacements.mark();
+ throw new CoordinatorBehindException(String.format("Routing is correct, but coordinator needs to catch-up at least to epoch %s to maintain consistency. Current coordinator epoch is %s",
+ forToken.lastModified(), message.epoch()));
+ }
+
+ return metadata;
+ }
+
+ private ClusterMetadata checkSchemaVersion(ClusterMetadata metadata, Message<T> message)
+ {
+ if (SchemaConstants.isSystemKeyspace(message.payload.getKeyspaceName()) || message.epoch().is(metadata.epoch))
+ return metadata;
+ String keyspace = message.payload.getKeyspaceName();
+ Keyspace ks = metadata.schema.getKeyspace(keyspace);
+ if (ks != null)
+ {
+ if (message.epoch().isAfter(metadata.epoch))
+ {
+ // coordinator is ahead - check each partition update if the schema is ahead of the schema we have for the table
+ for (PartitionUpdate pu : message.payload.getPartitionUpdates())
+ {
+ Epoch remoteSchemaEpoch = pu.serializedAtEpoch;
+ if (remoteSchemaEpoch != null && remoteSchemaEpoch.isAfter(metadata.epoch))
+ {
+ // the partition update was serialized after the epoch we currently know, catch up and
+ // make sure we've seen the epoch it has seen, otherwise fail request.
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ if (pu.serializedAtEpoch.isAfter(metadata.epoch))
+ throw new IllegalStateException(String.format("Coordinator %s is still ahead after fetching log, our epoch = %s, their epoch = %s",
+ message.from(),
+ metadata.epoch, message.epoch()));
+ }
+ }
+ }
+ else if (message.epoch().isBefore(metadata.schema.lastModified()))
+ {
+ // coordinator might not have seen the latest schema change - check each modified table individually
+ for (PartitionUpdate pu : message.payload.getPartitionUpdates())
+ {
+ // coordinator could be behind, check local tables
+ ColumnFamilyStore cfs = ks.getColumnFamilyStore(pu.metadata().id);
+ if (cfs != null)
+ {
+ Epoch remoteSchemaEpoch = pu.serializedAtEpoch;
+ if (remoteSchemaEpoch != null && remoteSchemaEpoch.isBefore(cfs.metadata().epoch))
+ {
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(String.format("Coordinator %s is behind, our epoch = %s, their epoch = %s",
+ message.from(),
+ metadata.epoch, message.epoch()));
+ }
+ }
+ else
+ {
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(String.format("Schema mismatch, coordinator %s is behind, we're missing table %s.%s, our epoch = %s, their epoch = %s",
+ message.from(),
+ pu.metadata().keyspace,
+ pu.metadata().name,
+ metadata.epoch, message.epoch()));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (message.epoch().isBefore(metadata.schema.lastModified()))
+ {
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(String.format("Schema mismatch, coordinator %s is behind, we're missing keyspace %s, our epoch = %s, their epoch = %s",
+ message.from(),
+ keyspace,
+ metadata.epoch, message.epoch()));
+ }
+ else
+ {
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ }
+ }
+
+ return metadata;
+ }
+
+ private static VersionedEndpoints.ForToken writePlacements(ClusterMetadata metadata, String keyspace, DecoratedKey key)
+ {
+ return metadata.placements.get(metadata.schema.getKeyspace(keyspace).getMetadata().params.replication).writes.forToken(key.getToken());
+ }
+}
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 1ef67878d5..3fc1fc5bce 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -90,14 +90,14 @@ import org.apache.cassandra.db.compaction.CompactionStrategyManager;
import org.apache.cassandra.db.compaction.OperationType;
import org.apache.cassandra.db.filter.ClusteringIndexFilter;
import org.apache.cassandra.db.filter.DataLimits;
+import org.apache.cassandra.db.memtable.Flushing;
+import org.apache.cassandra.db.memtable.Memtable;
+import org.apache.cassandra.db.memtable.ShardBoundaries;
import org.apache.cassandra.db.lifecycle.LifecycleNewTracker;
import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
import org.apache.cassandra.db.lifecycle.SSTableSet;
import org.apache.cassandra.db.lifecycle.Tracker;
import org.apache.cassandra.db.lifecycle.View;
-import org.apache.cassandra.db.memtable.Flushing;
-import org.apache.cassandra.db.memtable.Memtable;
-import org.apache.cassandra.db.memtable.ShardBoundaries;
import org.apache.cassandra.db.partitions.CachedPartition;
import org.apache.cassandra.db.partitions.PartitionUpdate;
import org.apache.cassandra.db.repair.CassandraTableRepairManager;
@@ -161,6 +161,8 @@ import org.apache.cassandra.service.snapshot.SnapshotLoader;
import org.apache.cassandra.service.snapshot.SnapshotManifest;
import org.apache.cassandra.service.snapshot.TableSnapshot;
import org.apache.cassandra.streaming.TableStreamManager;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.DefaultValue;
import org.apache.cassandra.utils.ExecutorUtils;
@@ -261,7 +263,8 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
static final String TOKEN_DELIMITER = ":";
/** Special values used when the local ranges are not changed with ring changes (e.g. local tables). */
- public static final int RING_VERSION_IRRELEVANT = -1;
+ // TODO - make this Epoch.EMPTY
+ public static final Epoch RING_VERSION_IRRELEVANT = Epoch.create(-1);
static
{
@@ -375,23 +378,28 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
}
public void reload()
+ {
+ reload(metadata());
+ }
+
+ public void reload(TableMetadata tableMetadata)
{
// metadata object has been mutated directly. make all the members jibe with new settings.
// only update these runtime-modifiable settings if they have not been modified.
if (!minCompactionThreshold.isModified())
for (ColumnFamilyStore cfs : concatWithIndexes())
- cfs.minCompactionThreshold = new DefaultValue(metadata().params.compaction.minCompactionThreshold());
+ cfs.minCompactionThreshold = new DefaultValue<>(tableMetadata.params.compaction.minCompactionThreshold());
if (!maxCompactionThreshold.isModified())
for (ColumnFamilyStore cfs : concatWithIndexes())
- cfs.maxCompactionThreshold = new DefaultValue(metadata().params.compaction.maxCompactionThreshold());
+ cfs.maxCompactionThreshold = new DefaultValue<>(tableMetadata.params.compaction.maxCompactionThreshold());
if (!crcCheckChance.isModified())
for (ColumnFamilyStore cfs : concatWithIndexes())
- cfs.crcCheckChance = new DefaultValue(metadata().params.crcCheckChance);
+ cfs.crcCheckChance = new DefaultValue<>(tableMetadata.params.crcCheckChance);
- compactionStrategyManager.maybeReloadParamsFromSchema(metadata().params.compaction);
+ compactionStrategyManager.maybeReloadParamsFromSchema(tableMetadata.params.compaction);
- indexManager.reload();
+ indexManager.reload(tableMetadata);
memtableFactory = metadata().params.memtable.factory();
switchMemtableOrNotify(FlushReason.SCHEMA_CHANGE, Memtable::metadataUpdated);
@@ -453,7 +461,9 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
{
CompressionParams params = CompressionParams.fromMap(opts);
params.validate();
- metadata.setLocalOverrides(metadata().unbuild().compression(params).build());
+
+ TableMetadata orig = metadata();
+ metadata.setLocalOverrides(orig.unbuild().compression(params).epoch(orig.epoch).build());
}
catch (ConfigurationException e)
{
@@ -470,27 +480,26 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
public ColumnFamilyStore(Keyspace keyspace,
String columnFamilyName,
Supplier<? extends SSTableId> sstableIdGenerator,
- TableMetadataRef metadata,
+ TableMetadata initMetadata,
Directories directories,
boolean loadSSTables,
- boolean registerBookeeping,
- boolean offline)
+ boolean registerBookeeping)
{
assert directories != null;
- assert metadata != null : "null metadata for " + keyspace + ':' + columnFamilyName;
+ assert initMetadata != null : "null metadata for " + keyspace + ':' + columnFamilyName;
this.keyspace = keyspace;
- this.metadata = metadata;
+ this.metadata = initMetadata.ref;
this.directories = directories;
name = columnFamilyName;
- minCompactionThreshold = new DefaultValue<>(metadata.get().params.compaction.minCompactionThreshold());
- maxCompactionThreshold = new DefaultValue<>(metadata.get().params.compaction.maxCompactionThreshold());
- crcCheckChance = new DefaultValue<>(metadata.get().params.crcCheckChance);
- viewManager = keyspace.viewManager.forTable(metadata.id);
+ minCompactionThreshold = new DefaultValue<>(initMetadata.params.compaction.minCompactionThreshold());
+ maxCompactionThreshold = new DefaultValue<>(initMetadata.params.compaction.maxCompactionThreshold());
+ crcCheckChance = new DefaultValue<>(initMetadata.params.crcCheckChance);
+ viewManager = keyspace.viewManager.forTable(initMetadata);
this.sstableIdGenerator = sstableIdGenerator;
sampleReadLatencyMicros = DatabaseDescriptor.getReadRpcTimeout(TimeUnit.MICROSECONDS) / 2;
additionalWriteLatencyMicros = DatabaseDescriptor.getWriteRpcTimeout(TimeUnit.MICROSECONDS) / 2;
- memtableFactory = metadata.get().params.memtable.factory();
+ memtableFactory = initMetadata.params.memtable.factory();
logger.info("Initializing {}.{}", getKeyspaceName(), name);
@@ -514,7 +523,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
{
Directories.SSTableLister sstableFiles = directories.sstableLister(Directories.OnTxnErr.IGNORE).skipTemporary(true);
sstables = SSTableReader.openAll(this, sstableFiles.list().entrySet(), metadata);
- data.addInitialSSTablesWithoutUpdatingSize(sstables);
+ data.addInitialSSTablesWithoutUpdatingSize(sstables, this);
}
// compaction strategy should be created after the CFS has been prepared
@@ -528,7 +537,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
// create the private ColumnFamilyStores for the secondary column indexes
indexManager = new SecondaryIndexManager(this);
- for (IndexMetadata info : metadata.get().indexes)
+ for (IndexMetadata info : initMetadata.indexes)
{
indexManager.addIndex(info, true);
}
@@ -563,7 +572,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
if (DatabaseDescriptor.isClientOrToolInitialized() || SchemaConstants.isSystemKeyspace(getKeyspaceName()))
topPartitions = null;
else
- topPartitions = new TopPartitionTracker(metadata());
+ topPartitions = new TopPartitionTracker(initMetadata);
}
public static String getTableMBeanName(String ks, String name, boolean isIndex)
@@ -741,32 +750,31 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
}
- public static ColumnFamilyStore createColumnFamilyStore(Keyspace keyspace, TableMetadataRef metadata, boolean loadSSTables)
+ public static ColumnFamilyStore createColumnFamilyStore(Keyspace keyspace, TableMetadata metadata, boolean loadSSTables)
{
return createColumnFamilyStore(keyspace, metadata.name, metadata, loadSSTables);
}
public static ColumnFamilyStore createColumnFamilyStore(Keyspace keyspace,
- String columnFamily,
- TableMetadataRef metadata,
- boolean loadSSTables)
+ String columnFamily,
+ TableMetadata metadata,
+ boolean loadSSTables)
{
- Directories directories = new Directories(metadata.get());
- return createColumnFamilyStore(keyspace, columnFamily, metadata, directories, loadSSTables, true, false);
+ Directories directories = new Directories(metadata);
+ return createColumnFamilyStore(keyspace, columnFamily, metadata, directories, loadSSTables, true);
}
/** This is only directly used by offline tools */
public static synchronized ColumnFamilyStore createColumnFamilyStore(Keyspace keyspace,
String columnFamily,
- TableMetadataRef metadata,
+ TableMetadata metadata,
Directories directories,
boolean loadSSTables,
- boolean registerBookkeeping,
- boolean offline)
+ boolean registerBookkeeping)
{
return new ColumnFamilyStore(keyspace, columnFamily,
directories.getUIDGenerator(SSTableIdFactory.instance.defaultBuilder()),
- metadata, directories, loadSSTables, registerBookkeeping, offline);
+ metadata, directories, loadSSTables, registerBookkeeping);
}
/**
@@ -1476,9 +1484,9 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
public static class VersionedLocalRanges extends ArrayList<Splitter.WeightedRange>
{
- public final long ringVersion;
+ public final Epoch ringVersion;
- public VersionedLocalRanges(long ringVersion, int initialSize)
+ public VersionedLocalRanges(Epoch ringVersion, int initialSize)
{
super(initialSize);
this.ringVersion = ringVersion;
@@ -1487,16 +1495,16 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
public VersionedLocalRanges localRangesWeighted()
{
+ ClusterMetadata metadata = ClusterMetadata.current();
if (!SchemaConstants.isLocalSystemKeyspace(getKeyspaceName())
- && getPartitioner() == StorageService.instance.getTokenMetadata().partitioner)
+ && getPartitioner() == metadata.partitioner)
{
DiskBoundaryManager.VersionedRangesAtEndpoint versionedLocalRanges = DiskBoundaryManager.getVersionedLocalRanges(this);
Set<Range<Token>> localRanges = versionedLocalRanges.rangesAtEndpoint.ranges();
- long ringVersion = versionedLocalRanges.ringVersion;
-
+ Epoch epoch = versionedLocalRanges.epoch;
if (!localRanges.isEmpty())
{
- VersionedLocalRanges weightedRanges = new VersionedLocalRanges(ringVersion, localRanges.size());
+ VersionedLocalRanges weightedRanges = new VersionedLocalRanges(epoch, localRanges.size());
for (Range<Token> r : localRanges)
{
// WeightedRange supports only unwrapped ranges as it relies
@@ -1509,7 +1517,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
}
else
{
- return fullWeightedRange(ringVersion, getPartitioner());
+ return fullWeightedRange(epoch, getPartitioner());
}
}
else
@@ -1527,11 +1535,13 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
return ShardBoundaries.NONE;
ShardBoundaries shardBoundaries = cachedShardBoundaries;
+ ClusterMetadata metadata = ClusterMetadata.currentNullable();
+ if (metadata == null)
+ return ShardBoundaries.NONE;
if (shardBoundaries == null ||
shardBoundaries.shardCount() != shardCount ||
- (shardBoundaries.ringVersion != RING_VERSION_IRRELEVANT &&
- shardBoundaries.ringVersion != StorageService.instance.getTokenMetadata().getRingVersion()))
+ (!shardBoundaries.epoch.equals(Epoch.EMPTY) && !shardBoundaries.epoch.equals(metadata.epoch)))
{
VersionedLocalRanges weightedRanges = localRangesWeighted();
@@ -1545,9 +1555,9 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
}
@VisibleForTesting
- public static VersionedLocalRanges fullWeightedRange(long ringVersion, IPartitioner partitioner)
+ public static VersionedLocalRanges fullWeightedRange(Epoch epoch, IPartitioner partitioner)
{
- VersionedLocalRanges ranges = new VersionedLocalRanges(ringVersion, 1);
+ VersionedLocalRanges ranges = new VersionedLocalRanges(epoch, 1);
ranges.add(new Splitter.WeightedRange(1.0, new Range<>(partitioner.getMinimumToken(), partitioner.getMinimumToken())));
return ranges;
}
@@ -3341,7 +3351,12 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
public DiskBoundaries getDiskBoundaries()
{
- return diskBoundaryManager.getDiskBoundaries(this);
+ return diskBoundaryManager.getDiskBoundaries(this, metadata.get());
+ }
+
+ public DiskBoundaries getDiskBoundaries(TableMetadata initialMetadata)
+ {
+ return diskBoundaryManager.getDiskBoundaries(this, initialMetadata);
}
public void invalidateLocalRanges()
diff --git a/src/java/org/apache/cassandra/db/CounterMutationVerbHandler.java b/src/java/org/apache/cassandra/db/CounterMutationVerbHandler.java
index e4c7669806..2fef53a993 100644
--- a/src/java/org/apache/cassandra/db/CounterMutationVerbHandler.java
+++ b/src/java/org/apache/cassandra/db/CounterMutationVerbHandler.java
@@ -21,20 +21,20 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.net.IVerbHandler;
+import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.net.Message;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.service.StorageProxy;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
-public class CounterMutationVerbHandler implements IVerbHandler<CounterMutation>
+public class CounterMutationVerbHandler extends AbstractMutationVerbHandler<CounterMutation>
{
public static final CounterMutationVerbHandler instance = new CounterMutationVerbHandler();
private static final Logger logger = LoggerFactory.getLogger(CounterMutationVerbHandler.class);
- public void doVerb(final Message<CounterMutation> message)
+ protected void applyMutation(final Message<CounterMutation> message, InetAddressAndPort respondToAddress)
{
long queryStartNanoTime = nanoTime();
final CounterMutation cm = message.payload;
@@ -50,7 +50,7 @@ public class CounterMutationVerbHandler implements IVerbHandler<CounterMutation>
// it's own in that case.
StorageProxy.applyCounterMutationOnLeader(cm,
localDataCenter,
- () -> MessagingService.instance().send(message.emptyResponse(), message.from()),
+ () -> MessagingService.instance().send(message.emptyResponse(), respondToAddress),
queryStartNanoTime);
}
}
diff --git a/src/java/org/apache/cassandra/db/DiskBoundaries.java b/src/java/org/apache/cassandra/db/DiskBoundaries.java
index 7fe10f4c13..75868e35e6 100644
--- a/src/java/org/apache/cassandra/db/DiskBoundaries.java
+++ b/src/java/org/apache/cassandra/db/DiskBoundaries.java
@@ -27,28 +27,32 @@ import com.google.common.collect.ImmutableList;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.format.SSTableReader;
-import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.Epoch;
public class DiskBoundaries
{
public final List<Directories.DataDirectory> directories;
public final ImmutableList<PartitionPosition> positions;
- final long ringVersion;
+ final Epoch epoch;
final int directoriesVersion;
private final ColumnFamilyStore cfs;
private volatile boolean isInvalid = false;
public DiskBoundaries(ColumnFamilyStore cfs, Directories.DataDirectory[] directories, int diskVersion)
{
- this(cfs, directories, null, -1, diskVersion);
+ this(cfs, directories, null, Epoch.EMPTY, diskVersion);
}
@VisibleForTesting
- public DiskBoundaries(ColumnFamilyStore cfs, Directories.DataDirectory[] directories, List<PartitionPosition> positions, long ringVersion, int diskVersion)
+ public DiskBoundaries(ColumnFamilyStore cfs,
+ Directories.DataDirectory[] directories,
+ List<PartitionPosition> positions,
+ Epoch epoch,
+ int diskVersion)
{
this.directories = directories == null ? null : ImmutableList.copyOf(directories);
this.positions = positions == null ? null : ImmutableList.copyOf(positions);
- this.ringVersion = ringVersion;
+ this.epoch = epoch;
this.directoriesVersion = diskVersion;
this.cfs = cfs;
}
@@ -60,7 +64,7 @@ public class DiskBoundaries
DiskBoundaries that = (DiskBoundaries) o;
- if (ringVersion != that.ringVersion) return false;
+ if (!epoch.equals(that.epoch)) return false;
if (directoriesVersion != that.directoriesVersion) return false;
if (!directories.equals(that.directories)) return false;
return positions != null ? positions.equals(that.positions) : that.positions == null;
@@ -70,7 +74,7 @@ public class DiskBoundaries
{
int result = directories != null ? directories.hashCode() : 0;
result = 31 * result + (positions != null ? positions.hashCode() : 0);
- result = 31 * result + (int) (ringVersion ^ (ringVersion >>> 32));
+ result = 31 * result + epoch.hashCode();
result = 31 * result + directoriesVersion;
return result;
}
@@ -80,7 +84,7 @@ public class DiskBoundaries
return "DiskBoundaries{" +
"directories=" + directories +
", positions=" + positions +
- ", ringVersion=" + ringVersion +
+ ", epoch=" + epoch +
", directoriesVersion=" + directoriesVersion +
'}';
}
@@ -93,8 +97,7 @@ public class DiskBoundaries
if (isInvalid)
return true;
int currentDiskVersion = DisallowedDirectories.getDirectoriesVersion();
- long currentRingVersion = StorageService.instance.getTokenMetadata().getRingVersion();
- return currentDiskVersion != directoriesVersion || (ringVersion != -1 && currentRingVersion != ringVersion);
+ return currentDiskVersion != directoriesVersion;
}
public void invalidate()
diff --git a/src/java/org/apache/cassandra/db/DiskBoundaryManager.java b/src/java/org/apache/cassandra/db/DiskBoundaryManager.java
index 7857d0cff8..13d1585858 100644
--- a/src/java/org/apache/cassandra/db/DiskBoundaryManager.java
+++ b/src/java/org/apache/cassandra/db/DiskBoundaryManager.java
@@ -31,9 +31,12 @@ import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Splitter;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.locator.RangesAtEndpoint;
-import org.apache.cassandra.locator.TokenMetadata;
-import org.apache.cassandra.service.PendingRangeCalculatorService;
+import org.apache.cassandra.tcm.ClusterMetadataService;
+import org.apache.cassandra.tcm.Epoch;
+import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.ownership.DataPlacement;
import org.apache.cassandra.utils.FBUtilities;
public class DiskBoundaryManager
@@ -43,18 +46,24 @@ public class DiskBoundaryManager
public DiskBoundaries getDiskBoundaries(ColumnFamilyStore cfs)
{
- if (!cfs.getPartitioner().splitter().isPresent())
+ return getDiskBoundaries(cfs, cfs.metadata());
+ }
+
+ public DiskBoundaries getDiskBoundaries(ColumnFamilyStore cfs, TableMetadata metadata)
+ {
+ if (!metadata.partitioner.splitter().isPresent())
return new DiskBoundaries(cfs, cfs.getDirectories().getWriteableLocations(), DisallowedDirectories.getDirectoriesVersion());
+
if (diskBoundaries == null || diskBoundaries.isOutOfDate())
{
synchronized (this)
{
if (diskBoundaries == null || diskBoundaries.isOutOfDate())
{
- logger.debug("Refreshing disk boundary cache for {}.{}", cfs.getKeyspaceName(), cfs.getTableName());
+ logger.trace("Refreshing disk boundary cache for {}.{}", cfs.getKeyspaceName(), cfs.getTableName());
DiskBoundaries oldBoundaries = diskBoundaries;
- diskBoundaries = getDiskBoundaryValue(cfs);
- logger.debug("Updating boundaries from {} to {} for {}.{}", oldBoundaries, diskBoundaries, cfs.getKeyspaceName(), cfs.getTableName());
+ diskBoundaries = getDiskBoundaryValue(cfs, metadata.partitioner);
+ logger.trace("Updating boundaries from {} to {} for {}.{}", oldBoundaries, diskBoundaries, cfs.getKeyspaceName(), cfs.getTableName());
}
}
}
@@ -70,12 +79,12 @@ public class DiskBoundaryManager
static class VersionedRangesAtEndpoint
{
public final RangesAtEndpoint rangesAtEndpoint;
- public final long ringVersion;
+ public final Epoch epoch;
- VersionedRangesAtEndpoint(RangesAtEndpoint rangesAtEndpoint, long ringVersion)
+ VersionedRangesAtEndpoint(RangesAtEndpoint rangesAtEndpoint, Epoch epoch)
{
this.rangesAtEndpoint = rangesAtEndpoint;
- this.ringVersion = ringVersion;
+ this.epoch = epoch;
}
}
@@ -83,26 +92,35 @@ public class DiskBoundaryManager
{
RangesAtEndpoint localRanges;
- long ringVersion;
- TokenMetadata tmd;
+ Epoch epoch;
+ ClusterMetadata metadata;
do
{
- tmd = StorageService.instance.getTokenMetadata();
- ringVersion = tmd.getRingVersion();
- localRanges = getLocalRanges(cfs, tmd);
- logger.debug("Got local ranges {} (ringVersion = {})", localRanges, ringVersion);
+ metadata = ClusterMetadata.current();
+ epoch = metadata.epoch;
+ localRanges = getLocalRanges(cfs, metadata);
+ logger.debug("Got local ranges {} (epoch = {})", localRanges, epoch);
}
- while (ringVersion != tmd.getRingVersion()); // if ringVersion is different here it means that
- // it might have changed before we calculated localRanges - recalculate
-
- return new VersionedRangesAtEndpoint(localRanges, ringVersion);
+ while (!metadata.epoch.equals(ClusterMetadata.current().epoch)); // if epoch is different here it means that
+ // it might have changed before we calculated localRanges - recalculate
+ return new VersionedRangesAtEndpoint(localRanges, epoch);
}
- private static DiskBoundaries getDiskBoundaryValue(ColumnFamilyStore cfs)
+ private static DiskBoundaries getDiskBoundaryValue(ColumnFamilyStore cfs, IPartitioner partitioner)
{
- VersionedRangesAtEndpoint rangesAtEndpoint = getVersionedLocalRanges(cfs);
- RangesAtEndpoint localRanges = rangesAtEndpoint.rangesAtEndpoint;
- long ringVersion = rangesAtEndpoint.ringVersion;
+ if (ClusterMetadataService.instance() == null)
+ return new DiskBoundaries(cfs, cfs.getDirectories().getWriteableLocations(), null, Epoch.EMPTY, DisallowedDirectories.getDirectoriesVersion());
+
+ RangesAtEndpoint localRanges;
+
+ ClusterMetadata metadata;
+ do
+ {
+ metadata = ClusterMetadata.current();
+ localRanges = getLocalRanges(cfs, metadata);
+ logger.debug("Got local ranges {} (epoch = {})", localRanges, metadata.epoch);
+ }
+ while (metadata.epoch != ClusterMetadata.current().epoch);
int directoriesVersion;
Directories.DataDirectory[] dirs;
@@ -114,29 +132,31 @@ public class DiskBoundaryManager
while (directoriesVersion != DisallowedDirectories.getDirectoriesVersion()); // if directoriesVersion has changed we need to recalculate
if (localRanges == null || localRanges.isEmpty())
- return new DiskBoundaries(cfs, dirs, null, ringVersion, directoriesVersion);
+ return new DiskBoundaries(cfs, dirs, null, metadata.epoch, directoriesVersion);
- List<PartitionPosition> positions = getDiskBoundaries(localRanges, cfs.getPartitioner(), dirs);
+ List<PartitionPosition> positions = getDiskBoundaries(localRanges, partitioner, dirs);
- return new DiskBoundaries(cfs, dirs, positions, ringVersion, directoriesVersion);
+ return new DiskBoundaries(cfs, dirs, positions, metadata.epoch, directoriesVersion);
}
- private static RangesAtEndpoint getLocalRanges(ColumnFamilyStore cfs, TokenMetadata tmd)
+
+ private static RangesAtEndpoint getLocalRanges(ColumnFamilyStore cfs, ClusterMetadata metadata)
{
RangesAtEndpoint localRanges;
+ DataPlacement placement;
if (StorageService.instance.isBootstrapMode()
- && !StorageService.isReplacingSameAddress()) // When replacing same address, the node marks itself as UN locally
+ && !StorageService.isReplacingSameAddress()) // When replacing same address, the node marks itself as UN locally
{
- PendingRangeCalculatorService.instance.blockUntilFinished();
- localRanges = tmd.getPendingRanges(cfs.getKeyspaceName(), FBUtilities.getBroadcastAddressAndPort());
+ placement = metadata.placements.get(cfs.keyspace.getMetadata().params.replication);
}
else
{
- // Reason we use use the future settled TMD is that if we decommission a node, we want to stream
+ // Reason we use use the future settled metadata is that if we decommission a node, we want to stream
// from that node to the correct location on disk, if we didn't, we would put new files in the wrong places.
// We do this to minimize the amount of data we need to move in rebalancedisks once everything settled
- localRanges = cfs.keyspace.getReplicationStrategy().getAddressReplicas(tmd.cloneAfterAllSettled(), FBUtilities.getBroadcastAddressAndPort());
+ placement = metadata.writePlacementAllSettled(cfs.keyspace.getMetadata());
}
+ localRanges = placement.writes.byEndpoint().get(FBUtilities.getBroadcastAddressAndPort());
return localRanges;
}
diff --git a/src/java/org/apache/cassandra/db/Keyspace.java b/src/java/org/apache/cassandra/db/Keyspace.java
index a06c7e137a..ded130f8cc 100644
--- a/src/java/org/apache/cassandra/db/Keyspace.java
+++ b/src/java/org/apache/cassandra/db/Keyspace.java
@@ -56,13 +56,11 @@ import org.apache.cassandra.locator.AbstractReplicationStrategy;
import org.apache.cassandra.metrics.KeyspaceMetrics;
import org.apache.cassandra.repair.KeyspaceRepairManager;
import org.apache.cassandra.schema.KeyspaceMetadata;
-import org.apache.cassandra.schema.ReplicationParams;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.schema.TableMetadataRef;
import org.apache.cassandra.service.snapshot.TableSnapshot;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.ByteBufferUtil;
@@ -91,6 +89,7 @@ public class Keyspace
private static int TEST_FAIL_MV_LOCKS_COUNT = CassandraRelevantProperties.TEST_FAIL_MV_LOCKS_COUNT.getInt();
public final KeyspaceMetrics metric;
+ public final KeyspaceMetadataRef metadataRef;
// It is possible to call Keyspace.open without a running daemon, so it makes sense to ensure
// proper directories here as well as in CassandraDaemon.
@@ -100,8 +99,6 @@ public class Keyspace
DatabaseDescriptor.createAllDirectories();
}
- private volatile KeyspaceMetadata metadata;
-
//OpOrder is defined globally since we need to order writes across
//Keyspaces in the case of Views (batchlog of view mutations)
public static final OpOrder writeOrder = new OpOrder();
@@ -109,12 +106,11 @@ public class Keyspace
/* ColumnFamilyStore per column family */
private final ConcurrentMap<TableId, ColumnFamilyStore> columnFamilyStores = new ConcurrentHashMap<>();
- private volatile AbstractReplicationStrategy replicationStrategy;
public final ViewManager viewManager;
private final KeyspaceWriteHandler writeHandler;
- private volatile ReplicationParams replicationParams;
private final KeyspaceRepairManager repairManager;
private final SchemaProvider schema;
+ private final String name;
private static volatile boolean initialized = false;
@@ -148,23 +144,15 @@ public class Keyspace
public static Keyspace open(String keyspaceName)
{
assert initialized || SchemaConstants.isLocalSystemKeyspace(keyspaceName) : "Initialized: " + initialized;
- return open(keyspaceName, Schema.instance, true);
+ Keyspace ks = Schema.instance.getKeyspaceInstance(keyspaceName);
+ assert ks != null : "Unknown keyspace " + keyspaceName;
+ return ks;
}
// to only be used by org.apache.cassandra.tools.Standalone* classes
public static Keyspace openWithoutSSTables(String keyspaceName)
{
- return open(keyspaceName, Schema.instance, false);
- }
-
- public static Keyspace open(String keyspaceName, SchemaProvider schema, boolean loadSSTables)
- {
- return schema.maybeAddKeyspaceInstance(keyspaceName, () -> new Keyspace(keyspaceName, schema, loadSSTables));
- }
-
- public static ColumnFamilyStore openAndGetStore(TableMetadataRef tableRef)
- {
- return open(tableRef.keyspace).getColumnFamilyStore(tableRef.id);
+ return Schema.instance.getKeyspaceInstance(keyspaceName);
}
public static ColumnFamilyStore openAndGetStore(TableMetadata table)
@@ -188,15 +176,9 @@ public class Keyspace
}
}
- public void setMetadata(KeyspaceMetadata metadata)
- {
- this.metadata = metadata;
- createReplicationStrategy(metadata);
- }
-
public KeyspaceMetadata getMetadata()
{
- return metadata;
+ return metadataRef.get();
}
public Collection<ColumnFamilyStore> getColumnFamilyStores()
@@ -216,7 +198,7 @@ public class Keyspace
{
ColumnFamilyStore cfs = columnFamilyStores.get(id);
if (cfs == null)
- throw new IllegalArgumentException("Unknown CF " + id);
+ throw new IllegalArgumentException(String.format("Unknown CF %s %s", id, columnFamilyStores));
return cfs;
}
@@ -317,38 +299,53 @@ public class Keyspace
return getColumnFamilyStores().stream().flatMap(cfs -> cfs.listSnapshots().values().stream());
}
+ public static Keyspace forSchema(String keyspaceName, SchemaProvider schema)
+ {
+ return new Keyspace(keyspaceName, schema, true);
+ }
+
private Keyspace(String keyspaceName, SchemaProvider schema, boolean loadSSTables)
+ {
+ this(schema, schema.getKeyspaceMetadata(keyspaceName), loadSSTables);
+ }
+
+ public Keyspace(SchemaProvider schema, KeyspaceMetadata metadata, boolean loadSSTables)
{
this.schema = schema;
- metadata = schema.getKeyspaceMetadata(keyspaceName);
- assert metadata != null : "Unknown keyspace " + keyspaceName;
-
+ this.name = metadata.name;
+
+ assert metadata != null : "Unknown keyspace " + metadata.name;
+
if (metadata.isVirtual())
- throw new IllegalStateException("Cannot initialize Keyspace with virtual metadata " + keyspaceName);
- createReplicationStrategy(metadata);
+ throw new IllegalStateException("Cannot initialize Keyspace with virtual metadata " + metadata.name);
this.metric = new KeyspaceMetrics(this);
this.viewManager = new ViewManager(this);
+
+ this.metadataRef = new KeyspaceMetadataRef(metadata, schema);
for (TableMetadata cfm : metadata.tablesAndViews())
{
logger.trace("Initializing {}.{}", getName(), cfm.name);
- initCf(schema.getTableMetadataRef(cfm.id), loadSSTables);
+ initCf(cfm, loadSSTables);
}
- this.viewManager.reload(false);
+
+ this.viewManager.reload(metadata);
+ this.metadataRef.unsetInitial();
this.repairManager = new CassandraKeyspaceRepairManager(this);
this.writeHandler = new CassandraKeyspaceWriteHandler(this);
}
- private Keyspace(KeyspaceMetadata metadata)
+ public Keyspace(KeyspaceMetadata metadata)
{
this.schema = Schema.instance;
- this.metadata = metadata;
- createReplicationStrategy(metadata);
+ this.name = metadata.name;
+
this.metric = new KeyspaceMetrics(this);
this.viewManager = new ViewManager(this);
this.repairManager = new CassandraKeyspaceRepairManager(this);
this.writeHandler = new CassandraKeyspaceWriteHandler(this);
+ this.metadataRef = new KeyspaceMetadataRef(metadata, schema);
}
public KeyspaceRepairManager getRepairManager()
@@ -361,18 +358,6 @@ public class Keyspace
return new Keyspace(metadata);
}
- private void createReplicationStrategy(KeyspaceMetadata ksm)
- {
- logger.info("Creating replication strategy " + ksm.name + " params " + ksm.params);
- replicationStrategy = ksm.createReplicationStrategy();
- if (!ksm.params.replication.equals(replicationParams))
- {
- logger.debug("New replication settings for keyspace {} - invalidating disk boundary caches", ksm.name);
- columnFamilyStores.values().forEach(ColumnFamilyStore::invalidateLocalRanges);
- }
- replicationParams = ksm.params.replication;
- }
-
// best invoked on the compaction manager.
public void dropCf(TableId tableId, boolean dropData)
{
@@ -433,7 +418,7 @@ public class Keyspace
/**
* adds a cf to internal structures, ends up creating disk files).
*/
- public void initCf(TableMetadataRef metadata, boolean loadSSTables)
+ public void initCf(TableMetadata metadata, boolean loadSSTables)
{
ColumnFamilyStore cfs = columnFamilyStores.get(metadata.id);
@@ -442,7 +427,8 @@ public class Keyspace
// CFS being created for the first time, either on server startup or new CF being added.
// We don't worry about races here; startup is safe, and adding multiple idential CFs
// simultaneously is a "don't do that" scenario.
- ColumnFamilyStore oldCfs = columnFamilyStores.putIfAbsent(metadata.id, ColumnFamilyStore.createColumnFamilyStore(this, metadata, loadSSTables));
+ ColumnFamilyStore oldCfs = columnFamilyStores.putIfAbsent(metadata.id,
+ ColumnFamilyStore.createColumnFamilyStore(this, metadata, loadSSTables));
// CFS mbean instantiation will error out before we hit this, but in case that changes...
if (oldCfs != null)
throw new IllegalStateException("added multiple mappings for cf id " + metadata.id);
@@ -452,7 +438,7 @@ public class Keyspace
// re-initializing an existing CF. This will happen if you cleared the schema
// on this node and it's getting repopulated from the rest of the cluster.
assert cfs.name.equals(metadata.name);
- cfs.reload();
+ cfs.reload(metadata);
}
}
@@ -514,7 +500,7 @@ public class Keyspace
boolean isDeferrable,
Promise<?> future)
{
- if (TEST_FAIL_WRITES && metadata.name.equals(TEST_FAIL_WRITES_KS))
+ if (TEST_FAIL_WRITES && getMetadata().name.equals(TEST_FAIL_WRITES_KS))
throw new RuntimeException("Testing write failures");
Lock[] locks = null;
@@ -626,7 +612,7 @@ public class Keyspace
try
{
Tracing.trace("Creating materialized view mutations from base table replica");
- viewManager.forTable(upd.metadata().id).pushViewReplicaUpdates(upd, makeDurable, baseComplete);
+ viewManager.forTable(upd.metadata()).pushViewReplicaUpdates(upd, makeDurable, baseComplete);
}
catch (Throwable t)
{
@@ -661,7 +647,7 @@ public class Keyspace
public AbstractReplicationStrategy getReplicationStrategy()
{
- return replicationStrategy;
+ return getMetadata().replicationStrategy;
}
public List<Future<?>> flush(ColumnFamilyStore.FlushReason reason)
@@ -749,6 +735,11 @@ public class Keyspace
return Schema.instance.getKeyspaces().stream().map(Schema.instance::getKeyspaceInstance).filter(Objects::nonNull);
}
+ public static Iterable<Keyspace> nonSystem()
+ {
+ return Iterables.transform(Schema.instance.distributedKeyspaces().names(), Keyspace::open);
+ }
+
public static Iterable<Keyspace> nonLocalStrategy()
{
return Iterables.transform(Schema.instance.distributedKeyspaces().names(), Keyspace::open);
@@ -767,6 +758,37 @@ public class Keyspace
public String getName()
{
- return metadata.name;
+ return name;
+ }
+
+ private static class KeyspaceMetadataRef
+ {
+ // We need "initial" keyspace metadata for initCF to run, due to circular dependency
+ // between keyspace keyspace -> column family -> keyspace metadata. There are some
+ // calls within initCF that try accessing keyspace metadata, which requires the metadata
+ // of initializing keyspace to already be visible via ClusterMetadata#schema.
+ private KeyspaceMetadata initial;
+
+ private final String name;
+ private final SchemaProvider provider;
+
+ public KeyspaceMetadataRef(KeyspaceMetadata initial, SchemaProvider provider)
+ {
+ this.initial = initial;
+ this.name = initial.name;
+ this.provider = provider;
+ }
+
+ public KeyspaceMetadata get()
+ {
+ if (initial != null)
+ return initial;
+ return provider.getKeyspaceMetadata(name);
+ }
+
+ public void unsetInitial()
+ {
+ this.initial = null;
+ }
}
}
diff --git a/src/java/org/apache/cassandra/db/MutationVerbHandler.java b/src/java/org/apache/cassandra/db/MutationVerbHandler.java
index 1ab6711fdb..62b762f069 100644
--- a/src/java/org/apache/cassandra/db/MutationVerbHandler.java
+++ b/src/java/org/apache/cassandra/db/MutationVerbHandler.java
@@ -24,7 +24,7 @@ import org.apache.cassandra.tracing.Tracing;
import static org.apache.cassandra.db.commitlog.CommitLogSegment.ENTRY_OVERHEAD_SIZE;
-public class MutationVerbHandler implements IVerbHandler<Mutation>
+public class MutationVerbHandler extends AbstractMutationVerbHandler<Mutation>
{
public static final MutationVerbHandler instance = new MutationVerbHandler();
@@ -51,7 +51,7 @@ public class MutationVerbHandler implements IVerbHandler<Mutation>
InetAddressAndPort respondToAddress = message.respondTo();
try
{
- message.payload.applyFuture().addCallback(o -> respond(message, respondToAddress), wto -> failed());
+ processMessage(message, respondToAddress);
}
catch (WriteTimeoutException wto)
{
@@ -59,6 +59,11 @@ public class MutationVerbHandler implements IVerbHandler<Mutation>
}
}
+ protected void applyMutation(Message<Mutation> message, InetAddressAndPort respondToAddress)
+ {
+ message.payload.applyFuture().addCallback(o -> respond(message, respondToAddress), wto -> failed());
+ }
+
private static void forwardToLocalNodes(Message<Mutation> originalMessage, ForwardingInfo forwardTo)
{
Message.Builder<Mutation> builder =
diff --git a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
index 7aa1e01b6a..4a08c23542 100644
--- a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
+++ b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
@@ -53,6 +53,7 @@ import org.apache.cassandra.net.Verb;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.StorageProxy;
+import org.apache.cassandra.tcm.Epoch;
import org.apache.cassandra.tracing.Tracing;
/**
@@ -65,25 +66,27 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
protected final DataRange dataRange;
protected final Slices requestedSlices;
- private PartitionRangeReadCommand(boolean isDigest,
- int digestVersion,
- boolean acceptsTransient,
- TableMetadata metadata,
- long nowInSec,
- ColumnFilter columnFilter,
- RowFilter rowFilter,
- DataLimits limits,
- DataRange dataRange,
- Index.QueryPlan indexQueryPlan,
- boolean trackWarnings)
- {
- super(Kind.PARTITION_RANGE, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
+ @VisibleForTesting
+ protected PartitionRangeReadCommand(Epoch serializedAtEpoch,
+ boolean isDigest,
+ int digestVersion,
+ boolean acceptsTransient,
+ TableMetadata metadata,
+ long nowInSec,
+ ColumnFilter columnFilter,
+ RowFilter rowFilter,
+ DataLimits limits,
+ DataRange dataRange,
+ Index.QueryPlan indexQueryPlan,
+ boolean trackWarnings)
+ {
+ super(serializedAtEpoch, Kind.PARTITION_RANGE, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
this.dataRange = dataRange;
this.requestedSlices = dataRange.clusteringIndexFilter.getSlices(metadata());
-
}
- private static PartitionRangeReadCommand create(boolean isDigest,
+ private static PartitionRangeReadCommand create(Epoch serializedAtEpoch,
+ boolean isDigest,
int digestVersion,
boolean acceptsTransient,
TableMetadata metadata,
@@ -109,7 +112,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
indexQueryPlan,
trackWarnings);
}
- return new PartitionRangeReadCommand(isDigest,
+ return new PartitionRangeReadCommand(serializedAtEpoch,
+ isDigest,
digestVersion,
acceptsTransient,
metadata,
@@ -129,7 +133,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
DataLimits limits,
DataRange dataRange)
{
- return create(false,
+ return create(metadata.epoch,
+ false,
0,
false,
metadata,
@@ -152,7 +157,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
*/
public static PartitionRangeReadCommand allDataRead(TableMetadata metadata, long nowInSec)
{
- return create(false,
+ return create(metadata.epoch,
+ false,
0,
false,
metadata,
@@ -202,7 +208,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
// DataLimits.CQLGroupByLimits.GroupByAwareCounter assumes that if GroupingState.hasClustering(), then we're in
// the middle of a group, but we can't make that assumption if we query and range "in advance" of where we are
// on the ring.
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -217,7 +224,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
public PartitionRangeReadCommand copy()
{
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -233,7 +241,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
@Override
protected PartitionRangeReadCommand copyAsDigestQuery()
{
- return create(true,
+ return create(serializedAtEpoch(),
+ true,
digestVersion(),
false,
metadata(),
@@ -249,7 +258,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
@Override
protected PartitionRangeReadCommand copyAsTransientQuery()
{
- return create(false,
+ return create(serializedAtEpoch(),
+ false,
0,
true,
metadata(),
@@ -265,7 +275,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
@Override
public PartitionRangeReadCommand withUpdatedLimit(DataLimits newLimits)
{
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -281,7 +292,8 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
@Override
public PartitionRangeReadCommand withUpdatedLimitsAndDataRange(DataLimits newLimits, DataRange newDataRange)
{
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -515,6 +527,7 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
{
public ReadCommand deserialize(DataInputPlus in,
int version,
+ Epoch serializedAtEpoch,
boolean isDigest,
int digestVersion,
boolean acceptsTransient,
@@ -527,7 +540,7 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
throws IOException
{
DataRange range = DataRange.serializer.deserialize(in, version, metadata);
- return PartitionRangeReadCommand.create(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, range, indexQueryPlan, false);
+ return PartitionRangeReadCommand.create(serializedAtEpoch, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, range, indexQueryPlan, false);
}
}
@@ -545,7 +558,7 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
Index.QueryPlan indexQueryPlan,
boolean trackWarnings)
{
- super(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, dataRange, indexQueryPlan, trackWarnings);
+ super(metadata.epoch, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, dataRange, indexQueryPlan, trackWarnings);
}
@Override
diff --git a/src/java/org/apache/cassandra/db/ReadCommand.java b/src/java/org/apache/cassandra/db/ReadCommand.java
index b8ac0a2229..84cc9bfa24 100644
--- a/src/java/org/apache/cassandra/db/ReadCommand.java
+++ b/src/java/org/apache/cassandra/db/ReadCommand.java
@@ -38,7 +38,10 @@ import org.slf4j.LoggerFactory;
import io.netty.util.concurrent.FastThreadLocal;
import org.apache.cassandra.config.*;
import org.apache.cassandra.db.filter.*;
+import org.apache.cassandra.exceptions.CoordinatorBehindException;
import org.apache.cassandra.exceptions.QueryCancelledException;
+import org.apache.cassandra.exceptions.UnknownTableException;
+import org.apache.cassandra.metrics.TCMMetrics;
import org.apache.cassandra.net.MessageFlag;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.net.ParamType;
@@ -67,9 +70,12 @@ import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.service.ActiveRepairService;
import org.apache.cassandra.service.ClientWarn;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.CassandraUInt;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.NoSpamLogger;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.TimeUUID;
@@ -100,6 +106,7 @@ public abstract class ReadCommand extends AbstractReadQuery
private final boolean isDigestQuery;
private final boolean acceptsTransient;
+ private final Epoch serializedAtEpoch;
// if a digest query, the version for which the digest is expected. Ignored if not a digest.
private int digestVersion;
@@ -112,6 +119,7 @@ public abstract class ReadCommand extends AbstractReadQuery
{
public abstract ReadCommand deserialize(DataInputPlus in,
int version,
+ Epoch serializedAtEpoch,
boolean isDigest,
int digestVersion,
boolean acceptsTransient,
@@ -136,7 +144,8 @@ public abstract class ReadCommand extends AbstractReadQuery
}
}
- protected ReadCommand(Kind kind,
+ protected ReadCommand(Epoch serializedAtEpoch,
+ Kind kind,
boolean isDigestQuery,
int digestVersion,
boolean acceptsTransient,
@@ -158,6 +167,7 @@ public abstract class ReadCommand extends AbstractReadQuery
this.acceptsTransient = acceptsTransient;
this.indexQueryPlan = indexQueryPlan;
this.trackWarnings = trackWarnings;
+ this.serializedAtEpoch = serializedAtEpoch;
}
public static ReadCommand getCommand()
@@ -197,6 +207,15 @@ public abstract class ReadCommand extends AbstractReadQuery
return isDigestQuery;
}
+ /**
+ * the schema version on the table when serializing this read command
+ * @return
+ */
+ public Epoch serializedAtEpoch()
+ {
+ return serializedAtEpoch;
+ }
+
/**
* If the query is a digest one, the requested digest version.
*
@@ -1011,6 +1030,11 @@ public abstract class ReadCommand extends AbstractReadQuery
@VisibleForTesting
public static class Serializer implements IVersionedSerializer<ReadCommand>
{
+ private static final NoSpamLogger noSpamLogger = NoSpamLogger.getLogger(logger, 10L, TimeUnit.SECONDS);
+ private static final NoSpamLogger.NoSpamLogStatement schemaMismatchStmt =
+ noSpamLogger.getStatement("Schema epoch mismatch during read command deserialization. " +
+ "TableId: {}, remote epoch: {}, local epoch: {}", 10L, TimeUnit.SECONDS);
+
private final SchemaProvider schema;
public Serializer()
@@ -1075,6 +1099,8 @@ public abstract class ReadCommand extends AbstractReadQuery
if (command.isDigestQuery())
out.writeUnsignedVInt32(command.digestVersion());
command.metadata().id.serialize(out);
+ if (version >= MessagingService.VERSION_50)
+ Epoch.serializer.serialize(command.serializedAtEpoch, out);
out.writeInt(version >= MessagingService.VERSION_50 ? CassandraUInt.fromLong(command.nowInSec()) : (int) command.nowInSec());
ColumnFilter.serializer.serialize(command.columnFilter(), out, version);
RowFilter.serializer.serialize(command.rowFilter(), out, version);
@@ -1098,28 +1124,47 @@ public abstract class ReadCommand extends AbstractReadQuery
// better complain loudly than doing the wrong thing.
if (isForThrift(flags))
throw new IllegalStateException("Received a command with the thrift flag set. "
- + "This means thrift is in use in a mixed 3.0/3.X and 4.0+ cluster, "
- + "which is unsupported. Make sure to stop using thrift before "
- + "upgrading to 4.0");
+ + "This means thrift is in use in a mixed 3.0/3.X and 4.0+ cluster, "
+ + "which is unsupported. Make sure to stop using thrift before "
+ + "upgrading to 4.0");
boolean hasIndex = hasIndex(flags);
- int digestVersion = isDigest ? in.readUnsignedVInt32() : 0;
- TableMetadata metadata = schema.getExistingTableMetadata(TableId.deserialize(in));
- long nowInSec = version >= MessagingService.VERSION_50 ? CassandraUInt.toLong(in.readInt()) : in.readInt();
- ColumnFilter columnFilter = ColumnFilter.serializer.deserialize(in, version, metadata);
- RowFilter rowFilter = RowFilter.serializer.deserialize(in, version, metadata);
- DataLimits limits = DataLimits.serializer.deserialize(in, version, metadata);
+ int digestVersion = isDigest ? (int)in.readUnsignedVInt() : 0;
+ TableId tableId = TableId.deserialize(in);
+ Epoch schemaVersion = null;
+ if (version >= MessagingService.VERSION_50)
+ schemaVersion = Epoch.serializer.deserialize(in);
+ TableMetadata tableMetadata;
+ try
+ {
+ tableMetadata = schema.getExistingTableMetadata(tableId);
+ }
+ catch (UnknownTableException e)
+ {
+ ClusterMetadata metadata = ClusterMetadata.current();
+ Epoch localCurrentEpoch = metadata.epoch;
+ if (schemaVersion != null && localCurrentEpoch.isAfter(schemaVersion))
+ {
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(e.getMessage());
+ }
+ throw e;
+ }
+ long nowInSec = version >= MessagingService.VERSION_50 ? CassandraUInt.toLong(in.readInt()) : in.readInt();
+ ColumnFilter columnFilter = ColumnFilter.serializer.deserialize(in, version, tableMetadata);
+ RowFilter rowFilter = RowFilter.serializer.deserialize(in, version, tableMetadata);
+ DataLimits limits = DataLimits.serializer.deserialize(in, version, tableMetadata);
Index.QueryPlan indexQueryPlan = null;
if (hasIndex)
{
- IndexMetadata index = deserializeIndexMetadata(in, version, metadata);
- Index.Group indexGroup = Keyspace.openAndGetStore(metadata).indexManager.getIndexGroup(index);
+ IndexMetadata index = deserializeIndexMetadata(in, version, tableMetadata);
+ Index.Group indexGroup = Keyspace.openAndGetStore(tableMetadata).indexManager.getIndexGroup(index);
if (indexGroup != null)
indexQueryPlan = indexGroup.queryPlanFor(rowFilter);
}
- return kind.selectionDeserializer.deserialize(in, version, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan);
+ return kind.selectionDeserializer.deserialize(in, version, schemaVersion, isDigest, digestVersion, acceptsTransient, tableMetadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan);
}
private IndexMetadata deserializeIndexMetadata(DataInputPlus in, int version, TableMetadata metadata) throws IOException
@@ -1144,6 +1189,7 @@ public abstract class ReadCommand extends AbstractReadQuery
return 2 // kind + flags
+ (command.isDigestQuery() ? TypeSizes.sizeofUnsignedVInt(command.digestVersion()) : 0)
+ command.metadata().id.serializedSize()
+ + (version >= MessagingService.VERSION_50 ? Epoch.serializer.serializedSize(command.metadata().epoch) : 0)
+ TypeSizes.INT_SIZE // command.nowInSec() is serialized as uint
+ ColumnFilter.serializer.serializedSize(command.columnFilter(), version)
+ RowFilter.serializer.serializedSize(command.rowFilter(), version)
diff --git a/src/java/org/apache/cassandra/db/ReadCommandVerbHandler.java b/src/java/org/apache/cassandra/db/ReadCommandVerbHandler.java
index d8069eebf4..5d430f32cf 100644
--- a/src/java/org/apache/cassandra/db/ReadCommandVerbHandler.java
+++ b/src/java/org/apache/cassandra/db/ReadCommandVerbHandler.java
@@ -22,15 +22,24 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator;
+import org.apache.cassandra.exceptions.CoordinatorBehindException;
+import org.apache.cassandra.exceptions.InvalidRoutingException;
+import org.apache.cassandra.exceptions.QueryCancelledException;
+import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.QueryCancelledException;
import org.apache.cassandra.locator.Replica;
+import org.apache.cassandra.metrics.TCMMetrics;
+import org.apache.cassandra.schema.SchemaConstants;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadataService;
import org.apache.cassandra.net.IVerbHandler;
import org.apache.cassandra.net.Message;
import org.apache.cassandra.net.MessagingService;
-import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
import org.apache.cassandra.tracing.Tracing;
+import org.apache.cassandra.utils.FBUtilities;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
@@ -42,16 +51,17 @@ public class ReadCommandVerbHandler implements IVerbHandler<ReadCommand>
public void doVerb(Message<ReadCommand> message)
{
- if (StorageService.instance.isBootstrapMode())
+ if (message.epoch().isAfter(Epoch.EMPTY))
{
- throw new RuntimeException("Cannot service reads while bootstrapping!");
+ ClusterMetadata metadata = ClusterMetadata.current();
+ metadata = checkTokenOwnership(metadata, message);
+ metadata = checkSchemaVersion(metadata, message);
}
- ReadCommand command = message.payload;
- validateTransientStatus(message);
MessageParams.reset();
long timeout = message.expiresAtNanos() - message.createdAtNanos();
+ ReadCommand command = message.payload;
command.setMonitoringTime(message.createdAtNanos(), message.isCrossNode(), timeout, DatabaseDescriptor.getSlowQueryTimeout(NANOSECONDS));
if (message.trackWarnings())
@@ -103,40 +113,110 @@ public class ReadCommandVerbHandler implements IVerbHandler<ReadCommand>
}
}
- private void validateTransientStatus(Message<ReadCommand> message)
+ private ClusterMetadata checkSchemaVersion(ClusterMetadata metadata, Message<ReadCommand> message)
{
- ReadCommand command = message.payload;
- if (command.metadata().isVirtual())
- return;
- Token token;
+ ReadCommand readCommand = message.payload;
- if (command instanceof SinglePartitionReadCommand)
- token = ((SinglePartitionReadCommand) command).partitionKey().getToken();
- else
- token = ((PartitionRangeReadCommand) command).dataRange().keyRange().right.getToken();
+ if (SchemaConstants.isSystemKeyspace(readCommand.metadata().keyspace) ||
+ readCommand.serializedAtEpoch() == null) // don't try to catch up with pre-5.0 nodes
+ return metadata;
- Replica replica = Keyspace.open(command.metadata().keyspace)
- .getReplicationStrategy()
- .getLocalReplicaFor(token);
+ Keyspace ks = metadata.schema.getKeyspace(readCommand.metadata().keyspace);
+ ColumnFamilyStore cfs = ks != null ? ks.getColumnFamilyStore(readCommand.metadata().id) : null;
+ Epoch localComparisonEpoch = metadata.epoch;
+ if (cfs != null)
+ localComparisonEpoch = cfs.metadata().epoch;
- if (replica == null)
+ if (localComparisonEpoch.isBefore(readCommand.serializedAtEpoch()))
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ else if (localComparisonEpoch.isAfter(readCommand.serializedAtEpoch()))
{
- if (command.isTopK())
- return;
-
- logger.warn("Received a read request from {} for a range that is not owned by the current replica {}.",
- message.from(),
- command);
- return;
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(String.format("Coordinator schema for %s.%s with epoch %s is behind our schema %s",
+ message.payload.metadata().keyspace,
+ message.payload.metadata().name,
+ readCommand.serializedAtEpoch(),
+ localComparisonEpoch));
}
+ ks = metadata.schema.getKeyspace(readCommand.metadata().keyspace);
+ if (ks == null || ks.getColumnFamilyStore(readCommand.metadata().id) == null)
+ throw new IllegalStateException("Unknown table " + readCommand.metadata().id +" after fetching remote log entries");
+ return metadata;
+ }
- if (!command.acceptsTransient() && replica.isTransient())
+ private ClusterMetadata checkTokenOwnership(ClusterMetadata metadata, Message<ReadCommand> message)
+ {
+ ReadCommand command = message.payload;
+ if (command.metadata().isVirtual())
+ return metadata;
+
+ if (command.isTopK())
+ return metadata;
+
+ if (command instanceof SinglePartitionReadCommand)
{
- MessagingService.instance().metrics.recordDroppedMessage(message, message.elapsedSinceCreated(NANOSECONDS), NANOSECONDS);
- throw new InvalidRequestException(String.format("Attempted to serve %s data request from %s node in %s",
- command.acceptsTransient() ? "transient" : "full",
- replica.isTransient() ? "transient" : "full",
- this));
+ Token token = ((SinglePartitionReadCommand) command).partitionKey().getToken();
+ Replica localReplica = getLocalReplica(metadata, token, command.metadata().keyspace);
+ if (localReplica == null)
+ {
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ localReplica = getLocalReplica(metadata, token, command.metadata().keyspace);
+ }
+ if (localReplica == null)
+ {
+ StorageService.instance.incOutOfRangeOperationCount();
+ Keyspace.open(command.metadata().keyspace).metric.outOfRangeTokenReads.inc();
+ throw InvalidRoutingException.forTokenRead(message.from(), token, metadata.epoch, message.payload);
+ }
+
+ if (!command.acceptsTransient() && localReplica.isTransient())
+ {
+ MessagingService.instance().metrics.recordDroppedMessage(message, message.elapsedSinceCreated(NANOSECONDS), NANOSECONDS);
+ throw new InvalidRequestException(String.format("Attempted to serve %s data request from %s node in %s",
+ command.acceptsTransient() ? "transient" : "full",
+ localReplica.isTransient() ? "transient" : "full",
+ this));
+ }
}
+ else
+ {
+ AbstractBounds<PartitionPosition> range = ((PartitionRangeReadCommand) command).dataRange().keyRange();
+
+ // TODO: preexisting issue: for the range queries or queries that span multiple replicas, we can only make requests where the right token is owned, but not the left one
+ Replica maxTokenLocalReplica = getLocalReplica(metadata, range.right.getToken(), command.metadata().keyspace);
+ if (maxTokenLocalReplica == null)
+ {
+ metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
+ maxTokenLocalReplica = getLocalReplica(metadata, range.right.getToken(), command.metadata().keyspace);
+ }
+ if (maxTokenLocalReplica == null)
+ {
+ StorageService.instance.incOutOfRangeOperationCount();
+ Keyspace.open(command.metadata().keyspace).metric.outOfRangeTokenReads.inc();
+ throw InvalidRoutingException.forRangeRead(message.from(), range, metadata.epoch, message.payload);
+ }
+
+
+ // TODO: preexisting issue: we should change the whole range for transient-ness, not just the right token
+ if (command.acceptsTransient() != maxTokenLocalReplica.isTransient())
+ {
+ MessagingService.instance().metrics.recordDroppedMessage(message, message.elapsedSinceCreated(NANOSECONDS), NANOSECONDS);
+ throw new InvalidRequestException(String.format("Attempted to serve %s data request from %s node in %s",
+ command.acceptsTransient() ? "transient" : "full",
+ maxTokenLocalReplica.isTransient() ? "transient" : "full",
+ this));
+ }
+ }
+ return metadata;
+ }
+
+ private static Replica getLocalReplica(ClusterMetadata metadata, Token token, String keyspace)
+ {
+ return metadata.placements
+ .get(metadata.schema.getKeyspaces().getNullable(keyspace).params.replication)
+ .reads
+ .forToken(token)
+ .get()
+ .lookup(FBUtilities.getBroadcastAddressAndPort());
}
}
diff --git a/src/java/org/apache/cassandra/db/ReadRepairVerbHandler.java b/src/java/org/apache/cassandra/db/ReadRepairVerbHandler.java
index 903b3d43bd..8ca29eba13 100644
--- a/src/java/org/apache/cassandra/db/ReadRepairVerbHandler.java
+++ b/src/java/org/apache/cassandra/db/ReadRepairVerbHandler.java
@@ -17,17 +17,17 @@
*/
package org.apache.cassandra.db;
-import org.apache.cassandra.net.IVerbHandler;
+import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.net.Message;
import org.apache.cassandra.net.MessagingService;
-public class ReadRepairVerbHandler implements IVerbHandler<Mutation>
+public class ReadRepairVerbHandler extends AbstractMutationVerbHandler<Mutation>
{
public static final ReadRepairVerbHandler instance = new ReadRepairVerbHandler();
- public void doVerb(Message<Mutation> message)
+ void applyMutation(Message<Mutation> message, InetAddressAndPort respondToAddress)
{
message.payload.apply();
- MessagingService.instance().send(message.emptyResponse(), message.from());
+ MessagingService.instance().send(message.emptyResponse(), respondToAddress);
}
}
diff --git a/src/java/org/apache/cassandra/db/ReadResponse.java b/src/java/org/apache/cassandra/db/ReadResponse.java
index a9e2cec4a7..d4906b2dd5 100644
--- a/src/java/org/apache/cassandra/db/ReadResponse.java
+++ b/src/java/org/apache/cassandra/db/ReadResponse.java
@@ -34,6 +34,8 @@ import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.utils.ByteBufferUtil;
+import static org.apache.cassandra.db.RepairedDataInfo.NO_OP_REPAIRED_DATA_INFO;
+
public abstract class ReadResponse
{
// Serializer for single partition read response
@@ -48,6 +50,11 @@ public abstract class ReadResponse
return new LocalDataResponse(data, command, rdi);
}
+ public static ReadResponse createDataResponse(UnfilteredPartitionIterator data, ReadCommand command)
+ {
+ return new LocalDataResponse(data, command, NO_OP_REPAIRED_DATA_INFO);
+ }
+
public static ReadResponse createSimpleDataResponse(UnfilteredPartitionIterator data, ColumnFilter selection)
{
return new LocalDataResponse(data, selection);
diff --git a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
index ae692fc5b8..aa7b72e4ef 100644
--- a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
+++ b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
@@ -76,6 +76,7 @@ import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.CacheService;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.StorageProxy;
+import org.apache.cassandra.tcm.Epoch;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.btree.BTreeSet;
@@ -91,7 +92,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
protected final ClusteringIndexFilter clusteringIndexFilter;
@VisibleForTesting
- protected SinglePartitionReadCommand(boolean isDigest,
+ protected SinglePartitionReadCommand(Epoch serializedAtEpoch,
+ boolean isDigest,
int digestVersion,
boolean acceptsTransient,
TableMetadata metadata,
@@ -104,24 +106,25 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
Index.QueryPlan indexQueryPlan,
boolean trackWarnings)
{
- super(Kind.SINGLE_PARTITION, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
+ super(serializedAtEpoch, Kind.SINGLE_PARTITION, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
assert partitionKey.getPartitioner() == metadata.partitioner;
this.partitionKey = partitionKey;
this.clusteringIndexFilter = clusteringIndexFilter;
}
- private static SinglePartitionReadCommand create(boolean isDigest,
- int digestVersion,
- boolean acceptsTransient,
- TableMetadata metadata,
- long nowInSec,
- ColumnFilter columnFilter,
- RowFilter rowFilter,
- DataLimits limits,
- DecoratedKey partitionKey,
- ClusteringIndexFilter clusteringIndexFilter,
- Index.QueryPlan indexQueryPlan,
- boolean trackWarnings)
+ private static SinglePartitionReadCommand create(Epoch serializedAtEpoch,
+ boolean isDigest,
+ int digestVersion,
+ boolean acceptsTransient,
+ TableMetadata metadata,
+ long nowInSec,
+ ColumnFilter columnFilter,
+ RowFilter rowFilter,
+ DataLimits limits,
+ DecoratedKey partitionKey,
+ ClusteringIndexFilter clusteringIndexFilter,
+ Index.QueryPlan indexQueryPlan,
+ boolean trackWarnings)
{
if (metadata.isVirtual())
{
@@ -138,7 +141,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
indexQueryPlan,
trackWarnings);
}
- return new SinglePartitionReadCommand(isDigest,
+ return new SinglePartitionReadCommand(serializedAtEpoch,
+ isDigest,
digestVersion,
acceptsTransient,
metadata,
@@ -175,7 +179,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
ClusteringIndexFilter clusteringIndexFilter,
Index.QueryPlan indexQueryPlan)
{
- return create(false,
+ return create(metadata.epoch,
+ false,
0,
false,
metadata,
@@ -352,7 +357,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
public SinglePartitionReadCommand copy()
{
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -369,7 +375,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
@Override
protected SinglePartitionReadCommand copyAsDigestQuery()
{
- return create(true,
+ return create(serializedAtEpoch(),
+ true,
digestVersion(),
acceptsTransient(),
metadata(),
@@ -386,7 +393,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
@Override
protected SinglePartitionReadCommand copyAsTransientQuery()
{
- return create(false,
+ return create(serializedAtEpoch(),
+ false,
0,
true,
metadata(),
@@ -403,7 +411,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
@Override
public SinglePartitionReadCommand withUpdatedLimit(DataLimits newLimits)
{
- return create(isDigestQuery(),
+ return create(serializedAtEpoch(),
+ isDigestQuery(),
digestVersion(),
acceptsTransient(),
metadata(),
@@ -1302,6 +1311,7 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
{
public ReadCommand deserialize(DataInputPlus in,
int version,
+ Epoch serializedAtEpoch,
boolean isDigest,
int digestVersion,
boolean acceptsTransient,
@@ -1315,7 +1325,7 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
{
DecoratedKey key = metadata.partitioner.decorateKey(metadata.partitionKeyType.readBuffer(in, DatabaseDescriptor.getMaxValueSize()));
ClusteringIndexFilter filter = ClusteringIndexFilter.serializer.deserialize(in, version, metadata);
- return SinglePartitionReadCommand.create(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, key, filter, indexQueryPlan, false);
+ return SinglePartitionReadCommand.create(serializedAtEpoch, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, key, filter, indexQueryPlan, false);
}
}
@@ -1362,7 +1372,7 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
Index.QueryPlan indexQueryPlan,
boolean trackWarnings)
{
- super(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings);
+ super(metadata.epoch, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings);
}
@Override
diff --git a/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java b/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
index f9233bf904..56e8370cda 100644
--- a/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
+++ b/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
@@ -19,7 +19,10 @@ package org.apache.cassandra.db;
import java.util.*;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,15 +32,17 @@ import org.apache.cassandra.db.lifecycle.View;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.io.sstable.format.SSTableReader;
-import org.apache.cassandra.locator.TokenMetadata;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.SchemaChangeListener;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.membership.NodeId;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.concurrent.Refs;
+import static org.apache.cassandra.tcm.compatibility.TokenRingUtils.getAllRanges;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
/**
@@ -62,8 +67,7 @@ public class SizeEstimatesRecorder implements SchemaChangeListener, Runnable
public void run()
{
- TokenMetadata metadata = StorageService.instance.getTokenMetadata().cloneOnlyTokenMap();
- if (!metadata.isMember(FBUtilities.getBroadcastAddressAndPort()))
+ if (!ClusterMetadata.current().directory.allAddresses().contains(FBUtilities.getBroadcastAddressAndPort()))
{
logger.debug("Node is not part of the ring; not recording size estimates");
return;
@@ -73,6 +77,9 @@ public class SizeEstimatesRecorder implements SchemaChangeListener, Runnable
for (Keyspace keyspace : Keyspace.nonLocalStrategy())
{
+ if (keyspace.getMetadata().params.replication.isMeta())
+ continue;
+
// In tools the call to describe_splits_ex() used to be coupled with the call to describe_local_ring() so
// most access was for the local primary range; after creating the size_estimates table this was changed
// to be the primary range.
@@ -88,7 +95,7 @@ public class SizeEstimatesRecorder implements SchemaChangeListener, Runnable
// range. If we publish multiple ranges downstream integrations may start to see duplicate data.
// See CASSANDRA-15637
Collection<Range<Token>> primaryRanges = StorageService.instance.getPrimaryRanges(keyspace.getName());
- Collection<Range<Token>> localPrimaryRanges = StorageService.instance.getLocalPrimaryRange();
+ Collection<Range<Token>> localPrimaryRanges = getLocalPrimaryRange();
boolean rangesAreEqual = primaryRanges.equals(localPrimaryRanges);
for (ColumnFamilyStore table : keyspace.getColumnFamilyStores())
{
@@ -116,6 +123,34 @@ public class SizeEstimatesRecorder implements SchemaChangeListener, Runnable
}
}
+ @VisibleForTesting
+ public static Collection<Range<Token>> getLocalPrimaryRange()
+ {
+ ClusterMetadata metadata = ClusterMetadata.current();
+ NodeId localNodeId = metadata.myNodeId();
+ return getLocalPrimaryRange(metadata, localNodeId);
+ }
+
+ @VisibleForTesting
+ public static Collection<Range<Token>> getLocalPrimaryRange(ClusterMetadata metadata, NodeId nodeId)
+ {
+ String dc = metadata.directory.location(nodeId).datacenter;
+ Set<Token> tokens = new HashSet<>(metadata.tokenMap.tokens(nodeId));
+
+ // filter tokens to the single DC
+ List<Token> filteredTokens = Lists.newArrayList();
+ for (Token token : metadata.tokenMap.tokens())
+ {
+ NodeId owner = metadata.tokenMap.owner(token);
+ if (dc.equals(metadata.directory.location(owner).datacenter))
+ filteredTokens.add(token);
+ }
+ return getAllRanges(filteredTokens).stream()
+ .filter(t -> tokens.contains(t.right))
+ .collect(Collectors.toList());
+ }
+
+ @SuppressWarnings("resource")
private static Map<Range<Token>, Pair<Long, Long>> computeSizeEstimates(ColumnFamilyStore table, Collection<Range<Token>> ranges)
{
// for each local primary range, estimate (crudely) mean partition size and partitions count.
diff --git a/src/java/org/apache/cassandra/db/SystemKeyspace.java b/src/java/org/apache/cassandra/db/SystemKeyspace.java
index b8ecc5afb4..d751f6ea2c 100644
--- a/src/java/org/apache/cassandra/db/SystemKeyspace.java
+++ b/src/java/org/apache/cassandra/db/SystemKeyspace.java
@@ -36,7 +36,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import javax.management.openmbean.OpenDataException;
@@ -59,7 +58,6 @@ import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.cql3.statements.schema.CreateTableStatement;
-import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.db.commitlog.CommitLogPosition;
import org.apache.cassandra.db.compaction.CompactionHistoryTabularData;
import org.apache.cassandra.db.marshal.ByteBufferAccessor;
@@ -77,6 +75,9 @@ import org.apache.cassandra.dht.LocalPartitioner;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.gms.EndpointState;
+import org.apache.cassandra.gms.HeartBeatState;
+import org.apache.cassandra.gms.VersionedValue;
import org.apache.cassandra.io.sstable.SSTableId;
import org.apache.cassandra.io.sstable.SequenceBasedSSTableId;
import org.apache.cassandra.io.util.DataInputBuffer;
@@ -110,6 +111,10 @@ import org.apache.cassandra.service.paxos.PaxosState;
import org.apache.cassandra.service.paxos.uncommitted.PaxosRows;
import org.apache.cassandra.service.paxos.uncommitted.PaxosUncommittedIndex;
import org.apache.cassandra.streaming.StreamOperation;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
+import org.apache.cassandra.tcm.Sealed;
+import org.apache.cassandra.tcm.membership.NodeState;
import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.CassandraVersion;
@@ -127,6 +132,14 @@ import static org.apache.cassandra.config.DatabaseDescriptor.paxosStatePurging;
import static org.apache.cassandra.cql3.QueryProcessor.executeInternal;
import static org.apache.cassandra.cql3.QueryProcessor.executeInternalWithNowInSec;
import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
+import static org.apache.cassandra.gms.ApplicationState.DC;
+import static org.apache.cassandra.gms.ApplicationState.HOST_ID;
+import static org.apache.cassandra.gms.ApplicationState.INTERNAL_ADDRESS_AND_PORT;
+import static org.apache.cassandra.gms.ApplicationState.NATIVE_ADDRESS_AND_PORT;
+import static org.apache.cassandra.gms.ApplicationState.RACK;
+import static org.apache.cassandra.gms.ApplicationState.RELEASE_VERSION;
+import static org.apache.cassandra.gms.ApplicationState.STATUS_WITH_PORT;
+import static org.apache.cassandra.gms.ApplicationState.TOKENS;
import static org.apache.cassandra.service.paxos.Commit.latest;
import static org.apache.cassandra.utils.CassandraVersion.NULL_VERSION;
import static org.apache.cassandra.utils.CassandraVersion.UNREADABLE_VERSION;
@@ -163,6 +176,10 @@ public final class SystemKeyspace
public static final String PREPARED_STATEMENTS = "prepared_statements";
public static final String REPAIRS = "repairs";
public static final String TOP_PARTITIONS = "top_partitions";
+ public static final String METADATA_LOG = "local_metadata_log";
+ public static final String SNAPSHOT_TABLE_NAME = "metadata_snapshots";
+ public static final String SEALED_PERIODS_TABLE_NAME = "metadata_sealed_periods";
+ public static final String LAST_SEALED_PERIOD_TABLE_NAME = "metadata_last_sealed_period";
/**
* By default the system keyspace tables should be stored in a single data directory to allow the server
@@ -195,13 +212,15 @@ public final class SystemKeyspace
COMPACTION_HISTORY, SSTABLE_ACTIVITY_V2, TABLE_ESTIMATES, TABLE_ESTIMATES_TYPE_PRIMARY,
TABLE_ESTIMATES_TYPE_LOCAL_PRIMARY, AVAILABLE_RANGES_V2, TRANSFERRED_RANGES_V2, VIEW_BUILDS_IN_PROGRESS,
BUILT_VIEWS, PREPARED_STATEMENTS, REPAIRS, TOP_PARTITIONS, LEGACY_PEERS, LEGACY_PEER_EVENTS,
- LEGACY_TRANSFERRED_RANGES, LEGACY_AVAILABLE_RANGES, LEGACY_SIZE_ESTIMATES, LEGACY_SSTABLE_ACTIVITY);
+ LEGACY_TRANSFERRED_RANGES, LEGACY_AVAILABLE_RANGES, LEGACY_SIZE_ESTIMATES, LEGACY_SSTABLE_ACTIVITY,
+ METADATA_LOG, SNAPSHOT_TABLE_NAME, SEALED_PERIODS_TABLE_NAME, LAST_SEALED_PERIOD_TABLE_NAME);
public static final Set<String> TABLE_NAMES = ImmutableSet.of(
BATCHES, PAXOS, PAXOS_REPAIR_HISTORY, BUILT_INDEXES, LOCAL, PEERS_V2, PEER_EVENTS_V2,
COMPACTION_HISTORY, SSTABLE_ACTIVITY_V2, TABLE_ESTIMATES, AVAILABLE_RANGES_V2, TRANSFERRED_RANGES_V2, VIEW_BUILDS_IN_PROGRESS,
BUILT_VIEWS, PREPARED_STATEMENTS, REPAIRS, TOP_PARTITIONS, LEGACY_PEERS, LEGACY_PEER_EVENTS,
- LEGACY_TRANSFERRED_RANGES, LEGACY_AVAILABLE_RANGES, LEGACY_SIZE_ESTIMATES, LEGACY_SSTABLE_ACTIVITY);
+ LEGACY_TRANSFERRED_RANGES, LEGACY_AVAILABLE_RANGES, LEGACY_SIZE_ESTIMATES, LEGACY_SSTABLE_ACTIVITY,
+ METADATA_LOG, SNAPSHOT_TABLE_NAME, SEALED_PERIODS_TABLE_NAME, LAST_SEALED_PERIOD_TABLE_NAME);
public static final TableMetadata Batches =
parse(BATCHES,
@@ -466,7 +485,45 @@ public final class SystemKeyspace
+ "cfids set<uuid>, "
+ "PRIMARY KEY (parent_id))").build();
- /** @deprecated See CASSANDRA-7544 */
+ public static final TableMetadata LocalMetadataLog =
+ parse(METADATA_LOG,
+ "Local Metadata Log",
+ "CREATE TABLE %s ("
+ + "period bigint,"
+ + "current_epoch bigint static,"
+ + "epoch bigint,"
+ + "entry_id bigint,"
+ + "transformation blob,"
+ + "kind text,"
+ + "PRIMARY KEY (period, epoch))")
+ .compaction(CompactionParams.twcs(ImmutableMap.of("compaction_window_unit","DAYS",
+ "compaction_window_size","1")))
+ .build();
+
+ public static final TableMetadata Snapshots = parse(SNAPSHOT_TABLE_NAME,
+ "ClusterMetadata snapshots",
+ "CREATE TABLE IF NOT EXISTS %s (" +
+ "epoch bigint PRIMARY KEY," +
+ "period bigint," +
+ "snapshot blob)")
+ .build();
+
+ public static final TableMetadata SealedPeriods = parse(SEALED_PERIODS_TABLE_NAME,
+ "ClusterMetadata sealed periods",
+ "CREATE TABLE IF NOT EXISTS %s (" +
+ "max_epoch bigint PRIMARY KEY," +
+ "period bigint)")
+ .partitioner(new LocalPartitioner(LongType.instance))
+ .build();
+
+ public static final TableMetadata LastSealedPeriod = parse(LAST_SEALED_PERIOD_TABLE_NAME,
+ "ClusterMetadata last sealed period",
+ "CREATE TABLE IF NOT EXISTS %s (" +
+ "key text PRIMARY KEY," +
+ "epoch bigint," +
+ "period bigint)")
+ .build();
+
@Deprecated(since = "4.0")
private static final TableMetadata LegacyPeers =
parse(LEGACY_PEERS,
@@ -557,7 +614,11 @@ public final class SystemKeyspace
BuiltViews,
PreparedStatements,
Repairs,
- TopPartitions);
+ TopPartitions,
+ LocalMetadataLog,
+ LastSealedPeriod,
+ SealedPeriods,
+ Snapshots);
}
private static volatile Map<TableId, Pair<CommitLogPosition, Long>> truncationRecords;
@@ -567,16 +628,31 @@ public final class SystemKeyspace
NEEDS_BOOTSTRAP,
COMPLETED,
IN_PROGRESS,
- DECOMMISSIONED
- }
+ DECOMMISSIONED;
- public static void persistLocalMetadata()
- {
- persistLocalMetadata(UUID::randomUUID);
+ public static BootstrapState fromNodeState(NodeState nodeState)
+ {
+ if (nodeState == null) // todo, handle this properly
+ return DECOMMISSIONED;
+ switch (nodeState)
+ {
+ case REGISTERED:
+ return NEEDS_BOOTSTRAP;
+ case BOOTSTRAPPING:
+ case BOOT_REPLACING:
+ return IN_PROGRESS;
+ case JOINED:
+ case LEAVING:
+ case MOVING:
+ return COMPLETED;
+ case LEFT:
+ default:
+ return DECOMMISSIONED;
+ }
+ }
}
- @VisibleForTesting
- public static void persistLocalMetadata(Supplier<UUID> nodeIdSupplier)
+ public static void persistLocalMetadata()
{
String req = "INSERT INTO system.%s (" +
"key," +
@@ -610,13 +686,6 @@ public final class SystemKeyspace
DatabaseDescriptor.getStoragePort(),
FBUtilities.getJustLocalAddress(),
DatabaseDescriptor.getStoragePort());
-
- // We should store host ID as soon as possible in the system.local table and flush that table to disk so that
- // we can be sure that those changes are stored in sstable and not in the commit log (see CASSANDRA-18153).
- // It is very unlikely that when upgrading the host id is not flushed to disk, but if that's the case, we limit
- // this change only to the new installations or the user should just flush system.local table.
- if (!CommitLog.instance.hasFilesToReplay())
- SystemKeyspace.getOrInitializeLocalHostId(nodeIdSupplier);
}
public static void updateCompactionHistory(TimeUUID taskId,
@@ -831,7 +900,10 @@ public final class SystemKeyspace
public static synchronized void updateTokens(InetAddressAndPort ep, Collection<Token> tokens)
{
if (ep.equals(FBUtilities.getBroadcastAddressAndPort()))
+ {
+ updateLocalTokens(tokens);
return;
+ }
String req = "INSERT INTO system.%s (peer, tokens) VALUES (?, ?)";
executeInternal(String.format(req, LEGACY_PEERS), ep.getAddress(), tokensAsSet(tokens));
@@ -895,11 +967,11 @@ public final class SystemKeyspace
executeInternal(format(req, LOCAL, LOCAL), version);
}
- private static Set<String> tokensAsSet(Collection<Token> tokens)
+ public static Set<String> tokensAsSet(Collection<Token> tokens)
{
if (tokens.isEmpty())
return Collections.emptySet();
- Token.TokenFactory factory = StorageService.instance.getTokenFactory();
+ Token.TokenFactory factory = ClusterMetadata.current().partitioner.getTokenFactory();
Set<String> s = new HashSet<>(tokens.size());
for (Token tk : tokens)
s.add(factory.toString(tk));
@@ -908,7 +980,7 @@ public final class SystemKeyspace
private static Collection<Token> deserializeTokens(Collection<String> tokensStrings)
{
- Token.TokenFactory factory = StorageService.instance.getTokenFactory();
+ Token.TokenFactory factory = ClusterMetadata.current().partitioner.getTokenFactory();
List<Token> tokens = new ArrayList<>(tokensStrings.size());
for (String tk : tokensStrings)
tokens.add(factory.fromString(tk));
@@ -928,9 +1000,10 @@ public final class SystemKeyspace
}
/**
+ *
* This method is used to update the System Keyspace with the new tokens for this node
*/
- public static synchronized void updateTokens(Collection<Token> tokens)
+ public static synchronized void updateLocalTokens(Collection<Token> tokens)
{
assert !tokens.isEmpty() : "removeEndpoint should be used instead";
@@ -1240,27 +1313,6 @@ public final class SystemKeyspace
return null;
}
- /**
- * Read the host ID from the system keyspace, creating (and storing) one if
- * none exists.
- */
- public static synchronized UUID getOrInitializeLocalHostId()
- {
- return getOrInitializeLocalHostId(UUID::randomUUID);
- }
-
- private static synchronized UUID getOrInitializeLocalHostId(Supplier<UUID> nodeIdSupplier)
- {
- UUID hostId = getLocalHostId();
- if (hostId != null)
- return hostId;
-
- // ID not found, generate a new one, persist, and then return it.
- hostId = nodeIdSupplier.get();
- logger.warn("No host ID found, created {} (Note: This should happen exactly once per node).", hostId);
- return setLocalHostId(hostId);
- }
-
/**
* Sets the local host ID explicitly. Should only be called outside of SystemTable when replacing a node.
*/
@@ -1316,6 +1368,20 @@ public final class SystemKeyspace
return null;
}
+ public static Set<String> allKnownDatacenters()
+ {
+ Set<String> dcs = new HashSet<>();
+ dcs.add(getDatacenter());
+ String req = "SELECT data_center FROM system.%s";
+ UntypedResultSet result = executeInternal(format(req, PEERS_V2));
+ if (result != null)
+ {
+ for (UntypedResultSet.Row row : result)
+ dcs.add(row.getString("data_center"));
+ }
+ return dcs;
+ }
+
/**
* Load the current paxos state for the table and key
*/
@@ -1937,4 +2003,122 @@ public final class SystemKeyspace
return TopPartitionTracker.StoredTopPartitions.EMPTY;
}
}
+
+ public static void storeSnapshot(Epoch epoch, long period, ByteBuffer snapshot)
+ {
+ logger.info("Storing snapshot of cluster metadata at epoch {} (period {})", epoch, period);
+ String query = String.format("INSERT INTO %s.%s (epoch, period, snapshot) VALUES (?, ?, ?)", SchemaConstants.SYSTEM_KEYSPACE_NAME, SNAPSHOT_TABLE_NAME);
+ executeInternal(query, epoch.getEpoch(), period, snapshot);
+ }
+
+ public static ByteBuffer getSnapshot(Epoch epoch)
+ {
+ logger.info("Getting snapshot of epoch = {}", epoch);
+ String query = String.format("SELECT SNAPSHOT FROM %s.%s WHERE epoch = ?", SchemaConstants.SYSTEM_KEYSPACE_NAME, SNAPSHOT_TABLE_NAME);
+ UntypedResultSet res = executeInternal(query, epoch.getEpoch());
+ if (res == null || res.isEmpty())
+ return null;
+ return res.one().getBytes("snapshot").duplicate();
+ }
+
+ public static Sealed findSealedPeriodForEpochScan(Epoch search)
+ {
+ String query = String.format("SELECT max_epoch, period FROM %s.%s WHERE max_epoch >= ? LIMIT 1 ALLOW FILTERING", SchemaConstants.SYSTEM_KEYSPACE_NAME, SEALED_PERIODS_TABLE_NAME);
+ UntypedResultSet res = executeInternal(query, search.getEpoch());
+ if (res != null && !res.isEmpty())
+ {
+ long period = res.one().getLong("period");
+ long epoch = res.one().getLong("max_epoch");
+ return new Sealed(period, epoch);
+ }
+
+ // nothing found for this epoch, is the table empty or is the search epoch > the maximum
+ query = String.format("SELECT max_epoch, period FROM %s.%s LIMIT 1", SchemaConstants.SYSTEM_KEYSPACE_NAME, SEALED_PERIODS_TABLE_NAME);
+ res = executeInternal(query);
+ // table is empty, so any scan for the epoch will have to begin at Period.EMPTY
+ if (res == null || res.isEmpty())
+ return Sealed.EMPTY;
+
+ // the index table has some data, but is the search target greater than the max epoch in last sealed period?
+ // This query is relatively costly, so we do it last. Retain the min period/epoch that we did find in the
+ // previous query just in case we need them
+ // TODO add a nodetool command to rebuild the local sealed periods table
+ long lowestPeriod = res.one().getLong("period");
+ long lowestMaxEpoch = res.one().getLong("max_epoch");
+ logger.info("Scanning sealed periods by epoch table, this may be an expensive operation and the index table {} should be rebuilt", SEALED_PERIODS_TABLE_NAME);
+ query = String.format("SELECT max(max_epoch) AS max_epoch FROM %s.%s LIMIT 1 ALLOW FILTERING;", SchemaConstants.SYSTEM_KEYSPACE_NAME, SEALED_PERIODS_TABLE_NAME);
+ res = executeInternal(query);
+
+ // should never happen because the previous query returned the min, but just in case the table has been
+ // truncated since then, return the min Sealed.
+ if (res == null || res.isEmpty())
+ return new Sealed(lowestPeriod, lowestMaxEpoch);
+
+ // use the max epoch to look up the sealed period
+ long maxEpoch = res.one().getLong("max_epoch");
+ query = String.format("SELECT period FROM %s.%s WHERE max_epoch = ?", SchemaConstants.SYSTEM_KEYSPACE_NAME, SEALED_PERIODS_TABLE_NAME);
+ res = executeInternal(query, maxEpoch);
+ if (res == null || res.isEmpty())
+ return new Sealed(lowestPeriod, lowestMaxEpoch);
+ // this is the last recorded sealed period *before* the target epoch, so any scan should start at the
+ // *next* period, so we bump both period and epoch by 1
+ long maxPeriod = res.one().getLong("period");
+ return new Sealed(maxPeriod + 1, maxEpoch + 1);
+ }
+
+ public static Sealed getLastSealedPeriod()
+ {
+ String query = String.format("SELECT epoch, period FROM %s.%s WHERE key = 'latest'", SchemaConstants.SYSTEM_KEYSPACE_NAME, LAST_SEALED_PERIOD_TABLE_NAME);
+ UntypedResultSet res = executeInternal(query);
+ if (res == null || res.isEmpty())
+ return Sealed.EMPTY;
+ long epoch = res.one().getLong("epoch");
+ long period = res.one().getLong("period");
+ return new Sealed(period, Epoch.create(epoch));
+ }
+
+ public static void sealPeriod(long period, Epoch epoch)
+ {
+ String query = String.format("INSERT INTO %s.%s (max_epoch, period) VALUES (?,?)", SchemaConstants.SYSTEM_KEYSPACE_NAME, SEALED_PERIODS_TABLE_NAME);
+ executeInternal(query, epoch.getEpoch(), period);
+ query = String.format("UPDATE %s.%s SET period = ?, epoch = ? WHERE key = 'latest'", SchemaConstants.SYSTEM_KEYSPACE_NAME, LAST_SEALED_PERIOD_TABLE_NAME);
+ executeInternal(query, period, epoch.getEpoch());
+ }
+
+ public static Map<InetAddressAndPort, EndpointState> peerEndpointStates()
+ {
+ Map<InetAddressAndPort, EndpointState> epstates = new HashMap<>();
+ VersionedValue.VersionedValueFactory vf = StorageService.instance.valueFactory;
+ String query = String.format("select * from %s.%s", SchemaConstants.SYSTEM_KEYSPACE_NAME, PEERS_V2);
+ UntypedResultSet res = executeInternal(query);
+ for (UntypedResultSet.Row row : res)
+ {
+ EndpointState epstate = new EndpointState(new HeartBeatState(0, 0));
+ InetAddressAndPort endpoint = InetAddressAndPort.getByAddressOverrideDefaults(row.getInetAddress("peer"), row.getInt("peer_port"));
+ epstate.addApplicationState(DC, vf.datacenter(row.getString("data_center")));
+ epstate.addApplicationState(RACK, vf.rack(row.getString("rack")));
+ epstate.addApplicationState(RELEASE_VERSION, vf.releaseVersion(row.getString("release_version")));
+ epstate.addApplicationState(HOST_ID, vf.hostId(row.getUUID("host_id")));
+ Collection<Token> tokens = deserializeTokens(row.getSet("tokens", UTF8Type.instance));
+ epstate.addApplicationState(STATUS_WITH_PORT, vf.normal(tokens));
+ epstate.addApplicationState(TOKENS, vf.tokens(tokens));
+
+ if (row.has("preferred_ip"))
+ {
+ epstate.addApplicationState(INTERNAL_ADDRESS_AND_PORT,
+ vf.internalAddressAndPort(InetAddressAndPort.getByAddressOverrideDefaults(row.getInetAddress("preferred_ip"),
+ row.getInt("preferred_port"))));
+ }
+
+ if (row.has("native_ip"))
+ {
+ epstate.addApplicationState(NATIVE_ADDRESS_AND_PORT,
+ vf.nativeaddressAndPort(InetAddressAndPort.getByAddressOverrideDefaults(row.getInetAddress("native_ip"),
+ row.getInt("native_port"))));
+ }
+
+ epstates.put(endpoint, epstate);
+ }
+ return epstates;
+ }
}
diff --git a/src/java/org/apache/cassandra/db/commitlog/AbstractCommitLogSegmentManager.java b/src/java/org/apache/cassandra/db/commitlog/AbstractCommitLogSegmentManager.java
index e6cc2fa814..e5e82f9662 100644
--- a/src/java/org/apache/cassandra/db/commitlog/AbstractCommitLogSegmentManager.java
+++ b/src/java/org/apache/cassandra/db/commitlog/AbstractCommitLogSegmentManager.java
@@ -320,11 +320,12 @@ public abstract class AbstractCommitLogSegmentManager
void forceRecycleAll(Collection<TableId> droppedTables)
{
List<CommitLogSegment> segmentsToRecycle = new ArrayList<>(activeSegments);
- CommitLogSegment last = segmentsToRecycle.get(segmentsToRecycle.size() - 1);
+ CommitLogSegment last = segmentsToRecycle.isEmpty() ? null : segmentsToRecycle.get(segmentsToRecycle.size() - 1);
advanceAllocatingFrom(last);
// wait for the commit log modifications
- last.waitForModifications();
+ if (last != null)
+ last.waitForModifications();
// make sure the writes have materialized inside of the memtables by waiting for all outstanding writes
// to complete
@@ -350,7 +351,7 @@ public abstract class AbstractCommitLogSegmentManager
}
CommitLogSegment first;
- if ((first = activeSegments.peek()) != null && first.id <= last.id)
+ if ((first = activeSegments.peek()) != null && last != null && first.id <= last.id)
logger.error("Failed to force-recycle all segments; at least one segment is still in use with dirty CFs.");
}
catch (Throwable t)
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
index 0eeed14be6..f228540394 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
@@ -96,6 +96,7 @@ import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
import org.apache.cassandra.io.sstable.metadata.StatsMetadata;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.io.util.FileUtils;
+import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.locator.RangesAtEndpoint;
import org.apache.cassandra.metrics.CompactionMetrics;
import org.apache.cassandra.metrics.TableMetrics;
@@ -113,10 +114,13 @@ import org.apache.cassandra.utils.OutputHandler;
import org.apache.cassandra.utils.Throwables;
import org.apache.cassandra.utils.TimeUUID;
import org.apache.cassandra.utils.WrappedRunnable;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.ownership.DataPlacement;
import org.apache.cassandra.utils.concurrent.Future;
import org.apache.cassandra.utils.concurrent.ImmediateFuture;
import org.apache.cassandra.utils.concurrent.Refs;
+
import static java.util.Collections.singleton;
import static org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory;
import static org.apache.cassandra.concurrent.FutureTask.callable;
@@ -617,13 +621,26 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
assert !cfStore.isIndex();
Keyspace keyspace = cfStore.keyspace;
- // if local ranges is empty, it means no data should remain
- final RangesAtEndpoint replicas = StorageService.instance.getLocalReplicas(keyspace.getName());
- final Set<Range<Token>> allRanges = replicas.ranges();
- final Set<Range<Token>> transientRanges = replicas.onlyTransient().ranges();
- final Set<Range<Token>> fullRanges = replicas.onlyFull().ranges();
+ if (!StorageService.instance.isJoined())
+ {
+ logger.info("Cleanup cannot run before a node has joined the ring");
+ return AllSSTableOpStatus.ABORTED;
+ }
+ if (cfStore.keyspace.getMetadata().params.replication.isMeta())
+ return AllSSTableOpStatus.SUCCESSFUL; // todo - we probably want to be able to cleanup MetaStrategy keyspaces
final boolean hasIndexes = cfStore.indexManager.hasIndexes();
+ // if local ranges is empty, it means no data should remain
+ // we only consider write placements during cleanup as range movements always ensure
+ // overlap between new replicas accepting reads and old replicas accepting writes
+ ClusterMetadata cm = ClusterMetadata.current();
+ DataPlacement placement = cm.placements.get(keyspace.getMetadata().params.replication);
+ InetAddressAndPort local = FBUtilities.getBroadcastAddressAndPort();
+ RangesAtEndpoint localWrites = placement.writes.byEndpoint().get(local);
+ final Set<Range<Token>> allRanges = new HashSet<>(localWrites.ranges());
+ final Set<Range<Token>> transientRanges = new HashSet<>(localWrites.onlyTransient().ranges());
+ final Set<Range<Token>> fullRanges = new HashSet<>(localWrites.onlyFull().ranges());
+
return parallelAllSSTableOperation(cfStore, new OneSSTableOperation()
{
@Override
@@ -665,7 +682,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
public void execute(LifecycleTransaction txn) throws IOException
{
CleanupStrategy cleanupStrategy = CleanupStrategy.get(cfStore, allRanges, transientRanges, txn.onlyOne().isRepaired(), FBUtilities.nowInSeconds());
- doCleanupOne(cfStore, txn, cleanupStrategy, replicas.ranges(), hasIndexes);
+ doCleanupOne(cfStore, txn, cleanupStrategy, allRanges, hasIndexes);
}
}, jobs, OperationType.CLEANUP);
}
@@ -1291,7 +1308,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
/* Used in tests. */
public void disableAutoCompaction()
{
- for (String ksname : Schema.instance.distributedKeyspaces().names())
+ for (String ksname : Schema.instance.getKeyspaces())
{
for (ColumnFamilyStore cfs : Keyspace.open(ksname).getColumnFamilyStores())
cfs.disableAutoCompaction();
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java
index dfcd9aee4e..c31a9b2259 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java
@@ -70,6 +70,7 @@ import org.apache.cassandra.io.sstable.metadata.StatsMetadata;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.notifications.INotification;
import org.apache.cassandra.notifications.INotificationConsumer;
+import org.apache.cassandra.notifications.InitialSSTableAddedNotification;
import org.apache.cassandra.notifications.SSTableAddedNotification;
import org.apache.cassandra.notifications.SSTableDeletingNotification;
import org.apache.cassandra.notifications.SSTableListChangedNotification;
@@ -890,6 +891,11 @@ public class CompactionStrategyManager implements INotificationConsumer
SSTableAddedNotification flushedNotification = (SSTableAddedNotification) notification;
handleFlushNotification(flushedNotification.added);
}
+ else if (notification instanceof InitialSSTableAddedNotification)
+ {
+ InitialSSTableAddedNotification flushedNotification = (InitialSSTableAddedNotification) notification;
+ handleFlushNotification(flushedNotification.added);
+ }
else if (notification instanceof SSTableListChangedNotification)
{
SSTableListChangedNotification listChangedNotification = (SSTableListChangedNotification) notification;
diff --git a/src/java/org/apache/cassandra/db/compaction/ShardManagerNoDisks.java b/src/java/org/apache/cassandra/db/compaction/ShardManagerNoDisks.java
index 6174612a94..0b89111ccd 100644
--- a/src/java/org/apache/cassandra/db/compaction/ShardManagerNoDisks.java
+++ b/src/java/org/apache/cassandra/db/compaction/ShardManagerNoDisks.java
@@ -55,8 +55,8 @@ public class ShardManagerNoDisks implements ShardManager
public boolean isOutOfDate(long ringVersion)
{
- return ringVersion != localRanges.ringVersion &&
- localRanges.ringVersion != ColumnFamilyStore.RING_VERSION_IRRELEVANT;
+ return ringVersion != localRanges.ringVersion.getEpoch() &&
+ !localRanges.ringVersion.is(ColumnFamilyStore.RING_VERSION_IRRELEVANT);
}
@Override
diff --git a/src/java/org/apache/cassandra/db/compaction/UnifiedCompactionStrategy.java b/src/java/org/apache/cassandra/db/compaction/UnifiedCompactionStrategy.java
index 2539c21b8e..0cb1f46cc8 100644
--- a/src/java/org/apache/cassandra/db/compaction/UnifiedCompactionStrategy.java
+++ b/src/java/org/apache/cassandra/db/compaction/UnifiedCompactionStrategy.java
@@ -52,7 +52,7 @@ import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.SSTableMultiWriter;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.utils.Clock;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Overlaps;
@@ -295,13 +295,14 @@ public class UnifiedCompactionStrategy extends AbstractCompactionStrategy
private void maybeUpdateShardManager()
{
- if (shardManager != null && !shardManager.isOutOfDate(StorageService.instance.getTokenMetadata().getRingVersion()))
+ // TODO - modify ShardManager::isOutOfDate to take an Epoch
+ if (shardManager != null && !shardManager.isOutOfDate(ClusterMetadata.current().epoch.getEpoch()))
return; // the disk boundaries (and thus the local ranges too) have not changed since the last time we calculated
synchronized (this)
{
// Recheck after entering critical section, another thread may have beaten us to it.
- while (shardManager == null || shardManager.isOutOfDate(StorageService.instance.getTokenMetadata().getRingVersion()))
+ while (shardManager == null || shardManager.isOutOfDate(ClusterMetadata.current().epoch.getEpoch()))
shardManager = ShardManager.create(cfs);
// Note: this can just as well be done without the synchronization (races would be benign, just doing some
// redundant work). For the current usages of this blocking is fine and expected to perform no worse.
diff --git a/src/java/org/apache/cassandra/db/filter/RowFilter.java b/src/java/org/apache/cassandra/db/filter/RowFilter.java
index cefd941622..da9bc61271 100644
--- a/src/java/org/apache/cassandra/db/filter/RowFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java
@@ -65,6 +65,7 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
private static final Logger logger = LoggerFactory.getLogger(RowFilter.class);
public static final Serializer serializer = new Serializer();
+ public static final RowFilter NONE = new CQLFilter(Collections.emptyList());
protected final List<Expression> expressions;
diff --git a/src/java/org/apache/cassandra/db/guardrails/Guardrail.java b/src/java/org/apache/cassandra/db/guardrails/Guardrail.java
index 0f6831cbbc..b9d21a412d 100644
--- a/src/java/org/apache/cassandra/db/guardrails/Guardrail.java
+++ b/src/java/org/apache/cassandra/db/guardrails/Guardrail.java
@@ -95,7 +95,7 @@ public abstract class Guardrail
*/
public boolean enabled(@Nullable ClientState state)
{
- return DatabaseDescriptor.isDaemonInitialized() && (state == null || state.isOrdinaryUser());
+ return DatabaseDescriptor.isDaemonInitialized() && (state == null || (state.isOrdinaryUser() && state.applyGuardrails()));
}
protected void warn(String message)
diff --git a/src/java/org/apache/cassandra/db/lifecycle/Tracker.java b/src/java/org/apache/cassandra/db/lifecycle/Tracker.java
index e959c72fa9..5decf00384 100644
--- a/src/java/org/apache/cassandra/db/lifecycle/Tracker.java
+++ b/src/java/org/apache/cassandra/db/lifecycle/Tracker.java
@@ -230,9 +230,15 @@ public class Tracker
addSSTablesInternal(sstables, true, false, true);
}
- public void addInitialSSTablesWithoutUpdatingSize(Iterable<SSTableReader> sstables)
+ public void addInitialSSTablesWithoutUpdatingSize(Iterable<SSTableReader> sstables, ColumnFamilyStore cfs)
{
- addSSTablesInternal(sstables, true, false, false);
+ if (!isDummy())
+ {
+ for (SSTableReader reader : sstables)
+ reader.setupOnline();
+ }
+ apply(updateLiveSet(emptySet(), sstables));
+ notifyAdded(sstables, true);
}
public void updateInitialSSTableSize(Iterable<SSTableReader> sstables)
diff --git a/src/java/org/apache/cassandra/db/memtable/ShardBoundaries.java b/src/java/org/apache/cassandra/db/memtable/ShardBoundaries.java
index 864899f6a4..5412c2cf62 100644
--- a/src/java/org/apache/cassandra/db/memtable/ShardBoundaries.java
+++ b/src/java/org/apache/cassandra/db/memtable/ShardBoundaries.java
@@ -25,6 +25,7 @@ import com.google.common.annotations.VisibleForTesting;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.PartitionPosition;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.tcm.Epoch;
/**
* Holds boundaries (tokens) used to map a particular token (so partition key) to a shard id.
@@ -43,21 +44,21 @@ public class ShardBoundaries
// - there is only 1 shard configured
// - the default partitioner doesn't support splitting
// - the keyspace is local system keyspace
- public static final ShardBoundaries NONE = new ShardBoundaries(EMPTY_TOKEN_ARRAY, -1);
+ public static final ShardBoundaries NONE = new ShardBoundaries(EMPTY_TOKEN_ARRAY, Epoch.EMPTY);
private final Token[] boundaries;
- public final long ringVersion;
+ public final Epoch epoch;
@VisibleForTesting
- public ShardBoundaries(Token[] boundaries, long ringVersion)
+ public ShardBoundaries(Token[] boundaries, Epoch epoch)
{
this.boundaries = boundaries;
- this.ringVersion = ringVersion;
+ this.epoch = epoch;
}
- public ShardBoundaries(List<Token> boundaries, long ringVersion)
+ public ShardBoundaries(List<Token> boundaries, Epoch epoch)
{
- this(boundaries.toArray(EMPTY_TOKEN_ARRAY), ringVersion);
+ this(boundaries.toArray(EMPTY_TOKEN_ARRAY), epoch);
}
/**
diff --git a/src/java/org/apache/cassandra/db/partitions/PartitionUpdate.java b/src/java/org/apache/cassandra/db/partitions/PartitionUpdate.java
index 1047fc0a70..9f25468495 100644
--- a/src/java/org/apache/cassandra/db/partitions/PartitionUpdate.java
+++ b/src/java/org/apache/cassandra/db/partitions/PartitionUpdate.java
@@ -35,11 +35,17 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.filter.ColumnFilter;
import org.apache.cassandra.db.rows.*;
+import org.apache.cassandra.exceptions.CoordinatorBehindException;
+import org.apache.cassandra.exceptions.UnknownTableException;
import org.apache.cassandra.index.IndexRegistry;
import org.apache.cassandra.io.util.DataInputBuffer;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.io.util.DataOutputPlus;
+import org.apache.cassandra.metrics.TCMMetrics;
+import org.apache.cassandra.tcm.ClusterMetadata;
+import org.apache.cassandra.tcm.Epoch;
+import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.TableId;
@@ -73,10 +79,12 @@ public class PartitionUpdate extends AbstractBTreePartition
private final BTreePartitionData holder;
private final DeletionInfo deletionInfo;
private final TableMetadata metadata;
+ public final Epoch serializedAtEpoch;
private final boolean canHaveShadowedData;
private PartitionUpdate(TableMetadata metadata,
+ Epoch serializedAtEpoch,
DecoratedKey key,
BTreePartitionData holder,
MutableDeletionInfo deletionInfo,
@@ -87,6 +95,7 @@ public class PartitionUpdate extends AbstractBTreePartition
this.holder = holder;
this.deletionInfo = deletionInfo;
this.canHaveShadowedData = canHaveShadowedData;
+ this.serializedAtEpoch = serializedAtEpoch;
}
/**
@@ -101,7 +110,7 @@ public class PartitionUpdate extends AbstractBTreePartition
{
MutableDeletionInfo deletionInfo = MutableDeletionInfo.live();
BTreePartitionData holder = new BTreePartitionData(RegularAndStaticColumns.NONE, BTree.empty(), deletionInfo, Rows.EMPTY_STATIC_ROW, EncodingStats.NO_STATS);
- return new PartitionUpdate(metadata, key, holder, deletionInfo, false);
+ return new PartitionUpdate(metadata, metadata.epoch, key, holder, deletionInfo, false);
}
/**
@@ -118,7 +127,7 @@ public class PartitionUpdate extends AbstractBTreePartition
{
MutableDeletionInfo deletionInfo = new MutableDeletionInfo(timestamp, nowInSec);
BTreePartitionData holder = new BTreePartitionData(RegularAndStaticColumns.NONE, BTree.empty(), deletionInfo, Rows.EMPTY_STATIC_ROW, EncodingStats.NO_STATS);
- return new PartitionUpdate(metadata, key, holder, deletionInfo, false);
+ return new PartitionUpdate(metadata, metadata.epoch, key, holder, deletionInfo, false);
}
/**
@@ -144,7 +153,7 @@ public class PartitionUpdate extends AbstractBTreePartition
staticRow == null ? Rows.EMPTY_STATIC_ROW : staticRow,
EncodingStats.NO_STATS
);
- return new PartitionUpdate(metadata, key, holder, deletionInfo, false);
+ return new PartitionUpdate(metadata, metadata.epoch, key, holder, deletionInfo, false);
}
/**
@@ -191,7 +200,7 @@ public class PartitionUpdate extends AbstractBTreePartition
iterator = UnfilteredRowIterators.withOnlyQueriedData(iterator, filter);
BTreePartitionData holder = build(iterator, 16);
MutableDeletionInfo deletionInfo = (MutableDeletionInfo) holder.deletionInfo;
- return new PartitionUpdate(iterator.metadata(), iterator.partitionKey(), holder, deletionInfo, false);
+ return new PartitionUpdate(iterator.metadata(), iterator.metadata().epoch, iterator.partitionKey(), holder, deletionInfo, false);
}
/**
@@ -210,7 +219,7 @@ public class PartitionUpdate extends AbstractBTreePartition
iterator = RowIterators.withOnlyQueriedData(iterator, filter);
MutableDeletionInfo deletionInfo = MutableDeletionInfo.live();
BTreePartitionData holder = build(iterator, deletionInfo, true);
- return new PartitionUpdate(iterator.metadata(), iterator.partitionKey(), holder, deletionInfo, false);
+ return new PartitionUpdate(iterator.metadata(), iterator.metadata().epoch, iterator.partitionKey(), holder, deletionInfo, false);
}
@@ -223,7 +232,7 @@ public class PartitionUpdate extends AbstractBTreePartition
columnSet.add(column.column());
RegularAndStaticColumns columns = RegularAndStaticColumns.builder().addAll(columnSet).build();
- return new PartitionUpdate(this.metadata, this.partitionKey, this.holder.withColumns(columns), this.deletionInfo.mutableCopy(), false);
+ return new PartitionUpdate(this.metadata, this.metadata.epoch, this.partitionKey, this.holder.withColumns(columns), this.deletionInfo.mutableCopy(), false);
}
@@ -465,7 +474,7 @@ public class PartitionUpdate extends AbstractBTreePartition
/**
*
- * @return the estimated number of rows affected by this mutation
+ * @return the estimated number of rows affected by this mutation
*/
public int affectedRowCount()
{
@@ -506,7 +515,7 @@ public class PartitionUpdate extends AbstractBTreePartition
for (Row row : this)
{
if (row.deletion().isLive())
- // If the row is live, this will include simple tombstones as well as cells w/ actual data.
+ // If the row is live, this will include simple tombstones as well as cells w/ actual data.
count += row.columnCount();
else
// We have a row deletion, so account for the columns that might be deleted.
@@ -539,7 +548,14 @@ public class PartitionUpdate extends AbstractBTreePartition
*/
public static SimpleBuilder simpleBuilder(TableMetadata metadata, Object... partitionKeyValues)
{
- return new SimpleBuilders.PartitionUpdateBuilder(metadata, partitionKeyValues);
+ // Here we dereference the current version of the supplied TableMetadata. The reason for this is that in some
+ // places we still reference static TableMetadata instances.
+ // For instance, TraceKeyspace contains Sessions & Events static members which are created at startup when the
+ // current epoch is Epoch.EMPTY. These are used to construct mutations when tracing is enabled and when the
+ // mutations are serialised and sent between replica & coordinator the epoch comparisons in PartitionUpdate
+ // deserializer trigger an IncompatibleSchemaException.
+ // TODO ultimately remove the use of static TableMetadata instances in System/Tracing/Auth keyspaces.
+ return new SimpleBuilders.PartitionUpdateBuilder(metadata.ref.get(), partitionKeyValues);
}
public void validateIndexedColumns()
@@ -554,7 +570,7 @@ public class PartitionUpdate extends AbstractBTreePartition
MutableDeletionInfo deletionInfo,
boolean canHaveShadowedData)
{
- return new PartitionUpdate(metadata, key, holder, deletionInfo, canHaveShadowedData);
+ return new PartitionUpdate(metadata, metadata.epoch, key, holder, deletionInfo, canHaveShadowedData);
}
/**
@@ -713,24 +729,45 @@ public class PartitionUpdate extends AbstractBTreePartition
assert !iter.isReverseOrder();
update.metadata.id.serialize(out);
+ if (version >= MessagingService.VERSION_50)
+ Epoch.serializer.serialize(update.metadata.epoch != null ? update.metadata.epoch : Epoch.EMPTY, out);
UnfilteredRowIteratorSerializer.serializer.serialize(iter, null, out, version, update.rowCount());
}
}
public PartitionUpdate deserialize(DataInputPlus in, int version, DeserializationHelper.Flag flag) throws IOException
{
- TableMetadata metadata = Schema.instance.getExistingTableMetadata(TableId.deserialize(in));
- UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(metadata, null, in, version, flag);
+ TableId tableId = TableId.deserialize(in);
+ Epoch remoteVersion = null;
+ if (version >= MessagingService.VERSION_50)
+ remoteVersion = Epoch.serializer.deserialize(in);
+ TableMetadata tableMetadata;
+ try
+ {
+ tableMetadata = Schema.instance.getExistingTableMetadata(tableId);
+ }
+ catch (UnknownTableException e)
+ {
+ ClusterMetadata metadata = ClusterMetadata.current();
+ Epoch localCurrentEpoch = metadata.epoch;
+ if (remoteVersion != null && localCurrentEpoch.isAfter(remoteVersion))
+ {
+ TCMMetrics.instance.coordinatorBehindSchema.mark();
+ throw new CoordinatorBehindException(e.getMessage(), e);
+ }
+ throw e;
+ }
+ UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(tableMetadata, null, in, version, flag);
if (header.isEmpty)
- return emptyUpdate(metadata, header.key);
+ return emptyUpdate(tableMetadata, header.key);
assert !header.isReversed;
assert header.rowEstimate >= 0;
- MutableDeletionInfo.Builder deletionBuilder = MutableDeletionInfo.builder(header.partitionDeletion, metadata.comparator, false);
+ MutableDeletionInfo.Builder deletionBuilder = MutableDeletionInfo.builder(header.partitionDeletion, tableMetadata.comparator, false);
Object[] rows;
try (BTree.FastBuilder<Row> builder = BTree.fastBuilder();
- UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version, metadata, flag, header))
+ UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version, tableMetadata, flag, header))
{
while (partition.hasNext())
{
@@ -744,19 +781,27 @@ public class PartitionUpdate extends AbstractBTreePartition
}
MutableDeletionInfo deletionInfo = deletionBuilder.build();
- return new PartitionUpdate(metadata,
+ return new PartitionUpdate(tableMetadata,
+ remoteVersion,
header.key,
new BTreePartitionData(header.sHeader.columns(), rows, deletionInfo, header.staticRow, header.sHeader.stats()),
deletionInfo,
false);
}
- public static boolean isEmpty(ByteBuffer in, DeserializationHelper.Flag flag, DecoratedKey key) throws IOException
+ public static boolean isEmpty(ByteBuffer in, DeserializationHelper.Flag flag, DecoratedKey key, int version) throws IOException
{
int position = in.position();
position += 16; // CFMetaData.serializer.deserialize(in, version);
if (position >= in.limit())
throw new EOFException();
+
+ if (version >= MessagingService.VERSION_50)
+ {
+ long epoch = VIntCoding.getUnsignedVInt(in, position);
+ position += VIntCoding.computeVIntSize(epoch);
+ }
+
// DecoratedKey key = metadata.decorateKey(ByteBufferUtil.readWithVIntLength(in));
int keyLength = VIntCoding.getUnsignedVInt32(in, position);
position += keyLength + VIntCoding.computeUnsignedVIntSize(keyLength);
@@ -771,6 +816,7 @@ public class PartitionUpdate extends AbstractBTreePartition
try (UnfilteredRowIterator iter = update.unfilteredIterator())
{
return update.metadata.id.serializedSize()
+ + (version >= MessagingService.VERSION_50 ? Epoch.serializer.serializedSize(update.metadata.epoch) : 0)
+ UnfilteredRowIteratorSerializer.serializer.serializedSize(iter, null, version, update.rowCount());
}
}
@@ -964,6 +1010,7 @@ public class PartitionUpdate extends AbstractBTreePartition
isBuilt = true;
return new PartitionUpdate(metadata,
+ metadata.epoch,
partitionKey(),
new BTreePartitionData(columns,
merged,
diff --git a/src/java/org/apache/cassandra/db/streaming/CassandraCompressedStreamReader.java b/src/java/org/apache/cassandra/db/streaming/CassandraCompressedStreamReader.java
index 0e0fcaa960..db5fb25373 100644
--- a/src/java/org/apache/cassandra/db/streaming/CassandraCompressedStreamReader.java
+++ b/src/java/org/apache/cassandra/db/streaming/CassandraCompressedStreamReader.java
@@ -74,8 +74,8 @@ public class CassandraCompressedStreamReader extends CassandraStreamReader
try (CompressedInputStream cis = new CompressedInputStream(inputPlus, compressionInfo, ChecksumType.CRC32, cfs::getCrcCheckChance))
{
TrackedDataInputPlus in = new TrackedDataInputPlus(cis);
- deserializer = new StreamDeserializer(cfs.metadata(), in, inputVersion, getHeader(cfs.metadata()));
writer = createWriter(cfs, totalSize, repairedAt, pendingRepair, inputVersion.format);
+ deserializer = new StreamDeserializer(cfs.metadata(), in, inputVersion, getHeader(cfs.metadata()), session, writer);
String filename = writer.getFilename();
String sectionName = filename + '-' + fileSeqNum;
int sectionIdx = 0;
diff --git a/src/java/org/apache/cassandra/db/streaming/CassandraStreamReader.java b/src/java/org/apache/cassandra/db/streaming/CassandraStreamReader.java
index 9819d4cf27..af4b4dbc18 100644
--- a/src/java/org/apache/cassandra/db/streaming/CassandraStreamReader.java
+++ b/src/java/org/apache/cassandra/db/streaming/CassandraStreamReader.java
@@ -20,6 +20,9 @@ package org.apache.cassandra.db.streaming;
import java.io.IOError;
import java.io.IOException;
import java.util.Collection;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.concurrent.TimeUnit;
import com.google.common.base.Preconditions;
import com.google.common.collect.UnmodifiableIterator;
@@ -38,6 +41,8 @@ import org.apache.cassandra.db.rows.EncodingStats;
import org.apache.cassandra.db.rows.Row;
import org.apache.cassandra.db.rows.Unfiltered;
import org.apache.cassandra.db.rows.UnfilteredRowIterator;
+import org.apache.cassandra.dht.Range;
+import org.apache.cassandra.dht.Token;
import org.apache.cassandra.exceptions.UnknownColumnException;
import org.apache.cassandra.io.sstable.RangeAwareSSTableWriter;
import org.apache.cassandra.io.sstable.SSTableMultiWriter;
@@ -47,15 +52,19 @@ import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.sstable.format.Version;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.TrackedDataInputPlus;
+import org.apache.cassandra.metrics.StorageMetrics;
import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
+import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.streaming.ProgressInfo;
+import org.apache.cassandra.streaming.StreamReceivedOutOfTokenRangeException;
import org.apache.cassandra.streaming.StreamReceiver;
import org.apache.cassandra.streaming.StreamSession;
import org.apache.cassandra.streaming.compress.StreamCompressionInputStream;
import org.apache.cassandra.streaming.messages.StreamMessageHeader;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.NoSpamLogger;
import org.apache.cassandra.utils.TimeUUID;
import static org.apache.cassandra.net.MessagingService.current_version;
@@ -66,6 +75,7 @@ import static org.apache.cassandra.net.MessagingService.current_version;
public class CassandraStreamReader implements IStreamReader
{
private static final Logger logger = LoggerFactory.getLogger(CassandraStreamReader.class);
+ private static final String logMessageTemplate = "[Stream #{}] Received streamed SSTable {} from {} containing key outside valid ranges {}";
protected final TableId tableId;
protected final long estimatedKeys;
protected final Collection<SSTableReader.PartitionPositionBounds> sections;
@@ -121,8 +131,8 @@ public class CassandraStreamReader implements IStreamReader
try (StreamCompressionInputStream streamCompressionInputStream = new StreamCompressionInputStream(inputPlus, current_version))
{
TrackedDataInputPlus in = new TrackedDataInputPlus(streamCompressionInputStream);
- deserializer = new StreamDeserializer(cfs.metadata(), in, inputVersion, getHeader(cfs.metadata()));
writer = createWriter(cfs, totalSize, repairedAt, pendingRepair, inputVersion.format);
+ deserializer = getDeserializer(cfs.metadata(), in, inputVersion, session, writer);
String sequenceName = writer.getFilename() + '-' + fileSeqNum;
long lastBytesRead = 0;
while (in.getBytesRead() < totalSize)
@@ -149,6 +159,15 @@ public class CassandraStreamReader implements IStreamReader
}
}
+ protected StreamDeserializer getDeserializer(TableMetadata metadata,
+ TrackedDataInputPlus in,
+ Version inputVersion,
+ StreamSession session,
+ SSTableMultiWriter writer) throws IOException
+ {
+ return new StreamDeserializer(metadata, in, inputVersion, getHeader(metadata), session, writer);
+ }
+
protected SerializationHeader getHeader(TableMetadata metadata) throws UnknownColumnException
{
return header != null? header.toHeader(metadata) : null; //pre-3.0 sstable have no SerializationHeader
@@ -188,29 +207,52 @@ public class CassandraStreamReader implements IStreamReader
private final SerializationHeader header;
private final DeserializationHelper helper;
- private DecoratedKey key;
- private DeletionTime partitionLevelDeletion;
- private SSTableSimpleIterator iterator;
- private Row staticRow;
+ private final List<Range<Token>> ownedRanges;
+ private final StreamSession session;
+ private final SSTableMultiWriter writer;
+
+ private int lastCheckedRangeIndex;
+ protected DecoratedKey key;
+ protected DeletionTime partitionLevelDeletion;
+ protected SSTableSimpleIterator iterator;
+ protected Row staticRow;
private IOException exception;
private Version version;
- public StreamDeserializer(TableMetadata metadata, DataInputPlus in, Version version, SerializationHeader header) throws IOException
+ public StreamDeserializer(TableMetadata metadata, DataInputPlus in, Version version, SerializationHeader header, StreamSession session, SSTableMultiWriter writer) throws IOException
{
this.metadata = metadata;
this.in = in;
this.helper = new DeserializationHelper(metadata, version.correspondingMessagingVersion(), DeserializationHelper.Flag.PRESERVE_SIZE);
this.header = header;
this.version = version;
+ ownedRanges = Range.normalize(StorageService.instance.getLocalAndPendingRanges(metadata.keyspace));
+ lastCheckedRangeIndex = 0;
+
+ this.session = session;
+ this.writer = writer;
}
- public StreamDeserializer newPartition() throws IOException
+ public UnfilteredRowIterator newPartition() throws IOException
+ {
+ readKey();
+ readPartition();
+ return this;
+ }
+
+ protected void readKey() throws IOException
{
key = metadata.partitioner.decorateKey(ByteBufferUtil.readWithShortLength(in));
+ lastCheckedRangeIndex = verifyKeyInOwnedRanges(key,
+ ownedRanges,
+ lastCheckedRangeIndex);
+ }
+
+ protected void readPartition() throws IOException
+ {
partitionLevelDeletion = DeletionTime.getSerializer(version).deserialize(in);
iterator = SSTableSimpleIterator.create(metadata, in, header, helper, partitionLevelDeletion);
staticRow = iterator.readStaticRow();
- return this;
}
public TableMetadata metadata()
@@ -291,5 +333,27 @@ public class CassandraStreamReader implements IStreamReader
public void close()
{
}
+
+ private int verifyKeyInOwnedRanges(final DecoratedKey key,
+ List<Range<Token>> ownedRanges,
+ int lastCheckedRangeIndex)
+ {
+ if (lastCheckedRangeIndex < ownedRanges.size())
+ {
+ ListIterator<Range<Token>> rangesToCheck = ownedRanges.listIterator(lastCheckedRangeIndex);
+ while (rangesToCheck.hasNext())
+ {
+ Range<Token> range = rangesToCheck.next();
+ if (range.contains(key.getToken()))
+ return lastCheckedRangeIndex;
+
+ lastCheckedRangeIndex++;
+ }
+ }
+
+ StorageMetrics.totalOpsForInvalidToken.inc();
+ NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, 1, TimeUnit.SECONDS, logMessageTemplate, session.planId(), writer.getFilename(), session.peer, ownedRanges);
+ throw new StreamReceivedOutOfTokenRangeException(ownedRanges, key, writer.getFilename());
+ }
}
}
diff --git a/src/java/org/apache/cassandra/db/view/TableViews.java b/src/java/org/apache/cassandra/db/view/TableViews.java
index 366d4278e0..f717e3ec85 100644
--- a/src/java/org/apache/cassandra/db/view/TableViews.java
+++ b/src/java/org/apache/cassandra/db/view/TableViews.java
@@ -17,7 +17,14 @@
*/
package org.apache.cassandra.db.view;
-import java.util.*;
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -27,14 +34,36 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
-import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.Clustering;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.DecoratedKey;
+import org.apache.cassandra.db.DeletionInfo;
+import org.apache.cassandra.db.DeletionTime;
+import org.apache.cassandra.db.Keyspace;
+import org.apache.cassandra.db.Mutation;
+import org.apache.cassandra.db.RangeTombstone;
+import org.apache.cassandra.db.ReadExecutionController;
+import org.apache.cassandra.db.ReadQuery;
+import org.apache.cassandra.db.SinglePartitionReadCommand;
+import org.apache.cassandra.db.Slice;
+import org.apache.cassandra.db.Slices;
+import org.apache.cassandra.db.SystemKeyspace;
import org.apache.cassandra.db.commitlog.CommitLogPosition;
-import org.apache.cassandra.db.filter.*;
-import org.apache.cassandra.db.partitions.*;
-import org.apache.cassandra.db.rows.*;
+import org.apache.cassandra.db.filter.ClusteringIndexFilter;
+import org.apache.cassandra.db.filter.ClusteringIndexNamesFilter;
+import org.apache.cassandra.db.filter.ClusteringIndexSliceFilter;
+import org.apache.cassandra.db.filter.ColumnFilter;
+import org.apache.cassandra.db.filter.DataLimits;
+import org.apache.cassandra.db.filter.RowFilter;
+import org.apache.cassandra.db.partitions.PartitionUpdate;
+import org.apache.cassandra.db.partitions.UnfilteredPartitionIterators;
+import org.apache.cassandra.db.rows.BTreeRow;
+import org.apache.cassandra.db.rows.RangeTombstoneMarker;
+import org.apache.cassandra.db.rows.Row;
+import org.apache.cassandra.db.rows.Rows;
+import org.apache.cassandra.db.rows.Unfiltered;
+import org.apache.cassandra.db.rows.UnfilteredRowIterator;
import org.apache.cassandra.dht.Token;
-import org.apache.cassandra.schema.Schema;
-import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.schema.TableMetadataRef;
import org.apache.cassandra.service.StorageProxy;
@@ -57,9 +86,9 @@ public class TableViews extends AbstractCollection<View>
// list is the best option.
private final List<View> views = new CopyOnWriteArrayList();
- public TableViews(TableId id)
+ public TableViews(TableMetadata tableMetadata)
{
- baseTableMetadata = Schema.instance.getTableMetadataRef(id);
+ baseTableMetadata = tableMetadata.ref;
}
public boolean hasViews()
diff --git a/src/java/org/apache/cassandra/db/view/ViewBuilder.java b/src/java/org/apache/cassandra/db/view/ViewBuilder.java
index daedf48f29..c59cfec855 100644
--- a/src/java/org/apache/cassandra/db/view/ViewBuilder.java
+++ b/src/java/org/apache/cassandra/db/view/ViewBuilder.java
@@ -43,6 +43,7 @@ import org.apache.cassandra.locator.RangesAtEndpoint;
import org.apache.cassandra.locator.Replicas;
import org.apache.cassandra.schema.SystemDistributedKeyspace;
import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.tcm.ClusterMetadata;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.concurrent.Future;
@@ -66,7 +67,7 @@ class ViewBuilder
private final ColumnFamilyStore baseCfs;
private final View view;
private final String ksName;
- private final UUID localHostId = SystemKeyspace.getOrInitializeLocalHostId();
+ private final UUID localHostId;
private final Set<Range<Token>> builtRanges = Sets.newConcurrentHashSet();
private final Map<Range<Token>, Pair<Token, Long>> pendingRanges = Maps.newConcurrentMap();
private final Set<ViewBuilderTask> tasks = Sets.newConcurrentHashSet();
@@ -79,6 +80,7 @@ class ViewBuilder
this.baseCfs = baseCfs;
this.view = view;
ksName = baseCfs.metadata.keyspace;
+ this.localHostId = ClusterMetadata.current().myNodeId().toUUID();
}
public void start()
diff --git a/src/java/org/apache/cassandra/db/view/ViewBuilderTask.java b/src/java/org/apache/cassandra/db/view/ViewBuilderTask.java
index 7bda2fddac..0b53542c7d 100644
--- a/src/java/org/apache/cassandra/db/view/ViewBuilderTask.java
+++ b/src/java/org/apache/cassandra/db/view/ViewBuilderTask.java
@@ -110,7 +110,7 @@ public class ViewBuilderTask extends CompactionInfo.Holder implements Callable<L
UnfilteredRowIterator data = UnfilteredPartitionIterators.getOnlyElement(command.executeLocally(orderGroup), command))
{
Iterator<Collection<Mutation>> mutations = baseCfs.keyspace.viewManager
- .forTable(baseCfs.metadata.id)
+ .forTable(baseCfs.metadata.get())
.generateViewUpdates(Collections.singleton(view), data, empty, nowInSec, true);
AtomicLong noBase = new AtomicLong(Long.MAX_VALUE);
diff --git a/src/java/org/apache/cassandra/db/view/ViewManager.java b/src/java/org/apache/cassandra/db/view/ViewManager.java
index 106a15fdd9..cf6b916e05 100644
--- a/src/java/org/apache/cassandra/db/view/ViewManager.java
+++ b/src/java/org/apache/cassandra/db/view/ViewManager.java
@@ -28,12 +28,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.schema.TableId;
-import org.apache.cassandra.schema.ViewMetadata;
+import org.apache.cassandra.schema.*;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.partitions.*;
-import org.apache.cassandra.schema.SystemDistributedKeyspace;
-import org.apache.cassandra.schema.Views;
import org.apache.cassandra.service.StorageService;
import static org.apache.cassandra.config.CassandraRelevantProperties.MV_ENABLE_COORDINATOR_BATCHLOG;
@@ -84,7 +81,7 @@ public class ViewManager
if (coordinatorBatchlog && keyspace.getReplicationStrategy().getReplicationFactor().allReplicas == 1)
continue;
- if (!forTable(update.metadata().id).updatedViews(update).isEmpty())
+ if (!forTable(update.metadata()).updatedViews(update).isEmpty())
return true;
}
}
@@ -97,9 +94,9 @@ public class ViewManager
return viewsByName.values();
}
- public void reload(boolean buildAllViews)
+ public void reload(KeyspaceMetadata keyspaceMetadata)
{
- Views views = keyspace.getMetadata().views;
+ Views views = keyspaceMetadata.views;
Map<String, ViewMetadata> newViewsByName = Maps.newHashMapWithExpectedSize(views.size());
for (ViewMetadata definition : views)
{
@@ -111,10 +108,16 @@ public class ViewManager
if (!viewsByName.containsKey(entry.getKey()))
addView(entry.getValue());
}
+ }
- if (!buildAllViews)
- return;
-
+ public void buildViews()
+ {
+ Views views = keyspace.getMetadata().views;
+ Map<String, ViewMetadata> newViewsByName = Maps.newHashMapWithExpectedSize(views.size());
+ for (ViewMetadata definition : views)
+ {
+ newViewsByName.put(definition.name(), definition);
+ }
// Building views involves updating view build status in the system_distributed
// keyspace and therefore it requires ring information. This check prevents builds
// being submitted when Keyspaces are initialized during CassandraDaemon::setup as
@@ -149,7 +152,7 @@ public class ViewManager
}
View view = new View(definition, keyspace.getColumnFamilyStore(definition.baseTableId));
- forTable(view.getDefinition().baseTableId).add(view);
+ forTable(keyspace.getMetadata().tables.getNullable(view.getDefinition().baseTableId)).add(view);
viewsByName.put(definition.name(), view);
}
@@ -166,7 +169,7 @@ public class ViewManager
return;
view.stopBuild();
- forTable(view.getDefinition().baseTableId).removeByName(name);
+ forTable(view.getDefinition().baseTableMetadata()).removeByName(name);
SystemKeyspace.setViewRemoved(keyspace.getName(), view.name);
SystemDistributedKeyspace.setViewRemoved(keyspace.getName(), view.name);
}
@@ -182,13 +185,13 @@ public class ViewManager
view.build();
}
- public TableViews forTable(TableId id)
+ public TableViews forTable(TableMetadata metadata)
{
- TableViews views = viewsByBaseTable.get(id);
+ TableViews views = viewsByBaseTable.get(metadata.id);
if (views == null)
{
- views = new TableViews(id);
- TableViews previous = viewsByBaseTable.putIfAbsent(id, views);
+ views = new TableViews(metadata);
+ TableViews previous = viewsByBaseTable.putIfAbsent(metadata.id, views);
if (previous != null)
views = previous;
}
diff --git a/src/java/org/apache/cassandra/db/view/ViewUtils.java b/src/java/org/apache/cassandra/db/view/ViewUtils.java
index 55a462c31b..b41150b7a5 100644
--- a/src/java/org/apache/cassandra/db/view/ViewUtils.java
+++ b/src/java/org/apache/cassandra/db/view/ViewUtils.java
@@ -24,10 +24,11 @@ import java.util.function.Predicate;
import com.google.common.collect.Iterables;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.Token;
-import org.apache.cassandra.locator.AbstractReplicationStrategy;
import org.apache.cassandra.locator.EndpointsForToken;
import org.apache.cassandra.locator.NetworkTopologyStrategy;
import org.apache.cassandra.locator.Replica;
+import org.apache.cassandra.schema.KeyspaceMetadata;
+import org.apache.cassandra.tcm.ClusterMetadata;
public final class ViewUtils
{
@@ -57,11 +58,13 @@ public final class ViewUtils
*
* @return Optional.empty() if this method is called using a base token which does not belong to this replica
*/
- public static Optional<Replica> getViewNaturalEndpoint(AbstractReplicationStrategy replicationStrategy, Token baseToken, Token viewToken)
+ public static Optional<Replica> getViewNaturalEndpoint(ClusterMetadata metadata, String keyspace, Token baseToken, Token viewToken)
{
String localDataCenter = DatabaseDescriptor.getEndpointSnitch().getLocalDatacenter();
- EndpointsForToken naturalBaseReplicas = replicationStrategy.getNaturalReplicasForToken(baseToken);
- EndpointsForToken naturalViewReplicas = replicationStrategy.getNaturalReplicasForToken(viewToken);
+ KeyspaceMetadata keyspaceMetadata = metadata.schema.getKeyspaces().getNullable(keyspace);
+
+ EndpointsForToken naturalBaseReplicas = metadata.placements.get(keyspaceMetadata.params.replication).reads.forToken(baseToken).get();
+ EndpointsForToken naturalViewReplicas = metadata.placements.get(keyspaceMetadata.params.replication).reads.forToken(viewToken).get();
Optional<Replica> localReplica = Iterables.tryFind(naturalViewReplicas, Replica::isSelf).toJavaUtil();
if (localReplica.isPresent())
@@ -69,7 +72,7 @@ public final class ViewUtils
// We only select replicas from our own DC
// TODO: this is poor encapsulation, leaking implementation details of replication strategy
- Predicate<Replica> isLocalDC = r -> !(replicationStrategy instanceof NetworkTopologyStrategy)
+ Predicate<Replica> isLocalDC = r -> !(keyspaceMetadata.replicationStrategy instanceof NetworkTopologyStrategy)
|| DatabaseDescriptor.getEndpointSnitch().getDatacenter(r).equals(localDataCenter);
// We have to remove any endpoint which is shared between the base and the view, as it will select itself
@@ -84,7 +87,9 @@ public final class ViewUtils
// The replication strategy will be the same for the base and the view, as they must belong to the same keyspace.
// Since the same replication strategy is used, the same placement should be used and we should get the same
// number of replicas for all of the tokens in the ring.
- assert baseReplicas.size() == viewReplicas.size() : "Replication strategy should have the same number of endpoints for the base and the view";
+ assert baseReplicas.size() == viewReplicas.size() :
+ String.format("Replication strategy should have the same number of endpoints for the base (%d) and the view (%d)",
+ baseReplicas.size(), viewReplicas.size());
int baseIdx = -1;
for (int i=0; i<baseReplicas.size(); i++)
diff --git a/src/java/org/apache/cassandra/db/virtual/ClusterMetadataLogTable.java b/src/java/org/apache/cassandra/db/virtual/ClusterMetadataLogTable.java
new file mode 100644
index 0000000000..4316a82cc0
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/virtual/ClusterMetadataLogTable.java
@@ -0,0 +1,87 @@
+/*
+ * 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
... 109788 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org