public static CassandraKeyValueService create( MetricsManager metricsManager, CassandraKeyValueServiceConfig config, Optional<LeaderConfig> leaderConfig, CassandraMutationTimestampProvider mutationTimestampProvider) { return create( metricsManager, config, CassandraKeyValueServiceRuntimeConfig::getDefault, leaderConfig, mutationTimestampProvider, AtlasDbConstants.DEFAULT_INITIALIZE_ASYNC); }
private static boolean canCreateCassandraKeyValueService() { return CassandraKeyValueServiceImpl.createForTesting( KVS_CONFIG, LEADER_CONFIG) .isInitialized(); } }
private void tryInitialize() { createTable(AtlasDbConstants.DEFAULT_METADATA_TABLE, AtlasDbConstants.EMPTY_TABLE_METADATA); lowerConsistencyWhenSafe(); upgradeFromOlderInternalSchema(); CassandraKeyValueServices.warnUserInInitializationIfClusterAlreadyInInconsistentState( clientPool, config); }
Map<Cell, Value> existingMetadataAtNewName = get(AtlasDbConstants.DEFAULT_METADATA_TABLE, tableRefToNewCell.values().stream() .collect(Collectors.toMap(Functions.identity(), Functions.constant(Long.MAX_VALUE)))); Map<Cell, Value> existingMetadataAtOldName = get(AtlasDbConstants.DEFAULT_METADATA_TABLE, tableRefToOldCell.values().stream() .collect(Collectors.toMap(Functions.identity(), Functions.constant(Long.MAX_VALUE)))); if (metadataIsDifferent( existingMetadataAtNewName.get(newCell).getContents(), tableRefToMetadata.get(tableRef))) { updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); if (metadataIsDifferent( existingMetadataAtOldName.get(tableRefToOldCell.get(tableRef)).getContents(), tableRefToMetadata.get(tableRef))) { updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); putMetadataAndMaybeAlterTables(possiblyNeedToPerformSettingsChanges, updatedMetadata, updatedCfs);
@VisibleForTesting void upgradeFromOlderInternalSchema() { try { Map<TableReference, byte[]> metadataForTables = getMetadataForTables(); final Collection<CfDef> updatedCfs = Lists.newArrayListWithExpectedSize(metadataForTables.size()); Optional<byte[]> relevantMetadata = lookupClusterSideMetadata(metadataForTables, tableRef); if (relevantMetadata.isPresent()) { byte[] clusterSideMetadata = relevantMetadata.get(); CfDef clientSideCf = getCfForTable(tableRef, clusterSideMetadata, config.gcGraceSeconds()); if (!ColumnFamilyDefinitions.isMatchingCf(clientSideCf, clusterSideCf)) { putMetadataAndMaybeAlterTables(true, emptyMetadataUpdate, updatedCfs); log.info("New table-related settings were applied on startup!!"); } else {
@Test public void testCfEqualityChecker() throws TException { CassandraKeyValueServiceImpl kvs; if (keyValueService instanceof CassandraKeyValueService) { kvs = (CassandraKeyValueServiceImpl) keyValueService; } else if (keyValueService instanceof TableSplittingKeyValueService) { // scylla tests KeyValueService delegate = ((TableSplittingKeyValueService) keyValueService).getDelegate(NEVER_SEEN); assertTrue("The nesting of Key Value Services has apparently changed", delegate instanceof CassandraKeyValueService); kvs = (CassandraKeyValueServiceImpl) delegate; } else { throw new IllegalArgumentException("Can't run this cassandra-specific test against a non-cassandra KVS"); } kvs.createTable(NEVER_SEEN, getMetadata()); List<CfDef> knownCfs = kvs.getClientPool().runWithRetry(client -> client.describe_keyspace(CASSANDRA.getConfig().getKeyspaceOrThrow()).getCf_defs()); CfDef clusterSideCf = Iterables.getOnlyElement(knownCfs.stream() .filter(cf -> cf.getName().equals(getInternalTestTableName())) .collect(Collectors.toList())); assertTrue("After serialization and deserialization to database, Cf metadata did not match.", ColumnFamilyDefinitions.isMatchingCf(kvs.getCfForTable(NEVER_SEEN, getMetadata(), FOUR_DAYS_IN_SECONDS), clusterSideCf)); }
private UUID getUuidForTable(TableReference tableRef) { String internalTableName = CassandraKeyValueServiceImpl.internalTableName(tableRef); String keyspace = config.getKeyspaceOrThrow(); String fullTableNameForUuid = keyspace + "." + internalTableName; return UUID.nameUUIDFromBytes(fullTableNameForUuid.getBytes()); } }
@Test public void ifWrapperIsNotInitializedDelegateIsNotCalled() { when(kvsWrapper.isInitialized()).thenReturn(false); TableReference tableRef = TableReference.create(Namespace.DEFAULT_NAMESPACE, "test"); assertThatThrownBy(() -> kvsWrapper.createTable(tableRef, AtlasDbConstants.GENERIC_TABLE_METADATA)) .isInstanceOf(NotInitializedException.class); verify(kvs, never()).createTable(any(TableReference.class), any()); } }
@Override public CassandraClientPool getClientPool() { return CassandraKeyValueServiceImpl.this.getClientPool(); }
@Test @SuppressWarnings("Slf4jConstantLogMessage") public void upgradeFromOlderInternalSchemaDoesNotErrorOnTablesWithUpperCaseCharacters() { TableReference tableRef = TableReference.createFromFullyQualifiedName("test.uPgrAdefRomolDerintErnalscHema"); keyValueService.put( AtlasDbConstants.DEFAULT_METADATA_TABLE, ImmutableMap.of(CassandraKeyValueServices.getMetadataCell(tableRef), ORIGINAL_METADATA), System.currentTimeMillis()); keyValueService.createTable(tableRef, ORIGINAL_METADATA); ((CassandraKeyValueServiceImpl) keyValueService).upgradeFromOlderInternalSchema(); verify(logger, never()).error(anyString(), any(Object.class)); }
private Void multiPutForSingleHostInternal(final InetSocketAddress host, final Set<TableReference> tableRefs, final List<TableCellAndValue> batch, long timestamp) throws Exception { final MutationMap mutationMap = convertToMutations(batch, timestamp); return clientPool.runWithRetryOnHost(host, new FunctionCheckedException<CassandraClient, Void, Exception>() { @Override public Void apply(CassandraClient client) throws Exception { return wrappingQueryRunner.batchMutate("multiPut", client, tableRefs, mutationMap, WRITE_CONSISTENCY); } @Override public String toString() { return "batch_mutate(" + host + ", " + tableRefs + ", " + batch.size() + " values)"; } }); }
private static CassandraKeyValueService createAndInitialize( MetricsManager metricsManager, CassandraKeyValueServiceConfig config, CassandraClientPool clientPool, Optional<LeaderConfig> leaderConfig, CassandraMutationTimestampProvider mutationTimestampProvider, Logger log, boolean initializeAsync) { CassandraKeyValueServiceImpl keyValueService = new CassandraKeyValueServiceImpl( log, metricsManager, config, clientPool, leaderConfig, mutationTimestampProvider); keyValueService.wrapper.initialize(initializeAsync); return keyValueService.wrapper.isInitialized() ? keyValueService : keyValueService.wrapper; }
private static CassandraKeyValueService createOrShutdownClientPool( MetricsManager metricsManager, CassandraKeyValueServiceConfig config, CassandraClientPool clientPool, Optional<LeaderConfig> leaderConfig, CassandraMutationTimestampProvider mutationTimestampProvider, Logger log, boolean initializeAsync) { try { return createAndInitialize(metricsManager, config, clientPool, leaderConfig, mutationTimestampProvider, log, initializeAsync); } catch (Exception e) { log.warn("Error occurred in creating Cassandra KVS. Now attempting to shut down client pool...", e); try { clientPool.shutdown(); log.info("Cassandra client pool shut down."); } catch (RuntimeException internalException) { log.info("An error occurred whilst shutting down the Cassandra client pool", internalException); throw internalException; } throw Throwables.rewrapAndThrowUncheckedException(e); } }
@VisibleForTesting void upgradeFromOlderInternalSchema() { try { Map<TableReference, byte[]> metadataForTables = getMetadataForTables(); final Collection<CfDef> updatedCfs = Lists.newArrayListWithExpectedSize(metadataForTables.size()); Optional<byte[]> relevantMetadata = lookupClusterSideMetadata(metadataForTables, tableRef); if (relevantMetadata.isPresent()) { byte[] clusterSideMetadata = relevantMetadata.get(); CfDef clientSideCf = getCfForTable(tableRef, clusterSideMetadata, config.gcGraceSeconds()); if (!ColumnFamilyDefinitions.isMatchingCf(clientSideCf, clusterSideCf)) { putMetadataAndMaybeAlterTables(true, emptyMetadataUpdate, updatedCfs); log.info("New table-related settings were applied on startup!!"); } else {
Map<Cell, Value> existingMetadataAtNewName = get(AtlasDbConstants.DEFAULT_METADATA_TABLE, tableRefToNewCell.values().stream() .collect(Collectors.toMap(Functions.identity(), Functions.constant(Long.MAX_VALUE)))); Map<Cell, Value> existingMetadataAtOldName = get(AtlasDbConstants.DEFAULT_METADATA_TABLE, tableRefToOldCell.values().stream() .collect(Collectors.toMap(Functions.identity(), Functions.constant(Long.MAX_VALUE)))); if (metadataIsDifferent( existingMetadataAtNewName.get(newCell).getContents(), tableRefToMetadata.get(tableRef))) { updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); if (metadataIsDifferent( existingMetadataAtOldName.get(tableRefToOldCell.get(tableRef)).getContents(), tableRefToMetadata.get(tableRef))) { updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); updatedCfs.add(getCfForTable(tableRef, tableRefToMetadata.get(tableRef), config.gcGraceSeconds())); putMetadataAndMaybeAlterTables(possiblyNeedToPerformSettingsChanges, updatedMetadata, updatedCfs);
private static Arg<String> quotedTableName(TableReference tableRef) { String tableNameWithQuotes = "\"" + CassandraKeyValueServiceImpl.internalTableName(tableRef) + "\""; return LoggingArgs.customTableName(tableRef, tableNameWithQuotes); }
@Test public void ifWrapperIsInitializedDelegateIsCalled() { when(kvsWrapper.isInitialized()).thenReturn(true); TableReference tableRef = TableReference.create(Namespace.DEFAULT_NAMESPACE, "test"); kvsWrapper.createTable(tableRef, AtlasDbConstants.GENERIC_TABLE_METADATA); verify(kvs).createTable(any(TableReference.class), any()); }
@Override public CassandraClientPool getClientPool() { return CassandraKeyValueServiceImpl.this.getClientPool(); }
@Test @SuppressWarnings("Slf4jConstantLogMessage") public void upgradeFromOlderInternalSchemaDoesNotErrorOnTablesWithOldMetadata() { TableReference tableRef = TableReference.createFromFullyQualifiedName("test.oldTimeyTable"); keyValueService.put( AtlasDbConstants.DEFAULT_METADATA_TABLE, ImmutableMap.of(CassandraKeyValueServices.getOldMetadataCell(tableRef), ORIGINAL_METADATA), System.currentTimeMillis()); keyValueService.createTable(tableRef, ORIGINAL_METADATA); ((CassandraKeyValueServiceImpl) keyValueService).upgradeFromOlderInternalSchema(); verify(logger, never()).error(anyString(), any(Object.class)); }
private Void multiPutForSingleHostInternal(final InetSocketAddress host, final Set<TableReference> tableRefs, final List<TableCellAndValue> batch, long timestamp) throws Exception { final MutationMap mutationMap = convertToMutations(batch, timestamp); return clientPool.runWithRetryOnHost(host, new FunctionCheckedException<CassandraClient, Void, Exception>() { @Override public Void apply(CassandraClient client) throws Exception { return wrappingQueryRunner.batchMutate("multiPut", client, tableRefs, mutationMap, WRITE_CONSISTENCY); } @Override public String toString() { return "batch_mutate(" + host + ", " + tableRefs + ", " + batch.size() + " values)"; } }); }