You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ma...@apache.org on 2014/02/06 10:11:38 UTC

[2/2] git commit: Make it possible to cache a configurable amount of rows in row cache.

Make it possible to cache a configurable amount of rows in row cache.

Patch by pcmanus and marcuse, reviewed by pcmanus for CASSANDRA-5357


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/ab6eaed8
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/ab6eaed8
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/ab6eaed8

Branch: refs/heads/trunk
Commit: ab6eaed8f6bdef21323be561a22e9fdb16bbd0fc
Parents: 98e6b08
Author: Marcus Eriksson <ma...@apache.org>
Authored: Thu Feb 6 10:08:55 2014 +0100
Committer: Marcus Eriksson <ma...@apache.org>
Committed: Thu Feb 6 10:08:55 2014 +0100

----------------------------------------------------------------------
 interface/cassandra.thrift                      |   3 +-
 .../org/apache/cassandra/thrift/CfDef.java      | 404 ++++++++++++-------
 .../cassandra/thrift/cassandraConstants.java    |   2 +-
 pylib/cqlshlib/cql3handling.py                  |   1 +
 .../org/apache/cassandra/cli/CliClient.java     |   5 +
 .../org/apache/cassandra/config/CFMetaData.java |  66 ++-
 .../cassandra/cql/AlterTableStatement.java      |   1 +
 .../org/apache/cassandra/cql/CFPropDefs.java    |   2 +
 .../cql/CreateColumnFamilyStatement.java        |   1 +
 .../cassandra/cql3/statements/CFPropDefs.java   |   8 +
 .../org/apache/cassandra/db/ColumnFamily.java   |   9 +
 .../apache/cassandra/db/ColumnFamilyStore.java  | 150 ++++++-
 .../apache/cassandra/db/RowIteratorFactory.java |  11 +-
 .../cassandra/db/filter/IDiskAtomFilter.java    |  13 +-
 .../cassandra/db/filter/NamesQueryFilter.java   |  23 +-
 .../cassandra/db/filter/SliceQueryFilter.java   |  36 ++
 .../cassandra/metrics/ColumnFamilyMetrics.java  |  13 +
 .../apache/cassandra/service/CacheService.java  |  18 +-
 .../org/apache/cassandra/cli/CliHelp.yaml       |   4 +
 .../unit/org/apache/cassandra/SchemaLoader.java |   3 +-
 .../org/apache/cassandra/db/RowCacheTest.java   |  78 ++++
 21 files changed, 678 insertions(+), 173 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/interface/cassandra.thrift
----------------------------------------------------------------------
diff --git a/interface/cassandra.thrift b/interface/cassandra.thrift
index 289be1f..5f551ce 100644
--- a/interface/cassandra.thrift
+++ b/interface/cassandra.thrift
@@ -55,7 +55,7 @@ namespace rb CassandraThrift
 # An effort should be made not to break forward-client-compatibility either
 # (e.g. one should avoid removing obsolete fields from the IDL), but no
 # guarantees in this respect are made by the Cassandra project.
-const string VERSION = "19.38.0"
+const string VERSION = "19.38.1"
 
 
 #
@@ -473,6 +473,7 @@ struct CfDef {
     41: optional i32 index_interval,
     42: optional string speculative_retry="NONE",
     43: optional list<TriggerDef> triggers,
+    44: optional string cells_per_row_to_cache = "100",
 
     /* All of the following are now ignored and unsupplied. */
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java
----------------------------------------------------------------------
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 0bdb500..990b17e 100644
--- a/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java
+++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/CfDef.java
@@ -70,7 +70,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.I32, (short)16);
   private static final org.apache.thrift.protocol.TField MIN_COMPACTION_THRESHOLD_FIELD_DESC = new org.apache.thrift.protocol.TField("min_compaction_threshold", org.apache.thrift.protocol.TType.I32, (short)17);
   private static final org.apache.thrift.protocol.TField MAX_COMPACTION_THRESHOLD_FIELD_DESC = new org.apache.thrift.protocol.TField("max_compaction_threshold", org.apache.thrift.protocol.TType.I32, (short)18);
-  private static final org.apache.thrift.protocol.TField REPLICATE_ON_WRITE_FIELD_DESC = new org.apache.thrift.protocol.TField("replicate_on_write", org.apache.thrift.protocol.TType.BOOL, (short)24);
   private static final org.apache.thrift.protocol.TField KEY_VALIDATION_CLASS_FIELD_DESC = new org.apache.thrift.protocol.TField("key_validation_class", org.apache.thrift.protocol.TType.STRING, (short)26);
   private static final org.apache.thrift.protocol.TField KEY_ALIAS_FIELD_DESC = new org.apache.thrift.protocol.TField("key_alias", org.apache.thrift.protocol.TType.STRING, (short)28);
   private static final org.apache.thrift.protocol.TField COMPACTION_STRATEGY_FIELD_DESC = new org.apache.thrift.protocol.TField("compaction_strategy", org.apache.thrift.protocol.TType.STRING, (short)29);
@@ -85,6 +84,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   private static final org.apache.thrift.protocol.TField INDEX_INTERVAL_FIELD_DESC = new org.apache.thrift.protocol.TField("index_interval", org.apache.thrift.protocol.TType.I32, (short)41);
   private static final org.apache.thrift.protocol.TField SPECULATIVE_RETRY_FIELD_DESC = new org.apache.thrift.protocol.TField("speculative_retry", org.apache.thrift.protocol.TType.STRING, (short)42);
   private static final org.apache.thrift.protocol.TField TRIGGERS_FIELD_DESC = new org.apache.thrift.protocol.TField("triggers", org.apache.thrift.protocol.TType.LIST, (short)43);
+  private static final org.apache.thrift.protocol.TField CELLS_PER_ROW_TO_CACHE_FIELD_DESC = new org.apache.thrift.protocol.TField("cells_per_row_to_cache", org.apache.thrift.protocol.TType.STRING, (short)44);
   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);
@@ -92,6 +92,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   private static final org.apache.thrift.protocol.TField MEMTABLE_FLUSH_AFTER_MINS_FIELD_DESC = new org.apache.thrift.protocol.TField("memtable_flush_after_mins", org.apache.thrift.protocol.TType.I32, (short)21);
   private static final org.apache.thrift.protocol.TField MEMTABLE_THROUGHPUT_IN_MB_FIELD_DESC = new org.apache.thrift.protocol.TField("memtable_throughput_in_mb", org.apache.thrift.protocol.TType.I32, (short)22);
   private static final org.apache.thrift.protocol.TField MEMTABLE_OPERATIONS_IN_MILLIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("memtable_operations_in_millions", org.apache.thrift.protocol.TType.DOUBLE, (short)23);
+  private static final org.apache.thrift.protocol.TField REPLICATE_ON_WRITE_FIELD_DESC = new org.apache.thrift.protocol.TField("replicate_on_write", org.apache.thrift.protocol.TType.BOOL, (short)24);
   private static final org.apache.thrift.protocol.TField MERGE_SHARDS_CHANCE_FIELD_DESC = new org.apache.thrift.protocol.TField("merge_shards_chance", org.apache.thrift.protocol.TType.DOUBLE, (short)25);
   private static final org.apache.thrift.protocol.TField ROW_CACHE_PROVIDER_FIELD_DESC = new org.apache.thrift.protocol.TField("row_cache_provider", org.apache.thrift.protocol.TType.STRING, (short)27);
   private static final org.apache.thrift.protocol.TField ROW_CACHE_KEYS_TO_SAVE_FIELD_DESC = new org.apache.thrift.protocol.TField("row_cache_keys_to_save", org.apache.thrift.protocol.TType.I32, (short)31);
@@ -115,7 +116,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   public int id; // optional
   public int min_compaction_threshold; // optional
   public int max_compaction_threshold; // optional
-  public boolean replicate_on_write; // optional
   public String key_validation_class; // optional
   public ByteBuffer key_alias; // optional
   public String compaction_strategy; // optional
@@ -130,6 +130,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   public int index_interval; // optional
   public String speculative_retry; // optional
   public List<TriggerDef> triggers; // optional
+  public String cells_per_row_to_cache; // optional
   /**
    * @deprecated
    */
@@ -161,6 +162,10 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   /**
    * @deprecated
    */
+  public boolean replicate_on_write; // optional
+  /**
+   * @deprecated
+   */
   public double merge_shards_chance; // optional
   /**
    * @deprecated
@@ -186,7 +191,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     ID((short)16, "id"),
     MIN_COMPACTION_THRESHOLD((short)17, "min_compaction_threshold"),
     MAX_COMPACTION_THRESHOLD((short)18, "max_compaction_threshold"),
-    REPLICATE_ON_WRITE((short)24, "replicate_on_write"),
     KEY_VALIDATION_CLASS((short)26, "key_validation_class"),
     KEY_ALIAS((short)28, "key_alias"),
     COMPACTION_STRATEGY((short)29, "compaction_strategy"),
@@ -201,6 +205,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     INDEX_INTERVAL((short)41, "index_interval"),
     SPECULATIVE_RETRY((short)42, "speculative_retry"),
     TRIGGERS((short)43, "triggers"),
+    CELLS_PER_ROW_TO_CACHE((short)44, "cells_per_row_to_cache"),
     /**
      * @deprecated
      */
@@ -232,6 +237,10 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     /**
      * @deprecated
      */
+    REPLICATE_ON_WRITE((short)24, "replicate_on_write"),
+    /**
+     * @deprecated
+     */
     MERGE_SHARDS_CHANCE((short)25, "merge_shards_chance"),
     /**
      * @deprecated
@@ -281,8 +290,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
           return MIN_COMPACTION_THRESHOLD;
         case 18: // MAX_COMPACTION_THRESHOLD
           return MAX_COMPACTION_THRESHOLD;
-        case 24: // REPLICATE_ON_WRITE
-          return REPLICATE_ON_WRITE;
         case 26: // KEY_VALIDATION_CLASS
           return KEY_VALIDATION_CLASS;
         case 28: // KEY_ALIAS
@@ -311,6 +318,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
           return SPECULATIVE_RETRY;
         case 43: // TRIGGERS
           return TRIGGERS;
+        case 44: // CELLS_PER_ROW_TO_CACHE
+          return CELLS_PER_ROW_TO_CACHE;
         case 9: // ROW_CACHE_SIZE
           return ROW_CACHE_SIZE;
         case 11: // KEY_CACHE_SIZE
@@ -325,6 +334,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
           return MEMTABLE_THROUGHPUT_IN_MB;
         case 23: // MEMTABLE_OPERATIONS_IN_MILLIONS
           return MEMTABLE_OPERATIONS_IN_MILLIONS;
+        case 24: // REPLICATE_ON_WRITE
+          return REPLICATE_ON_WRITE;
         case 25: // MERGE_SHARDS_CHANCE
           return MERGE_SHARDS_CHANCE;
         case 27: // ROW_CACHE_PROVIDER
@@ -376,24 +387,24 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   private static final int __ID_ISSET_ID = 2;
   private static final int __MIN_COMPACTION_THRESHOLD_ISSET_ID = 3;
   private static final int __MAX_COMPACTION_THRESHOLD_ISSET_ID = 4;
-  private static final int __REPLICATE_ON_WRITE_ISSET_ID = 5;
-  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 __POPULATE_IO_CACHE_ON_FLUSH_ISSET_ID = 8;
-  private static final int __MEMTABLE_FLUSH_PERIOD_IN_MS_ISSET_ID = 9;
-  private static final int __DEFAULT_TIME_TO_LIVE_ISSET_ID = 10;
-  private static final int __INDEX_INTERVAL_ISSET_ID = 11;
-  private static final int __ROW_CACHE_SIZE_ISSET_ID = 12;
-  private static final int __KEY_CACHE_SIZE_ISSET_ID = 13;
-  private static final int __ROW_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 14;
-  private static final int __KEY_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 15;
-  private static final int __MEMTABLE_FLUSH_AFTER_MINS_ISSET_ID = 16;
-  private static final int __MEMTABLE_THROUGHPUT_IN_MB_ISSET_ID = 17;
-  private static final int __MEMTABLE_OPERATIONS_IN_MILLIONS_ISSET_ID = 18;
+  private static final int __BLOOM_FILTER_FP_CHANCE_ISSET_ID = 5;
+  private static final int __DCLOCAL_READ_REPAIR_CHANCE_ISSET_ID = 6;
+  private static final int __POPULATE_IO_CACHE_ON_FLUSH_ISSET_ID = 7;
+  private static final int __MEMTABLE_FLUSH_PERIOD_IN_MS_ISSET_ID = 8;
+  private static final int __DEFAULT_TIME_TO_LIVE_ISSET_ID = 9;
+  private static final int __INDEX_INTERVAL_ISSET_ID = 10;
+  private static final int __ROW_CACHE_SIZE_ISSET_ID = 11;
+  private static final int __KEY_CACHE_SIZE_ISSET_ID = 12;
+  private static final int __ROW_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 13;
+  private static final int __KEY_CACHE_SAVE_PERIOD_IN_SECONDS_ISSET_ID = 14;
+  private static final int __MEMTABLE_FLUSH_AFTER_MINS_ISSET_ID = 15;
+  private static final int __MEMTABLE_THROUGHPUT_IN_MB_ISSET_ID = 16;
+  private static final int __MEMTABLE_OPERATIONS_IN_MILLIONS_ISSET_ID = 17;
+  private static final int __REPLICATE_ON_WRITE_ISSET_ID = 18;
   private static final int __MERGE_SHARDS_CHANCE_ISSET_ID = 19;
   private static final int __ROW_CACHE_KEYS_TO_SAVE_ISSET_ID = 20;
   private int __isset_bitfield = 0;
-  private _Fields optionals[] = {_Fields.COLUMN_TYPE,_Fields.COMPARATOR_TYPE,_Fields.SUBCOMPARATOR_TYPE,_Fields.COMMENT,_Fields.READ_REPAIR_CHANCE,_Fields.COLUMN_METADATA,_Fields.GC_GRACE_SECONDS,_Fields.DEFAULT_VALIDATION_CLASS,_Fields.ID,_Fields.MIN_COMPACTION_THRESHOLD,_Fields.MAX_COMPACTION_THRESHOLD,_Fields.REPLICATE_ON_WRITE,_Fields.KEY_VALIDATION_CLASS,_Fields.KEY_ALIAS,_Fields.COMPACTION_STRATEGY,_Fields.COMPACTION_STRATEGY_OPTIONS,_Fields.COMPRESSION_OPTIONS,_Fields.BLOOM_FILTER_FP_CHANCE,_Fields.CACHING,_Fields.DCLOCAL_READ_REPAIR_CHANCE,_Fields.POPULATE_IO_CACHE_ON_FLUSH,_Fields.MEMTABLE_FLUSH_PERIOD_IN_MS,_Fields.DEFAULT_TIME_TO_LIVE,_Fields.INDEX_INTERVAL,_Fields.SPECULATIVE_RETRY,_Fields.TRIGGERS,_Fields.ROW_CACHE_SIZE,_Fields.KEY_CACHE_SIZE,_Fields.ROW_CACHE_SAVE_PERIOD_IN_SECONDS,_Fields.KEY_CACHE_SAVE_PERIOD_IN_SECONDS,_Fields.MEMTABLE_FLUSH_AFTER_MINS,_Fields.MEMTABLE_THROUGHPUT_IN_MB,_Fields.MEMTABLE_OPERATIONS_IN_MILLIONS,_Fields.MERGE_SHARDS_CHANCE,_Fields.ROW_C
 ACHE_PROVIDER,_Fields.ROW_CACHE_KEYS_TO_SAVE};
+  private _Fields optionals[] = {_Fields.COLUMN_TYPE,_Fields.COMPARATOR_TYPE,_Fields.SUBCOMPARATOR_TYPE,_Fields.COMMENT,_Fields.READ_REPAIR_CHANCE,_Fields.COLUMN_METADATA,_Fields.GC_GRACE_SECONDS,_Fields.DEFAULT_VALIDATION_CLASS,_Fields.ID,_Fields.MIN_COMPACTION_THRESHOLD,_Fields.MAX_COMPACTION_THRESHOLD,_Fields.KEY_VALIDATION_CLASS,_Fields.KEY_ALIAS,_Fields.COMPACTION_STRATEGY,_Fields.COMPACTION_STRATEGY_OPTIONS,_Fields.COMPRESSION_OPTIONS,_Fields.BLOOM_FILTER_FP_CHANCE,_Fields.CACHING,_Fields.DCLOCAL_READ_REPAIR_CHANCE,_Fields.POPULATE_IO_CACHE_ON_FLUSH,_Fields.MEMTABLE_FLUSH_PERIOD_IN_MS,_Fields.DEFAULT_TIME_TO_LIVE,_Fields.INDEX_INTERVAL,_Fields.SPECULATIVE_RETRY,_Fields.TRIGGERS,_Fields.CELLS_PER_ROW_TO_CACHE,_Fields.ROW_CACHE_SIZE,_Fields.KEY_CACHE_SIZE,_Fields.ROW_CACHE_SAVE_PERIOD_IN_SECONDS,_Fields.KEY_CACHE_SAVE_PERIOD_IN_SECONDS,_Fields.MEMTABLE_FLUSH_AFTER_MINS,_Fields.MEMTABLE_THROUGHPUT_IN_MB,_Fields.MEMTABLE_OPERATIONS_IN_MILLIONS,_Fields.REPLICATE_ON_WRITE,_Fields.ME
 RGE_SHARDS_CHANCE,_Fields.ROW_CACHE_PROVIDER,_Fields.ROW_CACHE_KEYS_TO_SAVE};
   public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
     Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
@@ -424,8 +435,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
     tmpMap.put(_Fields.MAX_COMPACTION_THRESHOLD, new org.apache.thrift.meta_data.FieldMetaData("max_compaction_threshold", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
-    tmpMap.put(_Fields.REPLICATE_ON_WRITE, new org.apache.thrift.meta_data.FieldMetaData("replicate_on_write", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
-        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
     tmpMap.put(_Fields.KEY_VALIDATION_CLASS, new org.apache.thrift.meta_data.FieldMetaData("key_validation_class", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
     tmpMap.put(_Fields.KEY_ALIAS, new org.apache.thrift.meta_data.FieldMetaData("key_alias", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
@@ -459,6 +468,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     tmpMap.put(_Fields.TRIGGERS, new org.apache.thrift.meta_data.FieldMetaData("triggers", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
             new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TriggerDef.class))));
+    tmpMap.put(_Fields.CELLS_PER_ROW_TO_CACHE, new org.apache.thrift.meta_data.FieldMetaData("cells_per_row_to_cache", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
     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, 
@@ -473,6 +484,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
     tmpMap.put(_Fields.MEMTABLE_OPERATIONS_IN_MILLIONS, new org.apache.thrift.meta_data.FieldMetaData("memtable_operations_in_millions", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE)));
+    tmpMap.put(_Fields.REPLICATE_ON_WRITE, new org.apache.thrift.meta_data.FieldMetaData("replicate_on_write", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
     tmpMap.put(_Fields.MERGE_SHARDS_CHANCE, new org.apache.thrift.meta_data.FieldMetaData("merge_shards_chance", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE)));
     tmpMap.put(_Fields.ROW_CACHE_PROVIDER, new org.apache.thrift.meta_data.FieldMetaData("row_cache_provider", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
@@ -494,6 +507,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
 
     this.speculative_retry = "NONE";
 
+    this.cells_per_row_to_cache = "100";
+
   }
 
   public CfDef(
@@ -543,7 +558,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     this.id = other.id;
     this.min_compaction_threshold = other.min_compaction_threshold;
     this.max_compaction_threshold = other.max_compaction_threshold;
-    this.replicate_on_write = other.replicate_on_write;
     if (other.isSetKey_validation_class()) {
       this.key_validation_class = other.key_validation_class;
     }
@@ -581,6 +595,9 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       }
       this.triggers = __this__triggers;
     }
+    if (other.isSetCells_per_row_to_cache()) {
+      this.cells_per_row_to_cache = other.cells_per_row_to_cache;
+    }
     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;
@@ -588,6 +605,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     this.memtable_flush_after_mins = other.memtable_flush_after_mins;
     this.memtable_throughput_in_mb = other.memtable_throughput_in_mb;
     this.memtable_operations_in_millions = other.memtable_operations_in_millions;
+    this.replicate_on_write = other.replicate_on_write;
     this.merge_shards_chance = other.merge_shards_chance;
     if (other.isSetRow_cache_provider()) {
       this.row_cache_provider = other.row_cache_provider;
@@ -621,8 +639,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     this.min_compaction_threshold = 0;
     setMax_compaction_thresholdIsSet(false);
     this.max_compaction_threshold = 0;
-    setReplicate_on_writeIsSet(false);
-    this.replicate_on_write = false;
     this.key_validation_class = null;
     this.key_alias = null;
     this.compaction_strategy = null;
@@ -645,6 +661,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     this.speculative_retry = "NONE";
 
     this.triggers = null;
+    this.cells_per_row_to_cache = "100";
+
     setRow_cache_sizeIsSet(false);
     this.row_cache_size = 0.0;
     setKey_cache_sizeIsSet(false);
@@ -659,6 +677,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     this.memtable_throughput_in_mb = 0;
     setMemtable_operations_in_millionsIsSet(false);
     this.memtable_operations_in_millions = 0.0;
+    setReplicate_on_writeIsSet(false);
+    this.replicate_on_write = false;
     setMerge_shards_chanceIsSet(false);
     this.merge_shards_chance = 0.0;
     this.row_cache_provider = null;
@@ -988,29 +1008,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __MAX_COMPACTION_THRESHOLD_ISSET_ID, value);
   }
 
-  public boolean isReplicate_on_write() {
-    return this.replicate_on_write;
-  }
-
-  public CfDef setReplicate_on_write(boolean replicate_on_write) {
-    this.replicate_on_write = replicate_on_write;
-    setReplicate_on_writeIsSet(true);
-    return this;
-  }
-
-  public void unsetReplicate_on_write() {
-    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID);
-  }
-
-  /** Returns true if field replicate_on_write is set (has been assigned a value) and false otherwise */
-  public boolean isSetReplicate_on_write() {
-    return EncodingUtils.testBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID);
-  }
-
-  public void setReplicate_on_writeIsSet(boolean value) {
-    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID, value);
-  }
-
   public String getKey_validation_class() {
     return this.key_validation_class;
   }
@@ -1388,6 +1385,30 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     }
   }
 
+  public String getCells_per_row_to_cache() {
+    return this.cells_per_row_to_cache;
+  }
+
+  public CfDef setCells_per_row_to_cache(String cells_per_row_to_cache) {
+    this.cells_per_row_to_cache = cells_per_row_to_cache;
+    return this;
+  }
+
+  public void unsetCells_per_row_to_cache() {
+    this.cells_per_row_to_cache = null;
+  }
+
+  /** Returns true if field cells_per_row_to_cache is set (has been assigned a value) and false otherwise */
+  public boolean isSetCells_per_row_to_cache() {
+    return this.cells_per_row_to_cache != null;
+  }
+
+  public void setCells_per_row_to_cacheIsSet(boolean value) {
+    if (!value) {
+      this.cells_per_row_to_cache = null;
+    }
+  }
+
   /**
    * @deprecated
    */
@@ -1594,6 +1615,35 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
   /**
    * @deprecated
    */
+  public boolean isReplicate_on_write() {
+    return this.replicate_on_write;
+  }
+
+  /**
+   * @deprecated
+   */
+  public CfDef setReplicate_on_write(boolean replicate_on_write) {
+    this.replicate_on_write = replicate_on_write;
+    setReplicate_on_writeIsSet(true);
+    return this;
+  }
+
+  public void unsetReplicate_on_write() {
+    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID);
+  }
+
+  /** Returns true if field replicate_on_write is set (has been assigned a value) and false otherwise */
+  public boolean isSetReplicate_on_write() {
+    return EncodingUtils.testBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID);
+  }
+
+  public void setReplicate_on_writeIsSet(boolean value) {
+    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __REPLICATE_ON_WRITE_ISSET_ID, value);
+  }
+
+  /**
+   * @deprecated
+   */
   public double getMerge_shards_chance() {
     return this.merge_shards_chance;
   }
@@ -1785,14 +1835,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       }
       break;
 
-    case REPLICATE_ON_WRITE:
-      if (value == null) {
-        unsetReplicate_on_write();
-      } else {
-        setReplicate_on_write((Boolean)value);
-      }
-      break;
-
     case KEY_VALIDATION_CLASS:
       if (value == null) {
         unsetKey_validation_class();
@@ -1905,6 +1947,14 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       }
       break;
 
+    case CELLS_PER_ROW_TO_CACHE:
+      if (value == null) {
+        unsetCells_per_row_to_cache();
+      } else {
+        setCells_per_row_to_cache((String)value);
+      }
+      break;
+
     case ROW_CACHE_SIZE:
       if (value == null) {
         unsetRow_cache_size();
@@ -1961,6 +2011,14 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       }
       break;
 
+    case REPLICATE_ON_WRITE:
+      if (value == null) {
+        unsetReplicate_on_write();
+      } else {
+        setReplicate_on_write((Boolean)value);
+      }
+      break;
+
     case MERGE_SHARDS_CHANCE:
       if (value == null) {
         unsetMerge_shards_chance();
@@ -2029,9 +2087,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     case MAX_COMPACTION_THRESHOLD:
       return Integer.valueOf(getMax_compaction_threshold());
 
-    case REPLICATE_ON_WRITE:
-      return Boolean.valueOf(isReplicate_on_write());
-
     case KEY_VALIDATION_CLASS:
       return getKey_validation_class();
 
@@ -2074,6 +2129,9 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     case TRIGGERS:
       return getTriggers();
 
+    case CELLS_PER_ROW_TO_CACHE:
+      return getCells_per_row_to_cache();
+
     case ROW_CACHE_SIZE:
       return Double.valueOf(getRow_cache_size());
 
@@ -2095,6 +2153,9 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     case MEMTABLE_OPERATIONS_IN_MILLIONS:
       return Double.valueOf(getMemtable_operations_in_millions());
 
+    case REPLICATE_ON_WRITE:
+      return Boolean.valueOf(isReplicate_on_write());
+
     case MERGE_SHARDS_CHANCE:
       return Double.valueOf(getMerge_shards_chance());
 
@@ -2141,8 +2202,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       return isSetMin_compaction_threshold();
     case MAX_COMPACTION_THRESHOLD:
       return isSetMax_compaction_threshold();
-    case REPLICATE_ON_WRITE:
-      return isSetReplicate_on_write();
     case KEY_VALIDATION_CLASS:
       return isSetKey_validation_class();
     case KEY_ALIAS:
@@ -2171,6 +2230,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       return isSetSpeculative_retry();
     case TRIGGERS:
       return isSetTriggers();
+    case CELLS_PER_ROW_TO_CACHE:
+      return isSetCells_per_row_to_cache();
     case ROW_CACHE_SIZE:
       return isSetRow_cache_size();
     case KEY_CACHE_SIZE:
@@ -2185,6 +2246,8 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       return isSetMemtable_throughput_in_mb();
     case MEMTABLE_OPERATIONS_IN_MILLIONS:
       return isSetMemtable_operations_in_millions();
+    case REPLICATE_ON_WRITE:
+      return isSetReplicate_on_write();
     case MERGE_SHARDS_CHANCE:
       return isSetMerge_shards_chance();
     case ROW_CACHE_PROVIDER:
@@ -2325,15 +2388,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return false;
     }
 
-    boolean this_present_replicate_on_write = true && this.isSetReplicate_on_write();
-    boolean that_present_replicate_on_write = true && that.isSetReplicate_on_write();
-    if (this_present_replicate_on_write || that_present_replicate_on_write) {
-      if (!(this_present_replicate_on_write && that_present_replicate_on_write))
-        return false;
-      if (this.replicate_on_write != that.replicate_on_write)
-        return false;
-    }
-
     boolean this_present_key_validation_class = true && this.isSetKey_validation_class();
     boolean that_present_key_validation_class = true && that.isSetKey_validation_class();
     if (this_present_key_validation_class || that_present_key_validation_class) {
@@ -2460,6 +2514,15 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return false;
     }
 
+    boolean this_present_cells_per_row_to_cache = true && this.isSetCells_per_row_to_cache();
+    boolean that_present_cells_per_row_to_cache = true && that.isSetCells_per_row_to_cache();
+    if (this_present_cells_per_row_to_cache || that_present_cells_per_row_to_cache) {
+      if (!(this_present_cells_per_row_to_cache && that_present_cells_per_row_to_cache))
+        return false;
+      if (!this.cells_per_row_to_cache.equals(that.cells_per_row_to_cache))
+        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) {
@@ -2523,6 +2586,15 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return false;
     }
 
+    boolean this_present_replicate_on_write = true && this.isSetReplicate_on_write();
+    boolean that_present_replicate_on_write = true && that.isSetReplicate_on_write();
+    if (this_present_replicate_on_write || that_present_replicate_on_write) {
+      if (!(this_present_replicate_on_write && that_present_replicate_on_write))
+        return false;
+      if (this.replicate_on_write != that.replicate_on_write)
+        return false;
+    }
+
     boolean this_present_merge_shards_chance = true && this.isSetMerge_shards_chance();
     boolean that_present_merge_shards_chance = true && that.isSetMerge_shards_chance();
     if (this_present_merge_shards_chance || that_present_merge_shards_chance) {
@@ -2622,11 +2694,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     if (present_max_compaction_threshold)
       builder.append(max_compaction_threshold);
 
-    boolean present_replicate_on_write = true && (isSetReplicate_on_write());
-    builder.append(present_replicate_on_write);
-    if (present_replicate_on_write)
-      builder.append(replicate_on_write);
-
     boolean present_key_validation_class = true && (isSetKey_validation_class());
     builder.append(present_key_validation_class);
     if (present_key_validation_class)
@@ -2697,6 +2764,11 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     if (present_triggers)
       builder.append(triggers);
 
+    boolean present_cells_per_row_to_cache = true && (isSetCells_per_row_to_cache());
+    builder.append(present_cells_per_row_to_cache);
+    if (present_cells_per_row_to_cache)
+      builder.append(cells_per_row_to_cache);
+
     boolean present_row_cache_size = true && (isSetRow_cache_size());
     builder.append(present_row_cache_size);
     if (present_row_cache_size)
@@ -2732,6 +2804,11 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
     if (present_memtable_operations_in_millions)
       builder.append(memtable_operations_in_millions);
 
+    boolean present_replicate_on_write = true && (isSetReplicate_on_write());
+    builder.append(present_replicate_on_write);
+    if (present_replicate_on_write)
+      builder.append(replicate_on_write);
+
     boolean present_merge_shards_chance = true && (isSetMerge_shards_chance());
     builder.append(present_merge_shards_chance);
     if (present_merge_shards_chance)
@@ -2888,16 +2965,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return lastComparison;
       }
     }
-    lastComparison = Boolean.valueOf(isSetReplicate_on_write()).compareTo(other.isSetReplicate_on_write());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetReplicate_on_write()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.replicate_on_write, other.replicate_on_write);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
     lastComparison = Boolean.valueOf(isSetKey_validation_class()).compareTo(other.isSetKey_validation_class());
     if (lastComparison != 0) {
       return lastComparison;
@@ -3038,6 +3105,16 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return lastComparison;
       }
     }
+    lastComparison = Boolean.valueOf(isSetCells_per_row_to_cache()).compareTo(other.isSetCells_per_row_to_cache());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetCells_per_row_to_cache()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.cells_per_row_to_cache, other.cells_per_row_to_cache);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     lastComparison = Boolean.valueOf(isSetRow_cache_size()).compareTo(other.isSetRow_cache_size());
     if (lastComparison != 0) {
       return lastComparison;
@@ -3108,6 +3185,16 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         return lastComparison;
       }
     }
+    lastComparison = Boolean.valueOf(isSetReplicate_on_write()).compareTo(other.isSetReplicate_on_write());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetReplicate_on_write()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.replicate_on_write, other.replicate_on_write);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     lastComparison = Boolean.valueOf(isSetMerge_shards_chance()).compareTo(other.isSetMerge_shards_chance());
     if (lastComparison != 0) {
       return lastComparison;
@@ -3263,12 +3350,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       sb.append(this.max_compaction_threshold);
       first = false;
     }
-    if (isSetReplicate_on_write()) {
-      if (!first) sb.append(", ");
-      sb.append("replicate_on_write:");
-      sb.append(this.replicate_on_write);
-      first = false;
-    }
     if (isSetKey_validation_class()) {
       if (!first) sb.append(", ");
       sb.append("key_validation_class:");
@@ -3385,6 +3466,16 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       }
       first = false;
     }
+    if (isSetCells_per_row_to_cache()) {
+      if (!first) sb.append(", ");
+      sb.append("cells_per_row_to_cache:");
+      if (this.cells_per_row_to_cache == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.cells_per_row_to_cache);
+      }
+      first = false;
+    }
     if (isSetRow_cache_size()) {
       if (!first) sb.append(", ");
       sb.append("row_cache_size:");
@@ -3427,6 +3518,12 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       sb.append(this.memtable_operations_in_millions);
       first = false;
     }
+    if (isSetReplicate_on_write()) {
+      if (!first) sb.append(", ");
+      sb.append("replicate_on_write:");
+      sb.append(this.replicate_on_write);
+      first = false;
+    }
     if (isSetMerge_shards_chance()) {
       if (!first) sb.append(", ");
       sb.append("merge_shards_chance:");
@@ -3615,14 +3712,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
-          case 24: // REPLICATE_ON_WRITE
-            if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
-              struct.replicate_on_write = iprot.readBool();
-              struct.setReplicate_on_writeIsSet(true);
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
-            }
-            break;
           case 26: // KEY_VALIDATION_CLASS
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.key_validation_class = iprot.readString();
@@ -3770,6 +3859,14 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
+          case 44: // CELLS_PER_ROW_TO_CACHE
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.cells_per_row_to_cache = iprot.readString();
+              struct.setCells_per_row_to_cacheIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
           case 9: // ROW_CACHE_SIZE
             if (schemeField.type == org.apache.thrift.protocol.TType.DOUBLE) {
               struct.row_cache_size = iprot.readDouble();
@@ -3826,6 +3923,14 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
+          case 24: // REPLICATE_ON_WRITE
+            if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
+              struct.replicate_on_write = iprot.readBool();
+              struct.setReplicate_on_writeIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
           case 25: // MERGE_SHARDS_CHANCE
             if (schemeField.type == org.apache.thrift.protocol.TType.DOUBLE) {
               struct.merge_shards_chance = iprot.readDouble();
@@ -4115,6 +4220,13 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
           oprot.writeFieldEnd();
         }
       }
+      if (struct.cells_per_row_to_cache != null) {
+        if (struct.isSetCells_per_row_to_cache()) {
+          oprot.writeFieldBegin(CELLS_PER_ROW_TO_CACHE_FIELD_DESC);
+          oprot.writeString(struct.cells_per_row_to_cache);
+          oprot.writeFieldEnd();
+        }
+      }
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
@@ -4168,49 +4280,49 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       if (struct.isSetMax_compaction_threshold()) {
         optionals.set(10);
       }
-      if (struct.isSetReplicate_on_write()) {
+      if (struct.isSetKey_validation_class()) {
         optionals.set(11);
       }
-      if (struct.isSetKey_validation_class()) {
+      if (struct.isSetKey_alias()) {
         optionals.set(12);
       }
-      if (struct.isSetKey_alias()) {
+      if (struct.isSetCompaction_strategy()) {
         optionals.set(13);
       }
-      if (struct.isSetCompaction_strategy()) {
+      if (struct.isSetCompaction_strategy_options()) {
         optionals.set(14);
       }
-      if (struct.isSetCompaction_strategy_options()) {
+      if (struct.isSetCompression_options()) {
         optionals.set(15);
       }
-      if (struct.isSetCompression_options()) {
+      if (struct.isSetBloom_filter_fp_chance()) {
         optionals.set(16);
       }
-      if (struct.isSetBloom_filter_fp_chance()) {
+      if (struct.isSetCaching()) {
         optionals.set(17);
       }
-      if (struct.isSetCaching()) {
+      if (struct.isSetDclocal_read_repair_chance()) {
         optionals.set(18);
       }
-      if (struct.isSetDclocal_read_repair_chance()) {
+      if (struct.isSetPopulate_io_cache_on_flush()) {
         optionals.set(19);
       }
-      if (struct.isSetPopulate_io_cache_on_flush()) {
+      if (struct.isSetMemtable_flush_period_in_ms()) {
         optionals.set(20);
       }
-      if (struct.isSetMemtable_flush_period_in_ms()) {
+      if (struct.isSetDefault_time_to_live()) {
         optionals.set(21);
       }
-      if (struct.isSetDefault_time_to_live()) {
+      if (struct.isSetIndex_interval()) {
         optionals.set(22);
       }
-      if (struct.isSetIndex_interval()) {
+      if (struct.isSetSpeculative_retry()) {
         optionals.set(23);
       }
-      if (struct.isSetSpeculative_retry()) {
+      if (struct.isSetTriggers()) {
         optionals.set(24);
       }
-      if (struct.isSetTriggers()) {
+      if (struct.isSetCells_per_row_to_cache()) {
         optionals.set(25);
       }
       if (struct.isSetRow_cache_size()) {
@@ -4234,16 +4346,19 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       if (struct.isSetMemtable_operations_in_millions()) {
         optionals.set(32);
       }
-      if (struct.isSetMerge_shards_chance()) {
+      if (struct.isSetReplicate_on_write()) {
         optionals.set(33);
       }
-      if (struct.isSetRow_cache_provider()) {
+      if (struct.isSetMerge_shards_chance()) {
         optionals.set(34);
       }
-      if (struct.isSetRow_cache_keys_to_save()) {
+      if (struct.isSetRow_cache_provider()) {
         optionals.set(35);
       }
-      oprot.writeBitSet(optionals, 36);
+      if (struct.isSetRow_cache_keys_to_save()) {
+        optionals.set(36);
+      }
+      oprot.writeBitSet(optionals, 37);
       if (struct.isSetColumn_type()) {
         oprot.writeString(struct.column_type);
       }
@@ -4283,9 +4398,6 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       if (struct.isSetMax_compaction_threshold()) {
         oprot.writeI32(struct.max_compaction_threshold);
       }
-      if (struct.isSetReplicate_on_write()) {
-        oprot.writeBool(struct.replicate_on_write);
-      }
       if (struct.isSetKey_validation_class()) {
         oprot.writeString(struct.key_validation_class);
       }
@@ -4348,6 +4460,9 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
           }
         }
       }
+      if (struct.isSetCells_per_row_to_cache()) {
+        oprot.writeString(struct.cells_per_row_to_cache);
+      }
       if (struct.isSetRow_cache_size()) {
         oprot.writeDouble(struct.row_cache_size);
       }
@@ -4369,6 +4484,9 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       if (struct.isSetMemtable_operations_in_millions()) {
         oprot.writeDouble(struct.memtable_operations_in_millions);
       }
+      if (struct.isSetReplicate_on_write()) {
+        oprot.writeBool(struct.replicate_on_write);
+      }
       if (struct.isSetMerge_shards_chance()) {
         oprot.writeDouble(struct.merge_shards_chance);
       }
@@ -4387,7 +4505,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
       struct.setKeyspaceIsSet(true);
       struct.name = iprot.readString();
       struct.setNameIsSet(true);
-      BitSet incoming = iprot.readBitSet(36);
+      BitSet incoming = iprot.readBitSet(37);
       if (incoming.get(0)) {
         struct.column_type = iprot.readString();
         struct.setColumn_typeIsSet(true);
@@ -4443,22 +4561,18 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         struct.setMax_compaction_thresholdIsSet(true);
       }
       if (incoming.get(11)) {
-        struct.replicate_on_write = iprot.readBool();
-        struct.setReplicate_on_writeIsSet(true);
-      }
-      if (incoming.get(12)) {
         struct.key_validation_class = iprot.readString();
         struct.setKey_validation_classIsSet(true);
       }
-      if (incoming.get(13)) {
+      if (incoming.get(12)) {
         struct.key_alias = iprot.readBinary();
         struct.setKey_aliasIsSet(true);
       }
-      if (incoming.get(14)) {
+      if (incoming.get(13)) {
         struct.compaction_strategy = iprot.readString();
         struct.setCompaction_strategyIsSet(true);
       }
-      if (incoming.get(15)) {
+      if (incoming.get(14)) {
         {
           org.apache.thrift.protocol.TMap _map135 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
           struct.compaction_strategy_options = new HashMap<String,String>(2*_map135.size);
@@ -4473,7 +4587,7 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         }
         struct.setCompaction_strategy_optionsIsSet(true);
       }
-      if (incoming.get(16)) {
+      if (incoming.get(15)) {
         {
           org.apache.thrift.protocol.TMap _map139 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
           struct.compression_options = new HashMap<String,String>(2*_map139.size);
@@ -4488,39 +4602,39 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         }
         struct.setCompression_optionsIsSet(true);
       }
-      if (incoming.get(17)) {
+      if (incoming.get(16)) {
         struct.bloom_filter_fp_chance = iprot.readDouble();
         struct.setBloom_filter_fp_chanceIsSet(true);
       }
-      if (incoming.get(18)) {
+      if (incoming.get(17)) {
         struct.caching = iprot.readString();
         struct.setCachingIsSet(true);
       }
-      if (incoming.get(19)) {
+      if (incoming.get(18)) {
         struct.dclocal_read_repair_chance = iprot.readDouble();
         struct.setDclocal_read_repair_chanceIsSet(true);
       }
-      if (incoming.get(20)) {
+      if (incoming.get(19)) {
         struct.populate_io_cache_on_flush = iprot.readBool();
         struct.setPopulate_io_cache_on_flushIsSet(true);
       }
-      if (incoming.get(21)) {
+      if (incoming.get(20)) {
         struct.memtable_flush_period_in_ms = iprot.readI32();
         struct.setMemtable_flush_period_in_msIsSet(true);
       }
-      if (incoming.get(22)) {
+      if (incoming.get(21)) {
         struct.default_time_to_live = iprot.readI32();
         struct.setDefault_time_to_liveIsSet(true);
       }
-      if (incoming.get(23)) {
+      if (incoming.get(22)) {
         struct.index_interval = iprot.readI32();
         struct.setIndex_intervalIsSet(true);
       }
-      if (incoming.get(24)) {
+      if (incoming.get(23)) {
         struct.speculative_retry = iprot.readString();
         struct.setSpeculative_retryIsSet(true);
       }
-      if (incoming.get(25)) {
+      if (incoming.get(24)) {
         {
           org.apache.thrift.protocol.TList _list143 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
           struct.triggers = new ArrayList<TriggerDef>(_list143.size);
@@ -4534,6 +4648,10 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         }
         struct.setTriggersIsSet(true);
       }
+      if (incoming.get(25)) {
+        struct.cells_per_row_to_cache = iprot.readString();
+        struct.setCells_per_row_to_cacheIsSet(true);
+      }
       if (incoming.get(26)) {
         struct.row_cache_size = iprot.readDouble();
         struct.setRow_cache_sizeIsSet(true);
@@ -4563,14 +4681,18 @@ public class CfDef implements org.apache.thrift.TBase<CfDef, CfDef._Fields>, jav
         struct.setMemtable_operations_in_millionsIsSet(true);
       }
       if (incoming.get(33)) {
+        struct.replicate_on_write = iprot.readBool();
+        struct.setReplicate_on_writeIsSet(true);
+      }
+      if (incoming.get(34)) {
         struct.merge_shards_chance = iprot.readDouble();
         struct.setMerge_shards_chanceIsSet(true);
       }
-      if (incoming.get(34)) {
+      if (incoming.get(35)) {
         struct.row_cache_provider = iprot.readString();
         struct.setRow_cache_providerIsSet(true);
       }
-      if (incoming.get(35)) {
+      if (incoming.get(36)) {
         struct.row_cache_keys_to_save = iprot.readI32();
         struct.setRow_cache_keys_to_saveIsSet(true);
       }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java
----------------------------------------------------------------------
diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java
index 81b0ffb..a795fc4 100644
--- a/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java
+++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java
@@ -56,6 +56,6 @@ import org.slf4j.LoggerFactory;
 
 public class cassandraConstants {
 
-  public static final String VERSION = "19.39.0";
+  public static final String VERSION = "19.38.1";
 
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index c4fa97d..1e1b4d5 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -63,6 +63,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
     columnfamily_layout_options = (
         ('bloom_filter_fp_chance', None),
         ('caching', None),
+        ('rows_per_partition_to_cache', None),
         ('comment', None),
         ('dclocal_read_repair_chance', 'local_read_repair_chance'),
         ('gc_grace_seconds', None),

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/cli/CliClient.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java
index e842636..b30bee1 100644
--- a/src/java/org/apache/cassandra/cli/CliClient.java
+++ b/src/java/org/apache/cassandra/cli/CliClient.java
@@ -140,6 +140,7 @@ public class CliClient
         INDEX_INTERVAL,
         MEMTABLE_FLUSH_PERIOD_IN_MS,
         CACHING,
+        CELLS_PER_ROW_TO_CACHE,
         DEFAULT_TIME_TO_LIVE,
         SPECULATIVE_RETRY,
         POPULATE_IO_CACHE_ON_FLUSH,
@@ -1348,6 +1349,9 @@ public class CliClient
             case CACHING:
                 cfDef.setCaching(CliUtils.unescapeSQLString(mValue));
                 break;
+            case CELLS_PER_ROW_TO_CACHE:
+                cfDef.setCells_per_row_to_cache(mValue);
+                break;
             case DEFAULT_TIME_TO_LIVE:
                 cfDef.setDefault_time_to_live(Integer.parseInt(mValue));
                 break;
@@ -1819,6 +1823,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, "cells_per_row_to_cache", cfDef.cells_per_row_to_cache);
         writeAttr(output, false, "default_time_to_live", cfDef.default_time_to_live);
         writeAttr(output, false, "speculative_retry", cfDef.speculative_retry);
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index eeb5c68..f600b83 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -84,6 +84,7 @@ public final class CFMetaData
     public final static SpeculativeRetry DEFAULT_SPECULATIVE_RETRY = new SpeculativeRetry(SpeculativeRetry.RetryType.PERCENTILE, 0.99);
     public final static int DEFAULT_INDEX_INTERVAL = 128;
     public final static boolean DEFAULT_POPULATE_IO_CACHE_ON_FLUSH = false;
+    public final static RowsPerPartitionToCache DEFAULT_ROWS_PER_PARTITION_TO_CACHE = new RowsPerPartitionToCache(100, RowsPerPartitionToCache.Type.HEAD);
 
     // Note that this is the default only for user created tables
     public final static String DEFAULT_COMPRESSOR = LZ4Compressor.class.getCanonicalName();
@@ -145,6 +146,7 @@ public final class CFMetaData
                                                                     + "populate_io_cache_on_flush boolean,"
                                                                     + "index_interval int,"
                                                                     + "dropped_columns map<text, bigint>,"
+                                                                    + "rows_per_partition_to_cache text,"
                                                                     + "PRIMARY KEY (keyspace_name, columnfamily_name)"
                                                                     + ") WITH COMMENT='ColumnFamily definitions' AND gc_grace_seconds=8640");
 
@@ -311,6 +313,49 @@ public final class CFMetaData
         }
     }
 
+    public static class RowsPerPartitionToCache
+    {
+        public enum Type
+        {
+            ALL, HEAD
+        }
+        public final int rowsToCache;
+        public final Type type;
+
+        private RowsPerPartitionToCache(int rowsToCache, Type type)
+        {
+            this.rowsToCache = rowsToCache;
+            this.type = type;
+        }
+
+        public static RowsPerPartitionToCache fromString(String rpptc)
+        {
+            if (rpptc.equalsIgnoreCase("all"))
+                return new RowsPerPartitionToCache(Integer.MAX_VALUE, Type.ALL);
+            return new RowsPerPartitionToCache(Integer.parseInt(rpptc), Type.HEAD);
+        }
+
+        public boolean cacheFullPartitions()
+        {
+            return type == Type.ALL;
+        }
+
+        public String toString()
+        {
+            if (rowsToCache == Integer.MAX_VALUE)
+                return "ALL";
+            return String.valueOf(rowsToCache);
+        }
+
+        public boolean equals(Object rhs)
+        {
+            if (!(rhs instanceof RowsPerPartitionToCache))
+                return false;
+            RowsPerPartitionToCache rppc = (RowsPerPartitionToCache)rhs;
+            return rowsToCache == rppc.rowsToCache && type == rppc.type;
+        }
+    }
+
     public static class SpeculativeRetry
     {
         public enum RetryType
@@ -407,7 +452,7 @@ public final class CFMetaData
     private volatile Map<ColumnIdentifier, Long> droppedColumns = new HashMap<>();
     private volatile Map<String, TriggerDefinition> triggers = new HashMap<>();
     private volatile boolean isPurged = false;
-
+    private volatile RowsPerPartitionToCache rowsPerPartitionToCache = DEFAULT_ROWS_PER_PARTITION_TO_CACHE;
     /*
      * All CQL3 columns definition are stored in the columnMetadata map.
      * On top of that, we keep separated collection of each kind of definition, to
@@ -450,6 +495,7 @@ public final class CFMetaData
     public CFMetaData populateIoCacheOnFlush(boolean prop) {populateIoCacheOnFlush = prop; return this;}
     public CFMetaData droppedColumns(Map<ColumnIdentifier, Long> cols) {droppedColumns = cols; return this;}
     public CFMetaData triggers(Map<String, TriggerDefinition> prop) {triggers = prop; return this;}
+    public CFMetaData rowsPerPartitionToCache(RowsPerPartitionToCache prop) { rowsPerPartitionToCache = prop; return this; }
 
     /**
      * Create new ColumnFamily metadata with generated random ID.
@@ -636,6 +682,7 @@ public final class CFMetaData
                       .populateIoCacheOnFlush(oldCFMD.populateIoCacheOnFlush)
                       .droppedColumns(new HashMap<>(oldCFMD.droppedColumns))
                       .triggers(new HashMap<>(oldCFMD.triggers))
+                      .rowsPerPartitionToCache(oldCFMD.rowsPerPartitionToCache)
                       .rebuild();
     }
 
@@ -813,6 +860,11 @@ public final class CFMetaData
         return caching;
     }
 
+    public RowsPerPartitionToCache getRowsPerPartitionToCache()
+    {
+        return rowsPerPartitionToCache;
+    }
+
     public int getIndexInterval()
     {
         return indexInterval;
@@ -876,6 +928,7 @@ public final class CFMetaData
         if (populateIoCacheOnFlush != rhs.populateIoCacheOnFlush) return false;
         if (Objects.equal(droppedColumns, rhs.droppedColumns)) return false;
         if (Objects.equal(triggers, rhs.triggers)) return false;
+        if (!Objects.equal(rowsPerPartitionToCache, rhs.rowsPerPartitionToCache)) return false;
         return true;
     }
 
@@ -908,6 +961,7 @@ public final class CFMetaData
             .append(populateIoCacheOnFlush)
             .append(droppedColumns)
             .append(triggers)
+            .append(rowsPerPartitionToCache)
             .toHashCode();
     }
 
@@ -964,6 +1018,8 @@ public final class CFMetaData
             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);
+        if (!cf_def.isSetCells_per_row_to_cache())
+            cf_def.setCells_per_row_to_cache(CFMetaData.DEFAULT_ROWS_PER_PARTITION_TO_CACHE.toString());
     }
 
     public static CFMetaData fromThrift(org.apache.cassandra.thrift.CfDef cf_def) throws InvalidRequestException, ConfigurationException
@@ -1022,6 +1078,8 @@ public final class CFMetaData
                 newCFMD.populateIoCacheOnFlush(cf_def.populate_io_cache_on_flush);
             if (cf_def.isSetTriggers())
                 newCFMD.triggers(TriggerDefinition.fromThrift(cf_def.triggers));
+            if (cf_def.isSetCells_per_row_to_cache())
+                newCFMD.rowsPerPartitionToCache(RowsPerPartitionToCache.fromString(cf_def.cells_per_row_to_cache));
 
             CompressionParameters cp = CompressionParameters.create(cf_def.compression_options);
 
@@ -1117,6 +1175,7 @@ public final class CFMetaData
         bloomFilterFpChance = cfm.bloomFilterFpChance;
         memtableFlushPeriod = cfm.memtableFlushPeriod;
         caching = cfm.caching;
+        rowsPerPartitionToCache = cfm.rowsPerPartitionToCache;
         defaultTimeToLive = cfm.defaultTimeToLive;
         speculativeRetry = cfm.speculativeRetry;
         populateIoCacheOnFlush = cfm.populateIoCacheOnFlush;
@@ -1265,6 +1324,7 @@ public final class CFMetaData
         def.setIndex_interval(indexInterval);
         def.setMemtable_flush_period_in_ms(memtableFlushPeriod);
         def.setCaching(caching.toString());
+        def.setCells_per_row_to_cache(rowsPerPartitionToCache.toString());
         def.setDefault_time_to_live(defaultTimeToLive);
         def.setSpeculative_retry(speculativeRetry.toString());
         def.setTriggers(TriggerDefinition.toThrift(triggers));
@@ -1619,6 +1679,7 @@ public final class CFMetaData
 
         adder.add("memtable_flush_period_in_ms", memtableFlushPeriod);
         adder.add("caching", caching.toString());
+        adder.add("rows_per_partition_to_cache", rowsPerPartitionToCache.toString());
         adder.add("default_time_to_live", defaultTimeToLive);
         adder.add("compaction_strategy_class", compactionStrategyClass.getName());
         adder.add("compression_parameters", json(compressionParameters.asThriftOptions()));
@@ -1684,6 +1745,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("rows_per_partition_to_cache"))
+                 cfm.rowsPerPartitionToCache(RowsPerPartitionToCache.fromString(result.getString("rows_per_partition_to_cache")));
             if (result.has("default_time_to_live"))
                 cfm.defaultTimeToLive(result.getInt("default_time_to_live"));
             if (result.has("speculative_retry"))
@@ -2163,6 +2226,7 @@ public final class CFMetaData
             .append("bloomFilterFpChance", bloomFilterFpChance)
             .append("memtable_flush_period_in_ms", memtableFlushPeriod)
             .append("caching", caching)
+            .append("rowsPerPartitionToCache", rowsPerPartitionToCache)
             .append("defaultTimeToLive", defaultTimeToLive)
             .append("speculative_retry", speculativeRetry)
             .append("indexInterval", indexInterval)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/cql/AlterTableStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/AlterTableStatement.java b/src/java/org/apache/cassandra/cql/AlterTableStatement.java
index b5ac464..2fda212 100644
--- a/src/java/org/apache/cassandra/cql/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql/AlterTableStatement.java
@@ -180,6 +180,7 @@ public class AlterTableStatement
         cfm.minCompactionThreshold(minCompactionThreshold);
         cfm.maxCompactionThreshold(maxCompactionThreshold);
         cfm.caching(CFMetaData.Caching.fromString(cfProps.getPropertyString(CFPropDefs.KW_CACHING, cfm.getCaching().toString())));
+        cfm.rowsPerPartitionToCache(CFMetaData.RowsPerPartitionToCache.fromString(cfProps.getPropertyString(CFPropDefs.KW_ROWS_PER_PARTITION_TO_CACHE, cfm.getRowsPerPartitionToCache().toString())));
         cfm.defaultTimeToLive(cfProps.getPropertyInt(CFPropDefs.KW_DEFAULT_TIME_TO_LIVE, cfm.getDefaultTimeToLive()));
         cfm.speculativeRetry(CFMetaData.SpeculativeRetry.fromString(cfProps.getPropertyString(CFPropDefs.KW_SPECULATIVE_RETRY, cfm.getSpeculativeRetry().toString())));
         cfm.populateIoCacheOnFlush(cfProps.getPropertyBoolean(CFPropDefs.KW_POPULATE_IO_CACHE_ON_FLUSH, cfm.populateIoCacheOnFlush()));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/cql/CFPropDefs.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/CFPropDefs.java b/src/java/org/apache/cassandra/cql/CFPropDefs.java
index 2131d06..42e840e 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_MAXCOMPACTIONTHRESHOLD = "max_compaction_threshold";
     public static final String KW_COMPACTION_STRATEGY_CLASS = "compaction_strategy_class";
     public static final String KW_CACHING = "caching";
+    public static final String KW_ROWS_PER_PARTITION_TO_CACHE = "rows_per_partition_to_cache";
     public static final String KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live";
     public static final String KW_SPECULATIVE_RETRY = "speculative_retry";
     public static final String KW_POPULATE_IO_CACHE_ON_FLUSH = "populate_io_cache_on_flush";
@@ -91,6 +92,7 @@ public class CFPropDefs {
         keywords.add(KW_MAXCOMPACTIONTHRESHOLD);
         keywords.add(KW_COMPACTION_STRATEGY_CLASS);
         keywords.add(KW_CACHING);
+        keywords.add(KW_ROWS_PER_PARTITION_TO_CACHE);
         keywords.add(KW_DEFAULT_TIME_TO_LIVE);
         keywords.add(KW_SPECULATIVE_RETRY);
         keywords.add(KW_POPULATE_IO_CACHE_ON_FLUSH);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java b/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
index 7b5cbaf..e568dd7 100644
--- a/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
+++ b/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
@@ -197,6 +197,7 @@ public class CreateColumnFamilyStatement
                    .compactionStrategyOptions(cfProps.compactionStrategyOptions)
                    .compressionParameters(CompressionParameters.create(cfProps.compressionParameters))
                    .caching(CFMetaData.Caching.fromString(getPropertyString(CFPropDefs.KW_CACHING, CFMetaData.DEFAULT_CACHING_STRATEGY.toString())))
+                   .rowsPerPartitionToCache(CFMetaData.RowsPerPartitionToCache.fromString(cfProps.getPropertyString(CFPropDefs.KW_ROWS_PER_PARTITION_TO_CACHE, CFMetaData.DEFAULT_ROWS_PER_PARTITION_TO_CACHE.toString())))
                    .speculativeRetry(CFMetaData.SpeculativeRetry.fromString(getPropertyString(CFPropDefs.KW_SPECULATIVE_RETRY, CFMetaData.DEFAULT_SPECULATIVE_RETRY.toString())))
                    .bloomFilterFpChance(getPropertyDouble(CFPropDefs.KW_BF_FP_CHANCE, null))
                    .memtableFlushPeriod(getPropertyInt(CFPropDefs.KW_MEMTABLE_FLUSH_PERIOD, 0))

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/cql3/statements/CFPropDefs.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CFPropDefs.java b/src/java/org/apache/cassandra/cql3/statements/CFPropDefs.java
index 3929f3c..50fabf3 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CFPropDefs.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CFPropDefs.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.db.compaction.AbstractCompactionStrategy;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.SyntaxException;
 import org.apache.cassandra.io.compress.CompressionParameters;
+import org.apache.cassandra.service.CacheService;
 
 public class CFPropDefs extends PropertyDefinitions
 {
@@ -35,6 +36,7 @@ public class CFPropDefs extends PropertyDefinitions
     public static final String KW_MINCOMPACTIONTHRESHOLD = "min_threshold";
     public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_threshold";
     public static final String KW_CACHING = "caching";
+    public static final String KW_ROWS_PER_PARTITION_TO_CACHE = "rows_per_partition_to_cache";
     public static final String KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live";
     public static final String KW_INDEX_INTERVAL = "index_interval";
     public static final String KW_SPECULATIVE_RETRY = "speculative_retry";
@@ -57,6 +59,7 @@ public class CFPropDefs extends PropertyDefinitions
         keywords.add(KW_DCLOCALREADREPAIRCHANCE);
         keywords.add(KW_GCGRACESECONDS);
         keywords.add(KW_CACHING);
+        keywords.add(KW_ROWS_PER_PARTITION_TO_CACHE);
         keywords.add(KW_DEFAULT_TIME_TO_LIVE);
         keywords.add(KW_INDEX_INTERVAL);
         keywords.add(KW_SPECULATIVE_RETRY);
@@ -153,6 +156,11 @@ public class CFPropDefs extends PropertyDefinitions
         cfm.minCompactionThreshold(minCompactionThreshold);
         cfm.maxCompactionThreshold(maxCompactionThreshold);
         cfm.caching(CFMetaData.Caching.fromString(getString(KW_CACHING, cfm.getCaching().toString())));
+        CFMetaData.RowsPerPartitionToCache newRppc = CFMetaData.RowsPerPartitionToCache.fromString(getString(KW_ROWS_PER_PARTITION_TO_CACHE, cfm.getRowsPerPartitionToCache().toString()));
+        // we need to invalidate row cache if the amount of rows cached changes, otherwise we might serve out bad data.
+        if (!cfm.getRowsPerPartitionToCache().equals(newRppc))
+            CacheService.instance.invalidateRowCacheForCf(cfm.cfId);
+        cfm.rowsPerPartitionToCache(newRppc);
         cfm.defaultTimeToLive(getInt(KW_DEFAULT_TIME_TO_LIVE, cfm.getDefaultTimeToLive()));
         cfm.speculativeRetry(CFMetaData.SpeculativeRetry.fromString(getString(KW_SPECULATIVE_RETRY, cfm.getSpeculativeRetry().toString())));
         cfm.memtableFlushPeriod(getInt(KW_MEMTABLE_FLUSH_PERIOD, cfm.getMemtableFlushPeriod()));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/db/ColumnFamily.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamily.java b/src/java/org/apache/cassandra/db/ColumnFamily.java
index 00f0e35..610e869 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamily.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamily.java
@@ -42,6 +42,7 @@ import org.apache.cassandra.config.Schema;
 import org.apache.cassandra.db.composites.CellName;
 import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.composites.CellNames;
+import org.apache.cassandra.db.filter.ColumnCounter;
 import org.apache.cassandra.db.filter.ColumnSlice;
 import org.apache.cassandra.io.sstable.ColumnNameHelper;
 import org.apache.cassandra.io.sstable.ColumnStats;
@@ -87,6 +88,14 @@ public abstract class ColumnFamily implements Iterable<Cell>, IRowCacheEntry
         return metadata.cfType;
     }
 
+    public int liveCQL3RowCount(long now)
+    {
+        ColumnCounter counter = getComparator().isDense()
+                              ? new ColumnCounter(now)
+                              : new ColumnCounter.GroupByPrefix(now, getComparator(), metadata.clusteringColumns().size());
+        return counter.countAll(this).live();
+    }
+
     /**
      * Clones the column map.
      */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 14b3571..18f0612 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -58,6 +58,7 @@ import org.apache.cassandra.db.filter.ExtendedFilter;
 import org.apache.cassandra.db.filter.IDiskAtomFilter;
 import org.apache.cassandra.db.filter.QueryFilter;
 import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composites;
 import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.index.SecondaryIndex;
@@ -372,7 +373,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
         data.unreferenceSSTables();
         indexManager.invalidate();
 
-        invalidateCaches();
+        CacheService.instance.invalidateRowCacheForCf(metadata.cfId);
     }
 
     /**
@@ -1446,12 +1447,16 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
     }
 
     /**
-     * fetch the row given by filter.key if it is in the cache; if not, read it from disk and cache it
+     * Fetch the row and columns given by filter.key if it is in the cache; if not, read it from disk and cache it
+     *
+     * If row is cached, and the filter given is within its bounds, we return from cache, otherwise from disk
+     *
+     * If row is not cached, we figure out what filter is "biggest", read that from disk, then
+     * filter the result and either cache that or return it.
+     *
      * @param cfId the column family to read the row from
-     * @param filter the columns being queried.  Note that we still cache entire rows, but if a row is uncached
-     *               and we race to cache it, only the winner will read the entire row
-     * @return the entire row for filter.key, if present in the cache (or we can cache it), or just the column
-     *         specified by filter otherwise
+     * @param filter the columns being queried.
+     * @return the requested data for the filter provided
      */
     private ColumnFamily getThroughCache(UUID cfId, QueryFilter filter)
     {
@@ -1462,6 +1467,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
 
         // attempt a sentinel-read-cache sequence.  if a write invalidates our sentinel, we'll return our
         // (now potentially obsolete) data, but won't cache it. see CASSANDRA-3862
+        // TODO: don't evict entire rows on writes (#2864)
         IRowCacheEntry cached = CacheService.instance.rowCache.get(key);
         if (cached != null)
         {
@@ -1469,32 +1475,135 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
             {
                 // Some other read is trying to cache the value, just do a normal non-caching read
                 Tracing.trace("Row cache miss (race)");
+                metric.rowCacheMiss.inc();
                 return getTopLevelColumns(filter, Integer.MIN_VALUE);
             }
-            Tracing.trace("Row cache hit");
-            return (ColumnFamily) cached;
+
+            ColumnFamily cachedCf = (ColumnFamily)cached;
+            if (isFilterFullyCoveredBy(filter.filter, cachedCf, filter.timestamp))
+            {
+                metric.rowCacheHit.inc();
+                Tracing.trace("Row cache hit");
+                return cachedCf;
+            }
+
+            metric.rowCacheHitOutOfRange.inc();
+            Tracing.trace("Ignoring row cache as cached value could not satisfy query");
+            return getTopLevelColumns(filter, Integer.MIN_VALUE);
         }
 
+        metric.rowCacheMiss.inc();
         Tracing.trace("Row cache miss");
         RowCacheSentinel sentinel = new RowCacheSentinel();
         boolean sentinelSuccess = CacheService.instance.rowCache.putIfAbsent(key, sentinel);
-
+        ColumnFamily data = null;
+        ColumnFamily toCache = null;
         try
         {
-            ColumnFamily data = getTopLevelColumns(QueryFilter.getIdentityFilter(filter.key, name, filter.timestamp),
-                                                   Integer.MIN_VALUE);
-            if (sentinelSuccess && data != null)
-                CacheService.instance.rowCache.replace(key, sentinel, data);
+            // If we are explicitely asked to fill the cache with full partitions, we go ahead and query the whole thing
+            if (metadata.getRowsPerPartitionToCache().cacheFullPartitions())
+            {
+                data = getTopLevelColumns(QueryFilter.getIdentityFilter(filter.key, name, filter.timestamp), Integer.MIN_VALUE);
+                toCache = data;
+                Tracing.trace("Populating row cache with the whole partition");
+                if (sentinelSuccess && toCache != null)
+                    CacheService.instance.rowCache.replace(key, sentinel, toCache);
+                return filterColumnFamily(data, filter);
+            }
+
+            // Otherwise, if we want to cache the result of the query we're about to do, we must make sure this query
+            // covers what needs to be cached. And if the user filter does not satisfy that, we sometimes extend said
+            // filter so we can populate the cache but only if:
+            //   1) we can guarantee it is a strict extension, i.e. that we will still fetch the data asked by the user.
+            //   2) the extension does not make us query more than getRowsPerPartitionToCache() (as a mean to limit the
+            //      amount of extra work we'll do on a user query for the purpose of populating the cache).
+            //
+            // In practice, we can only guarantee those 2 points if the filter is one that queries the head of the
+            // partition (and if that filter actually counts CQL3 rows since that's what we cache and it would be
+            // bogus to compare the filter count to the 'rows to cache' otherwise).
+            if (filter.filter.isHeadFilter() && filter.filter.countCQL3Rows(metadata.comparator))
+            {
+                SliceQueryFilter sliceFilter = (SliceQueryFilter)filter.filter;
+                int rowsToCache = metadata.getRowsPerPartitionToCache().rowsToCache;
+
+                SliceQueryFilter cacheSlice = readFilterForCache();
+                QueryFilter cacheFilter = new QueryFilter(filter.key, name, cacheSlice, filter.timestamp);
+
+                // If the filter count is less than the number of rows cached, we simply extend it to make sure we do cover the
+                // number of rows to cache, and if that count is greater than the number of rows to cache, we simply filter what
+                // needs to be cached afterwards.
+                if (sliceFilter.count < rowsToCache)
+                {
+                    toCache = getTopLevelColumns(cacheFilter, Integer.MIN_VALUE);
+                    if (toCache != null)
+                    {
+                        Tracing.trace("Populating row cache ({} rows cached)", cacheSlice.lastCounted());
+                        data = filterColumnFamily(toCache, filter);
+                    }
+                }
+                else
+                {
+                    data = getTopLevelColumns(filter, Integer.MIN_VALUE);
+                    if (data != null)
+                    {
+                        // The filter limit was greater than the number of rows to cache. But, if the filter had a non-empty
+                        // finish bound, we may have gotten less than what needs to be cached, in which case we shouldn't cache it
+                        // (otherwise a cache hit would assume the whole partition is cached which is not the case).
+                        if (sliceFilter.finish().isEmpty() || sliceFilter.lastCounted() >= rowsToCache)
+                        {
+                            toCache = filterColumnFamily(data, cacheFilter);
+                            Tracing.trace("Caching {} rows (out of {} requested)", cacheSlice.lastCounted(), sliceFilter.count);
+                        }
+                        else
+                        {
+                            Tracing.trace("Not populating row cache, not enough rows fetched ({} fetched but {} required for the cache)", sliceFilter.lastCounted(), rowsToCache);
+                        }
+                    }
+                }
 
-            return data;
+                if (sentinelSuccess && toCache != null)
+                    CacheService.instance.rowCache.replace(key, sentinel, toCache);
+                return data;
+            }
+            else
+            {
+                Tracing.trace("Fetching data but not populating cache as query does not query from the start of the partition");
+                return getTopLevelColumns(filter, Integer.MIN_VALUE);
+            }
         }
         finally
         {
-            if (sentinelSuccess && data == null)
+            if (sentinelSuccess && toCache == null)
                 invalidateCachedRow(key);
         }
     }
 
+    public SliceQueryFilter readFilterForCache()
+    {
+        // We create a new filter everytime before for now SliceQueryFilter is unfortunatly mutable.
+        return new SliceQueryFilter(ColumnSlice.ALL_COLUMNS_ARRAY, false, metadata.getRowsPerPartitionToCache().rowsToCache, metadata.clusteringColumns().size());
+    }
+
+    public boolean isFilterFullyCoveredBy(IDiskAtomFilter filter, ColumnFamily cachedCf, long now)
+    {
+        // We can use the cached value only if we know that no data it doesn't contain could be covered
+        // by the query filter, that is if:
+        //   1) either the whole partition is cached
+        //   2) or we can ensure than any data the filter selects are in the cached partition
+
+        // When counting rows to decide if the whole row is cached, we should be careful with expiring
+        // columns: if we use a timestamp newer than the one that was used when populating the cache, we might
+        // end up deciding the whole partition is cached when it's really not (just some rows expired since the
+        // cf was cached). This is the reason for Integer.MIN_VALUE below.
+        boolean wholePartitionCached = cachedCf.liveCQL3RowCount(Integer.MIN_VALUE) < metadata.getRowsPerPartitionToCache().rowsToCache;
+
+        // Contrarily to the "wholePartitionCached" check above, we do want isFullyCoveredBy to take the
+        // timestamp of the query into account when dealing with expired columns. Otherwise, we could think
+        // the cached partition has enough live rows to satisfy the filter when it doesn't because some
+        // are now expired.
+        return wholePartitionCached || filter.isFullyCoveredBy(cachedCf, now);
+    }
+
     public int gcBefore(long now)
     {
         return (int) (now / 1000) - metadata.getGcGraceSeconds();
@@ -1527,7 +1636,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
                     return null;
                 }
 
-                result = filterColumnFamily(cached, filter);
+                result = cached;
             }
             else
             {
@@ -2085,14 +2194,12 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
             return null;
 
         IRowCacheEntry cached = CacheService.instance.rowCache.getInternal(new RowCacheKey(metadata.cfId, key));
-        return cached == null || cached instanceof RowCacheSentinel ? null : (ColumnFamily) cached;
+        return cached == null || cached instanceof RowCacheSentinel ? null : (ColumnFamily)cached;
     }
 
     private void invalidateCaches()
     {
-        for (RowCacheKey key : CacheService.instance.rowCache.getKeySet())
-            if (key.cfId == metadata.cfId)
-                invalidateCachedRow(key);
+        CacheService.instance.invalidateRowCacheForCf(metadata.cfId);
 
         if (metadata.isCounter())
             for (CounterCacheKey key : CacheService.instance.counterCache.getKeySet())
@@ -2100,6 +2207,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
                     CacheService.instance.counterCache.remove(key);
     }
 
+
     /**
      * @return true if @param key is contained in the row cache
      */
@@ -2238,7 +2346,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
                     index.truncateBlocking(truncatedAt);
 
                 SystemKeyspace.saveTruncationRecord(ColumnFamilyStore.this, truncatedAt, replayAfter);
-
+                logger.debug("cleaning out row cache");
                 invalidateCaches();
             }
         };

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/db/RowIteratorFactory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RowIteratorFactory.java b/src/java/org/apache/cassandra/db/RowIteratorFactory.java
index 93698a0..7077944 100644
--- a/src/java/org/apache/cassandra/db/RowIteratorFactory.java
+++ b/src/java/org/apache/cassandra/db/RowIteratorFactory.java
@@ -23,6 +23,7 @@ import org.apache.cassandra.db.columniterator.IColumnIteratorFactory;
 import org.apache.cassandra.db.columniterator.LazyColumnIterator;
 import org.apache.cassandra.db.columniterator.OnDiskAtomIterator;
 import org.apache.cassandra.db.filter.QueryFilter;
+import org.apache.cassandra.db.filter.IDiskAtomFilter;
 import org.apache.cassandra.io.sstable.SSTableReader;
 import org.apache.cassandra.io.sstable.SSTableScanner;
 import org.apache.cassandra.utils.CloseableIterator;
@@ -93,16 +94,18 @@ public class RowIteratorFactory
 
             protected Row getReduced()
             {
-                // First check if this row is in the rowCache. If it is we can skip the rest
+                // First check if this row is in the rowCache. If it is and it covers our filter, we can skip the rest
                 ColumnFamily cached = cfs.getRawCachedRow(key);
-                if (cached == null)
+                IDiskAtomFilter filter = range.columnFilter(key.key);
+
+                if (cached == null || !cfs.isFilterFullyCoveredBy(filter, cached, now))
                 {
                     // not cached: collate
-                    QueryFilter.collateOnDiskAtom(returnCF, colIters, range.columnFilter(key.key), gcBefore, now);
+                    QueryFilter.collateOnDiskAtom(returnCF, colIters, filter, gcBefore, now);
                 }
                 else
                 {
-                    QueryFilter keyFilter = new QueryFilter(key, cfs.name, range.columnFilter(key.key), now);
+                    QueryFilter keyFilter = new QueryFilter(key, cfs.name, filter, now);
                     returnCF = cfs.filterColumnFamily(cached, keyFilter);
                 }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/db/filter/IDiskAtomFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/IDiskAtomFilter.java b/src/java/org/apache/cassandra/db/filter/IDiskAtomFilter.java
index 2755afd..17967a8 100644
--- a/src/java/org/apache/cassandra/db/filter/IDiskAtomFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/IDiskAtomFilter.java
@@ -25,6 +25,7 @@ import java.util.Iterator;
 
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.columniterator.OnDiskAtomIterator;
+import org.apache.cassandra.db.composites.CellName;
 import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.io.IVersionedSerializer;
@@ -79,7 +80,17 @@ public interface IDiskAtomFilter
     public IDiskAtomFilter cloneShallow();
     public boolean maySelectPrefix(Comparator<Composite> cmp, Composite prefix);
 
-    boolean shouldInclude(SSTableReader sstable);
+    public boolean shouldInclude(SSTableReader sstable);
+
+    public boolean countCQL3Rows(CellNameType comparator);
+
+    public boolean isHeadFilter();
+
+    /**
+     * Whether the provided cf, that is assumed to contain the head of the
+     * partition, contains enough data to cover this filter.
+     */
+    public boolean isFullyCoveredBy(ColumnFamily cf, long now);
 
     public static class Serializer implements IVersionedSerializer<IDiskAtomFilter>
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ab6eaed8/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
index 6f577b9..208bbdf 100644
--- a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
@@ -145,11 +145,32 @@ public class NamesQueryFilter implements IDiskAtomFilter
         return true;
     }
 
-    public boolean countCQL3Rows()
+    public boolean isFullyCoveredBy(ColumnFamily cf, long now)
+    {
+        // cf will cover all the requested columns if the range it covers include
+        // all said columns
+        CellName first = cf.iterator(ColumnSlice.ALL_COLUMNS_ARRAY).next().name();
+        CellName last = cf.reverseIterator(ColumnSlice.ALL_COLUMNS_ARRAY).next().name();
+
+        return cf.getComparator().compare(first, columns.first()) <= 0
+            && cf.getComparator().compare(columns.last(), last) <= 0;
+    }
+
+    public boolean isHeadFilter()
+    {
+        return false;
+    }
+
+    public boolean countCQL3Rows(CellNameType comparator)
     {
         return countCQL3Rows;
     }
 
+    public boolean countCQL3Rows()
+    {
+        return countCQL3Rows(null);
+    }
+
     public ColumnCounter columnCounter(CellNameType comparator, long now)
     {
         return countCQL3Rows