/** Compares our trees, and triggers repairs for any ranges that mismatch. */ public void run() { InetAddress local = FBUtilities.getLocalAddress(); // restore partitioners (in case we were serialized) if (ltree.partitioner() == null) ltree.partitioner(StorageService.getPartitioner()); if (rtree.partitioner() == null) rtree.partitioner(StorageService.getPartitioner()); // compare trees, and collect differences differences.addAll(MerkleTree.difference(ltree, rtree)); // choose a repair method based on the significance of the difference String format = "Endpoints " + local + " and " + remote + " %s for " + cfname + " on " + range; if (differences.isEmpty()) { logger.info(String.format(format, "are consistent")); completed(remote, cfname); return; } // non-0 difference: perform streaming repair logger.info(String.format(format, "have " + differences.size() + " range(s) out of sync")); try { performStreamingRepair(); } catch (IOException e) { throw new RuntimeException(e); } }
/** @param params */ public void initParams(GpsParams params, StorageService service) { /* * Comes from storage service. This will do nothing for fresh start, * but it will load previous combo on re-activation */ mService = service; mMovement = mService.getMovement(); mImageDataSource = mService.getDBResource(); if (null == mMovement) { mMovement = new Movement(); } mPan = mService.getPan(); if (null == mPan) { mPan = new Pan(); } if (null != params) { mGpsParams = params; } else if (null != mDestination) { mGpsParams = new GpsParams(mDestination.getLocation()); } else { mGpsParams = new GpsParams(null); } mScale.setScaleAt(mGpsParams.getLatitude()); dbquery(true); postInvalidate(); }
/** * update storage summary with binaries repositories * * @param storageSummaryModel - storageSummary Model */ private void updateFileStoreSummary(StorageSummaryImpl storageSummaryModel) { StorageService storageService = ContextHelper.get().beanForType(StorageService.class); FileStoreStorageSummary fileStoreSummaryInfo = storageService.getFileStoreStorageSummary(); FileStoreSummary fileStoreSummary = new FileStoreSummary(); fileStoreSummary.setStorageType(fileStoreSummaryInfo.getBinariesStorageType().toString()); List<File> binariesFolders = fileStoreSummaryInfo.getBinariesFolders(); String storageDirLabel = "Filesystem storage is not used"; if (binariesFolders != null && !binariesFolders.isEmpty()) { storageDirLabel = String.join( ", ", binariesFolders.stream().map(File::getAbsolutePath).collect(Collectors.toList())); } fileStoreSummary.setStorageDirectory(storageDirLabel); fileStoreSummary.setTotalSpace( StorageUnit.toReadableString(fileStoreSummaryInfo.getTotalSpace())); fileStoreSummary.setUsedSpace( StorageUnit.toReadableString(fileStoreSummaryInfo.getUsedSpace()) + " (" + NumberFormatter.formatPercentage(fileStoreSummaryInfo.getUsedSpaceFraction()) + ")"); fileStoreSummary.setFreeSpace( StorageUnit.toReadableString(fileStoreSummaryInfo.getFreeSpace()) + " (" + NumberFormatter.formatPercentage(fileStoreSummaryInfo.getFreeSpaceFraction()) + ")"); storageSummaryModel.setFileStoreSummary(fileStoreSummary); }
@Test public void testFileSystemUpload() throws IOException { StorageService service = new FileSystemStorageService(); String url = service.upload(StorageServiceTest.class.getResourceAsStream("/test.jpg"), "test.jpg"); assertNotNull(url); }
/** * Tests that the system.peers table is not updated after a node has been removed. (See * CASSANDRA-6053) */ @Test public void testStateChangeOnRemovedNode() throws UnknownHostException { StorageService ss = StorageService.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); // create a ring of 2 nodes ArrayList<Token> endpointTokens = new ArrayList<>(); List<InetAddress> hosts = new ArrayList<>(); Util.createInitialRing( ss, partitioner, endpointTokens, new ArrayList<Token>(), hosts, new ArrayList<UUID>(), 2); InetAddress toRemove = hosts.get(1); SystemKeyspace.updatePeerInfo(toRemove, "data_center", "dc42"); SystemKeyspace.updatePeerInfo(toRemove, "rack", "rack42"); assertEquals("rack42", SystemKeyspace.loadDcRackInfo().get(toRemove).get("rack")); // mark the node as removed Gossiper.instance.injectApplicationState( toRemove, ApplicationState.STATUS, valueFactory.left( Collections.singleton(endpointTokens.get(1)), Gossiper.computeExpireTime())); assertTrue( Gossiper.instance.isDeadState(Gossiper.instance.getEndpointStateForEndpoint(hosts.get(1)))); // state changes made after the endpoint has left should be ignored ss.onChange(hosts.get(1), ApplicationState.RACK, valueFactory.rack("rack9999")); assertEquals("rack42", SystemKeyspace.loadDcRackInfo().get(toRemove).get("rack")); }
/** Return all of the neighbors with whom we share the provided range. */ static Set<InetAddress> getNeighbors(String table, Range<Token> toRepair) { StorageService ss = StorageService.instance; Map<Range<Token>, List<InetAddress>> replicaSets = ss.getRangeToAddressMap(table); Range<Token> rangeSuperSet = null; for (Range<Token> range : ss.getLocalRanges(table)) { if (range.contains(toRepair)) { rangeSuperSet = range; break; } else if (range.intersects(toRepair)) { throw new IllegalArgumentException( "Requested range intersects a local range but is not fully contained in one; this would lead to imprecise repair"); } } if (rangeSuperSet == null || !replicaSets.containsKey(toRepair)) return Collections.emptySet(); Set<InetAddress> neighbors = new HashSet<InetAddress>(replicaSets.get(rangeSuperSet)); neighbors.remove(FBUtilities.getBroadcastAddress()); // Excluding all node with version <= 0.7 since they don't know how to // create a correct merkle tree (they build it over the full range) Iterator<InetAddress> iter = neighbors.iterator(); while (iter.hasNext()) { InetAddress endpoint = iter.next(); if (Gossiper.instance.getVersion(endpoint) <= MessagingService.VERSION_07) { logger.info( "Excluding " + endpoint + " from repair because it is on version 0.7 or sooner. You should consider updating this node before running repair again."); iter.remove(); } } return neighbors; }
public static OrcStorageManager createOrcStorageManager( IDBI dbi, File temporary, int maxShardRows) throws IOException { File directory = new File(temporary, "data"); StorageService storageService = new FileStorageService(directory); storageService.start(); File backupDirectory = new File(temporary, "backup"); FileBackupStore fileBackupStore = new FileBackupStore(backupDirectory); fileBackupStore.start(); Optional<BackupStore> backupStore = Optional.of(fileBackupStore); ShardManager shardManager = createShardManager(dbi); ShardRecoveryManager recoveryManager = new ShardRecoveryManager( storageService, backupStore, new TestingNodeManager(), shardManager, MISSING_SHARD_DISCOVERY, 10); return createOrcStorageManager( storageService, backupStore, recoveryManager, new InMemoryShardRecorder(), maxShardRows, MAX_FILE_SIZE); }
@Test public void testStateJumpToLeft() throws UnknownHostException { StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); // create a ring of 6 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 7); // node hosts.get(2) goes jumps to left ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.left( Collections.singleton(endpointTokens.get(2)), Gossiper.computeExpireTime())); assertFalse(tmd.isMember(hosts.get(2))); // node hosts.get(4) goes to bootstrap Gossiper.instance.injectApplicationState( hosts.get(3), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(1)))); ss.onChange( hosts.get(3), ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(1)))); assertFalse(tmd.isMember(hosts.get(3))); assertEquals(1, tmd.getBootstrapTokens().size()); assertEquals(hosts.get(3), tmd.getBootstrapTokens().get(keyTokens.get(1))); // and then directly to 'left' Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(1)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.left(Collections.singleton(keyTokens.get(1)), Gossiper.computeExpireTime())); assertTrue(tmd.getBootstrapTokens().size() == 0); assertFalse(tmd.isMember(hosts.get(2))); assertFalse(tmd.isLeaving(hosts.get(2))); }
public TreeRequest deserialize(DataInput dis, int version) throws IOException { String sessId = dis.readUTF(); InetAddress endpoint = CompactEndpointSerializationHelper.deserialize(dis); CFPair cfpair = new CFPair(dis.readUTF(), dis.readUTF()); Range<Token> range; if (version > MessagingService.VERSION_07) range = (Range<Token>) AbstractBounds.serializer().deserialize(dis, version); else range = new Range<Token>( StorageService.getPartitioner().getMinimumToken(), StorageService.getPartitioner().getMinimumToken()); return new TreeRequest(sessId, endpoint, range, cfpair); }
/** * if initialtoken was specified, use that (split on comma). * otherwise, if num_tokens == 1, pick a token to assume half the load of the most-loaded node. * else choose num_tokens tokens at random */ public static Collection<Token> getBootstrapTokens(final TokenMetadata metadata) throws ConfigurationException { Collection<String> initialTokens = DatabaseDescriptor.getInitialTokens(); // if user specified tokens, use those if (initialTokens.size() > 0) { logger.debug("tokens manually specified as {}", initialTokens); List<Token> tokens = new ArrayList<Token>(initialTokens.size()); for (String tokenString : initialTokens) { Token token = StorageService.getPartitioner().getTokenFactory().fromString(tokenString); if (metadata.getEndpoint(token) != null) throw new ConfigurationException("Bootstrapping to existing token " + tokenString + " is not allowed (decommission/removenode the old node first)."); tokens.add(token); } return tokens; } int numTokens = DatabaseDescriptor.getNumTokens(); if (numTokens < 1) throw new ConfigurationException("num_tokens must be >= 1"); if (numTokens == 1) logger.warn("Picking random token for a single vnode. You should probably add more vnodes; failing that, you should probably specify the token manually"); return getRandomTokens(metadata, numTokens); }
/** @param canvas */ private void drawTFR(Canvas canvas) { mPaint.setColor(Color.RED); mPaint.setShadowLayer(0, 0, 0, 0); /* * Draw TFRs, weather */ if (mPref.shouldTFRAndMETARShow()) { LinkedList<TFRShape> shapes = null; if (null != mService) { shapes = mService.getTFRShapes(); } if (null != shapes) { mPaint.setColor(Color.RED); mPaint.setStrokeWidth(8); mPaint.setShadowLayer(0, 0, 0, 0); for (int shape = 0; shape < shapes.size(); shape++) { TFRShape cshape = shapes.get(shape); if (cshape.isVisible()) { /* * Find offsets of TFR then draw it */ cshape.drawShape(canvas, mOrigin, mScale, mMovement, mPaint, mFace); } } } } }
public static Collection<Token> getRandomTokens(TokenMetadata metadata, int numTokens) { Set<Token> tokens = new HashSet<Token>(numTokens); while (tokens.size() < numTokens) { Token token = StorageService.getPartitioner().getRandomToken(); if (metadata.getEndpoint(token) == null) tokens.add(token); } return tokens; }
private void doReadRepair() throws IOException { IResponseResolver<Row> readResponseResolver = new ReadResponseResolver(); /* Add the local storage endpoint to the replicas_ list */ replicas_.add(StorageService.getLocalStorageEndPoint()); IAsyncCallback responseHandler = new DataRepairHandler(ConsistencyManager.this.replicas_.size(), readResponseResolver); String table = DatabaseDescriptor.getTables().get(0); ReadMessage readMessage = new ReadMessage(table, row_.key(), columnFamily_); Message message = ReadMessage.makeReadMessage(readMessage); MessagingService.getMessagingInstance() .sendRR(message, replicas_.toArray(new EndPoint[0]), responseHandler); }
RangeNamesQueryPager( RangeSliceCommand command, ConsistencyLevel consistencyLevel, boolean localQuery, PagingState state) { this(command, consistencyLevel, localQuery); if (state != null) { lastReturnedKey = StorageService.getPartitioner().decorateKey(state.partitionKey); restoreState(state.remaining, true); } }
/** Return all of the neighbors with whom we share data. */ static Set<InetAddress> getNeighbors(String table, Range range) { StorageService ss = StorageService.instance; Map<Range, List<InetAddress>> replicaSets = ss.getRangeToAddressMap(table); if (!replicaSets.containsKey(range)) return Collections.emptySet(); Set<InetAddress> neighbors = new HashSet<InetAddress>(replicaSets.get(range)); neighbors.remove(FBUtilities.getLocalAddress()); // Excluding all node with version <= 0.7 since they don't know how to // create a correct merkle tree (they build it over the full range) Iterator<InetAddress> iter = neighbors.iterator(); while (iter.hasNext()) { InetAddress endpoint = iter.next(); if (Gossiper.instance.getVersion(endpoint) <= MessagingService.VERSION_07) { logger.info( "Excluding " + endpoint + " from repair because it is on version 0.7 or sooner. You should consider updating this node before running repair again."); iter.remove(); } } return neighbors; }
@Test public void testRemovingStatusForNonMember() throws UnknownHostException { // create a ring of 1 node StorageService ss = StorageService.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); Util.createInitialRing( ss, partitioner, new ArrayList<Token>(), new ArrayList<Token>(), new ArrayList<InetAddress>(), new ArrayList<UUID>(), 1); // make a REMOVING state change on a non-member endpoint; without the CASSANDRA-6564 fix, this // would result in an ArrayIndexOutOfBoundsException ss.onChange( InetAddress.getByName("192.168.1.42"), ApplicationState.STATUS, valueFactory.removingNonlocal(UUID.randomUUID())); }
/** Compares our trees, and triggers repairs for any ranges that mismatch. */ public void run() { // restore partitioners (in case we were serialized) if (r1.tree.partitioner() == null) r1.tree.partitioner(StorageService.getPartitioner()); if (r2.tree.partitioner() == null) r2.tree.partitioner(StorageService.getPartitioner()); // compare trees, and collect differences differences.addAll(MerkleTree.difference(r1.tree, r2.tree)); // choose a repair method based on the significance of the difference String format = String.format( "[repair #%s] Endpoints %s and %s %%s for %s", getName(), r1.endpoint, r2.endpoint, cfname); if (differences.isEmpty()) { logger.info(String.format(format, "are consistent")); completed(this); return; } // non-0 difference: perform streaming repair logger.info(String.format(format, "have " + differences.size() + " range(s) out of sync")); performStreamingRepair(); }
@Test public void testRewriter() throws Exception { OrcStorageManager manager = createOrcStorageManager(); long transactionId = TRANSACTION_ID; List<Long> columnIds = ImmutableList.of(3L, 7L); List<Type> columnTypes = ImmutableList.<Type>of(BIGINT, createVarcharType(10)); // create file with 2 rows StoragePageSink sink = createStoragePageSink(manager, columnIds, columnTypes); List<Page> pages = rowPagesBuilder(columnTypes).row(123L, "hello").row(456L, "bye").build(); sink.appendPages(pages); List<ShardInfo> shards = getFutureValue(sink.commit()); assertEquals(shardRecorder.getShards().size(), 1); // delete one row BitSet rowsToDelete = new BitSet(); rowsToDelete.set(0); Collection<Slice> fragments = manager.rewriteShard( transactionId, OptionalInt.empty(), shards.get(0).getShardUuid(), rowsToDelete); Slice shardDelta = Iterables.getOnlyElement(fragments); ShardDelta shardDeltas = jsonCodec(ShardDelta.class).fromJson(shardDelta.getBytes()); ShardInfo shardInfo = Iterables.getOnlyElement(shardDeltas.getNewShards()); // check that output file has one row assertEquals(shardInfo.getRowCount(), 1); // check that storage file is same as backup file File storageFile = storageService.getStorageFile(shardInfo.getShardUuid()); File backupFile = fileBackupStore.getBackupFile(shardInfo.getShardUuid()); assertFileEquals(storageFile, backupFile); // verify recorded shard List<RecordedShard> recordedShards = shardRecorder.getShards(); assertEquals(recordedShards.size(), 2); assertEquals(recordedShards.get(1).getTransactionId(), TRANSACTION_ID); assertEquals(recordedShards.get(1).getShardUuid(), shardInfo.getShardUuid()); }
@BeforeMethod public void setup() throws Exception { temporary = createTempDir(); File directory = new File(temporary, "data"); storageService = new FileStorageService(directory); storageService.start(); File backupDirectory = new File(temporary, "backup"); fileBackupStore = new FileBackupStore(backupDirectory); fileBackupStore.start(); backupStore = Optional.of(fileBackupStore); IDBI dbi = new DBI("jdbc:h2:mem:test" + System.nanoTime()); dummyHandle = dbi.open(); ShardManager shardManager = createShardManager(dbi); Duration discoveryInterval = new Duration(5, TimeUnit.MINUTES); recoveryManager = new ShardRecoveryManager( storageService, backupStore, nodeManager, shardManager, discoveryInterval, 10); shardRecorder = new InMemoryShardRecorder(); }
/** * Test whether write endpoints is correct when the node is leaving. Uses StorageService.onChange * and does not manipulate token metadata directly. */ @Test public void newTestWriteEndpointsDuringLeave() throws Exception { StorageService ss = StorageService.instance; final int RING_SIZE = 6; final int LEAVING_NODE = 3; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE); Map<Token, List<InetAddress>> expectedEndpoints = new HashMap<Token, List<InetAddress>>(); for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces()) { for (Token token : keyTokens) { List<InetAddress> endpoints = new ArrayList<InetAddress>(); Iterator<Token> tokenIter = TokenMetadata.ringIterator(tmd.sortedTokens(), token, false); while (tokenIter.hasNext()) { endpoints.add(tmd.getEndpoint(tokenIter.next())); } expectedEndpoints.put(token, endpoints); } } // Third node leaves ss.onChange( hosts.get(LEAVING_NODE), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(endpointTokens.get(LEAVING_NODE)))); assertTrue(tmd.isLeaving(hosts.get(LEAVING_NODE))); Thread.sleep(100); // because there is a tight race between submit and blockUntilFinished PendingRangeCalculatorService.instance.blockUntilFinished(); AbstractReplicationStrategy strategy; for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces()) { strategy = getStrategy(keyspaceName, tmd); for (Token token : keyTokens) { int replicationFactor = strategy.getReplicationFactor(); HashSet<InetAddress> actual = new HashSet<InetAddress>( tmd.getWriteEndpoints( token, keyspaceName, strategy.calculateNaturalEndpoints(token, tmd.cloneOnlyTokenMap()))); HashSet<InetAddress> expected = new HashSet<InetAddress>(); for (int i = 0; i < replicationFactor; i++) { expected.add(expectedEndpoints.get(token).get(i)); } // if the leaving node is in the endpoint list, // then we should expect it plus one extra for when it's gone if (expected.contains(hosts.get(LEAVING_NODE))) expected.add(expectedEndpoints.get(token).get(replicationFactor)); assertEquals("mismatched endpoint sets", expected, actual); } } }
@Test public void testWriter() throws Exception { OrcStorageManager manager = createOrcStorageManager(); List<Long> columnIds = ImmutableList.of(3L, 7L); List<Type> columnTypes = ImmutableList.<Type>of(BIGINT, createVarcharType(10)); StoragePageSink sink = createStoragePageSink(manager, columnIds, columnTypes); List<Page> pages = rowPagesBuilder(columnTypes).row(123L, "hello").row(456L, "bye").build(); sink.appendPages(pages); // shard is not recorded until flush assertEquals(shardRecorder.getShards().size(), 0); sink.flush(); // shard is recorded after flush List<RecordedShard> recordedShards = shardRecorder.getShards(); assertEquals(recordedShards.size(), 1); List<ShardInfo> shards = getFutureValue(sink.commit()); assertEquals(shards.size(), 1); ShardInfo shardInfo = Iterables.getOnlyElement(shards); UUID shardUuid = shardInfo.getShardUuid(); File file = storageService.getStorageFile(shardUuid); File backupFile = fileBackupStore.getBackupFile(shardUuid); assertEquals(recordedShards.get(0).getTransactionId(), TRANSACTION_ID); assertEquals(recordedShards.get(0).getShardUuid(), shardUuid); assertEquals(shardInfo.getRowCount(), 2); assertEquals(shardInfo.getCompressedSize(), file.length()); // verify primary and backup shard exist assertFile(file, "primary shard"); assertFile(backupFile, "backup shard"); assertFileEquals(file, backupFile); // remove primary shard to force recovery from backup assertTrue(file.delete()); assertTrue(file.getParentFile().delete()); assertFalse(file.exists()); recoveryManager.restoreFromBackup(shardUuid, OptionalLong.empty()); try (OrcDataSource dataSource = manager.openShard(shardUuid, READER_ATTRIBUTES)) { OrcRecordReader reader = createReader(dataSource, columnIds, columnTypes); assertEquals(reader.nextBatch(), 2); Block column0 = reader.readBlock(BIGINT, 0); assertEquals(column0.isNull(0), false); assertEquals(column0.isNull(1), false); assertEquals(BIGINT.getLong(column0, 0), 123L); assertEquals(BIGINT.getLong(column0, 1), 456L); Block column1 = reader.readBlock(createVarcharType(10), 1); assertEquals(createVarcharType(10).getSlice(column1, 0), utf8Slice("hello")); assertEquals(createVarcharType(10).getSlice(column1, 1), utf8Slice("bye")); assertEquals(reader.nextBatch(), -1); } }
public class RemoveTest { static final IPartitioner partitioner = new RandomPartitioner(); StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); static IPartitioner oldPartitioner; ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); InetAddress removalhost; UUID removalId; @BeforeClass public static void setupClass() throws IOException { oldPartitioner = StorageService.instance.setPartitionerUnsafe(partitioner); SchemaLoader.loadSchema(); } @AfterClass public static void tearDownClass() { StorageService.instance.setPartitionerUnsafe(oldPartitioner); SchemaLoader.stopGossiper(); } @Before public void setup() throws IOException, ConfigurationException { tmd.clearUnsafe(); // create a ring of 5 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 6); MessagingService.instance().listen(FBUtilities.getBroadcastAddress()); Gossiper.instance.start(1); removalhost = hosts.get(5); hosts.remove(removalhost); removalId = hostIds.get(5); hostIds.remove(removalId); } @After public void tearDown() { SinkManager.clear(); MessagingService.instance().clearCallbacksUnsafe(); MessagingService.instance().shutdown(); } @Test(expected = UnsupportedOperationException.class) public void testBadHostId() { ss.removeNode("ffffffff-aaaa-aaaa-aaaa-ffffffffffff"); } @Test(expected = UnsupportedOperationException.class) public void testLocalHostId() { // first ID should be localhost ss.removeNode(hostIds.get(0).toString()); } @Test public void testRemoveHostId() throws InterruptedException { ReplicationSink rSink = new ReplicationSink(); SinkManager.add(rSink); // start removal in background and send replication confirmations final AtomicBoolean success = new AtomicBoolean(false); Thread remover = new Thread() { public void run() { try { ss.removeNode(removalId.toString()); } catch (Exception e) { System.err.println(e); e.printStackTrace(); return; } success.set(true); } }; remover.start(); Thread.sleep(1000); // make sure removal is waiting for confirmation assertTrue(tmd.isLeaving(removalhost)); assertEquals(1, tmd.getLeavingEndpoints().size()); for (InetAddress host : hosts) { MessageOut msg = new MessageOut( host, MessagingService.Verb.REPLICATION_FINISHED, null, null, Collections.<String, byte[]>emptyMap()); MessagingService.instance().sendRR(msg, FBUtilities.getBroadcastAddress()); } remover.join(); assertTrue(success.get()); assertTrue(tmd.getLeavingEndpoints().isEmpty()); } /** sink that captures STREAM_REQUEST messages and calls finishStreamRequest on it */ class ReplicationSink implements IMessageSink { public MessageIn handleMessage(MessageIn msg, int id, InetAddress to) { if (!msg.verb.equals(MessagingService.Verb.STREAM_REQUEST)) return msg; StreamUtil.finishStreamRequest(msg, to); return null; } public MessageOut handleMessage(MessageOut msg, int id, InetAddress to) { return msg; } } }
@Test public void testStateJumpToLeaving() throws UnknownHostException { StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); // create a ring or 5 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 6); // node 2 leaves with _different_ token Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(0)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(keyTokens.get(0)))); assertEquals(keyTokens.get(0), tmd.getToken(hosts.get(2))); assertTrue(tmd.isLeaving(hosts.get(2))); assertNull(tmd.getEndpoint(endpointTokens.get(2))); // go to boostrap Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(1)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(1)))); assertFalse(tmd.isLeaving(hosts.get(2))); assertEquals(1, tmd.getBootstrapTokens().size()); assertEquals(hosts.get(2), tmd.getBootstrapTokens().get(keyTokens.get(1))); // jump to leaving again ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(keyTokens.get(1)))); assertEquals(hosts.get(2), tmd.getEndpoint(keyTokens.get(1))); assertTrue(tmd.isLeaving(hosts.get(2))); assertTrue(tmd.getBootstrapTokens().isEmpty()); // go to state left ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.left(Collections.singleton(keyTokens.get(1)), Gossiper.computeExpireTime())); assertFalse(tmd.isMember(hosts.get(2))); assertFalse(tmd.isLeaving(hosts.get(2))); }
@Test public void testStateJumpToNormal() throws UnknownHostException { StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); // create a ring or 5 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 6); // node 2 leaves ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(endpointTokens.get(2)))); assertTrue(tmd.isLeaving(hosts.get(2))); assertEquals(endpointTokens.get(2), tmd.getToken(hosts.get(2))); // back to normal Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(2)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(keyTokens.get(2)))); assertTrue(tmd.getLeavingEndpoints().isEmpty()); assertEquals(keyTokens.get(2), tmd.getToken(hosts.get(2))); // node 3 goes through leave and left and then jumps to normal at its new token ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(keyTokens.get(2)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.left(Collections.singleton(keyTokens.get(2)), Gossiper.computeExpireTime())); Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(4)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(keyTokens.get(4)))); assertTrue(tmd.getBootstrapTokens().isEmpty()); assertTrue(tmd.getLeavingEndpoints().isEmpty()); assertEquals(keyTokens.get(4), tmd.getToken(hosts.get(2))); }
public void onPause() { super.onPause(); StorageService.flush(); }
@Test public void testStateJumpToBootstrap() throws UnknownHostException { StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); // create a ring or 5 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 7); // node 2 leaves ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(endpointTokens.get(2)))); // don't bother to test pending ranges here, that is extensively tested by other // tests. Just check that the node is in appropriate lists. assertTrue(tmd.isMember(hosts.get(2))); assertTrue(tmd.isLeaving(hosts.get(2))); assertTrue(tmd.getBootstrapTokens().isEmpty()); // Bootstrap the node immedidiately to keyTokens.get(4) without going through STATE_LEFT Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(4)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(4)))); assertFalse(tmd.isMember(hosts.get(2))); assertFalse(tmd.isLeaving(hosts.get(2))); assertEquals(hosts.get(2), tmd.getBootstrapTokens().get(keyTokens.get(4))); // Bootstrap node hosts.get(3) to keyTokens.get(1) Gossiper.instance.injectApplicationState( hosts.get(3), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(1)))); ss.onChange( hosts.get(3), ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(1)))); assertFalse(tmd.isMember(hosts.get(3))); assertFalse(tmd.isLeaving(hosts.get(3))); assertEquals(hosts.get(2), tmd.getBootstrapTokens().get(keyTokens.get(4))); assertEquals(hosts.get(3), tmd.getBootstrapTokens().get(keyTokens.get(1))); // Bootstrap node hosts.get(2) further to keyTokens.get(3) Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(3)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(3)))); assertFalse(tmd.isMember(hosts.get(2))); assertFalse(tmd.isLeaving(hosts.get(2))); assertEquals(hosts.get(2), tmd.getBootstrapTokens().get(keyTokens.get(3))); assertNull(tmd.getBootstrapTokens().get(keyTokens.get(4))); assertEquals(hosts.get(3), tmd.getBootstrapTokens().get(keyTokens.get(1))); // Go to normal again for both nodes Gossiper.instance.injectApplicationState( hosts.get(3), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(2)))); Gossiper.instance.injectApplicationState( hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(3)))); ss.onChange( hosts.get(2), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(keyTokens.get(3)))); ss.onChange( hosts.get(3), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(keyTokens.get(2)))); assertTrue(tmd.isMember(hosts.get(2))); assertFalse(tmd.isLeaving(hosts.get(2))); assertEquals(keyTokens.get(3), tmd.getToken(hosts.get(2))); assertTrue(tmd.isMember(hosts.get(3))); assertFalse(tmd.isLeaving(hosts.get(3))); assertEquals(keyTokens.get(2), tmd.getToken(hosts.get(3))); assertTrue(tmd.getBootstrapTokens().isEmpty()); }
/** Test pending ranges and write endpoints when multiple nodes are on the move simultaneously */ @Test public void testSimultaneousMove() throws UnknownHostException { StorageService ss = StorageService.instance; final int RING_SIZE = 10; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = RandomPartitioner.instance; VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<Token>(); ArrayList<Token> keyTokens = new ArrayList<Token>(); List<InetAddress> hosts = new ArrayList<InetAddress>(); List<UUID> hostIds = new ArrayList<UUID>(); // create a ring or 10 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE); // nodes 6, 8 and 9 leave final int[] LEAVING = new int[] {6, 8, 9}; for (int leaving : LEAVING) ss.onChange( hosts.get(leaving), ApplicationState.STATUS, valueFactory.leaving(Collections.singleton(endpointTokens.get(leaving)))); // boot two new nodes with keyTokens.get(5) and keyTokens.get(7) InetAddress boot1 = InetAddress.getByName("127.0.1.1"); Gossiper.instance.initializeNodeUnsafe(boot1, UUID.randomUUID(), 1); Gossiper.instance.injectApplicationState( boot1, ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(5)))); ss.onChange( boot1, ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(5)))); InetAddress boot2 = InetAddress.getByName("127.0.1.2"); Gossiper.instance.initializeNodeUnsafe(boot2, UUID.randomUUID(), 1); Gossiper.instance.injectApplicationState( boot2, ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(7)))); ss.onChange( boot2, ApplicationState.STATUS, valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(7)))); Collection<InetAddress> endpoints = null; /* don't require test update every time a new keyspace is added to test/conf/cassandra.yaml */ Map<String, AbstractReplicationStrategy> keyspaceStrategyMap = new HashMap<String, AbstractReplicationStrategy>(); for (int i = 1; i <= 4; i++) { keyspaceStrategyMap.put( "LeaveAndBootstrapTestKeyspace" + i, getStrategy("LeaveAndBootstrapTestKeyspace" + i, tmd)); } // pre-calculate the results. Map<String, Multimap<Token, InetAddress>> expectedEndpoints = new HashMap<String, Multimap<Token, InetAddress>>(); expectedEndpoints.put(KEYSPACE1, HashMultimap.<Token, InetAddress>create()); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6")); expectedEndpoints .get(KEYSPACE1) .putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.1.1")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.8")); expectedEndpoints .get(KEYSPACE1) .putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.1.2", "127.0.0.1")); expectedEndpoints .get(KEYSPACE1) .putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.10", "127.0.0.1")); expectedEndpoints.get(KEYSPACE1).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.1")); expectedEndpoints.put(KEYSPACE2, HashMultimap.<Token, InetAddress>create()); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6")); expectedEndpoints .get(KEYSPACE2) .putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.1.1")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.8")); expectedEndpoints .get(KEYSPACE2) .putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.1.2", "127.0.0.1")); expectedEndpoints .get(KEYSPACE2) .putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.10", "127.0.0.1")); expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.1")); expectedEndpoints.put(KEYSPACE3, HashMultimap.<Token, InetAddress>create()); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("5"), makeAddrs("127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("15"), makeAddrs( "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.1.1", "127.0.0.8")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("25"), makeAddrs( "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.1.2", "127.0.0.1", "127.0.1.1")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("35"), makeAddrs( "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.1.2", "127.0.0.1", "127.0.0.2", "127.0.1.1")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("45"), makeAddrs( "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.1.2", "127.0.0.1", "127.0.0.2", "127.0.1.1", "127.0.0.3")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("55"), makeAddrs( "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.1.1", "127.0.1.2")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("65"), makeAddrs( "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.1.2", "127.0.0.3", "127.0.0.4")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("75"), makeAddrs( "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.1.2", "127.0.0.4", "127.0.0.5")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("85"), makeAddrs( "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5")); expectedEndpoints .get(KEYSPACE3) .putAll( new BigIntegerToken("95"), makeAddrs("127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5")); expectedEndpoints.put(KEYSPACE4, HashMultimap.<Token, InetAddress>create()); expectedEndpoints .get(KEYSPACE4) .putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2", "127.0.0.3", "127.0.0.4")); expectedEndpoints .get(KEYSPACE4) .putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3", "127.0.0.4", "127.0.0.5")); expectedEndpoints .get(KEYSPACE4) .putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4", "127.0.0.5", "127.0.0.6")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("35"), makeAddrs("127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.1.1", "127.0.0.8")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("45"), makeAddrs( "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.1.2", "127.0.0.1", "127.0.1.1")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("55"), makeAddrs( "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.1", "127.0.0.2", "127.0.1.1", "127.0.1.2")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("65"), makeAddrs( "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.1.2", "127.0.0.1", "127.0.0.2")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("75"), makeAddrs( "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.1.2", "127.0.0.2", "127.0.0.3")); expectedEndpoints .get(KEYSPACE4) .putAll( new BigIntegerToken("85"), makeAddrs("127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3")); expectedEndpoints .get(KEYSPACE4) .putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.1", "127.0.0.2", "127.0.0.3")); PendingRangeCalculatorService.instance.blockUntilFinished(); for (Map.Entry<String, AbstractReplicationStrategy> keyspaceStrategy : keyspaceStrategyMap.entrySet()) { String keyspaceName = keyspaceStrategy.getKey(); AbstractReplicationStrategy strategy = keyspaceStrategy.getValue(); for (int i = 0; i < keyTokens.size(); i++) { endpoints = tmd.getWriteEndpoints( keyTokens.get(i), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(i))); assertEquals( expectedEndpoints.get(keyspaceName).get(keyTokens.get(i)).size(), endpoints.size()); assertTrue( expectedEndpoints.get(keyspaceName).get(keyTokens.get(i)).containsAll(endpoints)); } // just to be sure that things still work according to the old tests, run them: if (strategy.getReplicationFactor() != 3) continue; // tokens 5, 15 and 25 should go three nodes for (int i = 0; i < 3; ++i) { endpoints = tmd.getWriteEndpoints( keyTokens.get(i), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(i))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(i + 1))); assertTrue(endpoints.contains(hosts.get(i + 2))); assertTrue(endpoints.contains(hosts.get(i + 3))); } // token 35 should go to nodes 4, 5, 6, 7 and boot1 endpoints = tmd.getWriteEndpoints( keyTokens.get(3), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(3))); assertEquals(5, endpoints.size()); assertTrue(endpoints.contains(hosts.get(4))); assertTrue(endpoints.contains(hosts.get(5))); assertTrue(endpoints.contains(hosts.get(6))); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(boot1)); // token 45 should go to nodes 5, 6, 7, 0, boot1 and boot2 endpoints = tmd.getWriteEndpoints( keyTokens.get(4), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(4))); assertEquals(6, endpoints.size()); assertTrue(endpoints.contains(hosts.get(5))); assertTrue(endpoints.contains(hosts.get(6))); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(boot1)); assertTrue(endpoints.contains(boot2)); // token 55 should go to nodes 6, 7, 8, 0, 1, boot1 and boot2 endpoints = tmd.getWriteEndpoints( keyTokens.get(5), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(5))); assertEquals(7, endpoints.size()); assertTrue(endpoints.contains(hosts.get(6))); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(boot1)); assertTrue(endpoints.contains(boot2)); // token 65 should go to nodes 7, 8, 9, 0, 1 and boot2 endpoints = tmd.getWriteEndpoints( keyTokens.get(6), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(6))); assertEquals(6, endpoints.size()); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(9))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(boot2)); // token 75 should to go nodes 8, 9, 0, 1, 2 and boot2 endpoints = tmd.getWriteEndpoints( keyTokens.get(7), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(7))); assertEquals(6, endpoints.size()); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(9))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); assertTrue(endpoints.contains(boot2)); // token 85 should go to nodes 9, 0, 1 and 2 endpoints = tmd.getWriteEndpoints( keyTokens.get(8), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(8))); assertEquals(4, endpoints.size()); assertTrue(endpoints.contains(hosts.get(9))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); // token 95 should go to nodes 0, 1 and 2 endpoints = tmd.getWriteEndpoints( keyTokens.get(9), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(9))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); } // Now finish node 6 and node 9 leaving, as well as boot1 (after this node 8 is still // leaving and boot2 in progress ss.onChange( hosts.get(LEAVING[0]), ApplicationState.STATUS, valueFactory.left( Collections.singleton(endpointTokens.get(LEAVING[0])), Gossiper.computeExpireTime())); ss.onChange( hosts.get(LEAVING[2]), ApplicationState.STATUS, valueFactory.left( Collections.singleton(endpointTokens.get(LEAVING[2])), Gossiper.computeExpireTime())); ss.onChange( boot1, ApplicationState.STATUS, valueFactory.normal(Collections.singleton(keyTokens.get(5)))); // adjust precalcuated results. this changes what the epected endpoints are. expectedEndpoints .get(KEYSPACE1) .get(new BigIntegerToken("55")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.8")); expectedEndpoints .get(KEYSPACE1) .get(new BigIntegerToken("85")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE2) .get(new BigIntegerToken("55")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.8")); expectedEndpoints .get(KEYSPACE2) .get(new BigIntegerToken("85")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("15")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.8")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("25")) .removeAll(makeAddrs("127.0.0.7", "127.0.1.2", "127.0.0.1")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("35")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.2")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("45")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.10", "127.0.0.3")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("55")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.10", "127.0.0.4")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("65")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("75")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE3) .get(new BigIntegerToken("85")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("35")) .removeAll(makeAddrs("127.0.0.7", "127.0.0.8")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("45")) .removeAll(makeAddrs("127.0.0.7", "127.0.1.2", "127.0.0.1")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("55")) .removeAll(makeAddrs("127.0.0.2", "127.0.0.7")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("65")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("75")) .removeAll(makeAddrs("127.0.0.10")); expectedEndpoints .get(KEYSPACE4) .get(new BigIntegerToken("85")) .removeAll(makeAddrs("127.0.0.10")); PendingRangeCalculatorService.instance.blockUntilFinished(); for (Map.Entry<String, AbstractReplicationStrategy> keyspaceStrategy : keyspaceStrategyMap.entrySet()) { String keyspaceName = keyspaceStrategy.getKey(); AbstractReplicationStrategy strategy = keyspaceStrategy.getValue(); for (int i = 0; i < keyTokens.size(); i++) { endpoints = tmd.getWriteEndpoints( keyTokens.get(i), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(i))); assertEquals( expectedEndpoints.get(keyspaceName).get(keyTokens.get(i)).size(), endpoints.size()); assertTrue( expectedEndpoints.get(keyspaceName).get(keyTokens.get(i)).containsAll(endpoints)); } if (strategy.getReplicationFactor() != 3) continue; // leave this stuff in to guarantee the old tests work the way they were supposed to. // tokens 5, 15 and 25 should go three nodes for (int i = 0; i < 3; ++i) { endpoints = tmd.getWriteEndpoints( keyTokens.get(i), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(i))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(i + 1))); assertTrue(endpoints.contains(hosts.get(i + 2))); assertTrue(endpoints.contains(hosts.get(i + 3))); } // token 35 goes to nodes 4, 5 and boot1 endpoints = tmd.getWriteEndpoints( keyTokens.get(3), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(3))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(4))); assertTrue(endpoints.contains(hosts.get(5))); assertTrue(endpoints.contains(boot1)); // token 45 goes to nodes 5, boot1 and node7 endpoints = tmd.getWriteEndpoints( keyTokens.get(4), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(4))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(5))); assertTrue(endpoints.contains(boot1)); assertTrue(endpoints.contains(hosts.get(7))); // token 55 goes to boot1, 7, boot2, 8 and 0 endpoints = tmd.getWriteEndpoints( keyTokens.get(5), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(5))); assertEquals(5, endpoints.size()); assertTrue(endpoints.contains(boot1)); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(boot2)); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(0))); // token 65 goes to nodes 7, boot2, 8, 0 and 1 endpoints = tmd.getWriteEndpoints( keyTokens.get(6), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(6))); assertEquals(5, endpoints.size()); assertTrue(endpoints.contains(hosts.get(7))); assertTrue(endpoints.contains(boot2)); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); // token 75 goes to nodes boot2, 8, 0, 1 and 2 endpoints = tmd.getWriteEndpoints( keyTokens.get(7), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(7))); assertEquals(5, endpoints.size()); assertTrue(endpoints.contains(boot2)); assertTrue(endpoints.contains(hosts.get(8))); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); // token 85 goes to nodes 0, 1 and 2 endpoints = tmd.getWriteEndpoints( keyTokens.get(8), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(8))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); // token 95 goes to nodes 0, 1 and 2 endpoints = tmd.getWriteEndpoints( keyTokens.get(9), keyspaceName, strategy.getNaturalEndpoints(keyTokens.get(9))); assertEquals(3, endpoints.size()); assertTrue(endpoints.contains(hosts.get(0))); assertTrue(endpoints.contains(hosts.get(1))); assertTrue(endpoints.contains(hosts.get(2))); } }
@Test(expected = UnsupportedOperationException.class) public void testBadHostId() { ss.removeNode("ffffffff-aaaa-aaaa-aaaa-ffffffffffff"); }
@Test(expected = UnsupportedOperationException.class) public void testLocalHostId() { // first ID should be localhost ss.removeNode(hostIds.get(0).toString()); }