diff --git a/CHANGES.txt b/CHANGES.txt index 6c5436e590..1861f885b8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 1.3 + * add default_tim_to_live (CASSANDRA-3974) * add memtable_flush_period_in_ms (CASSANDRA-4237) diff --git a/interface/cassandra.thrift b/interface/cassandra.thrift index 0a92a9dec6..e1e28abb1d 100644 --- a/interface/cassandra.thrift +++ b/interface/cassandra.thrift @@ -443,6 +443,7 @@ struct CfDef { 34: optional string caching="keys_only", 37: optional double dclocal_read_repair_chance = 0.0, 38: optional i32 memtable_flush_period_in_ms, + 39: optional i32 default_time_to_live, /* All of the following are now ignored and unsupplied. */ diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java index 50ec681414..7e4f56e6fe 100644 --- a/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java +++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java @@ -68,6 +68,7 @@ public class CfDef implements org.apache.thrift.TBase, jav private static final org.apache.thrift.protocol.TField CACHING_FIELD_DESC = new org.apache.thrift.protocol.TField("caching", org.apache.thrift.protocol.TType.STRING, (short)34); private static final org.apache.thrift.protocol.TField DCLOCAL_READ_REPAIR_CHANCE_FIELD_DESC = new org.apache.thrift.protocol.TField("dclocal_read_repair_chance", org.apache.thrift.protocol.TType.DOUBLE, (short)37); private static final org.apache.thrift.protocol.TField MEMTABLE_FLUSH_PERIOD_IN_MS_FIELD_DESC = new org.apache.thrift.protocol.TField("memtable_flush_period_in_ms", org.apache.thrift.protocol.TType.I32, (short)38); + private static final org.apache.thrift.protocol.TField DEFAULT_TIME_TO_LIVE_FIELD_DESC = new org.apache.thrift.protocol.TField("default_time_to_live", org.apache.thrift.protocol.TType.I32, (short)39); private static final org.apache.thrift.protocol.TField ROW_CACHE_SIZE_FIELD_DESC = new org.apache.thrift.protocol.TField("row_cache_size", org.apache.thrift.protocol.TType.DOUBLE, (short)9); private static final org.apache.thrift.protocol.TField KEY_CACHE_SIZE_FIELD_DESC = new org.apache.thrift.protocol.TField("key_cache_size", org.apache.thrift.protocol.TType.DOUBLE, (short)11); private static final org.apache.thrift.protocol.TField ROW_CACHE_SAVE_PERIOD_IN_SECONDS_FIELD_DESC = new org.apache.thrift.protocol.TField("row_cache_save_period_in_seconds", org.apache.thrift.protocol.TType.I32, (short)19); @@ -102,6 +103,7 @@ public class CfDef implements org.apache.thrift.TBase, jav public String caching; // required public double dclocal_read_repair_chance; // required public int memtable_flush_period_in_ms; // required + public int default_time_to_live; // required /** * @deprecated */ @@ -168,6 +170,7 @@ public class CfDef implements org.apache.thrift.TBase, jav CACHING((short)34, "caching"), DCLOCAL_READ_REPAIR_CHANCE((short)37, "dclocal_read_repair_chance"), MEMTABLE_FLUSH_PERIOD_IN_MS((short)38, "memtable_flush_period_in_ms"), + DEFAULT_TIME_TO_LIVE((short)39, "default_time_to_live"), /** * @deprecated */ @@ -268,6 +271,8 @@ public class CfDef implements org.apache.thrift.TBase, jav return DCLOCAL_READ_REPAIR_CHANCE; case 38: // MEMTABLE_FLUSH_PERIOD_IN_MS return MEMTABLE_FLUSH_PERIOD_IN_MS; + case 39: // DEFAULT_TIME_TO_LIVE + return DEFAULT_TIME_TO_LIVE; case 9: // ROW_CACHE_SIZE return ROW_CACHE_SIZE; case 11: // KEY_CACHE_SIZE @@ -337,16 +342,17 @@ public class CfDef implements org.apache.thrift.TBase, jav private static final int __BLOOM_FILTER_FP_CHANCE_ISSET_ID = 6; private static final int __DCLOCAL_READ_REPAIR_CHANCE_ISSET_ID = 7; private static final int __MEMTABLE_FLUSH_PERIOD_IN_MS_ISSET_ID = 8; - private static final int __ROW_CACHE_SIZE_ISSET_ID = 9; - private static final int __KEY_CACHE_SIZE_ISSET_ID = 10; - private static final int __ROW_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 11; - private static final int __KEY_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 12; - private static final int __MEMTABLE_FLUSH_AFTER_MINS_ISSET_ID = 13; - private static final int __MEMTABLE_THROUGHPUT_IN_MB_ISSET_ID = 14; - private static final int __MEMTABLE_OPERATIONS_IN_MILLIONS_ISSET_ID = 15; - private static final int __MERGE_SHARDS_CHANCE_ISSET_ID = 16; - private static final int __ROW_CACHE_KEYS_TO_SAVE_ISSET_ID = 17; - private BitSet __isset_bit_vector = new BitSet(18); + private static final int __DEFAULT_TIME_TO_LIVE_ISSET_ID = 9; + private static final int __ROW_CACHE_SIZE_ISSET_ID = 10; + private static final int __KEY_CACHE_SIZE_ISSET_ID = 11; + private static final int __ROW_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 12; + private static final int __KEY_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 13; + private static final int __MEMTABLE_FLUSH_AFTER_MINS_ISSET_ID = 14; + private static final int __MEMTABLE_THROUGHPUT_IN_MB_ISSET_ID = 15; + private static final int __MEMTABLE_OPERATIONS_IN_MILLIONS_ISSET_ID = 16; + private static final int __MERGE_SHARDS_CHANCE_ISSET_ID = 17; + private static final int __ROW_CACHE_KEYS_TO_SAVE_ISSET_ID = 18; + private BitSet __isset_bit_vector = new BitSet(19); public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { @@ -402,6 +408,8 @@ public class CfDef implements org.apache.thrift.TBase, jav new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE))); tmpMap.put(_Fields.MEMTABLE_FLUSH_PERIOD_IN_MS, new org.apache.thrift.meta_data.FieldMetaData("memtable_flush_period_in_ms", org.apache.thrift.TFieldRequirementType.OPTIONAL, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.DEFAULT_TIME_TO_LIVE, new org.apache.thrift.meta_data.FieldMetaData("default_time_to_live", org.apache.thrift.TFieldRequirementType.OPTIONAL, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); tmpMap.put(_Fields.ROW_CACHE_SIZE, new org.apache.thrift.meta_data.FieldMetaData("row_cache_size", org.apache.thrift.TFieldRequirementType.OPTIONAL, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE))); tmpMap.put(_Fields.KEY_CACHE_SIZE, new org.apache.thrift.meta_data.FieldMetaData("key_cache_size", org.apache.thrift.TFieldRequirementType.OPTIONAL, @@ -532,6 +540,7 @@ public class CfDef implements org.apache.thrift.TBase, jav } this.dclocal_read_repair_chance = other.dclocal_read_repair_chance; this.memtable_flush_period_in_ms = other.memtable_flush_period_in_ms; + this.default_time_to_live = other.default_time_to_live; this.row_cache_size = other.row_cache_size; this.key_cache_size = other.key_cache_size; this.row_cache_save_period_in_seconds = other.row_cache_save_period_in_seconds; @@ -587,6 +596,8 @@ public class CfDef implements org.apache.thrift.TBase, jav setMemtable_flush_period_in_msIsSet(false); this.memtable_flush_period_in_ms = 0; + setDefault_time_to_liveIsSet(false); + this.default_time_to_live = 0; setRow_cache_sizeIsSet(false); this.row_cache_size = 0.0; setKey_cache_sizeIsSet(false); @@ -1198,6 +1209,29 @@ public class CfDef implements org.apache.thrift.TBase, jav __isset_bit_vector.set(__MEMTABLE_FLUSH_PERIOD_IN_MS_ISSET_ID, value); } + public int getDefault_time_to_live() { + return this.default_time_to_live; + } + + public CfDef setDefault_time_to_live(int default_time_to_live) { + this.default_time_to_live = default_time_to_live; + setDefault_time_to_liveIsSet(true); + return this; + } + + public void unsetDefault_time_to_live() { + __isset_bit_vector.clear(__DEFAULT_TIME_TO_LIVE_ISSET_ID); + } + + /** Returns true if field default_time_to_live is set (has been assigned a value) and false otherwise */ + public boolean isSetDefault_time_to_live() { + return __isset_bit_vector.get(__DEFAULT_TIME_TO_LIVE_ISSET_ID); + } + + public void setDefault_time_to_liveIsSet(boolean value) { + __isset_bit_vector.set(__DEFAULT_TIME_TO_LIVE_ISSET_ID, value); + } + /** * @deprecated */ @@ -1675,6 +1709,14 @@ public class CfDef implements org.apache.thrift.TBase, jav } break; + case DEFAULT_TIME_TO_LIVE: + if (value == null) { + unsetDefault_time_to_live(); + } else { + setDefault_time_to_live((Integer)value); + } + break; + case ROW_CACHE_SIZE: if (value == null) { unsetRow_cache_size(); @@ -1829,6 +1871,9 @@ public class CfDef implements org.apache.thrift.TBase, jav case MEMTABLE_FLUSH_PERIOD_IN_MS: return Integer.valueOf(getMemtable_flush_period_in_ms()); + case DEFAULT_TIME_TO_LIVE: + return Integer.valueOf(getDefault_time_to_live()); + case ROW_CACHE_SIZE: return Double.valueOf(getRow_cache_size()); @@ -1916,6 +1961,8 @@ public class CfDef implements org.apache.thrift.TBase, jav return isSetDclocal_read_repair_chance(); case MEMTABLE_FLUSH_PERIOD_IN_MS: return isSetMemtable_flush_period_in_ms(); + case DEFAULT_TIME_TO_LIVE: + return isSetDefault_time_to_live(); case ROW_CACHE_SIZE: return isSetRow_cache_size(); case KEY_CACHE_SIZE: @@ -2160,6 +2207,15 @@ public class CfDef implements org.apache.thrift.TBase, jav return false; } + boolean this_present_default_time_to_live = true && this.isSetDefault_time_to_live(); + boolean that_present_default_time_to_live = true && that.isSetDefault_time_to_live(); + if (this_present_default_time_to_live || that_present_default_time_to_live) { + if (!(this_present_default_time_to_live && that_present_default_time_to_live)) + return false; + if (this.default_time_to_live != that.default_time_to_live) + return false; + } + boolean this_present_row_cache_size = true && this.isSetRow_cache_size(); boolean that_present_row_cache_size = true && that.isSetRow_cache_size(); if (this_present_row_cache_size || that_present_row_cache_size) { @@ -2372,6 +2428,11 @@ public class CfDef implements org.apache.thrift.TBase, jav if (present_memtable_flush_period_in_ms) builder.append(memtable_flush_period_in_ms); + boolean present_default_time_to_live = true && (isSetDefault_time_to_live()); + builder.append(present_default_time_to_live); + if (present_default_time_to_live) + builder.append(default_time_to_live); + boolean present_row_cache_size = true && (isSetRow_cache_size()); builder.append(present_row_cache_size); if (present_row_cache_size) @@ -2663,6 +2724,16 @@ public class CfDef implements org.apache.thrift.TBase, jav return lastComparison; } } + lastComparison = Boolean.valueOf(isSetDefault_time_to_live()).compareTo(typedOther.isSetDefault_time_to_live()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetDefault_time_to_live()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.default_time_to_live, typedOther.default_time_to_live); + if (lastComparison != 0) { + return lastComparison; + } + } lastComparison = Boolean.valueOf(isSetRow_cache_size()).compareTo(typedOther.isSetRow_cache_size()); if (lastComparison != 0) { return lastComparison; @@ -2985,6 +3056,14 @@ public class CfDef implements org.apache.thrift.TBase, jav org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type); } break; + case 39: // DEFAULT_TIME_TO_LIVE + if (field.type == org.apache.thrift.protocol.TType.I32) { + this.default_time_to_live = iprot.readI32(); + setDefault_time_to_liveIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type); + } + break; case 9: // ROW_CACHE_SIZE if (field.type == org.apache.thrift.protocol.TType.DOUBLE) { this.row_cache_size = iprot.readDouble(); @@ -3293,6 +3372,11 @@ public class CfDef implements org.apache.thrift.TBase, jav oprot.writeI32(this.memtable_flush_period_in_ms); oprot.writeFieldEnd(); } + if (isSetDefault_time_to_live()) { + oprot.writeFieldBegin(DEFAULT_TIME_TO_LIVE_FIELD_DESC); + oprot.writeI32(this.default_time_to_live); + oprot.writeFieldEnd(); + } oprot.writeFieldStop(); oprot.writeStructEnd(); } @@ -3491,6 +3575,12 @@ public class CfDef implements org.apache.thrift.TBase, jav sb.append(this.memtable_flush_period_in_ms); first = false; } + if (isSetDefault_time_to_live()) { + if (!first) sb.append(", "); + sb.append("default_time_to_live:"); + sb.append(this.default_time_to_live); + first = false; + } if (isSetRow_cache_size()) { if (!first) sb.append(", "); sb.append("row_cache_size:"); diff --git a/pylib/cqlshlib/cqlhandling.py b/pylib/cqlshlib/cqlhandling.py index f755e9584d..13a4359e8c 100644 --- a/pylib/cqlshlib/cqlhandling.py +++ b/pylib/cqlshlib/cqlhandling.py @@ -50,6 +50,7 @@ class CqlParsingRuleSet(pylexotron.ParsingRuleSet): ('max_compaction_threshold', None), ('replicate_on_write', None), ('compaction_strategy_class', 'compaction_strategy'), + ('default_time_to_live', None), ) obsolete_cf_options = ( @@ -834,7 +835,7 @@ def create_cf_option_val_completer(ctxt, cass): return [Hint('')] if this_opt == 'replicate_on_write': return [Hint('')] - if this_opt in ('min_compaction_threshold', 'max_compaction_threshold', 'gc_grace_seconds'): + if this_opt in ('min_compaction_threshold', 'max_compaction_threshold', 'gc_grace_seconds', 'default_time_to_live'): return [Hint('')] return [Hint('')] diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index 197a870423..ccda8b80b8 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -138,7 +138,8 @@ public class CliClient COMPRESSION_OPTIONS, BLOOM_FILTER_FP_CHANCE, MEMTABLE_FLUSH_PERIOD_IN_MS, - CACHING + CACHING, + DEFAULT_TIME_TO_LIVE } private static final String DEFAULT_PLACEMENT_STRATEGY = "org.apache.cassandra.locator.NetworkTopologyStrategy"; @@ -1330,6 +1331,9 @@ public class CliClient case CACHING: cfDef.setCaching(CliUtils.unescapeSQLString(mValue)); break; + case DEFAULT_TIME_TO_LIVE: + cfDef.setDefault_time_to_live(Integer.parseInt(mValue)); + break; default: //must match one of the above or we'd throw an exception at the valueOf statement above. assert(false); @@ -1784,6 +1788,7 @@ public class CliClient writeAttr(output, false, "replicate_on_write", cfDef.replicate_on_write); writeAttr(output, false, "compaction_strategy", cfDef.compaction_strategy); writeAttr(output, false, "caching", cfDef.caching); + writeAttr(output, false, "default_time_to_live", cfDef.default_time_to_live); if (cfDef.isSetBloom_filter_fp_chance()) writeAttr(output, false, "bloom_filter_fp_chance", cfDef.bloom_filter_fp_chance); @@ -2149,6 +2154,7 @@ public class CliClient sessionState.out.printf(" DC Local Read repair chance: %s%n", cf_def.dclocal_read_repair_chance); sessionState.out.printf(" Replicate on write: %s%n", cf_def.replicate_on_write); sessionState.out.printf(" Caching: %s%n", cf_def.caching); + sessionState.out.printf(" Default time to live: %s%n", cf_def.default_time_to_live); sessionState.out.printf(" Bloom Filter FP chance: %s%n", cf_def.isSetBloom_filter_fp_chance() ? cf_def.bloom_filter_fp_chance : "default"); // if we have connection to the cfMBean established diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java index c7b94bd85c..3cedf13308 100644 --- a/src/java/org/apache/cassandra/config/CFMetaData.java +++ b/src/java/org/apache/cassandra/config/CFMetaData.java @@ -75,6 +75,7 @@ public final class CFMetaData public final static Class DEFAULT_COMPACTION_STRATEGY_CLASS = SizeTieredCompactionStrategy.class; public final static ByteBuffer DEFAULT_KEY_NAME = ByteBufferUtil.bytes("KEY"); public final static Caching DEFAULT_CACHING_STRATEGY = Caching.KEYS_ONLY; + public final static int DEFAULT_DEFAULT_TIME_TO_LIVE = 0; // Note that this is the default only for user created tables public final static String DEFAULT_COMPRESSOR = SnappyCompressor.isAvailable() ? SnappyCompressor.class.getCanonicalName() : null; @@ -128,6 +129,7 @@ public final class CFMetaData + "key_aliases text," + "bloom_filter_fp_chance double," + "caching text," + + "default_time_to_live int," + "compaction_strategy_class text," + "compression_parameters text," + "value_alias text," @@ -261,6 +263,7 @@ public final class CFMetaData private volatile Double bloomFilterFpChance = null; private volatile Caching caching = DEFAULT_CACHING_STRATEGY; private int memtableFlushPeriod = 0; + private volatile int defaultTimeToLive = DEFAULT_DEFAULT_TIME_TO_LIVE; volatile Map column_metadata = new HashMap(); public volatile Class compactionStrategyClass = DEFAULT_COMPACTION_STRATEGY_CLASS; @@ -292,6 +295,7 @@ public final class CFMetaData public CFMetaData bloomFilterFpChance(Double prop) {bloomFilterFpChance = prop; return this;} public CFMetaData caching(Caching prop) {caching = prop; return this;} public CFMetaData memtableFlushPeriod(int prop) {memtableFlushPeriod = prop; return this;} + public CFMetaData defaultTimeToLive(int prop) {defaultTimeToLive = prop; return this;} public CFMetaData(String keyspace, String name, ColumnFamilyType type, AbstractType comp, AbstractType subcc) { @@ -431,7 +435,8 @@ public final class CFMetaData .compressionParameters(oldCFMD.compressionParameters) .bloomFilterFpChance(oldCFMD.bloomFilterFpChance) .caching(oldCFMD.caching) - .memtableFlushPeriod(oldCFMD.memtableFlushPeriod); + .memtableFlushPeriod(oldCFMD.memtableFlushPeriod) + .defaultTimeToLive(oldCFMD.defaultTimeToLive); } /** @@ -549,6 +554,11 @@ public final class CFMetaData return memtableFlushPeriod; } + public int getDefaultTimeToLive() + { + return defaultTimeToLive; + } + public boolean equals(Object obj) { if (obj == this) @@ -587,6 +597,7 @@ public final class CFMetaData .append(bloomFilterFpChance, rhs.bloomFilterFpChance) .append(memtableFlushPeriod, rhs.memtableFlushPeriod) .append(caching, rhs.caching) + .append(defaultTimeToLive, rhs.defaultTimeToLive) .isEquals(); } @@ -618,6 +629,7 @@ public final class CFMetaData .append(bloomFilterFpChance) .append(memtableFlushPeriod) .append(caching) + .append(defaultTimeToLive) .toHashCode(); } @@ -656,6 +668,8 @@ public final class CFMetaData put(CompressionParameters.SSTABLE_COMPRESSION, DEFAULT_COMPRESSOR); }}); } + if (!cf_def.isSetDefault_time_to_live()) + cf_def.setDefault_time_to_live(CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE); if (!cf_def.isSetDclocal_read_repair_chance()) cf_def.setDclocal_read_repair_chance(CFMetaData.DEFAULT_DCLOCAL_READ_REPAIR_CHANCE); } @@ -695,6 +709,8 @@ public final class CFMetaData newCFMD.caching(Caching.fromString(cf_def.caching)); if (cf_def.isSetRead_repair_chance()) newCFMD.readRepairChance(cf_def.read_repair_chance); + if (cf_def.isSetDefault_time_to_live()) + newCFMD.defaultTimeToLive(cf_def.default_time_to_live); if (cf_def.isSetDclocal_read_repair_chance()) newCFMD.dcLocalReadRepairChance(cf_def.dclocal_read_repair_chance); @@ -802,6 +818,7 @@ public final class CFMetaData bloomFilterFpChance = cfm.bloomFilterFpChance; memtableFlushPeriod = cfm.memtableFlushPeriod; caching = cfm.caching; + defaultTimeToLive = cfm.defaultTimeToLive; MapDifference columnDiff = Maps.difference(column_metadata, cfm.column_metadata); // columns that are no longer needed @@ -896,6 +913,7 @@ public final class CFMetaData def.setBloom_filter_fp_chance(bloomFilterFpChance); def.setMemtable_flush_period_in_ms(memtableFlushPeriod); def.setCaching(caching.toString()); + def.setDefault_time_to_live(defaultTimeToLive); return def; } @@ -1236,6 +1254,7 @@ public final class CFMetaData cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "key_aliases")); cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "bloom_filter_fp_chance")); cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "caching")); + cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "default_time_to_live")); cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "compaction_strategy_class")); cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "compression_parameters")); cf.addColumn(DeletedColumn.create(ldt, timestamp, cfName, "value_alias")); @@ -1287,6 +1306,7 @@ public final class CFMetaData : Column.create(bloomFilterFpChance, timestamp, cfName, "bloom_filter_fp_chance")); cf.addColumn(Column.create(memtableFlushPeriod, timestamp, cfName, "memtable_flush_period_in_ms")); cf.addColumn(Column.create(caching.toString(), timestamp, cfName, "caching")); + cf.addColumn(Column.create(defaultTimeToLive, timestamp, cfName, "default_time_to_live")); cf.addColumn(Column.create(compactionStrategyClass.getName(), timestamp, cfName, "compaction_strategy_class")); cf.addColumn(Column.create(json(compressionParameters.asThriftOptions()), timestamp, cfName, "compression_parameters")); cf.addColumn(valueAlias == null ? DeletedColumn.create(ldt, timestamp, cfName, "value_alias") @@ -1333,6 +1353,8 @@ public final class CFMetaData if (result.has("memtable_flush_period_in_ms")) cfm.memtableFlushPeriod(result.getInt("memtable_flush_period_in_ms")); cfm.caching(Caching.valueOf(result.getString("caching"))); + if (result.has("default_time_to_live")) + cfm.defaultTimeToLive(result.getInt("default_time_to_live")); cfm.compactionStrategyClass(createCompactionStrategy(result.getString("compaction_strategy_class"))); cfm.compressionParameters(CompressionParameters.create(fromJsonMap(result.getString("compression_parameters")))); cfm.columnAliases(aliasesFromStrings(fromJsonList(result.getString("column_aliases")))); @@ -1503,6 +1525,7 @@ public final class CFMetaData .append("bloomFilterFpChance", bloomFilterFpChance) .append("memtable_flush_period_in_ms", memtableFlushPeriod) .append("caching", caching) + .append("defaultTimeToLive", defaultTimeToLive) .toString(); } } diff --git a/src/java/org/apache/cassandra/cql/AlterTableStatement.java b/src/java/org/apache/cassandra/cql/AlterTableStatement.java index 397f371a87..7575224063 100644 --- a/src/java/org/apache/cassandra/cql/AlterTableStatement.java +++ b/src/java/org/apache/cassandra/cql/AlterTableStatement.java @@ -186,6 +186,7 @@ public class AlterTableStatement cfm.minCompactionThreshold(cfProps.getPropertyInt(CFPropDefs.KW_MINCOMPACTIONTHRESHOLD, cfm.getMinCompactionThreshold())); cfm.maxCompactionThreshold(cfProps.getPropertyInt(CFPropDefs.KW_MAXCOMPACTIONTHRESHOLD, cfm.getMaxCompactionThreshold())); cfm.caching(CFMetaData.Caching.fromString(cfProps.getPropertyString(CFPropDefs.KW_CACHING, cfm.getCaching().toString()))); + cfm.defaultTimeToLive(cfProps.getPropertyInt(CFPropDefs.KW_DEFAULT_TIME_TO_LIVE, cfm.getDefaultTimeToLive())); cfm.bloomFilterFpChance(cfProps.getPropertyDouble(CFPropDefs.KW_BF_FP_CHANCE, cfm.getBloomFilterFpChance())); cfm.memtableFlushPeriod(cfProps.getPropertyInt(CFPropDefs.KW_MEMTABLE_FLUSH_PERIOD, cfm.getMemtableFlushPeriod())); diff --git a/src/java/org/apache/cassandra/cql/CFPropDefs.java b/src/java/org/apache/cassandra/cql/CFPropDefs.java index 091ee6a113..69454761fe 100644 --- a/src/java/org/apache/cassandra/cql/CFPropDefs.java +++ b/src/java/org/apache/cassandra/cql/CFPropDefs.java @@ -49,6 +49,7 @@ public class CFPropDefs { public static final String KW_REPLICATEONWRITE = "replicate_on_write"; public static final String KW_COMPACTION_STRATEGY_CLASS = "compaction_strategy_class"; public static final String KW_CACHING = "caching"; + public static final String KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live"; public static final String KW_BF_FP_CHANCE = "bloom_filter_fp_chance"; public static final String KW_MEMTABLE_FLUSH_PERIOD = "memtable_flush_period_in_ms"; @@ -91,6 +92,7 @@ public class CFPropDefs { keywords.add(KW_REPLICATEONWRITE); keywords.add(KW_COMPACTION_STRATEGY_CLASS); keywords.add(KW_CACHING); + keywords.add(KW_DEFAULT_TIME_TO_LIVE); keywords.add(KW_BF_FP_CHANCE); keywords.add(KW_MEMTABLE_FLUSH_PERIOD); @@ -180,6 +182,17 @@ public class CFPropDefs { KW_MINCOMPACTIONTHRESHOLD, CFMetaData.DEFAULT_MIN_COMPACTION_THRESHOLD)); } + + Integer defaultTimeToLive = getPropertyInt(KW_DEFAULT_TIME_TO_LIVE, null); + + if (defaultTimeToLive != null) + { + if (defaultTimeToLive < 0) + throw new InvalidRequestException(String.format("%s cannot be smaller than %s, (default %s)", + KW_DEFAULT_TIME_TO_LIVE, + 0, + CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE)); + } } /** Map a keyword to the corresponding value */ diff --git a/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java b/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java index 992166e311..90b8f55a00 100644 --- a/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java +++ b/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java @@ -193,7 +193,8 @@ public class CreateColumnFamilyStatement .compressionParameters(CompressionParameters.create(cfProps.compressionParameters)) .caching(CFMetaData.Caching.fromString(getPropertyString(CFPropDefs.KW_CACHING, CFMetaData.DEFAULT_CACHING_STRATEGY.toString()))) .bloomFilterFpChance(getPropertyDouble(CFPropDefs.KW_BF_FP_CHANCE, null)) - .memtableFlushPeriod(getPropertyInt(CFPropDefs.KW_MEMTABLE_FLUSH_PERIOD, 0)); + .memtableFlushPeriod(getPropertyInt(CFPropDefs.KW_MEMTABLE_FLUSH_PERIOD, 0)) + .defaultTimeToLive(getPropertyInt(CFPropDefs.KW_DEFAULT_TIME_TO_LIVE, CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE)); // CQL2 can have null keyAliases if (keyAlias != null) diff --git a/src/java/org/apache/cassandra/cql3/CFPropDefs.java b/src/java/org/apache/cassandra/cql3/CFPropDefs.java index 61cefffce3..3907517686 100644 --- a/src/java/org/apache/cassandra/cql3/CFPropDefs.java +++ b/src/java/org/apache/cassandra/cql3/CFPropDefs.java @@ -41,6 +41,7 @@ public class CFPropDefs extends PropertyDefinitions public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_threshold"; public static final String KW_REPLICATEONWRITE = "replicate_on_write"; public static final String KW_CACHING = "caching"; + public static final String KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live"; public static final String KW_BF_FP_CHANCE = "bloom_filter_fp_chance"; public static final String KW_MEMTABLE_FLUSH_PERIOD = "memtable_flush_period_in_ms"; @@ -60,6 +61,7 @@ public class CFPropDefs extends PropertyDefinitions keywords.add(KW_GCGRACESECONDS); keywords.add(KW_REPLICATEONWRITE); keywords.add(KW_CACHING); + keywords.add(KW_DEFAULT_TIME_TO_LIVE); keywords.add(KW_BF_FP_CHANCE); keywords.add(KW_COMPACTION); keywords.add(KW_COMPRESSION); @@ -89,6 +91,17 @@ public class CFPropDefs extends PropertyDefinitions compactionStrategyClass = CFMetaData.createCompactionStrategy(strategy); compactionOptions.remove(COMPACTION_STRATEGY_CLASS_KEY); } + + Integer defaultTimeToLive = getInt(KW_DEFAULT_TIME_TO_LIVE, null); + + if (defaultTimeToLive != null) + { + if (defaultTimeToLive < 0) + throw new ConfigurationException(String.format("%s cannot be smaller than %s, (default %s)", + KW_DEFAULT_TIME_TO_LIVE, + 0, + CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE)); + } } public Map getCompactionOptions() throws SyntaxException @@ -125,6 +138,7 @@ public class CFPropDefs extends PropertyDefinitions cfm.minCompactionThreshold(toInt(KW_MINCOMPACTIONTHRESHOLD, getCompactionOptions().get(KW_MINCOMPACTIONTHRESHOLD), cfm.getMinCompactionThreshold())); cfm.maxCompactionThreshold(toInt(KW_MAXCOMPACTIONTHRESHOLD, getCompactionOptions().get(KW_MAXCOMPACTIONTHRESHOLD), cfm.getMaxCompactionThreshold())); cfm.caching(CFMetaData.Caching.fromString(getString(KW_CACHING, cfm.getCaching().toString()))); + cfm.defaultTimeToLive(getInt(KW_DEFAULT_TIME_TO_LIVE, cfm.getDefaultTimeToLive())); cfm.bloomFilterFpChance(getDouble(KW_BF_FP_CHANCE, cfm.getBloomFilterFpChance())); cfm.memtableFlushPeriod(getInt(KW_MEMTABLE_FLUSH_PERIOD, cfm.getMemtableFlushPeriod())); diff --git a/src/java/org/apache/cassandra/cql3/UpdateParameters.java b/src/java/org/apache/cassandra/cql3/UpdateParameters.java index 1372c876bf..299eeab887 100644 --- a/src/java/org/apache/cassandra/cql3/UpdateParameters.java +++ b/src/java/org/apache/cassandra/cql3/UpdateParameters.java @@ -19,7 +19,9 @@ package org.apache.cassandra.cql3; import java.nio.ByteBuffer; import java.util.List; +import java.util.Map; +import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.db.*; /** @@ -27,13 +29,15 @@ import org.apache.cassandra.db.*; */ public class UpdateParameters { + public final CFMetaData metadata; public final List variables; public final long timestamp; private final int ttl; public final int localDeletionTime; - public UpdateParameters(List variables, long timestamp, int ttl) + public UpdateParameters(CFMetaData metadata, List variables, long timestamp, int ttl) { + this.metadata = metadata; this.variables = variables; this.timestamp = timestamp; this.ttl = ttl; @@ -42,9 +46,7 @@ public class UpdateParameters public Column makeColumn(ByteBuffer name, ByteBuffer value) { - return ttl > 0 - ? new ExpiringColumn(name, value, timestamp, ttl) - : new Column(name, value, timestamp); + return Column.create(name, value, timestamp, ttl, metadata); } public Column makeTombstone(ByteBuffer name) diff --git a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java index 7d543dcf93..c14a82035e 100644 --- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java @@ -99,7 +99,7 @@ public class DeleteStatement extends ModificationStatement Map rows = toRead != null ? readRows(keys, builder, toRead, (CompositeType)cfDef.cfm.comparator, local, cl) : null; Collection rowMutations = new ArrayList(keys.size()); - UpdateParameters params = new UpdateParameters(variables, getTimestamp(now), -1); + UpdateParameters params = new UpdateParameters(cfDef.cfm, variables, getTimestamp(now), -1); for (ByteBuffer key : keys) rowMutations.add(mutationForKey(cfDef, key, builder, isRange, params, rows == null ? null : rows.get(key))); diff --git a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java index 97844ad33a..e5d457f312 100644 --- a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java @@ -133,7 +133,7 @@ public class UpdateStatement extends ModificationStatement Map rows = toRead != null ? readRows(keys, builder, toRead, (CompositeType)cfDef.cfm.comparator, local, cl) : null; Collection mutations = new LinkedList(); - UpdateParameters params = new UpdateParameters(variables, getTimestamp(now), getTimeToLive()); + UpdateParameters params = new UpdateParameters(cfDef.cfm, variables, getTimestamp(now), getTimeToLive()); for (ByteBuffer key: keys) mutations.add(mutationForKey(cfDef, key, builder, params, rows == null ? null : rows.get(key), cl)); diff --git a/src/java/org/apache/cassandra/db/Column.java b/src/java/org/apache/cassandra/db/Column.java index 23eaa7eae7..cce64b03f1 100644 --- a/src/java/org/apache/cassandra/db/Column.java +++ b/src/java/org/apache/cassandra/db/Column.java @@ -292,6 +292,16 @@ public class Column implements IColumn return getLocalDeletionTime() < gcBefore; } + public static Column create(ByteBuffer name, ByteBuffer value, long timestamp, int ttl, CFMetaData metadata) + { + if (ttl <= 0) + ttl = metadata.getDefaultTimeToLive(); + + return ttl > 0 + ? new ExpiringColumn(name, value, timestamp, ttl) + : new Column(name, value, timestamp); + } + public static Column create(String value, long timestamp, String... names) { return new Column(decomposeName(names), UTF8Type.instance.decompose(value), timestamp); diff --git a/src/java/org/apache/cassandra/db/ColumnFamily.java b/src/java/org/apache/cassandra/db/ColumnFamily.java index c2dd118f0c..b8dd63c5e4 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamily.java +++ b/src/java/org/apache/cassandra/db/ColumnFamily.java @@ -165,11 +165,7 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn { assert path.columnName != null : path; assert !metadata().getDefaultValidator().isCommutative(); - Column column; - if (timeToLive > 0) - column = new ExpiringColumn(path.columnName, value, timestamp, timeToLive); - else - column = new Column(path.columnName, value, timestamp); + Column column = Column.create(path.columnName, value, timestamp, timeToLive, metadata()); addColumn(path.superColumnName, column); }