Allow invalidating permissions and cache time

Patch by brandonwilliams reviewed by aleksey for CASSANDRA-8722


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

Branch: refs/heads/trunk
Commit: 9caf0457ad8920788506f902ce4d9c130c881031
Parents: 1376b8e
Author: Brandon Williams <brandonwilli...@apache.org>
Authored: Fri Mar 13 10:57:43 2015 -0500
Committer: Brandon Williams <brandonwilli...@apache.org>
Committed: Fri Mar 13 10:57:43 2015 -0500

----------------------------------------------------------------------
 CHANGES.txt                                     |  2 +-
 src/java/org/apache/cassandra/auth/Auth.java    |  5 +-
 .../apache/cassandra/auth/PermissionsCache.java | 69 ++++++++++++++++----
 .../cassandra/auth/PermissionsCacheMBean.java   | 31 +++++++++
 .../org/apache/cassandra/config/Config.java     |  4 +-
 .../cassandra/config/DatabaseDescriptor.java    | 10 +++
 6 files changed, 102 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index cd29e9d..04861f0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.4
+ * Allow invalidating permissions and cache time (CASSANDRA-8722)
  * Log warning when queries that will require ALLOW FILTERING in Cassandra 3.0
    are executed (CASSANDRA-8418)
  * Fix cassandra-stress so it respects the CL passed in user mode 
(CASSANDRA-8948)
@@ -40,7 +41,6 @@
  * Fix Adler32 digest for compressed sstables (CASSANDRA-8778)
  * Add nodetool statushandoff/statusbackup (CASSANDRA-8912)
 Merged from 2.0:
-2.0.14:
  * Fix duplicate up/down messages sent to native clients (CASSANDRA-7816)
  * Expose commit log archive status via JMX (CASSANDRA-8734)
  * Provide better exceptions for invalid replication strategy parameters

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/src/java/org/apache/cassandra/auth/Auth.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/Auth.java 
b/src/java/org/apache/cassandra/auth/Auth.java
index 05e5061..dac2af8 100644
--- a/src/java/org/apache/cassandra/auth/Auth.java
+++ b/src/java/org/apache/cassandra/auth/Auth.java
@@ -57,10 +57,7 @@ public class Auth
     public static final String USERS_CF = "users";
 
     // User-level permissions cache.
-    private static final PermissionsCache permissionsCache = new 
PermissionsCache(DatabaseDescriptor.getPermissionsValidity(),
-                                                                               
   DatabaseDescriptor.getPermissionsUpdateInterval(),
-                                                                               
   DatabaseDescriptor.getPermissionsCacheMaxEntries(),
-                                                                               
   DatabaseDescriptor.getAuthorizer());
+    private static final PermissionsCache permissionsCache = new 
PermissionsCache(DatabaseDescriptor.getAuthorizer());
 
     private static final String USERS_CF_SCHEMA = String.format("CREATE TABLE 
%s.%s ("
                                                                 + "name text,"

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/src/java/org/apache/cassandra/auth/PermissionsCache.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/PermissionsCache.java 
b/src/java/org/apache/cassandra/auth/PermissionsCache.java
index 9e0dfa9..bc96d82 100644
--- a/src/java/org/apache/cassandra/auth/PermissionsCache.java
+++ b/src/java/org/apache/cassandra/auth/PermissionsCache.java
@@ -17,9 +17,11 @@
  */
 package org.apache.cassandra.auth;
 
+import java.lang.management.ManagementFactory;
 import java.util.Set;
 import java.util.concurrent.*;
 
+import org.apache.cassandra.config.DatabaseDescriptor;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -31,19 +33,33 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.concurrent.DebuggableThreadPoolExecutor;
 import org.apache.cassandra.utils.Pair;
 
-public class PermissionsCache
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+public class PermissionsCache implements PermissionsCacheMBean
 {
     private static final Logger logger = 
LoggerFactory.getLogger(PermissionsCache.class);
 
+    private final String MBEAN_NAME = 
"org.apache.cassandra.auth:type=PermissionsCache";
+
     private final ThreadPoolExecutor cacheRefreshExecutor = new 
DebuggableThreadPoolExecutor("PermissionsCacheRefresh",
                                                                                
              Thread.NORM_PRIORITY);
     private final IAuthorizer authorizer;
-    private final LoadingCache<Pair<AuthenticatedUser, IResource>, 
Set<Permission>> cache;
+    private volatile LoadingCache<Pair<AuthenticatedUser, IResource>, 
Set<Permission>> cache;
 
-    public PermissionsCache(int validityPeriod, int updateInterval, int 
maxEntries, IAuthorizer authorizer)
+    public PermissionsCache(IAuthorizer authorizer)
     {
         this.authorizer = authorizer;
-        this.cache = initCache(validityPeriod, updateInterval, maxEntries);
+        this.cache = initCache(null);
+        try
+        {
+            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+            mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
     }
 
     public Set<Permission> getPermissions(AuthenticatedUser user, IResource 
resource)
@@ -61,20 +77,46 @@ public class PermissionsCache
         }
     }
 
-    private LoadingCache<Pair<AuthenticatedUser, IResource>, Set<Permission>> 
initCache(int validityPeriod,
-                                                                               
         int updateInterval,
-                                                                               
         int maxEntries)
+    public void invalidate()
+    {
+        cache = initCache(null);
+    }
+
+    public void setValidity(int validityPeriod)
+    {
+        DatabaseDescriptor.setPermissionsValidity(validityPeriod);
+        cache = initCache(cache);
+    }
+
+    public int getValidity()
+    {
+        return DatabaseDescriptor.getPermissionsValidity();
+    }
+
+    public void setUpdateInterval(int updateInterval)
+    {
+        DatabaseDescriptor.setPermissionsUpdateInterval(updateInterval);
+        cache = initCache(cache);
+    }
+
+    public int getUpdateInterval()
+    {
+        return DatabaseDescriptor.getPermissionsUpdateInterval();
+    }
+
+    private LoadingCache<Pair<AuthenticatedUser, IResource>, Set<Permission>> 
initCache(
+                                                             
LoadingCache<Pair<AuthenticatedUser, IResource>, Set<Permission>> existing)
     {
         if (authorizer instanceof AllowAllAuthorizer)
             return null;
 
-        if (validityPeriod <= 0)
+        if (DatabaseDescriptor.getPermissionsValidity() <= 0)
             return null;
 
-        return CacheBuilder.newBuilder()
-                           .refreshAfterWrite(updateInterval, 
TimeUnit.MILLISECONDS)
-                           .expireAfterWrite(validityPeriod, 
TimeUnit.MILLISECONDS)
-                           .maximumSize(maxEntries)
+        LoadingCache<Pair<AuthenticatedUser, IResource>, Set<Permission>> 
newcache = CacheBuilder.newBuilder()
+                           
.refreshAfterWrite(DatabaseDescriptor.getPermissionsUpdateInterval(), 
TimeUnit.MILLISECONDS)
+                           
.expireAfterWrite(DatabaseDescriptor.getPermissionsValidity(), 
TimeUnit.MILLISECONDS)
+                           
.maximumSize(DatabaseDescriptor.getPermissionsCacheMaxEntries())
                            .build(new CacheLoader<Pair<AuthenticatedUser, 
IResource>, Set<Permission>>()
                            {
                                public Set<Permission> 
load(Pair<AuthenticatedUser, IResource> userResource)
@@ -104,5 +146,8 @@ public class PermissionsCache
                                    return task;
                                }
                            });
+        if (existing != null)
+            newcache.putAll(existing.asMap());
+        return newcache;
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/src/java/org/apache/cassandra/auth/PermissionsCacheMBean.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/PermissionsCacheMBean.java 
b/src/java/org/apache/cassandra/auth/PermissionsCacheMBean.java
new file mode 100644
index 0000000..d07c98f
--- /dev/null
+++ b/src/java/org/apache/cassandra/auth/PermissionsCacheMBean.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+public interface PermissionsCacheMBean
+{
+    public void invalidate();
+
+    public void setValidity(int validityPeriod);
+
+    public int getValidity();
+
+    public void setUpdateInterval(int updateInterval);
+
+    public int getUpdateInterval();
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/src/java/org/apache/cassandra/config/Config.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Config.java 
b/src/java/org/apache/cassandra/config/Config.java
index c683d7b..ccd4467 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -42,9 +42,9 @@ public class Config
     public String cluster_name = "Test Cluster";
     public String authenticator;
     public String authorizer;
-    public int permissions_validity_in_ms = 2000;
+    public volatile int permissions_validity_in_ms = 2000;
     public int permissions_cache_max_entries = 1000;
-    public int permissions_update_interval_in_ms = -1;
+    public volatile int permissions_update_interval_in_ms = -1;
 
     /* Hashing strategy Random or OPHF */
     public String partitioner;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9caf0457/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java 
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 924ab3c..4426f20 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -714,6 +714,11 @@ public class DatabaseDescriptor
         return conf.permissions_validity_in_ms;
     }
 
+    public static void setPermissionsValidity(int timeout)
+    {
+        conf.permissions_validity_in_ms = timeout;
+    }
+
     public static int getPermissionsCacheMaxEntries()
     {
         return conf.permissions_cache_max_entries;
@@ -726,6 +731,11 @@ public class DatabaseDescriptor
              : conf.permissions_update_interval_in_ms;
     }
 
+    public static void setPermissionsUpdateInterval(int updateInterval)
+    {
+        conf.permissions_update_interval_in_ms = updateInterval;
+    }
+
     public static int getThriftFramedTransportSize()
     {
         return conf.thrift_framed_transport_size_in_mb * 1024 * 1024;

Reply via email to