use of org.apache.cassandra.db.ColumnFamilyStore in project cassandra by apache.
the class AbstractReadExecutor method getReadExecutor.
/**
* @return an executor appropriate for the configured speculative read policy
*/
public static AbstractReadExecutor getReadExecutor(SinglePartitionReadCommand command, ConsistencyLevel consistencyLevel, long queryStartNanoTime) throws UnavailableException {
Keyspace keyspace = Keyspace.open(command.metadata().keyspace);
List<InetAddress> allReplicas = StorageProxy.getLiveSortedEndpoints(keyspace, command.partitionKey());
// 11980: Excluding EACH_QUORUM reads from potential RR, so that we do not miscount DC responses
ReadRepairDecision repairDecision = consistencyLevel == ConsistencyLevel.EACH_QUORUM ? ReadRepairDecision.NONE : newReadRepairDecision(command.metadata());
List<InetAddress> targetReplicas = consistencyLevel.filterForQuery(keyspace, allReplicas, repairDecision);
// Throw UAE early if we don't have enough replicas.
consistencyLevel.assureSufficientLiveNodes(keyspace, targetReplicas);
if (repairDecision != ReadRepairDecision.NONE) {
Tracing.trace("Read-repair {}", repairDecision);
ReadRepairMetrics.attempted.mark();
}
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(command.metadata().id);
SpeculativeRetryParam retry = cfs.metadata().params.speculativeRetry;
// 11980: Disable speculative retry if using EACH_QUORUM in order to prevent miscounting DC responses
if (retry.equals(SpeculativeRetryParam.NONE) || consistencyLevel == ConsistencyLevel.EACH_QUORUM || consistencyLevel.blockFor(keyspace) == allReplicas.size())
return new NeverSpeculatingReadExecutor(keyspace, command, consistencyLevel, targetReplicas, queryStartNanoTime);
if (targetReplicas.size() == allReplicas.size()) {
// (same amount of requests in total, but we turn 1 digest request into a full blown data request).
return new AlwaysSpeculatingReadExecutor(keyspace, cfs, command, consistencyLevel, targetReplicas, queryStartNanoTime);
}
// RRD.NONE or RRD.DC_LOCAL w/ multiple DCs.
InetAddress extraReplica = allReplicas.get(targetReplicas.size());
// we might have to find a replacement that's not already in targetReplicas.
if (repairDecision == ReadRepairDecision.DC_LOCAL && targetReplicas.contains(extraReplica)) {
for (InetAddress address : allReplicas) {
if (!targetReplicas.contains(address)) {
extraReplica = address;
break;
}
}
}
targetReplicas.add(extraReplica);
if (retry.equals(SpeculativeRetryParam.ALWAYS))
return new AlwaysSpeculatingReadExecutor(keyspace, cfs, command, consistencyLevel, targetReplicas, queryStartNanoTime);
else
// PERCENTILE or CUSTOM.
return new SpeculatingReadExecutor(keyspace, cfs, command, consistencyLevel, targetReplicas, queryStartNanoTime);
}
use of org.apache.cassandra.db.ColumnFamilyStore in project cassandra by apache.
the class AutoSavingCache method loadSaved.
public int loadSaved() {
int count = 0;
long start = System.nanoTime();
// modern format, allows both key and value (so key cache load can be purely sequential)
File dataPath = getCacheDataPath(CURRENT_VERSION);
File crcPath = getCacheCrcPath(CURRENT_VERSION);
if (dataPath.exists() && crcPath.exists()) {
DataInputStreamPlus in = null;
try {
logger.info("reading saved cache {}", dataPath);
in = new DataInputStreamPlus(new LengthAvailableInputStream(new BufferedInputStream(streamFactory.getInputStream(dataPath, crcPath)), dataPath.length()));
//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()))
throw new RuntimeException("Cache schema version " + schemaVersion + " does not match current schema version " + Schema.instance.getVersion());
ArrayDeque<Future<Pair<K, V>>> futures = new ArrayDeque<Future<Pair<K, V>>>();
while (in.available() > 0) {
//tableId and indexName are serialized by the serializers in CacheService
//That is delegated there because there are serializer specific conditions
//where a cache key is skipped and not written
TableId tableId = TableId.deserialize(in);
String indexName = in.readUTF();
if (indexName.isEmpty())
indexName = null;
ColumnFamilyStore cfs = Schema.instance.getColumnFamilyStoreInstance(tableId);
if (indexName != null && cfs != null)
cfs = cfs.indexManager.getIndexByName(indexName).getBackingTable().orElse(null);
Future<Pair<K, V>> entryFuture = cacheLoader.deserialize(in, cfs);
// Key cache entry can return null, if the SSTable doesn't exist.
if (entryFuture == null)
continue;
futures.offer(entryFuture);
count++;
/*
* Kind of unwise to accrue an unbounded number of pending futures
* So now there is this loop to keep a bounded number pending.
*/
do {
while (futures.peek() != null && futures.peek().isDone()) {
Future<Pair<K, V>> future = futures.poll();
Pair<K, V> entry = future.get();
if (entry != null && entry.right != null)
put(entry.left, entry.right);
}
if (futures.size() > 1000)
Thread.yield();
} while (futures.size() > 1000);
}
Future<Pair<K, V>> future = null;
while ((future = futures.poll()) != null) {
Pair<K, V> entry = future.get();
if (entry != null && entry.right != null)
put(entry.left, entry.right);
}
} catch (CorruptFileException e) {
JVMStabilityInspector.inspectThrowable(e);
logger.warn(String.format("Non-fatal checksum error reading saved cache %s", dataPath.getAbsolutePath()), e);
} catch (Throwable t) {
JVMStabilityInspector.inspectThrowable(t);
logger.info(String.format("Harmless error reading saved cache %s", dataPath.getAbsolutePath()), t);
} finally {
FileUtils.closeQuietly(in);
}
}
if (logger.isTraceEnabled())
logger.trace("completed reading ({} ms; {} keys) saved cache {}", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start), count, dataPath);
return count;
}
use of org.apache.cassandra.db.ColumnFamilyStore in project cassandra by apache.
the class AlterTableStatement method announceMigration.
public Event.SchemaChange announceMigration(QueryState queryState, boolean isLocalOnly) throws RequestValidationException {
TableMetadata current = Schema.instance.validateTable(keyspace(), columnFamily());
if (current.isView())
throw new InvalidRequestException("Cannot use ALTER TABLE on Materialized View");
TableMetadata.Builder builder = current.unbuild();
ColumnIdentifier columnName = null;
ColumnMetadata def = null;
CQL3Type.Raw dataType = null;
boolean isStatic = false;
CQL3Type validator = null;
List<ViewMetadata> viewUpdates = new ArrayList<>();
Iterable<ViewMetadata> views = View.findAll(keyspace(), columnFamily());
switch(oType) {
case ALTER:
throw new InvalidRequestException("Altering of types is not allowed");
case ADD:
if (current.isDense())
throw new InvalidRequestException("Cannot add new column to a COMPACT STORAGE table");
for (AlterTableStatementColumn colData : colNameList) {
columnName = colData.getColumnName().getIdentifier(current);
def = builder.getColumn(columnName);
dataType = colData.getColumnType();
assert dataType != null;
isStatic = colData.getStaticType();
validator = dataType.prepare(keyspace());
if (isStatic) {
if (!current.isCompound())
throw new InvalidRequestException("Static columns are not allowed in COMPACT STORAGE tables");
if (current.clusteringColumns().isEmpty())
throw new InvalidRequestException("Static columns are only useful (and thus allowed) if the table has at least one clustering column");
}
if (def != null) {
switch(def.kind) {
case PARTITION_KEY:
case CLUSTERING:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with a PRIMARY KEY part", columnName));
default:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with an existing column", columnName));
}
}
// Cannot re-add a dropped counter column. See #7831.
if (current.isCounter() && current.getDroppedColumn(columnName.bytes) != null)
throw new InvalidRequestException(String.format("Cannot re-add previously dropped counter column %s", columnName));
AbstractType<?> type = validator.getType();
if (type.isCollection() && type.isMultiCell()) {
if (!current.isCompound())
throw new InvalidRequestException("Cannot use non-frozen collections in COMPACT STORAGE tables");
if (current.isSuper())
throw new InvalidRequestException("Cannot use non-frozen collections with super column families");
// If there used to be a non-frozen collection column with the same name (that has been dropped),
// we could still have some data using the old type, and so we can't allow adding a collection
// with the same name unless the types are compatible (see #6276).
DroppedColumn dropped = current.droppedColumns.get(columnName.bytes);
if (dropped != null && dropped.column.type instanceof CollectionType && dropped.column.type.isMultiCell() && !type.isCompatibleWith(dropped.column.type)) {
String message = String.format("Cannot add a collection with the name %s because a collection with the same name" + " and a different type (%s) has already been used in the past", columnName, dropped.column.type.asCQL3Type());
throw new InvalidRequestException(message);
}
}
builder.addColumn(isStatic ? ColumnMetadata.staticColumn(current, columnName.bytes, type) : ColumnMetadata.regularColumn(current, columnName.bytes, type));
// as well
if (!isStatic)
for (ViewMetadata view : views) if (view.includeAllColumns)
viewUpdates.add(view.withAddedRegularColumn(ColumnMetadata.regularColumn(view.metadata, columnName.bytes, type)));
}
break;
case DROP:
if (!current.isCQLTable())
throw new InvalidRequestException("Cannot drop columns from a non-CQL3 table");
for (AlterTableStatementColumn colData : colNameList) {
columnName = colData.getColumnName().getIdentifier(current);
def = builder.getColumn(columnName);
if (def == null)
throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));
switch(def.kind) {
case PARTITION_KEY:
case CLUSTERING:
throw new InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", columnName));
case REGULAR:
case STATIC:
builder.removeRegularOrStaticColumn(def.name);
builder.recordColumnDrop(def, deleteTimestamp == null ? queryState.getTimestamp() : deleteTimestamp);
break;
}
// If the dropped column is required by any secondary indexes
// we reject the operation, as the indexes must be dropped first
Indexes allIndexes = current.indexes;
if (!allIndexes.isEmpty()) {
ColumnFamilyStore store = Keyspace.openAndGetStore(current);
Set<IndexMetadata> dependentIndexes = store.indexManager.getDependentIndexes(def);
if (!dependentIndexes.isEmpty()) {
throw new InvalidRequestException(String.format("Cannot drop column %s because it has " + "dependent secondary indexes (%s)", def, dependentIndexes.stream().map(i -> i.name).collect(Collectors.joining(","))));
}
}
// If a column is dropped which is included in a view, we don't allow the drop to take place.
boolean rejectAlter = false;
StringBuilder viewNames = new StringBuilder();
for (ViewMetadata view : views) {
if (!view.includes(columnName))
continue;
if (rejectAlter)
viewNames.append(',');
rejectAlter = true;
viewNames.append(view.name);
}
if (rejectAlter)
throw new InvalidRequestException(String.format("Cannot drop column %s, depended on by materialized views (%s.{%s})", columnName.toString(), keyspace(), viewNames.toString()));
}
break;
case OPTS:
if (attrs == null)
throw new InvalidRequestException("ALTER TABLE WITH invoked, but no parameters found");
attrs.validate();
TableParams params = attrs.asAlteredTableParams(current.params);
if (!Iterables.isEmpty(views) && params.gcGraceSeconds == 0) {
throw new InvalidRequestException("Cannot alter gc_grace_seconds of the base table of a " + "materialized view to 0, since this value is used to TTL " + "undelivered updates. Setting gc_grace_seconds too low might " + "cause undelivered updates to expire " + "before being replayed.");
}
if (current.isCounter() && params.defaultTimeToLive > 0)
throw new InvalidRequestException("Cannot set default_time_to_live on a table with counters");
builder.params(params);
break;
case RENAME:
for (Map.Entry<ColumnMetadata.Raw, ColumnMetadata.Raw> entry : renames.entrySet()) {
ColumnIdentifier from = entry.getKey().getIdentifier(current);
ColumnIdentifier to = entry.getValue().getIdentifier(current);
def = current.getColumn(from);
if (def == null)
throw new InvalidRequestException(String.format("Cannot rename unknown column %s in table %s", from, current.name));
if (current.getColumn(to) != null)
throw new InvalidRequestException(String.format("Cannot rename column %s to %s in table %s; another column of that name already exist", from, to, current.name));
if (!def.isPrimaryKeyColumn())
throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", from));
if (!current.indexes.isEmpty()) {
ColumnFamilyStore store = Keyspace.openAndGetStore(current);
Set<IndexMetadata> dependentIndexes = store.indexManager.getDependentIndexes(def);
if (!dependentIndexes.isEmpty())
throw new InvalidRequestException(String.format("Cannot rename column %s because it has " + "dependent secondary indexes (%s)", from, dependentIndexes.stream().map(i -> i.name).collect(Collectors.joining(","))));
}
builder.renamePrimaryKeyColumn(from, to);
// If the view includes a renamed column, it must be renamed in the view table and the definition.
for (ViewMetadata view : views) {
if (!view.includes(from))
continue;
ColumnIdentifier viewFrom = entry.getKey().getIdentifier(view.metadata);
ColumnIdentifier viewTo = entry.getValue().getIdentifier(view.metadata);
viewUpdates.add(view.renamePrimaryKeyColumn(viewFrom, viewTo));
}
}
break;
}
// FIXME: Should really be a single announce for the table and views.
MigrationManager.announceTableUpdate(builder.build(), isLocalOnly);
for (ViewMetadata viewUpdate : viewUpdates) MigrationManager.announceViewUpdate(viewUpdate, isLocalOnly);
return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
}
use of org.apache.cassandra.db.ColumnFamilyStore in project cassandra by apache.
the class CompactionLogger method formatSSTables.
private JsonNode formatSSTables(AbstractCompactionStrategy strategy) {
ArrayNode node = json.arrayNode();
CompactionStrategyManager csm = csmRef.get();
ColumnFamilyStore cfs = cfsRef.get();
if (csm == null || cfs == null)
return node;
for (SSTableReader sstable : cfs.getLiveSSTables()) {
if (csm.getCompactionStrategyFor(sstable) == strategy)
node.add(formatSSTable(strategy, sstable));
}
return node;
}
use of org.apache.cassandra.db.ColumnFamilyStore in project cassandra by apache.
the class IndexSummaryManager method getCompactingAndNonCompactingSSTables.
/**
* Returns a Pair of all compacting and non-compacting sstables. Non-compacting sstables will be marked as
* compacting.
*/
@SuppressWarnings("resource")
private Pair<List<SSTableReader>, Map<TableId, LifecycleTransaction>> getCompactingAndNonCompactingSSTables() {
List<SSTableReader> allCompacting = new ArrayList<>();
Map<TableId, LifecycleTransaction> allNonCompacting = new HashMap<>();
for (Keyspace ks : Keyspace.all()) {
for (ColumnFamilyStore cfStore : ks.getColumnFamilyStores()) {
Set<SSTableReader> nonCompacting, allSSTables;
LifecycleTransaction txn = null;
do {
View view = cfStore.getTracker().getView();
allSSTables = ImmutableSet.copyOf(view.select(SSTableSet.CANONICAL));
nonCompacting = ImmutableSet.copyOf(view.getUncompacting(allSSTables));
} while (null == (txn = cfStore.getTracker().tryModify(nonCompacting, OperationType.UNKNOWN)));
allNonCompacting.put(cfStore.metadata.id, txn);
allCompacting.addAll(Sets.difference(allSSTables, nonCompacting));
}
}
return Pair.create(allCompacting, allNonCompacting);
}
Aggregations