SENTRY-2488: Add privilege cache to sentry hive bindings in DefaultAccessValidator (Arjun Mishra reviewed by Kalyan Kumar Kalvagadda)
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
index 9de47b3..a596d0b 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryValidator.java
@@ -16,7 +16,6 @@
 
 import static org.apache.hadoop.hive.metastore.MetaStoreUtils.DEFAULT_DATABASE_NAME;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
 import java.security.CodeSource;
@@ -174,7 +173,7 @@
 
     HiveAuthzBinding hiveAuthzBinding = null;
     try {
-      hiveAuthzBinding = getAuthzBinding();
+      hiveAuthzBinding = getAuthzBindingWithPrivilegeCache(authenticator.getUserName());
       if (stmtAuthPrivileges == null) {
         // We don't handle authorizing this statement
         return;
@@ -245,9 +244,24 @@
     }
   }
 
-  @VisibleForTesting
-  public HiveAuthzBinding getAuthzBinding() throws Exception {
-    return new HiveAuthzBinding(hiveHook, conf, authzConf);
+  /**
+   * Create a binding object with a cache of privileges that will last the session
+   * At the time of doing the authorization check we will only check against the cache
+   * as opposed to fetching from the database each time
+   * @param userName
+   * @return
+   * @throws Exception
+   */
+  public HiveAuthzBinding getAuthzBindingWithPrivilegeCache(String userName) throws Exception {
+    HiveAuthzBinding hiveAuthzBinding = new HiveAuthzBinding(hiveHook, conf, authzConf);
+    try {
+      HiveAuthzBinding hiveAuthzBindingWithCache = HiveAuthzBindingHookBase
+          .getHiveBindingWithPrivilegeCache(hiveAuthzBinding, userName);
+      return hiveAuthzBindingWithCache;
+    } catch (Exception e) {
+      LOG.error("Unable to build bindings with cache. Use bindings without cache", e);
+      return  hiveAuthzBinding;
+    }
   }
 
   private void addExtendHierarchy(HiveOperation hiveOp, HiveAuthzPrivileges stmtAuthPrivileges,
@@ -372,13 +386,13 @@
       try {
         switch (pType) {
           case DATABASE:
-            hiveAuthzBinding = getAuthzBinding();
+            hiveAuthzBinding = getAuthzBindingWithPrivilegeCache(authenticator.getUserName());
             authzObjectFilter = new MetastoreAuthzObjectFilter<HivePrivilegeObject>(hiveAuthzBinding,
               OBJECT_EXTRACTOR);
             listObjs = authzObjectFilter.filterDatabases(authenticator.getUserName(), listObjs);
             break;
           case TABLE_OR_VIEW:
-            hiveAuthzBinding = getAuthzBinding();
+            hiveAuthzBinding = getAuthzBindingWithPrivilegeCache(authenticator.getUserName());
             authzObjectFilter = new MetastoreAuthzObjectFilter<HivePrivilegeObject>(hiveAuthzBinding,
               OBJECT_EXTRACTOR);
             listObjs = authzObjectFilter.filterTables(authenticator.getUserName(), listObjs);
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
index 63d8d1c..46eb456 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzBindingHookBase.java
@@ -828,7 +828,7 @@
   }
 
   // create hiveBinding with PrivilegeCache
-  private static HiveAuthzBinding getHiveBindingWithPrivilegeCache(HiveAuthzBinding hiveAuthzBinding,
+  static HiveAuthzBinding getHiveBindingWithPrivilegeCache(HiveAuthzBinding hiveAuthzBinding,
       String userName) throws SemanticException {
     // get the original HiveAuthzBinding, and get the user's privileges by AuthorizationProvider
     AuthorizationProvider authProvider = hiveAuthzBinding.getCurrentAuthProvider();
diff --git a/sentry-provider/sentry-provider-cache/src/main/java/org/apache/sentry/provider/cache/SimplePrivilegeCache.java b/sentry-provider/sentry-provider-cache/src/main/java/org/apache/sentry/provider/cache/SimplePrivilegeCache.java
index 0ad4616..5de3135 100644
--- a/sentry-provider/sentry-provider-cache/src/main/java/org/apache/sentry/provider/cache/SimplePrivilegeCache.java
+++ b/sentry-provider/sentry-provider-cache/src/main/java/org/apache/sentry/provider/cache/SimplePrivilegeCache.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sentry.provider.cache;
 
+import java.util.Collections;
 import org.apache.sentry.core.common.ActiveRoleSet;
 import org.apache.sentry.core.common.Authorizable;
 import org.apache.sentry.core.common.utils.SentryConstants;
@@ -110,7 +111,7 @@
   @Override
   public void close() {
     if (cachedPrivileges != null) {
-      cachedPrivileges.clear();
+      cachedPrivileges = Collections.emptySet();
     }
   }