Fix Setting Virtual Table to update after startup config properties gc_log_threshold_in_ms, gc_warn_threshold_in_ms, conf.index_summary_capacity_in_mb, prepared_statements_cache_size_mb, key_cache_size_in_mb, counter_cache_size_in_mb
patch by Ekaterina Dimitrova; reviewed by Andres de la Pena for CASSANDRA-17737
diff --git a/CHANGES.txt b/CHANGES.txt
index 507fe7d..12b68b2 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,7 @@
 4.0.6
+ * Fix Setting Virtual Table - update after startup config properties gc_log_threshold_in_ms, gc_warn_threshold_in_ms,
+   conf.index_summary_capacity_in_mb, prepared_statements_cache_size_mb, key_cache_size_in_mb, counter_cache_size_in_mb
+   (CASSANDRA-17737)
  * Fix Settings Virtual Table - index_summary_resize_interval and index_summary_capacity were not updated after startup (CASSANDRA-17735)
  * Clean up ScheduledExecutors, CommitLog, and MessagingService shutdown for in-JVM dtests (CASSANDRA-17731)
  * Remove extra write to system table for prepared statements (CASSANDRA-17764)
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 049c4cc..c6b8ca7 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -356,8 +356,8 @@
     public volatile Long index_summary_capacity_in_mb;
     public volatile int index_summary_resize_interval_in_minutes = 60;
 
-    public int gc_log_threshold_in_ms = 200;
-    public int gc_warn_threshold_in_ms = 1000;
+    public volatile int gc_log_threshold_in_ms = 200;
+    public volatile int gc_warn_threshold_in_ms = 1000;
 
     // TTL for different types of trace events.
     public int tracetype_query_ttl = (int) TimeUnit.DAYS.toSeconds(1);
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index f1dc6ef..82a5ec7 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -699,6 +699,9 @@
 
             if (preparedStatementsCacheSizeInMB <= 0)
                 throw new NumberFormatException(); // to escape duplicating error message
+
+            // we need this assignment for the Settings virtual table - CASSANDRA-17734
+            conf.prepared_statements_cache_size_mb = preparedStatementsCacheSizeInMB;
         }
         catch (NumberFormatException e)
         {
@@ -715,6 +718,9 @@
 
             if (keyCacheSizeInMB < 0)
                 throw new NumberFormatException(); // to escape duplicating error message
+
+            // we need this assignment for the Settings Virtual Table - CASSANDRA-17734
+            conf.key_cache_size_in_mb = keyCacheSizeInMB;
         }
         catch (NumberFormatException e)
         {
@@ -738,6 +744,9 @@
                                              + conf.counter_cache_size_in_mb + "', supported values are <integer> >= 0.", false);
         }
 
+        // we need this assignment for the Settings virtual table - CASSANDRA-17735
+        conf.counter_cache_size_in_mb = counterCacheSizeInMB;
+
         // if set to empty/"auto" then use 5% of Heap size
         indexSummaryCapacityInMB = (conf.index_summary_capacity_in_mb == null)
                                    ? Math.max(1, (int) (Runtime.getRuntime().totalMemory() * 0.05 / 1024 / 1024))
@@ -747,6 +756,9 @@
             throw new ConfigurationException("index_summary_capacity_in_mb option was set incorrectly to '"
                                              + conf.index_summary_capacity_in_mb + "', it should be a non-negative integer.", false);
 
+        // we need this assignment for the Settings virtual table - CASSANDRA-17735
+        conf.index_summary_capacity_in_mb = indexSummaryCapacityInMB;
+
         if (conf.user_defined_function_fail_timeout < 0)
             throw new ConfigurationException("user_defined_function_fail_timeout must not be negative", false);
         if (conf.user_defined_function_warn_timeout < 0)
@@ -3015,6 +3027,11 @@
         return conf.gc_log_threshold_in_ms;
     }
 
+    public static void setGCLogThreshold(int gcLogThreshold)
+    {
+        conf.gc_log_threshold_in_ms = gcLogThreshold;
+    }
+
     public static EncryptionContext getEncryptionContext()
     {
         return encryptionContext;
@@ -3025,6 +3042,11 @@
         return conf.gc_warn_threshold_in_ms;
     }
 
+    public static void setGCWarnThreshold(int threshold)
+    {
+        conf.gc_warn_threshold_in_ms = threshold;
+    }
+
     public static boolean isCDCEnabled()
     {
         return conf.cdc_enabled;
diff --git a/src/java/org/apache/cassandra/service/GCInspector.java b/src/java/org/apache/cassandra/service/GCInspector.java
index 02fd720..0d42e72 100644
--- a/src/java/org/apache/cassandra/service/GCInspector.java
+++ b/src/java/org/apache/cassandra/service/GCInspector.java
@@ -28,11 +28,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
 import javax.management.Notification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
@@ -54,8 +51,6 @@
 {
     public static final String MBEAN_NAME = "org.apache.cassandra.service:type=GCInspector";
     private static final Logger logger = LoggerFactory.getLogger(GCInspector.class);
-    private volatile long gcLogThreshholdInMs = DatabaseDescriptor.getGCLogThreshold();
-    private volatile long gcWarnThreasholdInMs = DatabaseDescriptor.getGCWarnThreshold();
 
     /*
      * The field from java.nio.Bits that tracks the total number of allocated
@@ -293,9 +288,9 @@
                     break;
             }
             
-            if (gcWarnThreasholdInMs != 0 && duration > gcWarnThreasholdInMs)
+            if (getGcWarnThresholdInMs() != 0 && duration > getGcWarnThresholdInMs())
                 logger.warn(sb.toString());
-            else if (duration > gcLogThreshholdInMs)
+            else if (duration > getGcLogThresholdInMs())
                 logger.info(sb.toString());
             else if (logger.isTraceEnabled())
                 logger.trace(sb.toString());
@@ -346,37 +341,43 @@
 
     public void setGcWarnThresholdInMs(long threshold)
     {
+        long gcLogThresholdInMs = getGcLogThresholdInMs();
         if (threshold < 0)
             throw new IllegalArgumentException("Threshold must be greater than or equal to 0");
-        if (threshold != 0 && threshold <= gcLogThreshholdInMs)
-            throw new IllegalArgumentException("Threshold must be greater than gcLogTreasholdInMs which is currently " 
-                    + gcLogThreshholdInMs);
-        gcWarnThreasholdInMs = threshold;
+        if (threshold != 0 && threshold <= gcLogThresholdInMs)
+            throw new IllegalArgumentException("Threshold must be greater than gcLogThresholdInMs which is currently "
+                    + gcLogThresholdInMs);
+        if (threshold > Integer.MAX_VALUE)
+            throw new IllegalArgumentException("Threshold must be less than Integer.MAX_VALUE");
+        DatabaseDescriptor.setGCWarnThreshold((int)threshold);
     }
 
     public long getGcWarnThresholdInMs()
     {
-        return gcWarnThreasholdInMs;
+        return DatabaseDescriptor.getGCWarnThreshold();
     }
 
     public void setGcLogThresholdInMs(long threshold)
     {
         if (threshold <= 0)
-            throw new IllegalArgumentException("Threashold must be greater than 0");
-        if (gcWarnThreasholdInMs != 0 && threshold > gcWarnThreasholdInMs)
-            throw new IllegalArgumentException("Threashold must be less than gcWarnTreasholdInMs which is currently " 
-                    + gcWarnThreasholdInMs);
-        gcLogThreshholdInMs = threshold;
+            throw new IllegalArgumentException("Threshold must be greater than 0");
+
+        long gcWarnThresholdInMs = getGcWarnThresholdInMs();
+        if (gcWarnThresholdInMs != 0 && threshold > gcWarnThresholdInMs)
+            throw new IllegalArgumentException("Threshold must be less than gcWarnThresholdInMs which is currently "
+                                               + gcWarnThresholdInMs);
+
+        DatabaseDescriptor.setGCLogThreshold((int) threshold);
     }
 
     public long getGcLogThresholdInMs()
     {
-        return gcLogThreshholdInMs;
+        return DatabaseDescriptor.getGCLogThreshold();
     }
 
     public long getStatusThresholdInMs()
     {
-        return gcWarnThreasholdInMs != 0 ? gcWarnThreasholdInMs : gcLogThreshholdInMs;
+        return getGcWarnThresholdInMs() != 0 ? getGcWarnThresholdInMs() : getGcLogThresholdInMs();
     }
 
 }
diff --git a/test/unit/org/apache/cassandra/service/GCInspectorTest.java b/test/unit/org/apache/cassandra/service/GCInspectorTest.java
index 7e3a3d3..bcdf023 100644
--- a/test/unit/org/apache/cassandra/service/GCInspectorTest.java
+++ b/test/unit/org/apache/cassandra/service/GCInspectorTest.java
@@ -64,11 +64,16 @@
     {
         gcInspector.setGcWarnThresholdInMs(0);
         Assert.assertEquals(gcInspector.getStatusThresholdInMs(), gcInspector.getGcLogThresholdInMs());
+        Assert.assertEquals(0, DatabaseDescriptor.getGCWarnThreshold());
+        Assert.assertEquals(200, DatabaseDescriptor.getGCLogThreshold());
     }
     
     @Test(expected=IllegalArgumentException.class)
     public void ensureLogLessThanWarn()
     {
+        Assert.assertEquals(200, gcInspector.getGcLogThresholdInMs());
+        gcInspector.setGcWarnThresholdInMs(1000);
+        Assert.assertEquals(1000, gcInspector.getGcWarnThresholdInMs());
         gcInspector.setGcLogThresholdInMs(gcInspector.getGcWarnThresholdInMs() + 1);
     }
     
@@ -77,6 +82,16 @@
     {
         gcInspector.setGcLogThresholdInMs(200);
         gcInspector.setGcWarnThresholdInMs(1000);
+        Assert.assertEquals(200, DatabaseDescriptor.getGCLogThreshold());
+        Assert.assertEquals(200, gcInspector.getGcLogThresholdInMs());
+        Assert.assertEquals(1000, DatabaseDescriptor.getGCWarnThreshold());
+        Assert.assertEquals(1000, gcInspector.getGcWarnThresholdInMs());
     }
-    
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testMaxValue()
+    {
+        gcInspector.setGcLogThresholdInMs(200);
+        gcInspector.setGcWarnThresholdInMs(Integer.MAX_VALUE+1L);
+    }
 }