From d919cc998e80eacec09ba374ee0b92248eb8bad1 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 13 Mar 2015 18:32:30 -0500 Subject: [PATCH] Merge 8722 --- .../cassandra/auth/AuthenticatedUser.java | 5 +- .../cassandra/auth/PermissionsCache.java | 69 +++++++++++++++---- .../cassandra/auth/PermissionsCacheMBean.java | 31 +++++++++ .../org/apache/cassandra/config/Config.java | 4 +- .../cassandra/config/DatabaseDescriptor.java | 10 +++ 5 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 src/java/org/apache/cassandra/auth/PermissionsCacheMBean.java diff --git a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java index ee62503f0d..5e5730805b 100644 --- a/src/java/org/apache/cassandra/auth/AuthenticatedUser.java +++ b/src/java/org/apache/cassandra/auth/AuthenticatedUser.java @@ -38,10 +38,7 @@ public class AuthenticatedUser public static final AuthenticatedUser ANONYMOUS_USER = new AuthenticatedUser(ANONYMOUS_USERNAME); // 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 final String name; // primary Role of the logged in user diff --git a/src/java/org/apache/cassandra/auth/PermissionsCache.java b/src/java/org/apache/cassandra/auth/PermissionsCache.java index 9e0dfa9da1..bc96d829a7 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, Set> cache; + private volatile LoadingCache, Set> 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 getPermissions(AuthenticatedUser user, IResource resource) @@ -61,20 +77,46 @@ public class PermissionsCache } } - private LoadingCache, Set> 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, Set> initCache( + LoadingCache, Set> 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, Set> newcache = CacheBuilder.newBuilder() + .refreshAfterWrite(DatabaseDescriptor.getPermissionsUpdateInterval(), TimeUnit.MILLISECONDS) + .expireAfterWrite(DatabaseDescriptor.getPermissionsValidity(), TimeUnit.MILLISECONDS) + .maximumSize(DatabaseDescriptor.getPermissionsCacheMaxEntries()) .build(new CacheLoader, Set>() { public Set load(Pair userResource) @@ -104,5 +146,8 @@ public class PermissionsCache return task; } }); + if (existing != null) + newcache.putAll(existing.asMap()); + return newcache; } } 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 0000000000..d07c98f18b --- /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(); +} diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index a174a0f9bb..3ad088a367 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 authenticator; public String authorizer; public String role_manager; - 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; public int roles_validity_in_ms = 2000; public int roles_cache_max_entries = 1000; public int roles_update_interval_in_ms = -1; diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index af21f74b07..35ce7284c1 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -628,6 +628,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; @@ -657,6 +662,11 @@ public class DatabaseDescriptor : conf.roles_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;