/**
 * 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.sentry.provider.db.service.persistent;

import static org.apache.sentry.core.common.utils.SentryConstants.ACTION;
import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_JOINER;
import static org.apache.sentry.core.common.utils.SentryConstants.COLUMN_NAME;
import static org.apache.sentry.core.common.utils.SentryConstants.DB_NAME;
import static org.apache.sentry.core.common.utils.SentryConstants.EMPTY_CHANGE_ID;
import static org.apache.sentry.core.common.utils.SentryConstants.EMPTY_NOTIFICATION_ID;
import static org.apache.sentry.core.common.utils.SentryConstants.EMPTY_PATHS_MAPPING_ID;
import static org.apache.sentry.core.common.utils.SentryConstants.EMPTY_PATHS_SNAPSHOT_ID;
import static org.apache.sentry.core.common.utils.SentryConstants.GRANT_OPTION;
import static org.apache.sentry.core.common.utils.SentryConstants.INDEX_GROUP_ROLES_MAP;
import static org.apache.sentry.core.common.utils.SentryConstants.INDEX_USER_ROLES_MAP;
import static org.apache.sentry.core.common.utils.SentryConstants.KV_JOINER;
import static org.apache.sentry.core.common.utils.SentryConstants.NULL_COL;
import static org.apache.sentry.core.common.utils.SentryConstants.SERVER_NAME;
import static org.apache.sentry.core.common.utils.SentryConstants.TABLE_NAME;
import static org.apache.sentry.core.common.utils.SentryConstants.URI;
import static org.apache.sentry.core.common.utils.SentryUtils.isNULL;
import static org.apache.sentry.hdfs.Updateable.Update;
import static org.apache.sentry.service.common.ServiceConstants.ServerConfig.SENTRY_STATEMENT_BATCH_LIMIT;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.jdo.FetchGroup;
import javax.jdo.JDODataStoreException;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.sentry.SentryOwnerInfo;
import org.apache.sentry.api.common.ApiConstants.PrivilegeScope;
import org.apache.sentry.api.service.thrift.TSentryActiveRoleSet;
import org.apache.sentry.api.service.thrift.TSentryAuthorizable;
import org.apache.sentry.api.service.thrift.TSentryGrantOption;
import org.apache.sentry.api.service.thrift.TSentryGroup;
import org.apache.sentry.api.service.thrift.TSentryMappingData;
import org.apache.sentry.api.service.thrift.TSentryPrivilege;
import org.apache.sentry.api.service.thrift.TSentryPrivilegeMap;
import org.apache.sentry.api.service.thrift.TSentryRole;
import org.apache.sentry.core.common.exception.SentryAccessDeniedException;
import org.apache.sentry.core.common.exception.SentryAlreadyExistsException;
import org.apache.sentry.core.common.exception.SentryInvalidInputException;
import org.apache.sentry.core.common.exception.SentryNoSuchObjectException;
import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
import org.apache.sentry.core.common.utils.PathUtils;
import org.apache.sentry.core.common.utils.SentryConstants;
import org.apache.sentry.core.model.db.AccessConstants;
import org.apache.sentry.core.model.db.DBModelAuthorizable.AuthorizableType;
import org.apache.sentry.hdfs.PathsUpdate;
import org.apache.sentry.hdfs.UniquePathsUpdate;
import org.apache.sentry.hdfs.UpdateableAuthzPaths;
import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipal;
import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipalType;
import org.apache.sentry.provider.db.service.model.MAuthzPathsMapping;
import org.apache.sentry.provider.db.service.model.MAuthzPathsSnapshotId;
import org.apache.sentry.provider.db.service.model.MPath;
import org.apache.sentry.provider.db.service.model.MSentryChange;
import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege;
import org.apache.sentry.provider.db.service.model.MSentryGroup;
import org.apache.sentry.provider.db.service.model.MSentryHmsNotification;
import org.apache.sentry.provider.db.service.model.MSentryPathChange;
import org.apache.sentry.provider.db.service.model.MSentryPermChange;
import org.apache.sentry.provider.db.service.model.MSentryPrivilege;
import org.apache.sentry.provider.db.service.model.MSentryRole;
import org.apache.sentry.provider.db.service.model.MSentryUser;
import org.apache.sentry.provider.db.service.model.MSentryUtil;
import org.apache.sentry.provider.db.service.model.MSentryVersion;
import org.apache.sentry.service.common.SentryOwnerPrivilegeType;
import org.apache.sentry.service.common.ServiceConstants.SentryPrincipalType;
import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
import org.datanucleus.store.rdbms.exceptions.MissingTableException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.codahale.metrics.Gauge;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * SentryStore is the data access object for Sentry data. Strings
 * such as role and group names will be normalized to lowercase
 * in addition to starting and ending whitespace.
 * <p>
 * We have several places where we rely on transactions to support
 * read/modify/write semantics for incrementing IDs.
 * This works but using DB support is rather expensive and we can
 * user in-core serializations to help with this a least within a
 * single node and rely on DB for multi-node synchronization.
 * <p>
 * This isn't much of a problem for path updates since they are
 * driven by HMSFollower which usually runs on a single leader
 * node, but permission updates originate from clients
 * directly and may be highly concurrent.
 * <p>
 * We are internally serializing all permissions update anyway, so doing
 * partial serialization on every node helps. For this reason all
 * SentryStore calls that affect permission deltas are serialized.
 * <p>
 * See <a href="https://issues.apache.org/jira/browse/SENTRY-1824">SENTRY-1824</a>
 * for more detail.
 */
public class SentryStore implements SentryStoreInterface {
  private static final Logger LOGGER = LoggerFactory
      .getLogger(SentryStore.class);

  // For counters, representation of the "unknown value"
  private static final long COUNT_VALUE_UNKNOWN = -1L;

  // Representation for unknown HMS notification ID
  private static final long NOTIFICATION_UNKNOWN = -1L;

  private static final String EMPTY_GRANTOR_PRINCIPAL = "--";


  private static final Set<String> ALL_ACTIONS = Sets.newHashSet(
      AccessConstants.ALL, AccessConstants.ACTION_ALL,
      AccessConstants.SELECT, AccessConstants.INSERT, AccessConstants.ALTER,
      AccessConstants.CREATE, AccessConstants.DROP, AccessConstants.INDEX,
      AccessConstants.LOCK, AccessConstants.OWNER);

  // Now partial revoke just support action with SELECT,INSERT and ALL.
  // Now partial revoke just support action with SELECT,INSERT, and ALL.
  // e.g. If we REVOKE SELECT from a privilege with action ALL, it will leads to INSERT
  // e.g. If we REVOKE SELECT from a privilege with action ALL, it will leads to others individual
  // Otherwise, if we revoke other privilege(e.g. ALTER,DROP...), we will remove it from a role directly.
  private static final Set<String> PARTIAL_REVOKE_ACTIONS = Sets.newHashSet(AccessConstants.ALL,
      AccessConstants.ACTION_ALL.toLowerCase(), AccessConstants.SELECT, AccessConstants.INSERT);

  // Datanucleus property controlling whether query results are loaded at commit time
  // to make query usable post-commit
  private static final String LOAD_RESULTS_AT_COMMIT = "datanucleus.query.loadResultsAtCommit";

  private final PersistenceManagerFactory pmf;
  private Configuration conf;
  private final TransactionManager tm;

  // When it is true, execute DeltaTransactionBlock to persist delta changes.
  // When it is false, do not execute DeltaTransactionBlock
  private boolean persistUpdateDeltas;

  /**
   * counterWait is used to synchronize notifications between Thrift and HMSFollower.
   * Technically it doesn't belong here, but the only thing that connects HMSFollower
   * and Thrift API is SentryStore. An alternative could be a singleton CounterWait or
   * some factory that returns CounterWait instances keyed by name, but this complicates
   * things unnecessary.
   * <p>
   * Keeping it here isn't ideal but serves the purpose until we find a better home.
   */
  private final CounterWait counterWait;

  // 5 min interval
  private final long printSnapshotPersistTimeInterval = 300000;

  private final boolean ownerPrivilegeWithGrant;
  public static Properties getDataNucleusProperties(Configuration conf)
          throws SentrySiteConfigurationException, IOException {
    Properties prop = new Properties();
    prop.putAll(ServerConfig.SENTRY_STORE_DEFAULTS);
    String jdbcUrl = conf.get(ServerConfig.SENTRY_STORE_JDBC_URL, "").trim();
    Preconditions.checkArgument(!jdbcUrl.isEmpty(), "Required parameter " +
        ServerConfig.SENTRY_STORE_JDBC_URL + " is missed");
    String user = conf.get(ServerConfig.SENTRY_STORE_JDBC_USER, ServerConfig.
        SENTRY_STORE_JDBC_USER_DEFAULT).trim();
    //Password will be read from Credential provider specified using property
    // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
    // it falls back to reading directly from sentry-site.xml
    char[] passTmp = conf.getPassword(ServerConfig.SENTRY_STORE_JDBC_PASS);
    if (passTmp == null) {
      throw new SentrySiteConfigurationException("Error reading " +
              ServerConfig.SENTRY_STORE_JDBC_PASS);
    }
    String pass = new String(passTmp);

    String driverName = conf.get(ServerConfig.SENTRY_STORE_JDBC_DRIVER,
        ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
    prop.setProperty(ServerConfig.JAVAX_JDO_URL, jdbcUrl);
    prop.setProperty(ServerConfig.JAVAX_JDO_USER, user);
    prop.setProperty(ServerConfig.JAVAX_JDO_PASS, pass);
    prop.setProperty(ServerConfig.JAVAX_JDO_DRIVER_NAME, driverName);

    /*
     * Oracle doesn't support "repeatable-read" isolation level and testing
     * showed issues with "serializable" isolation level for Oracle 12,
     * so we use "read-committed" instead.
     *
     * JDBC URL always looks like jdbc:oracle:<drivertype>:@<database>
     *  we look at the second component.
     *
     * The isolation property can be overwritten via configuration property.
     */
    final String oracleDb = "oracle";
    if (prop.getProperty(ServerConfig.DATANUCLEUS_ISOLATION_LEVEL, "").
            equals(ServerConfig.DATANUCLEUS_REPEATABLE_READ) &&
                    jdbcUrl.contains(oracleDb)) {
      String[] parts = jdbcUrl.split(":");
      if ((parts.length > 1) && parts[1].equals(oracleDb)) {
        // For Oracle JDBC driver, replace "repeatable-read" with "read-committed"
        prop.setProperty(ServerConfig.DATANUCLEUS_ISOLATION_LEVEL,
                "read-committed");
      }
    }

    for (Map.Entry<String, String> entry : conf) {
      String key = entry.getKey();
      if (key.startsWith(ServerConfig.SENTRY_JAVAX_JDO_PROPERTY_PREFIX) ||
          key.startsWith(ServerConfig.SENTRY_DATANUCLEUS_PROPERTY_PREFIX)) {
        key = StringUtils.removeStart(key, ServerConfig.SENTRY_DB_PROPERTY_PREFIX);
        prop.setProperty(key, entry.getValue());
      }
    }
    // Disallow operations outside of transactions
    prop.setProperty("datanucleus.NontransactionalRead", "false");
    prop.setProperty("datanucleus.NontransactionalWrite", "false");
    int batchSize = conf.getInt(SENTRY_STATEMENT_BATCH_LIMIT, ServerConfig.
            SENTRY_STATEMENT_BATCH_LIMIT_DEFAULT);
    prop.setProperty("datanucleus.rdbms.statementBatchLimit", Integer.toString(batchSize));

    int allocationSize = conf.getInt(ServerConfig.SENTRY_DB_VALUE_GENERATION_ALLOCATION_SIZE, ServerConfig.
            SENTRY_DB_VALUE_GENERATION_ALLOCATION_SIZE_DEFAULT);
    prop.setProperty("datanucleus.valuegeneration.increment.allocationSize", Integer.toString(allocationSize));
    return prop;
  }

  public SentryStore(Configuration conf) throws Exception {
    this.conf = conf;
    Properties prop = getDataNucleusProperties(conf);
    boolean checkSchemaVersion = conf.get(
        ServerConfig.SENTRY_VERIFY_SCHEM_VERSION,
        ServerConfig.SENTRY_VERIFY_SCHEM_VERSION_DEFAULT).equalsIgnoreCase(
        "true");

    // Schema verification should be set to false only for testing.
    // If it is set to false, appropriate datanucleus properties will be set so that
    // database schema is automatically created. This is desirable only for running tests.
    // Sentry uses <code>SentrySchemaTool</code> to create schema with the help of sql scripts.

    if (!checkSchemaVersion) {
      prop.setProperty("datanucleus.schema.autoCreateAll", "true");
    }
    pmf = JDOHelper.getPersistenceManagerFactory(prop);
    tm = new TransactionManager(pmf, conf);
    verifySentryStoreSchema(checkSchemaVersion);
    long notificationTimeout = conf.getInt(ServerConfig.SENTRY_NOTIFICATION_SYNC_TIMEOUT_MS,
            ServerConfig.SENTRY_NOTIFICATION_SYNC_TIMEOUT_DEFAULT);
    counterWait = new CounterWait(notificationTimeout, TimeUnit.MILLISECONDS);

    ownerPrivilegeWithGrant = SentryOwnerPrivilegeType.ALL_WITH_GRANT.isConfSet(conf);
  }

  public void setPersistUpdateDeltas(boolean persistUpdateDeltas) {
    this.persistUpdateDeltas = persistUpdateDeltas;
  }


  public TransactionManager getTransactionManager() {
    return tm;
  }

  public CounterWait getCounterWait() {
    return counterWait;
  }

  // ensure that the backend DB schema is set
  void verifySentryStoreSchema(boolean checkVersion) throws Exception {
    if (!checkVersion) {
      setSentryVersion(SentryStoreSchemaInfo.getSentryVersion(),
          "Schema version set implicitly");
    } else {
      String currentVersion = getSentryVersion();
      if (!SentryStoreSchemaInfo.getSentryVersion().equals(currentVersion)) {
        throw new SentryAccessDeniedException(
            "The Sentry store schema version " + currentVersion
                + " is different from distribution version "
                + SentryStoreSchemaInfo.getSentryVersion());
      }
    }
  }

  public synchronized void stop() {
    if (pmf != null) {
      pmf.close();
    }
  }

  /**
   * Get a single role with the given name inside a transaction
   * @param pm Persistence Manager instance
   * @param roleName Role name (should not be null)
   * @return single role with the given name
   */
  public MSentryRole getRole(PersistenceManager pm, String roleName) {
    Query query = pm.newQuery(MSentryRole.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setFilter("this.roleName == :roleName");
    query.setUnique(true);

    FetchGroup grp = pm.getFetchGroup(MSentryRole.class, "fetchPrivileges");
    grp.addMember("privileges");
    pm.getFetchPlan().addGroup("fetchPrivileges");

    return (MSentryRole) query.execute(roleName);
  }

  /**
   * Get list of all roles. Should be called inside transaction.
   * @param pm Persistence manager instance
   * @return List of all roles
   */
  @SuppressWarnings("unchecked")
  public List<MSentryRole> getAllRoles(PersistenceManager pm) {
    Query query = pm.newQuery(MSentryRole.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

    FetchGroup grp = pm.getFetchGroup(MSentryRole.class, "fetchGroups");
    grp.addMember("groups");
    pm.getFetchPlan().addGroup("fetchGroups");

    return (List<MSentryRole>) query.execute();
  }

  /**
   * Get a single user with the given name inside a transaction
   * @param pm Persistence Manager instance
   * @param userName User name (should not be null)
   * @return single user with the given name
   */
  public MSentryUser getUser(PersistenceManager pm, String userName) {
    Query query = pm.newQuery(MSentryUser.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setFilter("this.userName == :userName");
    query.setUnique(true);

    FetchGroup grp = pm.getFetchGroup(MSentryUser.class, "fetchPrivileges");
    grp.addMember("privileges");
    pm.getFetchPlan().addGroup("fetchPrivileges");

    return (MSentryUser) query.execute(userName);
  }

  /**
   * Create a sentry user and persist it. User name is the primary key for the
   * user, so an attempt to create a user which exists fails with JDO exception.
   *
   * @param userName: Name of the user being persisted.
   *    The name is normalized.
   * @throws Exception
   */
  public void createSentryUser(final String userName) throws Exception {
    tm.executeTransactionWithRetry(
        pm -> {
          pm.setDetachAllOnCommit(false); // No need to detach objects
          String trimmedUserName = userName.trim();
          if (getUser(pm, trimmedUserName) != null) {
            throw new SentryAlreadyExistsException("User: " + trimmedUserName);
          }
          pm.makePersistent(
              new MSentryUser(trimmedUserName, System.currentTimeMillis(), Sets.newHashSet()));
          return null;
        });
  }

  /**
   * Normalize the string values - remove leading and trailing whitespaces and
   * convert to lower case
   * @return normalized input
   */
  private String trimAndLower(String input) {
    return input.trim().toLowerCase();
  }

  /**
   * Create a sentry role and persist it. Role name is the primary key for the
   * role, so an attempt to create a role which exists fails with JDO exception.
   *
   * @param roleName: Name of the role being persisted.
   *    The name is normalized.
   * @throws Exception
   */
  public void createSentryRole(final String roleName) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              String trimmedRoleName = trimAndLower(roleName);
              if (getRole(pm, trimmedRoleName) != null) {
                throw new SentryAlreadyExistsException("Role: " + trimmedRoleName);
              }
              pm.makePersistent(new MSentryRole(trimmedRoleName));
              return null;
              });
  }

  /**
   * Get count of object of the given class
   * @param tClass Class to count
   * @param <T> Class type
   * @return count of objects or -1 in case of error
     */
  @VisibleForTesting
  <T> Long getCount(final Class<T> tClass) {
    try {
      return tm.executeTransaction(
              pm -> {
                pm.setDetachAllOnCommit(false); // No need to detach objects
                Query query = pm.newQuery();
                query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
                query.setClass(tClass);
                query.setResult("count(this)");
                Long result = (Long)query.execute();
                return result;
              });
    } catch (Exception e) {
       return COUNT_VALUE_UNKNOWN;
    }
  }

  /**
   * @return number of roles
   */
  public Gauge<Long> getRoleCountGauge() {
    return () -> getCount(MSentryRole.class);
  }

  /**
   * @return Number of privileges
   */
  public Gauge<Long> getPrivilegeCountGauge() {
    return () -> getCount(MSentryPrivilege.class);
  }

  /**
   * @return Number of privileges
   */
  public Gauge<Long> getGenericModelPrivilegeCountGauge() {
    return () -> getCount(MSentryGMPrivilege.class);
  }

  /**
   * @return number of groups
   */
  public Gauge<Long> getGroupCountGauge() {
    return () -> getCount(MSentryGroup.class);
  }

  /**
   * @return Number of users
   */
  Gauge<Long> getUserCountGauge() {
    return () -> getCount(MSentryUser.class);
  }

  /**
   * @return Number of authz objects persisted
   */
  public Gauge<Long> getAuthzObjectsCountGauge() {
    return () -> {
      try {
        return getCount(MAuthzPathsMapping.class);
      } catch (Exception e) {
        LOGGER.error("Cannot read AUTHZ_PATHS_MAPPING table", e);
        return NOTIFICATION_UNKNOWN;
      }
    };
  }

  /**
   * @return Number of authz paths persisted
   */
  public Gauge<Long> getAuthzPathsCountGauge() {
    return () -> {
      try {
        return getCount(MPath.class);
      } catch (Exception e) {
        LOGGER.error("Cannot read AUTHZ_PATH table", e);
        return NOTIFICATION_UNKNOWN;
      }
    };
  }

  /**
   * @return number of threads waiting for HMS notifications to be processed
   */
  public Gauge<Integer> getHMSWaitersCountGauge() {
    return () -> counterWait.waitersCount();
  }

  /**
   * @return current value of last processed notification ID
   */
  public Gauge<Long> getLastNotificationIdGauge() {
    return () -> {
      try {
        return getLastProcessedNotificationID();
      } catch (Exception e) {
        LOGGER.error("Can not read current notificationId", e);
        return NOTIFICATION_UNKNOWN;
      }
    };
  }

  /**
   * @return ID of the path snapshot
   */
  public Gauge<Long> getLastPathsSnapshotIdGauge() {
    return () -> {
      try {
        return getCurrentAuthzPathsSnapshotID();
      } catch (Exception e) {
        LOGGER.error("Can not read current paths snapshot ID", e);
        return NOTIFICATION_UNKNOWN;
      }
    };
  }

  /**
   * @return Permissions change ID
   */
  public Gauge<Long> getPermChangeIdGauge() {
    return new Gauge<Long>() {
      @Override
      public Long getValue() {
        try {
          return tm.executeTransaction(
                  pm -> getLastProcessedChangeIDCore(pm, MSentryPermChange.class)
          );
        } catch (Exception e) {
          LOGGER.error("Can not read current permissions change ID", e);
          return NOTIFICATION_UNKNOWN;
        }
      }
    };
  }

  /**
   * @return Path change id
   */
  public Gauge<Long> getPathChangeIdGauge() {
    return () -> {
      try {
        return tm.executeTransaction(
                pm -> getLastProcessedChangeIDCore(pm, MSentryPathChange.class)
        );
      } catch (Exception e) {
        LOGGER.error("Can not read current path change ID", e);
        return NOTIFICATION_UNKNOWN;
      }
    };
  }

  /**
   * Lets the test code know how many privs are in the db, so that we know
   * if they are in fact being cleaned up when not being referenced any more.
   * @return The number of rows in the db priv table.
   */
  @VisibleForTesting
  long countMSentryPrivileges() {
    return getCount(MSentryPrivilege.class);
  }

  @VisibleForTesting
  void clearAllTables() {
    try {
      tm.executeTransaction(
              pm -> {
                pm.newQuery(MSentryRole.class).deletePersistentAll();
                pm.newQuery(MSentryGroup.class).deletePersistentAll();
                pm.newQuery(MSentryUser.class).deletePersistentAll();
                pm.newQuery(MSentryPrivilege.class).deletePersistentAll();
                pm.newQuery(MSentryPermChange.class).deletePersistentAll();
                pm.newQuery(MSentryPathChange.class).deletePersistentAll();
                pm.newQuery(MAuthzPathsMapping.class).deletePersistentAll();
                pm.newQuery(MPath.class).deletePersistentAll();
                pm.newQuery(MSentryHmsNotification.class).deletePersistentAll();
                pm.newQuery(MAuthzPathsSnapshotId.class).deletePersistentAll();
                return null;
              });
    } catch (Exception e) {
      // the method only for test, log the error and ignore the exception
      LOGGER.error(e.getMessage(), e);
    }
  }

  /**
   * Removes all the information related to HMS Objects from sentry store.
   */
  public void clearHmsPathInformation() throws Exception {
    LOGGER.info("Clearing all the Path information");
    tm.executeTransactionWithRetry(
            pm -> {
              // Data in MAuthzPathsSnapshotId.class is not cleared intentionally.
              // This data will help sentry retain the history of snapshots taken before
              // and help in picking appropriate ID even when hdfs sync is enabled/disabled.
              pm.newQuery(MSentryPathChange.class).deletePersistentAll();
              pm.newQuery(MAuthzPathsMapping.class).deletePersistentAll();
              pm.newQuery(MPath.class).deletePersistentAll();
              return null;
            });
  }

  /**
   * Purge a given delta change table, with a specified number of changes to be kept.
   *
   * @param cls the class of a perm/path delta change {@link MSentryPermChange} or
   *            {@link MSentryPathChange}.
   * @param pm a {@link PersistenceManager} instance.
   * @param changesToKeep the number of changes the caller want to keep.
   * @param <T> the type of delta change class.
   */
  @VisibleForTesting
  <T extends MSentryChange> void purgeDeltaChangeTableCore(
      Class<T> cls, PersistenceManager pm, long changesToKeep) {
    Preconditions.checkArgument(changesToKeep >= 0,
        "changes to keep must be a non-negative number");
    long lastChangedID = getLastProcessedChangeIDCore(pm, cls);
    long maxIDDeleted = lastChangedID - changesToKeep;

    Query query = pm.newQuery(cls);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

    // It is an approximation of "SELECT ... LIMIT CHANGE_TO_KEEP" in SQL, because JDO w/ derby
    // does not support "LIMIT".
    // See: http://www.datanucleus.org/products/datanucleus/jdo/jdoql_declarative.html
    query.setFilter("changeID <= maxChangedIdDeleted");
    query.declareParameters("long maxChangedIdDeleted");
    long numDeleted = query.deletePersistentAll(maxIDDeleted);
    if (numDeleted > 0) {
      LOGGER.info(String.format("Purged %d of %s to changeID=%d",
              numDeleted, cls.getSimpleName(), maxIDDeleted));
    }
  }

  /**
   * Purge notification id table, keeping a specified number of entries.
   * @param pm a {@link PersistenceManager} instance.
   * @param changesToKeep  the number of changes the caller want to keep.
   */
  @VisibleForTesting
  protected void purgeNotificationIdTableCore(PersistenceManager pm,
      long changesToKeep) {
    Preconditions.checkArgument(changesToKeep > 0,
      "You need to keep at least one entry in SENTRY_HMS_NOTIFICATION_ID table");
    long lastNotificationID = getLastProcessedNotificationIDCore(pm);
    Query query = pm.newQuery(MSentryHmsNotification.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

    // It is an approximation of "SELECT ... LIMIT CHANGE_TO_KEEP" in SQL, because JDO w/ derby
    // does not support "LIMIT".
    // See: http://www.datanucleus.org/products/datanucleus/jdo/jdoql_declarative.html
    query.setFilter("notificationId <= maxNotificationIdDeleted");
    query.declareParameters("long maxNotificationIdDeleted");
    long numDeleted = query.deletePersistentAll(lastNotificationID - changesToKeep);
    if (numDeleted > 0) {
      LOGGER.info("Purged {} of {}", numDeleted, MSentryHmsNotification.class.getSimpleName());
    }
  }

  /**
   * Purge delta change tables, {@link MSentryPermChange} and {@link MSentryPathChange}.
   * The number of deltas to keep is configurable
   */
  public void purgeDeltaChangeTables() {
    final int changesToKeep = conf.getInt(ServerConfig.SENTRY_DELTA_KEEP_COUNT,
            ServerConfig.SENTRY_DELTA_KEEP_COUNT_DEFAULT);
    LOGGER.info("Purging MSentryPathUpdate and MSentyPermUpdate tables, leaving {} entries",
            changesToKeep);
    try {
      tm.executeTransaction(pm -> {
        pm.setDetachAllOnCommit(false); // No need to detach objects
        purgeDeltaChangeTableCore(MSentryPermChange.class, pm, changesToKeep);
        LOGGER.info("MSentryPermChange table has been purged.");
        purgeDeltaChangeTableCore(MSentryPathChange.class, pm, changesToKeep);
        LOGGER.info("MSentryPathUpdate table has been purged.");
        return null;
      });
    } catch (Exception e) {
      LOGGER.error("Delta change cleaning process encountered an error", e);
    }
  }

  /**
   * Purge hms notification id table , {@link MSentryHmsNotification}.
   * The number of notifications id's to be kept is based on configuration
   * sentry.server.delta.keep.count
   */
  public void purgeNotificationIdTable() {
    final int changesToKeep = conf.getInt(ServerConfig.SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT,
      ServerConfig.SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT_DEFAULT);
    LOGGER.debug("Purging MSentryHmsNotification table, leaving {} entries",
      changesToKeep);
    try {
      tm.executeTransaction(pm -> {
        pm.setDetachAllOnCommit(false); // No need to detach objects
        purgeNotificationIdTableCore(pm, changesToKeep);
        return null;
      });
    } catch (Exception e) {
      LOGGER.error("MSentryHmsNotification cleaning process encountered an error", e);
    }
  }

  @Override
  public void alterSentryRoleGrantPrivileges(final String roleName,
    final Set<TSentryPrivilege> privileges) throws Exception {
    alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, privileges, null);
  }

  /**
   * Grant privileges to a principal and update sentry perm change table accordingly
   *
   * Iterate over each thrift privilege object and create the MSentryPrivilege equivalent object
   *
   * @param type
   * @param name
   * @param privileges
   * @param updatesToPersist
   * @throws Exception
   */
  synchronized void alterSentryGrantPrivileges(SentryPrincipalType type, final String name,
    final Set<TSentryPrivilege> privileges,
    final List<Update>updatesToPersist) throws Exception {

    execute(updatesToPersist, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      String trimmedEntityName = trimAndLower(name);

      for (TSentryPrivilege privilege : privileges) {
        // Alter sentry Role and grant Privilege.
        MSentryPrivilege mPrivilege = alterSentryGrantPrivilegeCore(pm, type,
            trimmedEntityName, privilege);

        if (mPrivilege != null) {
          // update the privilege to be the one actually updated.
          convertToTSentryPrivilege(mPrivilege, privilege);
        }
      }
      return null;
    });
  }

  @Override
  public void alterSentryRoleGrantPrivileges(final String roleName,
    final Set<TSentryPrivilege> privileges,
    final Map<TSentryPrivilege, Update> privilegesUpdateMap) throws Exception {

    Preconditions.checkNotNull(privilegesUpdateMap);
    alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, privileges, new ArrayList<>(privilegesUpdateMap.values()));
  }

  /**
   * Find the privilege in entityPrivileges that matches the input privilege.
   * Function contains() only returns if there is a match, but does not return matching privilege
   * in entityPrivileges.
   * inputPrivilege contains all privilege fields except the roles and users information.
   * we need to find the privilege with all users and roles that matches the inputPrivilege.
   * @param entityPrivileges the privileges to search, which is fetched from DB, containing
   * associated users and/or roles
   * @param inputPrivilege input privilege to match. It is constructed in memory, does not contain
   * associated users and/or roles
   * @return matched privilege in entityPrivileges. When there is no match, return null
   */
   private MSentryPrivilege findMatchPrivilege(
      Set<MSentryPrivilege> entityPrivileges,
      MSentryPrivilege inputPrivilege) {

     for (MSentryPrivilege entityPrivilege : entityPrivileges) {
       if (entityPrivilege.equals(inputPrivilege)) {
         return entityPrivilege;
       }
     }

     return null;
   }

  /**
   * For the TSentryPrivilege object create a corresponding MSentryPrivilege object
   *
   * If ALL is being granted and SELECT/INSERT already exist, the older
   * privielges need to be deleted first in order to prevent having overlapping privileges
   * 
   * @param pm
   * @param type
   * @param entityName
   * @param privilege
   * @return
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  private MSentryPrivilege alterSentryGrantPrivilegeCore(PersistenceManager pm,
     SentryPrincipalType type,
     String entityName, TSentryPrivilege privilege)
      throws SentryNoSuchObjectException, SentryInvalidInputException {
    MSentryPrivilege mPrivilege = null;

    entityName = entityName.trim();
    if (type.equals(SentryPrincipalType.ROLE)) {
      entityName = entityName.toLowerCase();
    }

    PrivilegePrincipal mEntity = getEntity(pm, entityName, type);
    if (mEntity == null) {
      if(type == SentryPrincipalType.ROLE) {
        throw noSuchRole(entityName);
      } else if(type == SentryPrincipalType.USER) {
        // User might not exist. Creating one.
        mEntity = new MSentryUser(entityName, System.currentTimeMillis(), Sets.newHashSet());
      }
    }

    if(privilege.getPrivilegeScope().equalsIgnoreCase(PrivilegeScope.URI.name())
        && StringUtils.isBlank(privilege.getURI())) {
      throw new SentryInvalidInputException("cannot grant URI privileges to Null or EMPTY location");
    }

    if ((!isNULL(privilege.getColumnName()) || !isNULL(privilege.getTableName())
        || !isNULL(privilege.getDbName()))
        && !AccessConstants.OWNER.equalsIgnoreCase(privilege.getAction())) {
      // If Grant is for ALL and individual privileges already exists (i.e. insert/select/create..)
      // need to remove it and GRANT ALL..
      if (AccessConstants.ALL.equalsIgnoreCase(privilege.getAction())
          || AccessConstants.ACTION_ALL.equalsIgnoreCase(privilege.getAction())) {
        dropPrivilegesForGrantAll(pm, mEntity, privilege);
      } else {
        // If Grant is for Either INSERT/SELECT and ALL already exists..
        // do nothing..
        TSentryPrivilege tAll = new TSentryPrivilege(privilege);
        tAll.setAction(AccessConstants.ALL);
        MSentryPrivilege mAll1 =
            findMatchPrivilege(mEntity.getPrivileges(), convertToMSentryPrivilege(tAll));
        tAll.setAction(AccessConstants.ACTION_ALL);
        MSentryPrivilege mAll2 =
            findMatchPrivilege(mEntity.getPrivileges(), convertToMSentryPrivilege(tAll));
        if (mAll1 != null) {
          return null;
        }
        if (mAll2 != null) {
          return null;
        }
      }
    }

    mPrivilege = getMSentryPrivilege(privilege, pm);
    if (mPrivilege == null) {
      mPrivilege = convertToMSentryPrivilege(privilege);
      mPrivilege.appendPrincipal(mEntity);
      pm.makePersistent(mPrivilege);
    } else {
      mEntity.appendPrivilege(mPrivilege);
      pm.makePersistent(mEntity);
    }

    return mPrivilege;
  }

  /**
   * Drop all individual privileges from the privilege entity that form the grant all operation.
   *
   * @param pm The PersistenceManager to persist the changes.
   * @param principal The Sentry principal from where to drop the privileges.
   * @param privilege The Sentry privilege that has the authorizable object from where to drop the privileges.
   * @throws SentryInvalidInputException If an error occurs when dropping the privileges.
   */
  private void dropPrivilegesForGrantAll(PersistenceManager pm, PrivilegePrincipal principal,
    TSentryPrivilege privilege) throws SentryInvalidInputException {

    // Re-use this object to search for the specific privilege
    TSentryPrivilege tNotAll = new TSentryPrivilege(privilege);

    for (String action : ALL_ACTIONS) {
      // These privileges do not form part of the grant all operation.
      // For instance, a role/user may have the OWNER and ALL privileges together.
      if (action.equalsIgnoreCase(AccessConstants.OWNER)) {
        continue;
      }

      // Set the action to search in the set of privileges of the entity
      tNotAll.setAction(action);

      MSentryPrivilege mAction =
        findMatchPrivilege(principal.getPrivileges(), convertToMSentryPrivilege(tNotAll));
      if (mAction != null) {
        mAction.removePrincipal(principal);
        persistPrivilege(pm, mAction);
      }
    }
  }

  /**
   * Alter a given sentry user to grant a set of privileges.
   * Internally calls alterSentryGrantPrivileges.
   *
   * @param userName User name
   * @param privileges Set of privileges
   * @throws Exception
   */
  public void alterSentryUserGrantPrivileges(final String userName,
    final Set<TSentryPrivilege> privileges) throws Exception {

    try {
      MSentryUser userEntry = getMSentryUserByName(userName, false);
      if (userEntry == null) {
        createSentryUser(userName);
      }
    } catch (SentryAlreadyExistsException e) {
        // the user may be created by other thread, so swallow the exception and proceed
    }

    alterSentryGrantPrivileges(SentryPrincipalType.USER, userName, privileges, null);
  }

  /**
   * Alter a give sentry user/role to set owner privilege, as well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   * Creates User, if it is not already there.
   * Internally calls alterSentryGrantPrivileges.
   * @param principalName principalType name to which permissions should be granted.
   * @param entityType Principal Type
   * @param privilege Privilege to be granted
   * @param update DeltaTransactionBlock
   * @throws Exception
   */
  public void alterSentryGrantOwnerPrivilege(final String principalName, SentryPrincipalType entityType,
                                              final TSentryPrivilege privilege,
                                              final Update update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects

      // Alter sentry Role and grant Privilege.
      MSentryPrivilege mPrivilege = alterSentryGrantPrivilegeCore(pm, entityType,
          principalName, privilege);

      if (mPrivilege != null) {
        // update the privilege to be the one actually updated.
        convertToTSentryPrivilege(mPrivilege, privilege);
      }
      return null;
    });
  }

  /**
   * Get the user entry by user name
   * @param userName the name of the user
   * @return the user entry
   * @throws Exception if the specified user does not exist
   */
  @VisibleForTesting
  public MSentryUser getMSentryUserByName(final String userName) throws Exception {
    return getMSentryUserByName(userName, true);
  }

  /**
   * Get the user entry by user name
   * @param userName the name of the user
   * @param throwExceptionIfNotExist true: throw exception if user does not exist; false: return null
   * @return the user entry or null
   * @throws Exception if the specified user does not exist and throwExceptionIfNotExist is true
   */
  MSentryUser getMSentryUserByName(final String userName, boolean throwExceptionIfNotExist) throws Exception {
    return tm.executeTransaction(
        new TransactionBlock<MSentryUser>() {
          public MSentryUser execute(PersistenceManager pm) throws Exception {
            String trimmedUserName = userName.trim();
            MSentryUser sentryUser = getUser(pm, trimmedUserName);
            if (sentryUser == null) {
              if (throwExceptionIfNotExist) {
                throw noSuchUser(trimmedUserName);
              }
              else {
                return null;
              }
            }
            return sentryUser;
          }
        });
  }

  /**
   * Alter a given sentry user to revoke a set of privileges.
   * Internally calls alterSentryRevokePrivileges.
   *
   * @param userName the given user name
   * @param tPrivileges a Set of privileges
   * @throws Exception
   *
   */
  public void alterSentryUserRevokePrivileges(final String userName,
    final Set<TSentryPrivilege> tPrivileges) throws Exception {
    alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, tPrivileges, null);
  }

  @Override
  public void alterSentryRoleRevokePrivileges(final String roleName,
    final Set<TSentryPrivilege> tPrivileges)
    throws Exception {
    alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, tPrivileges, null);
  }

  /**
   * Revoke privileges from a principal and update sentry perm change table accordingly
   *
   * Iterate over each thrift privilege object and delete the MSentryPrivilege equivalent object
   * and also all the children privilege objects
   *
   * @param type
   * @param principalName
   * @param privileges
   * @param updatesToDelete
   * @throws Exception
   */
  synchronized void alterSentryRevokePrivileges(SentryPrincipalType type, final String principalName,
    final Set<TSentryPrivilege> privileges,
    final List<Update> updatesToDelete) throws Exception {
    execute(updatesToDelete, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      String trimmedEntityName = safeTrimLower(principalName);

      for (TSentryPrivilege tPrivilege : privileges) {
        alterSentryRevokePrivilegeCore(pm, type, trimmedEntityName, tPrivilege);
      }
      return null;
    });
  }

  @Override
  public void alterSentryRoleRevokePrivileges(final String roleName, final Set<TSentryPrivilege> tPrivileges,
    final Map<TSentryPrivilege, Update> privilegesUpdateMap)
    throws Exception {

    Preconditions.checkNotNull(privilegesUpdateMap);
    alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, tPrivileges, new ArrayList<>(privilegesUpdateMap.values()));
  }

  /**
   * For the TSentryPrivilege object delete a corresponding MSentryPrivilege object
   *
   * Also delete the corresponding child privileges
   *
   * @param pm
   * @param type
   * @param entityName
   * @param privilege
   * @return
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  private void alterSentryRevokePrivilegeCore(PersistenceManager pm, SentryPrincipalType type,
      String entityName, TSentryPrivilege tPrivilege)
      throws SentryNoSuchObjectException, SentryInvalidInputException {
    if (entityName == null) {
      throw new SentryInvalidInputException("Null entityName");
    }

    entityName = entityName.trim();
    if (type.equals(SentryPrincipalType.ROLE)) {
      entityName = entityName.toLowerCase();
    }

    PrivilegePrincipal mEntity = getEntity(pm, entityName, type);
    if (mEntity == null) {
      if(type == SentryPrincipalType.ROLE) {
        throw noSuchRole(entityName);
      } else if(type == SentryPrincipalType.USER) {
        throw noSuchUser (entityName);
      }
    }
    if(tPrivilege.getPrivilegeScope().equalsIgnoreCase(PrivilegeScope.URI.name())
        && StringUtils.isBlank(tPrivilege.getURI())) {
      throw new SentryInvalidInputException("cannot revoke URI privileges from Null or EMPTY location");
    }

    // make sure to drop all equivalent privileges
    LOGGER.debug("tPrivilege to drop: {}", tPrivilege.toString());
    MSentryPrivilege mPrivilege = getMSentryPrivilege(tPrivilege, pm);
    if (mPrivilege == null) {
      LOGGER.debug("mPrivilege is null");
      mPrivilege = convertToMSentryPrivilege(tPrivilege);
    } else {
      LOGGER.debug("mPrivilege is found: {}", mPrivilege.toString());
      mPrivilege = pm.detachCopy(mPrivilege);
    }

    Set<MSentryPrivilege> privilegeGraph = new HashSet<>();
    Set<String> allEquivalentActions = getAllEquivalentActions(mPrivilege.getAction());
    for (String equivalentAction : allEquivalentActions) {
      MSentryPrivilege newActionPrivilege = new MSentryPrivilege(mPrivilege);
      newActionPrivilege.setAction(equivalentAction);
      if (newActionPrivilege.getGrantOption() != null) {
        privilegeGraph.add(newActionPrivilege);
      } else {
        MSentryPrivilege mTure = new MSentryPrivilege(newActionPrivilege);
        mTure.setGrantOption(true);
        privilegeGraph.add(mTure);
        MSentryPrivilege mFalse = new MSentryPrivilege(newActionPrivilege);
        mFalse.setGrantOption(false);
        privilegeGraph.add(mFalse);
      }
    }

    // Get the privilege graph
    populateChildren(pm, type, Sets.newHashSet(entityName), mPrivilege, privilegeGraph);
    for (MSentryPrivilege childPriv : privilegeGraph) {
      revokePrivilege(pm, tPrivilege, mEntity, childPriv);
    }
    persistEntity(pm , type, mEntity);
  }

  /**
   * Roles/Users can be granted ALL, SELECT, and INSERT on tables. When
   * a role/user has ALL and SELECT or INSERT are revoked, we need to remove the ALL
   * privilege and add SELECT (INSERT was revoked) or INSERT (SELECT was revoked).
   */
  private void revokePartial(PersistenceManager pm,
                             TSentryPrivilege requestedPrivToRevoke,
                             PrivilegePrincipal mEntity,
                             MSentryPrivilege currentPrivilege) throws SentryInvalidInputException {
    MSentryPrivilege persistedPriv =
      getMSentryPrivilege(convertToTSentryPrivilege(currentPrivilege), pm);
    if (persistedPriv == null) {
      // The privilege corresponding to the currentPrivilege doesn't exist in the persistent
      // store, so we create a fake one for the code below. The fake one is not associated with
      // any role and shouldn't be stored in the persistent storage.
      persistedPriv = convertToMSentryPrivilege(convertToTSentryPrivilege(currentPrivilege));
    }

    if (requestedPrivToRevoke.getAction().equalsIgnoreCase(AccessConstants.ALL) ||
            requestedPrivToRevoke.getAction().equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
      if ((!persistedPriv.getRoles().isEmpty() || !persistedPriv.getUsers().isEmpty()) &&
              mEntity != null) {
        persistedPriv.removePrincipal(mEntity);
        persistPrivilege(pm, persistedPriv);
      }
    } else {

      Set<String> addActions = new HashSet<String>();
      for (String actionToAdd : PARTIAL_REVOKE_ACTIONS) {
        if( !requestedPrivToRevoke.getAction().equalsIgnoreCase(actionToAdd) &&
            !currentPrivilege.getAction().equalsIgnoreCase(actionToAdd) &&
            !AccessConstants.ALL.equalsIgnoreCase(actionToAdd) &&
            !AccessConstants.ACTION_ALL.equalsIgnoreCase(actionToAdd)) {
          addActions.add(actionToAdd);
        }
      }

      if (mEntity != null) {
        revokePrivilegeAndGrantPartial(pm, mEntity, currentPrivilege, persistedPriv, addActions);
      }
    }
  }

  /**
   * Persists the changes in principal
   * @param pm persistence manager
   * @param type Type of privilege principal
   * @param principal privilege principal to persist
   *
   */
  private void persistEntity(PersistenceManager pm, SentryPrincipalType type, PrivilegePrincipal principal) {
    if (type == SentryPrincipalType.USER && isUserStale((MSentryUser) principal)) {
      pm.deletePersistent(principal);
      return;
    }
    pm.makePersistent(principal);
  }

  private boolean isUserStale(MSentryUser user) {
    if (user.getPrivileges().isEmpty() && user.getRoles().isEmpty()) {
      return true;
    }

    return false;
  }

  private void persistPrivilege(PersistenceManager pm, MSentryPrivilege privilege) {
    if (isPrivilegeStale(privilege)) {
        pm.deletePersistent(privilege);
      return;
    }

    pm.makePersistent(privilege);
  }


  private boolean isPrivilegeStale(MSentryPrivilege privilege) {
    if (privilege.getUsers().isEmpty() && privilege.getRoles().isEmpty()) {
      return true;
    }

    return false;
  }

  private boolean isPrivilegeStale(MSentryGMPrivilege privilege) {
    if (privilege.getRoles().isEmpty()) {
      return true;
    }

    return false;
  }

  private void revokePrivilegeAndGrantPartial(PersistenceManager pm, PrivilegePrincipal mEntity,
                                              MSentryPrivilege currentPrivilege,
                                              MSentryPrivilege persistedPriv,
                                              Set<String> addActions) throws SentryInvalidInputException {
    // If table / URI, remove ALL
    persistedPriv = getMSentryPrivilege(convertToTSentryPrivilege(persistedPriv), pm);
    if (persistedPriv != null) {
      persistedPriv.removePrincipal(mEntity);
      persistPrivilege(pm, persistedPriv);
    }
    currentPrivilege.setAction(AccessConstants.ALL);
    persistedPriv = getMSentryPrivilege(convertToTSentryPrivilege(currentPrivilege), pm);
    if (persistedPriv != null && mEntity.getPrivileges().contains(persistedPriv)) {
      persistedPriv.removePrincipal(mEntity);
      persistPrivilege(pm, persistedPriv);
      // add decomposed actions
      for (String addAction : addActions) {
        currentPrivilege.setAction(addAction);
        TSentryPrivilege tSentryPrivilege = convertToTSentryPrivilege(currentPrivilege);
        persistedPriv = getMSentryPrivilege(tSentryPrivilege, pm);
        if (persistedPriv == null) {
          persistedPriv = convertToMSentryPrivilege(tSentryPrivilege);
        }
        mEntity.appendPrivilege(persistedPriv);
      }
      persistedPriv.appendPrincipal(mEntity);
      pm.makePersistent(persistedPriv);
    }
  }

  /**
   * Revoke privilege from role
   */
  private void revokePrivilege(PersistenceManager pm, TSentryPrivilege tPrivilege,
                               PrivilegePrincipal mEntity, MSentryPrivilege mPrivilege)
    throws SentryInvalidInputException {
    if (PARTIAL_REVOKE_ACTIONS.contains(mPrivilege.getAction())) {
      // if this privilege is in partial revoke actions
      // we will do partial revoke
      revokePartial(pm, tPrivilege, mEntity, mPrivilege);
    } else {
      // otherwise,
      // we will revoke it from role directly
      MSentryPrivilege persistedPriv = getMSentryPrivilege(convertToTSentryPrivilege(mPrivilege), pm);
      if (persistedPriv != null) {
        persistedPriv.removePrincipal(mEntity);
        persistPrivilege(pm, persistedPriv);
      }
    }
  }

  /**
   * Explore Privilege graph and collect child privileges.
   * The responsibility to commit/rollback the transaction should be handled by the caller.
   */
  private void populateChildren(PersistenceManager pm, SentryPrincipalType entityType, Set<String> entityNames, MSentryPrivilege priv,
      Collection<MSentryPrivilege> children) throws SentryInvalidInputException {
    Preconditions.checkNotNull(pm);
    if (!isNULL(priv.getServerName()) || !isNULL(priv.getDbName())
        || !isNULL(priv.getTableName())) {
      // Get all TableLevel Privs
      Set<MSentryPrivilege> childPrivs = getChildPrivileges(pm, entityType, entityNames, priv);
      for (MSentryPrivilege childPriv : childPrivs) {
        // Only recurse for table level privs..
        if (!isNULL(childPriv.getDbName()) && !isNULL(childPriv.getTableName())
            && !isNULL(childPriv.getColumnName())) {
          populateChildren(pm, entityType, entityNames, childPriv, children);
        }
        // The method getChildPrivileges() didn't do filter on "action",
        // if the action is not "All", it should judge the action of children privilege.
        // For example: a user has a privilege “All on Col1”,
        // if the operation is “REVOKE INSERT on table”
        // the privilege should be the child of table level privilege.
        // but the privilege may still have other meaning, likes "SELECT, CREATE etc. on Col1".
        // and the privileges like "SELECT, CREATE etc. on Col1" should not be revoke.
        if (!priv.isActionALL()) {
          if (childPriv.isActionALL()) {
            // If the child privilege is All, we should convert it to the same
            // privilege with parent
            childPriv.setAction(priv.getAction());
          }
          // Only include privilege that imply the parent privilege.
          if (!priv.implies(childPriv)) {
            continue;
          }
        }
        children.add(childPriv);
      }
    }
  }

  private Set<MSentryPrivilege> getChildPrivileges(PersistenceManager pm, SentryPrincipalType entityType, Set<String> entityNames,
      MSentryPrivilege parent) throws SentryInvalidInputException {
    // Column and URI do not have children
    if (!isNULL(parent.getColumnName()) || !isNULL(parent.getURI())) {
      return Collections.emptySet();
    }

    Query query = pm.newQuery(MSentryPrivilege.class);
    QueryParamBuilder paramBuilder = null;
    if (entityType == SentryPrincipalType.ROLE) {
      paramBuilder = QueryParamBuilder.addRolesFilter(query, null, entityNames).add(SERVER_NAME, parent.getServerName());
    } else if (entityType == SentryPrincipalType.USER) {
      paramBuilder = QueryParamBuilder.addUsersFilter(query, null, entityNames).add(SERVER_NAME, parent.getServerName());
    } else {
      throw new SentryInvalidInputException("entityType" + entityType + " is not valid");
    }

    if (!isNULL(parent.getDbName())) {
      paramBuilder.add(DB_NAME, parent.getDbName());
      if (!isNULL(parent.getTableName())) {
        paramBuilder.add(TABLE_NAME, parent.getTableName())
            .addNotNull(COLUMN_NAME);
      } else {
        paramBuilder.addNotNull(TABLE_NAME);
      }
    } else {
      // Add condition dbName != NULL || URI != NULL
      paramBuilder.newChild()
          .addNotNull(DB_NAME)
          .addNotNull(URI);
    }

    query.setFilter(paramBuilder.toString());
    query.setResult("privilegeScope, serverName, dbName, tableName, columnName," +
        " URI, action, grantOption");
    List<Object[]> privObjects =
        (List<Object[]>) query.executeWithMap(paramBuilder.getArguments());
    Set<MSentryPrivilege> privileges = new HashSet<>(privObjects.size());
    for (Object[] privObj : privObjects) {
      String scope        = (String)privObj[0];
      String serverName   = (String)privObj[1];
      String dbName       = (String)privObj[2];
      String tableName    = (String) privObj[3];
      String columnName   = (String) privObj[4];
      String URI          = (String) privObj[5];
      String action       = (String) privObj[6];
      Boolean grantOption = (Boolean) privObj[7];
      MSentryPrivilege priv =
          new MSentryPrivilege(scope, serverName, dbName, tableName,
              columnName, URI, action, grantOption);
      privileges.add(priv);
    }
    return privileges;
  }

  /**
   * Drop a given sentry user.
   *
   * @param userName the given user name
   * @throws Exception
   */
  public void dropSentryUser(final String userName) throws Exception {
    tm.executeTransactionWithRetry(
        new TransactionBlock<Object>() {
          public Object execute(PersistenceManager pm) throws Exception {
            pm.setDetachAllOnCommit(false); // No need to detach objects
            dropSentryUserCore(pm, userName);
            return null;
          }
        });
  }

  /**
   * Drop a given sentry user. As well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   *
   * @param userName the given user name
   * @param update the corresponding permission delta update
   * @throws Exception
   */
  public synchronized void dropSentryUser(final String userName,
      final Update update) throws Exception {
    execute(update, new TransactionBlock<Object>() {
      public Object execute(PersistenceManager pm) throws Exception {
        pm.setDetachAllOnCommit(false); // No need to detach objects
        dropSentryUserCore(pm, userName);
        return null;
      }
    });
  }

  private void dropSentryUserCore(PersistenceManager pm, String userName)
      throws SentryNoSuchObjectException {
    String lUserName = userName.trim();
    MSentryUser sentryUser = getUser(pm, lUserName);
    if (sentryUser == null) {
      throw noSuchUser(lUserName);
    }
    removePrivilegesForUser(pm, sentryUser);
    pm.deletePersistent(sentryUser);
  }

  /**
   * Removes all the privileges associated with
   * a particular user. After this dis-association if the
   * privilege doesn't have any users associated it will be
   * removed from the underlying persistence layer.
   * @param pm Instance of PersistenceManager
   * @param sentryUser User for which all the privileges are to be removed.
   */
  private void removePrivilegesForUser(PersistenceManager pm, MSentryUser sentryUser) {
    List<MSentryPrivilege> privilegesCopy = new ArrayList<>(sentryUser.getPrivileges());

    sentryUser.removePrivileges();

    removeStaledPrivileges(pm, privilegesCopy);
  }

  /**
   * Return the privileges on the authorizable object specified in tPriv, and including
   * privileges on the child authorizable objects.
   * @param tPriv the privilege that specifies the authorizable object to find its privileges
   * @param pm persistant manager
   * @return  the privileges on the authorizable object specified in tPriv
   */
  @SuppressWarnings("unchecked")
  private List<MSentryPrivilege> getMSentryPrivileges(TSentryPrivilege tPriv, PersistenceManager pm) {
    Query query = pm.newQuery(MSentryPrivilege.class);
    QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
    paramBuilder
            .add(SERVER_NAME, tPriv.getServerName())
            .add("action", tPriv.getAction());

    if (!isNULL(tPriv.getDbName())) {
      paramBuilder.add(DB_NAME, tPriv.getDbName());
      if (!isNULL(tPriv.getTableName())) {
        paramBuilder.add(TABLE_NAME, tPriv.getTableName());
        if (!isNULL(tPriv.getColumnName())) {
          paramBuilder.add(COLUMN_NAME, tPriv.getColumnName());
        }
      }
    } else if (!isNULL(tPriv.getURI())) {
      // if db is null, uri is not null
      paramBuilder.add(URI, tPriv.getURI(), true);
    }

    query.setFilter(paramBuilder.toString());

    FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRolesUsers");
    grp.addMember("roles").addMember("users");
    pm.getFetchPlan().addGroup("fetchRolesUsers");

    return (List<MSentryPrivilege>) query.executeWithMap(paramBuilder.getArguments());
  }

  /**
   * Return the privileges on the authorizable object specified in tPriv, and not including
   * privileges on the child authorizable objects.
   * @param tPriv the privilege that specifies the authorizable object to find its privileges
   * @param pm persistant manager
   * @return  the privileges on the authorizable object specified in tPriv
   */
  @SuppressWarnings("unchecked")
  private List<MSentryPrivilege> getMSentryPrivilegesExactMatch(TSentryPrivilege tPriv, PersistenceManager pm) {
    Query query = pm.newQuery(MSentryPrivilege.class);
    QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
    paramBuilder
        .add(SERVER_NAME, tPriv.getServerName())
        .add("action", tPriv.getAction())
        .add(DB_NAME, tPriv.getDbName())
        .add(TABLE_NAME, tPriv.getTableName())
        .add(COLUMN_NAME, tPriv.getColumnName())
        .add(URI, tPriv.getURI(), true);

    query.setFilter(paramBuilder.toString());
    return (List<MSentryPrivilege>) query.executeWithMap(paramBuilder.getArguments());
  }

  private MSentryPrivilege getMSentryPrivilege(TSentryPrivilege tPriv, PersistenceManager pm) {
    Boolean grantOption = null;
    if (tPriv.getGrantOption().equals(TSentryGrantOption.TRUE)) {
      grantOption = true;
    } else if (tPriv.getGrantOption().equals(TSentryGrantOption.FALSE)) {
      grantOption = false;
    }

    QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
    paramBuilder.add(SERVER_NAME, tPriv.getServerName())
            .add(DB_NAME, tPriv.getDbName())
            .add(TABLE_NAME, tPriv.getTableName())
            .add(COLUMN_NAME, tPriv.getColumnName())
            .add(URI, tPriv.getURI(), true)
            .add(ACTION, tPriv.getAction())
            .addObject(GRANT_OPTION, grantOption);

    LOGGER.debug("getMSentryPrivilege query filter: {}", paramBuilder.toString());

    Query query = pm.newQuery(MSentryPrivilege.class);
    query.setUnique(true);
    query.setFilter(paramBuilder.toString());
    return (MSentryPrivilege)query.executeWithMap(paramBuilder.getArguments());
  }

  private Set<String> getAllEquivalentActions(String inputAction) {
    if (AccessConstants.ALL.equalsIgnoreCase(inputAction) ||
        AccessConstants.ACTION_ALL.equalsIgnoreCase(inputAction)) {
      return Sets.newHashSet(AccessConstants.ALL, AccessConstants.ACTION_ALL,
          AccessConstants.ACTION_ALL.toLowerCase());
    }

    return Sets.newHashSet(inputAction);
  }

  /**
   * Drop a given sentry role.
   *
   * @param roleName the given role name
   * @throws Exception
   */
  public void dropSentryRole(final String roleName) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              dropSentryRoleCore(pm, roleName);
              return null;
            });
  }

  /**
   * Drop a given sentry role. As well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   *
   * @param roleName the given role name
   * @param update the corresponding permission delta update
   * @throws Exception
   */
  public synchronized void dropSentryRole(final String roleName,
      final Update update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      dropSentryRoleCore(pm, roleName);
      return null;
    });
  }

  private void dropSentryRoleCore(PersistenceManager pm, String roleName)
      throws SentryNoSuchObjectException {
    String lRoleName = trimAndLower(roleName);
    MSentryRole sentryRole = getRole(pm, lRoleName);
    if (sentryRole == null) {
      throw noSuchRole(lRoleName);
    }
    removePrivileges(pm, sentryRole);
    pm.deletePersistent(sentryRole);
  }

  /**
   * Removes all the privileges associated with
   * a particular role. After this dis-association if the
   * privilege doesn't have any roles associated it will be
   * removed from the underlying persistence layer.
   * @param pm Instance of PersistenceManager
   * @param sentryRole Role for which all the privileges are to be removed.
   */
  private void removePrivileges(PersistenceManager pm, MSentryRole sentryRole) {
    List<MSentryPrivilege> privilegesCopy = new ArrayList<>(sentryRole.getPrivileges());
    List<MSentryGMPrivilege> gmPrivilegesCopy = new ArrayList<>(sentryRole.getGmPrivileges());

    sentryRole.removePrivileges();
    // with SENTRY-398 generic model
    sentryRole.removeGMPrivileges();

    removeStaledPrivileges(pm, privilegesCopy);
    removeStaledGMPrivileges(pm, gmPrivilegesCopy);
  }

  private void removeStaledPrivileges(PersistenceManager pm, List<MSentryPrivilege> privilegesCopy) {
    List<MSentryPrivilege> stalePrivileges = new ArrayList<>(0);
    for (MSentryPrivilege privilege : privilegesCopy) {
      if (isPrivilegeStale(privilege)) {
        stalePrivileges.add(privilege);
      }
    }
    if(!stalePrivileges.isEmpty()) {
      pm.deletePersistentAll(stalePrivileges);
    }
  }

  private void removeStaledGMPrivileges(PersistenceManager pm, List<MSentryGMPrivilege> privilegesCopy) {
    List<MSentryGMPrivilege> stalePrivileges = new ArrayList<>(0);
    for (MSentryGMPrivilege privilege : privilegesCopy) {
      if (isPrivilegeStale(privilege)) {
        stalePrivileges.add(privilege);
      }
    }
    if(!stalePrivileges.isEmpty()) {
      pm.deletePersistentAll(stalePrivileges);
    }
  }

  /**
   * Assign a given role to a set of groups.
   *
   * @param grantorPrincipal grantorPrincipal currently is not used.
   * @param roleName the role to be assigned to the groups.
   * @param groupNames the list of groups to be added to the role,
   * @throws Exception
   */
  public void alterSentryRoleAddGroups(final String grantorPrincipal,
      final String roleName, final Set<TSentryGroup> groupNames) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              alterSentryRoleAddGroupsCore(pm, roleName, groupNames);
              return null;
            });
  }

  /**
   * Assign a given role to a set of groups. As well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   *
   * @param grantorPrincipal grantorPrincipal currently is not used.
   * @param roleName the role to be assigned to the groups.
   * @param groupNames the list of groups to be added to the role,
   * @param update the corresponding permission delta update
   * @throws Exception
   */
  public synchronized void alterSentryRoleAddGroups(final String grantorPrincipal,
      final String roleName, final Set<TSentryGroup> groupNames,
      final Update update) throws Exception {

    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      alterSentryRoleAddGroupsCore(pm, roleName, groupNames);
      return null;
    });
  }

  private void alterSentryRoleAddGroupsCore(PersistenceManager pm, String roleName,
      Set<TSentryGroup> groupNames) throws SentryNoSuchObjectException {

    // All role names are stored in lowercase.
    String lRoleName = trimAndLower(roleName);
    MSentryRole role = getRole(pm, lRoleName);
    if (role == null) {
      throw noSuchRole(lRoleName);
    }

    // Add the group to the specified role if it does not belong to the role yet.
    Query query = pm.newQuery(MSentryGroup.class);
    query.setFilter("this.groupName == :groupName");
    query.setUnique(true);
    List<MSentryGroup> groups = Lists.newArrayList();
    for (TSentryGroup tGroup : groupNames) {
      String groupName = tGroup.getGroupName().trim();
      MSentryGroup group = (MSentryGroup) query.execute(groupName);
      if (group == null) {
        group = new MSentryGroup(groupName, System.currentTimeMillis(), Sets.newHashSet(role));
      }
      group.appendRole(role);
      groups.add(group);
    }
    pm.makePersistentAll(groups);
  }

  public void alterSentryRoleAddUsers(final String roleName,
      final Set<String> userNames) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              alterSentryRoleAddUsersCore(pm, roleName, userNames);
              return null;
            });
  }

  private void alterSentryRoleAddUsersCore(PersistenceManager pm, String roleName,
      Set<String> userNames) throws SentryNoSuchObjectException {
    String trimmedRoleName = trimAndLower(roleName);
    MSentryRole role = getRole(pm, trimmedRoleName);
    if (role == null) {
      throw noSuchRole(trimmedRoleName);
    }
    Query query = pm.newQuery(MSentryUser.class);
    query.setFilter("this.userName == :userName");
    query.setUnique(true);
    List<MSentryUser> users = Lists.newArrayList();
    for (String userName : userNames) {
      userName = userName.trim();
      MSentryUser user = (MSentryUser) query.execute(userName);
      if (user == null) {
        user = new MSentryUser(userName, System.currentTimeMillis(), Sets.newHashSet(role));
      }
      user.appendRole(role);
      users.add(user);
    }
    pm.makePersistentAll(users);
  }

  public void alterSentryRoleDeleteUsers(final String roleName,
      final Set<String> userNames) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              String trimmedRoleName = trimAndLower(roleName);
              MSentryRole role = getRole(pm, trimmedRoleName);
              if (role == null) {
                throw noSuchRole(trimmedRoleName);
              } else {
                Query query = pm.newQuery(MSentryUser.class);
                query.setFilter("this.userName == :userName");
                query.setUnique(true);
                List<MSentryUser> usersToSave = Lists.newArrayList();
                List<MSentryUser> usersToDelete = Lists.newArrayList();
                for (String userName : userNames) {
                  userName = userName.trim();
                  MSentryUser user = (MSentryUser) query.execute(userName);
                  if (user != null) {
                    user.removeRole(role);

                    if (isUserStale(user)) {
                      usersToDelete.add(user);
                    } else {
                      usersToSave.add(user);
                    }
                  }
                }

                pm.deletePersistentAll(usersToDelete);
                pm.makePersistentAll(usersToSave);
              }
              return null;
            });
  }

  /**
   * Revoke a given role to a set of groups.
   *
   * @param roleName the role to be assigned to the groups.
   * @param groupNames the list of groups to be added to the role,
   * @throws Exception
   */
  public void alterSentryRoleDeleteGroups(final String roleName,
      final Set<TSentryGroup> groupNames) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              String trimmedRoleName = trimAndLower(roleName);
              MSentryRole role = getRole(pm, trimmedRoleName);
              if (role == null) {
                throw noSuchRole(trimmedRoleName);
              }
              Query query = pm.newQuery(MSentryGroup.class);
              query.setFilter("this.groupName == :groupName");
              query.setUnique(true);
              List<MSentryGroup> groups = Lists.newArrayList();
              for (TSentryGroup tGroup : groupNames) {
                String groupName = tGroup.getGroupName().trim();
                MSentryGroup group = (MSentryGroup) query.execute(groupName);
                if (group != null) {
                  group.removeRole(role);
                  groups.add(group);
                }
              }
              pm.makePersistentAll(groups);
              return null;
            });
  }

  /**
   * Revoke a given role to a set of groups. As well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   *
   * @param roleName the role to be assigned to the groups.
   * @param groupNames the list of groups to be added to the role,
   * @param update the corresponding permission delta update
   * @throws Exception
   */
  public synchronized void alterSentryRoleDeleteGroups(final String roleName,
      final Set<TSentryGroup> groupNames, final Update update)
          throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      String trimmedRoleName = trimAndLower(roleName);
      MSentryRole role = getRole(pm, trimmedRoleName);
      if (role == null) {
        throw noSuchRole(trimmedRoleName);
      }

      // Remove the group from the specified role if it belongs to the role.
      Query query = pm.newQuery(MSentryGroup.class);
      query.setFilter("this.groupName == :groupName");
      query.setUnique(true);
      List<MSentryGroup> groups = Lists.newArrayList();
      for (TSentryGroup tGroup : groupNames) {
        String groupName = tGroup.getGroupName().trim();
        MSentryGroup group = (MSentryGroup) query.execute(groupName);
        if (group != null) {
          group.removeRole(role);
          groups.add(group);
        }
      }
      pm.makePersistentAll(groups);
      return null;
    });
  }

  @VisibleForTesting
  public MSentryRole getMSentryRoleByName(final String roleName) throws Exception {
    return tm.executeTransaction(
            pm -> {
              String trimmedRoleName = trimAndLower(roleName);
              MSentryRole sentryRole = getRole(pm, trimmedRoleName);
              if (sentryRole == null) {
                throw noSuchRole(trimmedRoleName);
              }
              return sentryRole;
            });
  }

  /**
   * Gets the MSentryPrivilege from sentry persistent storage based on TSentryPrivilege
   * provided
   *
   * Method is currently used only in test framework
   * @param tPrivilege
   * @return MSentryPrivilege if the privilege is found in the storage
   * null, if the privilege is not found in the storage.
   * @throws Exception
   */
  @VisibleForTesting
  MSentryPrivilege findMSentryPrivilegeFromTSentryPrivilege(final TSentryPrivilege tPrivilege) throws Exception {
    return tm.executeTransaction(
            pm -> getMSentryPrivilege(tPrivilege, pm));
  }

  /**
   * Returns a list with all the privileges in the sentry persistent storage
   *
   * Method is currently used only in test framework
   * @return List of all sentry privileges in the store
   * @throws Exception
   */
  @VisibleForTesting
  List<MSentryPrivilege> getAllMSentryPrivileges () throws Exception {
    return tm.executeTransaction(
            pm -> getAllMSentryPrivilegesCore(pm));
  }

  /**
   * Method Returns all the privileges present in the persistent store as a list.
   * @param pm PersistenceManager
   * @returns list of all the privileges in the persistent store
   */
  private List<MSentryPrivilege> getAllMSentryPrivilegesCore (PersistenceManager pm) {
    Query query = pm.newQuery(MSentryPrivilege.class);
    return (List<MSentryPrivilege>) query.execute();
  }

  private boolean hasAnyServerPrivileges(final Set<String> roleNames, final String serverName) throws Exception {
    if (roleNames == null || roleNames.isEmpty()) {
      return false;
    }
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              Query query = pm.newQuery(MSentryPrivilege.class);
              query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
              QueryParamBuilder paramBuilder = QueryParamBuilder.addRolesFilter(query,null, roleNames);
              paramBuilder.add(SERVER_NAME, serverName);
              query.setFilter(paramBuilder.toString());
              query.setResult("count(this)");
              Long numPrivs = (Long) query.executeWithMap(paramBuilder.getArguments());
              return numPrivs > 0;
            });
  }

  private List<MSentryPrivilege> getMSentryPrivileges(final SentryPrincipalType entityType, final Set<String> entityNames,
      final TSentryAuthorizable authHierarchy, boolean enableFetchPlan)
      throws Exception {
    if (entityNames == null || entityNames.isEmpty()) {
      return Collections.emptyList();
    }

    return tm.executeTransaction(
        pm -> {
          Query query = pm.newQuery(MSentryPrivilege.class);
          QueryParamBuilder paramBuilder = null;
          if (entityType == SentryPrincipalType.ROLE) {
            paramBuilder = QueryParamBuilder.addRolesFilter(query, null, entityNames);
          } else if (entityType == SentryPrincipalType.USER) {
            paramBuilder = QueryParamBuilder.addUsersFilter(query, null, entityNames);
          } else {
            throw new SentryInvalidInputException("entityType" + entityType + " is not valid");
          }

          if (authHierarchy != null && authHierarchy.getServer() != null) {
            paramBuilder.add(SERVER_NAME, authHierarchy.getServer());
            if (authHierarchy.getDb() != null) {
              paramBuilder.addNull(URI)
                  .newChild()
                  .add(DB_NAME, authHierarchy.getDb())
                  .addNull(DB_NAME);
              if (authHierarchy.getTable() != null
                  && !AccessConstants.ALL.equalsIgnoreCase(authHierarchy.getTable())) {
                if (!AccessConstants.SOME.equalsIgnoreCase(authHierarchy.getTable())) {
                  paramBuilder.addNull(URI)
                      .newChild()
                      .add(TABLE_NAME, authHierarchy.getTable())
                      .addNull(TABLE_NAME);
                }
                if (authHierarchy.getColumn() != null
                    && !AccessConstants.ALL.equalsIgnoreCase(authHierarchy.getColumn())
                    && !AccessConstants.SOME.equalsIgnoreCase(authHierarchy.getColumn())) {
                  paramBuilder.addNull(URI)
                      .newChild()
                      .add(COLUMN_NAME, authHierarchy.getColumn())
                      .addNull(COLUMN_NAME);
                }
              }
            }
            if (authHierarchy.getUri() != null) {
              paramBuilder.addNull(DB_NAME)
                  .newChild()
                  .addNull(URI)
                  .newChild()
                  .addNotNull(URI)
                  .addCustomParam("(:authURI.startsWith(URI))", "authURI", authHierarchy.getUri());
            }
          }

          if(enableFetchPlan) {
              if (entityType == SentryPrincipalType.ROLE) {
                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRoles");
                  grp.addMember("roles");
                  pm.getFetchPlan().addGroup("fetchRoles");
              } else if (entityType == SentryPrincipalType.USER) {
                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchUsers");
                  grp.addMember("users");
                  pm.getFetchPlan().addGroup("fetchUsers");
              }
          }

          query.setFilter(paramBuilder.toString());
          @SuppressWarnings("unchecked")
          List<MSentryPrivilege> result =
              (List<MSentryPrivilege>)
                  query.executeWithMap(paramBuilder.getArguments());
          return result;
        });
  }

  private List<MSentryPrivilege> getMSentryPrivilegesByAuth(
      final SentryPrincipalType entityType,
      final Set<String> entityNames,
      final TSentryAuthorizable
      authHierarchy) throws Exception {
      return tm.executeTransaction(
              pm -> {
                Query query = pm.newQuery(MSentryPrivilege.class);
                QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();

                if (entityNames == null || entityNames.isEmpty()) {
                  if (entityType == SentryPrincipalType.ROLE) {
                    paramBuilder.addString("!roles.isEmpty()");
                  } else if (entityType == SentryPrincipalType.USER) {
                    paramBuilder.addString("!users.isEmpty()");
                  } else {
                    throw new SentryInvalidInputException("entityType: " + entityType + " is invalid");
                  }
                } else {
                  if (entityType == SentryPrincipalType.ROLE) {
                    QueryParamBuilder.addRolesFilter(query, paramBuilder, entityNames);
                  } else if (entityType == SentryPrincipalType.USER) {
                    QueryParamBuilder.addUsersFilter(query, paramBuilder, entityNames);
                  } else {
                    throw new SentryInvalidInputException("entityType" + entityType + " is not valid");
                  }
                }
                if (authHierarchy.getServer() != null) {
                  paramBuilder.add(SERVER_NAME, authHierarchy.getServer());
                  if (authHierarchy.getDb() != null) {
                    paramBuilder.add(DB_NAME, authHierarchy.getDb()).addNull(URI);
                    if (authHierarchy.getTable() != null) {
                      paramBuilder.add(TABLE_NAME, authHierarchy.getTable());
                    } else {
                      paramBuilder.addNull(TABLE_NAME);
                    }
                  } else if (authHierarchy.getUri() != null) {
                    paramBuilder.addNotNull(URI)
                            .addNull(DB_NAME)
                            .addCustomParam("(:authURI.startsWith(URI))", "authURI", authHierarchy.getUri());
                  } else {
                    paramBuilder.addNull(DB_NAME)
                          .addNull(URI);
                  }
                } else {
                  // if no server, then return empty result
                  return Collections.emptyList();
                }

                if (entityType == SentryPrincipalType.ROLE) {
                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRoles");
                  grp.addMember("roles");
                  pm.getFetchPlan().addGroup("fetchRoles");
                } else if(entityType == SentryPrincipalType.USER) {
                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchUsers");
                  grp.addMember("users");
                  pm.getFetchPlan().addGroup("fetchUsers");
                }

                query.setFilter(paramBuilder.toString());
                @SuppressWarnings("unchecked")
                List<MSentryPrivilege> result = (List<MSentryPrivilege>)query.
                        executeWithMap(paramBuilder.getArguments());
                return result;
              });
  }
  /**
   * List the Owner privileges for an authorizable
   * @param pm persistance manager
   * @param authHierarchy Authorizable
   * @return privilege list
   * @throws Exception
   */
  private List<MSentryPrivilege> getMSentryOwnerPrivilegesByAuth(PersistenceManager pm,
      final TSentryAuthorizable
      authHierarchy) throws Exception {
    Query query = pm.newQuery(MSentryPrivilege.class);
    QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
    if (authHierarchy.getServer() != null) {
      paramBuilder.add(SERVER_NAME, authHierarchy.getServer());
      if (authHierarchy.getDb() != null) {
        paramBuilder.add(DB_NAME, authHierarchy.getDb()).addNull(URI);
        if (authHierarchy.getTable() != null) {
          paramBuilder.add(TABLE_NAME, authHierarchy.getTable());
        } else {
          paramBuilder.addNull(TABLE_NAME);
        }
      } else if (authHierarchy.getUri() != null) {
        paramBuilder.addNotNull(URI)
                .addNull(DB_NAME)
                .addCustomParam("(:authURI.startsWith(URI))", "authURI", authHierarchy.getUri());
      } else {
        paramBuilder.addNull(DB_NAME)
                .addNull(URI);
      }
      paramBuilder.add(ACTION, AccessConstants.OWNER);
    } else {
      // if no server, then return empty result
      return Collections.emptyList();
    }
    query.setFilter(paramBuilder.toString());

    FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRolesUsers");
    grp.addMember("roles").addMember("users");
    pm.getFetchPlan().addGroup("fetchRolesUsers");

    @SuppressWarnings("unchecked")
    List<MSentryPrivilege> result = (List<MSentryPrivilege>) query.
            executeWithMap(paramBuilder.getArguments());
    return result;
  }

  private Set<MSentryPrivilege> getMSentryPrivilegesByUserName(String userName)
      throws Exception {
    MSentryUser mSentryUser = getMSentryUserByName(userName);
    return mSentryUser.getPrivileges();
  }

  /**
   * Gets sentry privilege objects for a given userName from the persistence layer
   * @param userName : userName to look up
   * @return : Set of thrift sentry privilege objects
   * @throws Exception
   */

  public Set<TSentryPrivilege> getAllTSentryPrivilegesByUserName(String userName)
      throws Exception {
    return convertToTSentryPrivileges(getMSentryPrivilegesByUserName(userName));
  }

  /**
   * Get all privileges associated with the authorizable and roles from input roles or input groups
   * @param groups the groups to get roles, then get their privileges
   * @param activeRoles the roles to get privileges
   * @param authHierarchy the authorizables
   * @param isAdmin true: user is admin; false: is not admin
   * @return the privilege map. The key is role name
   * @throws Exception
   */
  public TSentryPrivilegeMap listSentryPrivilegesByAuthorizable(Set<String> groups,
      TSentryActiveRoleSet activeRoles,
      TSentryAuthorizable authHierarchy, boolean isAdmin)
      throws Exception {
    Map<String, Set<TSentryPrivilege>> resultPrivilegeMap = Maps.newTreeMap();
    Set<String> roles = getRolesToQuery(groups, null, new TSentryActiveRoleSet(true, null));

    if (activeRoles != null && !activeRoles.isAll()) {
      // need to check/convert to lowercase here since this is from user input
      for (String aRole : activeRoles.getRoles()) {
        roles.add(aRole.toLowerCase());
      }
    }

    // An empty 'roles' is a treated as a wildcard (in case of admin role)..
    // so if not admin, don't return anything if 'roles' is empty..
    if (isAdmin || !roles.isEmpty()) {
      List<MSentryPrivilege> mSentryPrivileges =
          getMSentryPrivilegesByAuth(SentryPrincipalType.ROLE, roles, authHierarchy);
      for (MSentryPrivilege priv : mSentryPrivileges) {
        for (MSentryRole role : priv.getRoles()) {
          TSentryPrivilege tPriv = convertToTSentryPrivilege(priv);
          if (resultPrivilegeMap.containsKey(role.getRoleName())) {
            resultPrivilegeMap.get(role.getRoleName()).add(tPriv);
          } else {
            Set<TSentryPrivilege> tPrivSet = Sets.newTreeSet();
            tPrivSet.add(tPriv);
            resultPrivilegeMap.put(role.getRoleName(), tPrivSet);
          }
        }
      }
    }
    return new TSentryPrivilegeMap(resultPrivilegeMap);
  }

  /**
   * List the Owners for an authorizable
   * @param authorizable Authorizable
   * @return List of owner for an authorizable
   * @throws Exception
   */
  public List<SentryOwnerInfo> listOwnersByAuthorizable(TSentryAuthorizable authorizable)
          throws Exception {
    List<SentryOwnerInfo> ownerInfolist = new ArrayList<>();
    return tm.executeTransaction(
            pm -> {
              List<MSentryPrivilege> mSentryPrivileges =
                      getMSentryOwnerPrivilegesByAuth(pm, authorizable);
              for (MSentryPrivilege priv : mSentryPrivileges) {
                for (PrivilegePrincipal user : priv.getUsers()) {
                  ownerInfolist.add(new SentryOwnerInfo(user.getPrincipalType(), user.getPrincipalName()));
                }
                for (PrivilegePrincipal role : priv.getRoles()) {
                  ownerInfolist.add(new SentryOwnerInfo(role.getPrincipalType(), role.getPrincipalName()));
                }
              }
              return ownerInfolist;
            });
  }

  /**
   * Get all privileges associated with the authorizable and input users
   * @param userNames the users to get their privileges
   * @param authHierarchy the authorizables
   * @param isAdmin true: user is admin; false: is not admin
   * @return the privilege map. The key is user name
   * @throws Exception
   */
  public TSentryPrivilegeMap listSentryPrivilegesByAuthorizableForUser(Set<String> userNames,
      TSentryAuthorizable authHierarchy, boolean isAdmin)
      throws Exception {
    Map<String, Set<TSentryPrivilege>> resultPrivilegeMap = Maps.newTreeMap();

    // An empty 'userNames' is a treated as a wildcard (in case of admin role)..
    // so if not admin, don't return anything if 'roles' is empty..
    if (isAdmin || ((userNames != null) && (!userNames.isEmpty()))) {
      List<MSentryPrivilege> mSentryPrivileges =
          getMSentryPrivilegesByAuth(SentryPrincipalType.USER, userNames, authHierarchy);
      for (MSentryPrivilege priv : mSentryPrivileges) {
        for (MSentryUser user : priv.getUsers()) {
          TSentryPrivilege tPriv = convertToTSentryPrivilege(priv);
          if (resultPrivilegeMap.containsKey(user.getUserName())) {
            resultPrivilegeMap.get(user.getUserName()).add(tPriv);
          } else {
            Set<TSentryPrivilege> tPrivSet = Sets.newTreeSet();
            tPrivSet.add(tPriv);
            resultPrivilegeMap.put(user.getUserName(), tPrivSet);
          }
        }
      }
    }
    return new TSentryPrivilegeMap(resultPrivilegeMap);
  }


  private Set<MSentryPrivilege> getMSentryPrivilegesByRoleName(String roleName)
      throws Exception {
    MSentryRole mSentryRole = getMSentryRoleByName(roleName);
    return mSentryRole.getPrivileges();
  }

  /**
   * Gets sentry privilege objects for a given roleName from the persistence layer
   * @param roleName : roleName to look up
   * @return : Set of thrift sentry privilege objects
   * @throws Exception
   */

  public Set<TSentryPrivilege> getAllTSentryPrivilegesByRoleName(String roleName)
      throws Exception {
    return convertToTSentryPrivileges(getMSentryPrivilegesByRoleName(roleName));
  }


  /**
   * Gets sentry privilege objects for criteria from the persistence layer
   * @param principalType : the type of the principalprincipal (required)
   * @param principalNames : principal names to look up (required)
   * @param authHierarchy : filter push down based on auth hierarchy (optional)
   * @return : Set of thrift sentry privilege objects
   * @throws SentryInvalidInputException
   */

  public Set<TSentryPrivilege> getTSentryPrivileges(SentryPrincipalType principalType, Set<String> principalNames,
                                                    TSentryAuthorizable authHierarchy)
          throws Exception {
    if (authHierarchy.getServer() == null) {
      throw new SentryInvalidInputException("serverName cannot be null !!");
    }
    if (authHierarchy.getTable() != null && authHierarchy.getDb() == null) {
      throw new SentryInvalidInputException("dbName cannot be null when tableName is present !!");
    }
    if (authHierarchy.getColumn() != null && authHierarchy.getTable() == null) {
      throw new SentryInvalidInputException("tableName cannot be null when columnName is present !!");
    }
    if (authHierarchy.getUri() == null && authHierarchy.getDb() == null) {
      throw new SentryInvalidInputException("One of uri or dbName must not be null !!");
    }
    return convertToTSentryPrivileges(getMSentryPrivileges(principalType, principalNames, authHierarchy, true));
  }

  /**
   * Return set of roles corresponding to the groups provided.<p>
   *
   * If groups contain a null group, return all available roles.<p>
   *
   * Everything is done in a single transaction so callers get a
   * fully-consistent view of the roles, so this can be called at the same tie as
   * some other method that modifies groups or roles.<p>
   *
   * <em><b>NOTE:</b> This function is performance-critical, so before you modify it, make
   * sure to measure performance effect. It is called every time when PolicyClient
   * (Hive or Impala) tries to get list of roles.
   * </em>
   *
   * @param groupNames Set of Sentry groups. Can contain {@code null}
   *                  in which case all roles should be returned
   * @param checkAllGroups If false, raise SentryNoSuchObjectException
   *                      if one of the groups is not available, otherwise
   *                      ignore non-existent groups
   * @return Set of TSentryRole toles corresponding to the given set of groups.
   * @throws SentryNoSuchObjectException if one of the groups is not present and
   * checkAllGroups is not set.
   * @throws Exception if DataNucleus operation fails.
   */
  public Set<TSentryRole> getTSentryRolesByGroupName(final Set<String> groupNames,
                                                     final boolean checkAllGroups) throws Exception {
    if (groupNames.isEmpty()) {
      return Collections.emptySet();
    }

    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects

              // Pre-allocate large sets for role names and results.
              // roleNames is used to avoid adding the same role mutiple times into
              // result. The result is set, but comparisons between TSentryRole objects
              // is more expensive then String comparisons.
              Set<String> roleNames = new HashSet<>(1024);
              Set<TSentryRole> result = new HashSet<>(1024);

              for(String group: groupNames) {
                if (group == null) {
                  // Special case - return all roles
                  List<MSentryRole> roles = getAllRoles(pm);
                  for (MSentryRole role: roles) {
                    result.add(convertToTSentryRole(role));
                  }
                  return result;
                }

                // Find group by name and all roles belonging to this group
                String trimmedGroup = group.trim();
                Query query = pm.newQuery(MSentryGroup.class);
                query.setFilter("this.groupName == :groupName");
                query.setUnique(true);

                FetchGroup grp = pm.getFetchGroup(MSentryGroup.class, "fetchRoles");
                grp.addMember("roles");
                pm.getFetchPlan().addGroup("fetchRoles");

                MSentryGroup mGroup = (MSentryGroup) query.execute(trimmedGroup);
                //TODO - Below is not optimized
                if (mGroup != null) {
                  // For each unique role found, add a new TSentryRole version of the role to result.
                  for (MSentryRole role: mGroup.getRoles()) {
                    String roleName = role.getRoleName();
                    if (roleNames.add(roleName)) {
                      result.add(convertToTSentryRole(role));
                    }
                  }
                } else if (!checkAllGroups) {
                    throw noSuchGroup(trimmedGroup);
                }
                query.closeAll();
              }
              return result;
            });
  }

  public Set<String> getRoleNamesForGroups(final Set<String> groups) throws Exception {
    if ((groups == null) || groups.isEmpty()) {
      return ImmutableSet.of();
    }

    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return getRoleNamesForGroupsCore(pm, groups);
            });
  }

  private Set<String> getRoleNamesForGroupsCore(PersistenceManager pm, Set<String> groups) {
    return convertToRoleNameSet(getRolesForGroups(pm, groups));
  }

  public Set<String> getRoleNamesForUsers(final Set<String> users) throws Exception {
    if ((users == null) || users.isEmpty()) {
      return ImmutableSet.of();
    }

    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return getRoleNamesForUsersCore(pm,users);
            });
  }

  private Set<String> getRoleNamesForUsersCore(PersistenceManager pm, Set<String> users) {
    return convertToRoleNameSet(getRolesForUsers(pm, users));
  }

  public Set<TSentryRole> getTSentryRolesByUserNames(final Set<String> users)
          throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              Set<MSentryRole> mSentryRoles = getRolesForUsers(pm, users);
              // Since {@link MSentryRole#getGroups()} is lazy-loading,
              // the conversion should be done before transaction is committed.
              return convertToTSentryRoles(mSentryRoles);
              });
  }

  public Set<MSentryRole> getRolesForGroups(PersistenceManager pm, Set<String> groups) {
    Set<MSentryRole> result = Sets.newHashSet();
    if (groups != null) {
      Query query = pm.newQuery(MSentryGroup.class);
      query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
      query.setFilter(":p1.contains(this.groupName)");

      FetchGroup grp = pm.getFetchGroup(MSentryGroup.class, "fetchRoles");
      grp.addMember("roles");
      pm.getFetchPlan().addGroup("fetchRoles");

      List<MSentryGroup> sentryGroups = (List) query.execute(groups.toArray());
      if (sentryGroups != null) {
        for (MSentryGroup sentryGroup : sentryGroups) {
          result.addAll(sentryGroup.getRoles());
        }
      }
    }
    return result;
  }

  private Set<MSentryRole> getRolesForUsers(PersistenceManager pm, Set<String> users) {
    Set<MSentryRole> result = Sets.newHashSet();
    if (users != null) {
      Query query = pm.newQuery(MSentryUser.class);
      query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
      query.setFilter(":p1.contains(this.userName)");

      FetchGroup grp = pm.getFetchGroup(MSentryUser.class, "fetchRoles");
      grp.addMember("roles");
      pm.getFetchPlan().addGroup("fetchRoles");

      List<MSentryUser> sentryUsers = (List) query.execute(users.toArray());
      if (sentryUsers != null) {
        for (MSentryUser sentryUser : sentryUsers) {
          result.addAll(sentryUser.getRoles());
        }
      }
    }
    return result;
  }

  @Override
  public Set<TSentryPrivilege> listSentryPrivilegesByUsersAndGroups(
      Set<String> groups, Set<String> users, TSentryActiveRoleSet roleSet,
      TSentryAuthorizable authHierarchy) throws Exception {
    return convertToTSentryPrivileges(listSentryPrivilegesForProviderCore(
        groups, users, roleSet, authHierarchy));
  }

  Set<String> listAllSentryPrivilegesForProvider(
      Set<String> groups, Set<String> users,
      TSentryActiveRoleSet roleSet) throws Exception {
    return listSentryPrivilegesForProvider(groups, users, roleSet, null);
  }

  public Set<String> listSentryPrivilegesForProvider(
      Set<String> groups, Set<String> users, TSentryActiveRoleSet roleSet,
      TSentryAuthorizable authHierarchy) throws Exception {
    Set<String> result = Sets.newHashSet();
    Set<MSentryPrivilege> mSentryPrivileges = listSentryPrivilegesForProviderCore(
        groups, users, roleSet, authHierarchy);
    for (MSentryPrivilege priv : mSentryPrivileges) {
      result.add(toAuthorizable(priv));
    }
    return result;
  }

  private Set<MSentryPrivilege> listSentryPrivilegesForProviderCore(Set<String> groups, Set<String> users,
      TSentryActiveRoleSet roleSet, TSentryAuthorizable authHierarchy) throws Exception {
    Set<MSentryPrivilege> privilegeSet = Sets.newHashSet();
    Set<String> rolesToQuery = getRolesToQuery(groups, users, roleSet);
    privilegeSet.addAll(getMSentryPrivileges(SentryPrincipalType.ROLE, rolesToQuery, authHierarchy, false));
    privilegeSet.addAll(getMSentryPrivileges(SentryPrincipalType.USER, users, authHierarchy, false));
    return privilegeSet;
  }

  public boolean hasAnyServerPrivileges(Set<String> groups, Set<String> users,
      TSentryActiveRoleSet roleSet, String server) throws Exception {
    Set<String> rolesToQuery = getRolesToQuery(groups, users, roleSet);
    if (hasAnyServerPrivileges(rolesToQuery, server)) {
      return true;
    }

    return hasAnyServerPrivilegesForUser(users, server);
  }

  private boolean hasAnyServerPrivilegesForUser(final Set<String> userNames, final String serverName) throws Exception {
    if (userNames == null || userNames.isEmpty()) {
      return false;
    }
    return tm.executeTransaction(
        new TransactionBlock<Boolean>() {
          public Boolean execute(PersistenceManager pm) throws Exception {
            pm.setDetachAllOnCommit(false); // No need to detach objects
            Query query = pm.newQuery(MSentryPrivilege.class);
            query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
            QueryParamBuilder paramBuilder = QueryParamBuilder.addUsersFilter(query,null, userNames);
            paramBuilder.add(SERVER_NAME, serverName);
            query.setFilter(paramBuilder.toString());
            query.setResult("count(this)");
            Long numPrivs = (Long) query.executeWithMap(paramBuilder.getArguments());
            return numPrivs > 0;
          }
        });
  }

  private Set<String> getRolesToQuery(final Set<String> groups, final Set<String> users,
      final TSentryActiveRoleSet roleSet) throws Exception {
      return tm.executeTransaction(
              pm -> {
                pm.setDetachAllOnCommit(false); // No need to detach objects
                Set<String> activeRoleNames = toTrimedLower(roleSet.getRoles());

                Set<String> roleNames = Sets.newHashSet();
                roleNames.addAll(toTrimedLower(getRoleNamesForGroupsCore(pm, groups)));
                roleNames.addAll(toTrimedLower(getRoleNamesForUsersCore(pm, users)));
                return roleSet.isAll() ? roleNames : Sets.intersection(activeRoleNames,
                    roleNames);
              });
  }

  @VisibleForTesting
  static String toAuthorizable(MSentryPrivilege privilege) {
    List<String> authorizable = new ArrayList<>(4);
    authorizable.add(KV_JOINER.join(AuthorizableType.Server.name().toLowerCase(),
        privilege.getServerName()));
    if (isNULL(privilege.getURI())) {
      if (!isNULL(privilege.getDbName())) {
        authorizable.add(KV_JOINER.join(AuthorizableType.Db.name().toLowerCase(),
            privilege.getDbName()));
        if (!isNULL(privilege.getTableName())) {
          authorizable.add(KV_JOINER.join(AuthorizableType.Table.name().toLowerCase(),
              privilege.getTableName()));
          if (!isNULL(privilege.getColumnName())) {
            authorizable.add(KV_JOINER.join(AuthorizableType.Column.name().toLowerCase(),
                privilege.getColumnName()));
          }
        }
      }
    } else {
      authorizable.add(KV_JOINER.join(AuthorizableType.URI.name().toLowerCase(),
          privilege.getURI()));
    }
    if (!isNULL(privilege.getAction())
        && !privilege.getAction().equalsIgnoreCase(AccessConstants.ALL)) {
      authorizable
      .add(KV_JOINER.join(SentryConstants.PRIVILEGE_NAME.toLowerCase(),
          privilege.getAction()));
    }

    if (privilege.getGrantOption()) {
      // include grant option field when it is true
      authorizable
          .add(KV_JOINER.join(SentryConstants.GRANT_OPTION.toLowerCase(),
              privilege.getGrantOption()));
    }

    return AUTHORIZABLE_JOINER.join(authorizable);
  }

  @VisibleForTesting
  public static Set<String> toTrimedLower(Set<String> s) {
    if (s == null || s.isEmpty()) {
      return Collections.emptySet();
    }

    Set<String> result = Sets.newHashSet();
    for (String v : s) {
      result.add(v.trim().toLowerCase());
    }
    return result;
  }


  /**
   * Converts model object(s) to thrift object(s).
   * Additionally does normalization
   * such as trimming whitespace and setting appropriate case. Also sets the create
   * time.
   */

  private Set<TSentryPrivilege> convertToTSentryPrivileges(Collection<MSentryPrivilege> mSentryPrivileges) {
    if (mSentryPrivileges.isEmpty()) {
      return Collections.emptySet();
    }
    Set<TSentryPrivilege> privileges = new HashSet<>(mSentryPrivileges.size());
    for(MSentryPrivilege mSentryPrivilege:mSentryPrivileges) {
      privileges.add(convertToTSentryPrivilege(mSentryPrivilege));
    }
    return privileges;
  }

  private Set<TSentryRole> convertToTSentryRoles(Set<MSentryRole> mSentryRoles) {
    if (mSentryRoles.isEmpty()) {
      return Collections.emptySet();
    }
    Set<TSentryRole> roles = new HashSet<>(mSentryRoles.size());
    for(MSentryRole mSentryRole:mSentryRoles) {
      roles.add(convertToTSentryRole(mSentryRole));
    }
    return roles;
  }

  private Set<String> convertToRoleNameSet(Set<MSentryRole> mSentryRoles) {
    if (mSentryRoles.isEmpty()) {
      return Collections.emptySet();
    }
    Set<String> roleNameSet = new HashSet<>(mSentryRoles.size());
    for (MSentryRole role : mSentryRoles) {
      roleNameSet.add(role.getRoleName());
    }
    return roleNameSet;
  }

  private TSentryRole convertToTSentryRole(MSentryRole mSentryRole) {
    String roleName = mSentryRole.getRoleName().intern();
    Set<MSentryGroup> groups = mSentryRole.getGroups();
    Set<TSentryGroup> sentryGroups = new HashSet<>(groups.size());
    for(MSentryGroup mSentryGroup: groups) {
      TSentryGroup group = convertToTSentryGroup(mSentryGroup);
      sentryGroups.add(group);
    }

    return new TSentryRole(roleName, sentryGroups, EMPTY_GRANTOR_PRINCIPAL);
  }

  private TSentryGroup convertToTSentryGroup(MSentryGroup mSentryGroup) {
    return new TSentryGroup(mSentryGroup.getGroupName().intern());
  }

  TSentryPrivilege convertToTSentryPrivilege(MSentryPrivilege mSentryPrivilege) {
    TSentryPrivilege privilege = new TSentryPrivilege();
    convertToTSentryPrivilege(mSentryPrivilege, privilege);
    return privilege;
  }

  private void convertToTSentryPrivilege(MSentryPrivilege mSentryPrivilege,
      TSentryPrivilege privilege) {
    privilege.setCreateTime(mSentryPrivilege.getCreateTime());
    privilege.setAction(fromNULLCol(mSentryPrivilege.getAction()));
    privilege.setPrivilegeScope(mSentryPrivilege.getPrivilegeScope());
    privilege.setServerName(fromNULLCol(mSentryPrivilege.getServerName()));
    privilege.setDbName(fromNULLCol(mSentryPrivilege.getDbName()));
    privilege.setTableName(fromNULLCol(mSentryPrivilege.getTableName()));
    privilege.setColumnName(fromNULLCol(mSentryPrivilege.getColumnName()));
    privilege.setURI(fromNULLCol(mSentryPrivilege.getURI()));
    if (mSentryPrivilege.getGrantOption() != null) {
      privilege.setGrantOption(TSentryGrantOption.valueOf(mSentryPrivilege.getGrantOption().toString().toUpperCase()));
    } else {
      privilege.setGrantOption(TSentryGrantOption.UNSET);
    }
  }

  /**
   * Converts thrift object to model object. Additionally does normalization
   * such as trimming whitespace and setting appropriate case.
   * @throws SentryInvalidInputException
   */
  private MSentryPrivilege convertToMSentryPrivilege(TSentryPrivilege privilege)
      throws SentryInvalidInputException {
    MSentryPrivilege mSentryPrivilege = new MSentryPrivilege();
    mSentryPrivilege.setServerName(toNULLCol(safeTrimLower(privilege.getServerName())));
    mSentryPrivilege.setDbName(toNULLCol(safeTrimLower(privilege.getDbName())));
    mSentryPrivilege.setTableName(toNULLCol(safeTrimLower(privilege.getTableName())));
    mSentryPrivilege.setColumnName(toNULLCol(safeTrimLower(privilege.getColumnName())));
    mSentryPrivilege.setPrivilegeScope(safeTrim(privilege.getPrivilegeScope()));
    mSentryPrivilege.setAction(toNULLCol(safeTrimLower(privilege.getAction())));
    mSentryPrivilege.setCreateTime(System.currentTimeMillis());
    mSentryPrivilege.setURI(toNULLCol(safeTrim(privilege.getURI())));
    if ( !privilege.getGrantOption().equals(TSentryGrantOption.UNSET) ) {
      mSentryPrivilege.setGrantOption(Boolean.valueOf(privilege.getGrantOption().toString()));
    } else {
      mSentryPrivilege.setGrantOption(null);
    }
    return mSentryPrivilege;
  }

  static String safeTrim(String s) {
    if (s == null) {
      return null;
    }
    return s.trim();
  }

  static String safeTrimLower(String s) {
    if (s == null) {
      return null;
    }
    return s.trim().toLowerCase();
  }

  String getSentryVersion() throws Exception {
    MSentryVersion mVersion = getMSentryVersion();
    return mVersion.getSchemaVersion();
  }

  void setSentryVersion(final String newVersion, final String verComment)
      throws Exception {
    tm.executeTransaction(
            pm -> {
              MSentryVersion mVersion;
              try {
                mVersion = getMSentryVersion();
                if (newVersion.equals(mVersion.getSchemaVersion())) {
                  // specified version already in there
                  return null;
                }
              } catch (SentryNoSuchObjectException e) {
                // if the version doesn't exist, then create it
                mVersion = new MSentryVersion();
              }
              mVersion.setSchemaVersion(newVersion);
              mVersion.setVersionComment(verComment);
              pm.makePersistent(mVersion);
              return null;
            });
  }

  private MSentryVersion getMSentryVersion() throws Exception {
    return tm.executeTransaction(
            pm -> {
              try {
                Query query = pm.newQuery(MSentryVersion.class);
                @SuppressWarnings("unchecked")
                List<MSentryVersion> mSentryVersions = (List<MSentryVersion>) query
                    .execute();
                pm.retrieveAll(mSentryVersions);
                if (mSentryVersions.isEmpty()) {
                  throw new SentryNoSuchObjectException("Matching Version");
                }
                if (mSentryVersions.size() > 1) {
                  throw new SentryAccessDeniedException(
                      "Metastore contains multiple versions");
                }
                return mSentryVersions.get(0);
              } catch (JDODataStoreException e) {
                if (e.getCause() instanceof MissingTableException) {
                  throw new SentryAccessDeniedException("Version table not found. "
                      + "The sentry store is not set or corrupt ");
                } else {
                  throw e;
                }
              }
            });
  }

  /**
   * Drop the given privilege from all entities.
   *
   * @param tAuthorizable the given authorizable object.
   * @throws Exception
   */
  public void dropPrivilege(final TSentryAuthorizable tAuthorizable) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects

              dropPrivilegeCore(pm, tAuthorizable);

              return null;
            });
  }

  /**
   * Drop the given privilege from all entities. As well as persist the corresponding
   * permission change to MSentryPermChange table in a single transaction.
   *
   * @param tAuthorizable the given authorizable object.
   * @param update the corresponding permission delta update.
   * @throws Exception
   */
  public synchronized void dropPrivilege(final TSentryAuthorizable tAuthorizable,
      final Update update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects

      dropPrivilegeCore(pm, tAuthorizable);

      return null;
    });
  }

  private void dropPrivilegeCore(PersistenceManager pm, TSentryAuthorizable tAuthorizable) throws Exception {

    // Drop the give privilege for all possible actions from all entities.
    TSentryPrivilege tPrivilege = toSentryPrivilege(tAuthorizable);
    tPrivilege.setGrantOption(TSentryGrantOption.UNSET);

    try {
      if (isMultiActionsSupported(tPrivilege)) {
        for (String privilegeAction : ALL_ACTIONS) {
          tPrivilege.setAction(privilegeAction);
          dropPrivilegeForAllEntities(pm, new TSentryPrivilege(tPrivilege));
        }
      } else {
        dropPrivilegeForAllEntities(pm, new TSentryPrivilege(tPrivilege));
      }
    } catch (JDODataStoreException e) {
      throw new SentryInvalidInputException("Failed to get privileges: "
          + e.getMessage());
    }
  }

  /**
   * Updates the owner privileges by revoking owner privileges to an authorizable and adding new
   * privilege based on the arguments provided.
   * @param tAuthorizable Authorizable to which owner privilege should be granted.
   * @param ownerName
   * @param principalType
   * @param updates Delta Updates.
   * @throws Exception
   */
  public synchronized void updateOwnerPrivilege(final TSentryAuthorizable tAuthorizable,
      String ownerName,  SentryPrincipalType principalType,
      final List<Update> updates) throws Exception {
    execute(updates, pm -> {
      if(principalType == null) {
        LOGGER.info("Invalid principal Type");
      }
      pm.setDetachAllOnCommit(false); // No need to detach objects
      TSentryPrivilege tOwnerPrivilege = toSentryPrivilege(tAuthorizable);
      tOwnerPrivilege.setAction(AccessConstants.OWNER);

      revokeOwnerPrivilegesCore(pm, tAuthorizable);

      try {
        if(ownerPrivilegeWithGrant) {
          tOwnerPrivilege.setGrantOption(TSentryGrantOption.TRUE);
        }
        //Granting the privilege.
        alterSentryGrantPrivilegeCore(pm, principalType, ownerName, tOwnerPrivilege);
        return null;
      } catch (JDODataStoreException e) {
        throw new SentryInvalidInputException("Failed to grant owner privilege on Authorizable : " +
                tAuthorizable.toString() + " to " + principalType.toString() + ": " + ownerName + " "
                + e.getMessage());
      }
    });
  }

  /**
   * Revokes all the owner privileges granted to an authorizable
   * @param tAuthorizable authorizable for which owner privilege should be revoked.
   * @param updates
   * @throws Exception
   */
  @VisibleForTesting
  void revokeOwnerPrivileges(final TSentryAuthorizable tAuthorizable, final List<Update> updates)
     throws Exception{
    execute(updates, pm -> {
      pm.setDetachAllOnCommit(false);
      revokeOwnerPrivilegesCore(pm, tAuthorizable);
      return null;
    });
  }

  public void revokeOwnerPrivilegesCore(PersistenceManager pm, final TSentryAuthorizable tAuthorizable)
      throws Exception{
    TSentryPrivilege tOwnerPrivilege = toSentryPrivilege(tAuthorizable);
    tOwnerPrivilege.setAction(AccessConstants.OWNER);

    // Finding owner privileges and removing them.
    List<MSentryPrivilege> mOwnerPrivileges = getMSentryPrivilegesExactMatch(tOwnerPrivilege, pm);
    for(MSentryPrivilege mOwnerPriv : mOwnerPrivileges) {
      Set<MSentryUser> users;
      users = mOwnerPriv.getUsers();
      // Making sure of removing stale users.
      for (MSentryUser user : users) {
        user.removePrivilege(mOwnerPriv);
        persistEntity(pm, SentryPrincipalType.USER, user);
      }
    }
    pm.deletePersistentAll(mOwnerPrivileges);
  }

  /**
   * Rename the privilege for all entities. Drop the old privilege name and create the new one.
   *
   * @param oldTAuthorizable the old authorizable name needs to be renamed.
   * @param newTAuthorizable the new authorizable name
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  public void renamePrivilege(final TSentryAuthorizable oldTAuthorizable,
      final TSentryAuthorizable newTAuthorizable) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects

              renamePrivilegeCore(pm, oldTAuthorizable, newTAuthorizable);
              return null;
            });
  }

  /**
   * Rename the privilege for all entities. Drop the old privilege name and create the new one.
   * As well as persist the corresponding permission change to MSentryPermChange table in a
   * single transaction.
   *
   * @param oldTAuthorizable the old authorizable name needs to be renamed.
   * @param newTAuthorizable the new authorizable name
   * @param update the corresponding permission delta update.
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  public synchronized void renamePrivilege(final TSentryAuthorizable oldTAuthorizable,
      final TSentryAuthorizable newTAuthorizable, final Update update)
        throws Exception {

    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects

      renamePrivilegeCore(pm, oldTAuthorizable, newTAuthorizable);
      return null;
    });
  }

  private void renamePrivilegeCore(PersistenceManager pm, TSentryAuthorizable oldTAuthorizable,
      final TSentryAuthorizable newTAuthorizable) throws Exception {
    TSentryPrivilege tPrivilege = toSentryPrivilege(oldTAuthorizable);
    TSentryPrivilege newPrivilege = toSentryPrivilege(newTAuthorizable);

    tPrivilege.setGrantOption(TSentryGrantOption.FALSE);
    newPrivilege.setGrantOption(TSentryGrantOption.FALSE);
    renamePrivilegeCore(pm, tPrivilege, newPrivilege);

    tPrivilege.setGrantOption(TSentryGrantOption.TRUE);
    newPrivilege.setGrantOption(TSentryGrantOption.TRUE);
    renamePrivilegeCore(pm, tPrivilege, newPrivilege);
  }

  private void renamePrivilegeCore(PersistenceManager pm, TSentryPrivilege tPrivilege,
      final TSentryPrivilege newPrivilege) throws Exception {

    try {
      // In case of tables or DBs, check all actions
      if (isMultiActionsSupported(tPrivilege)) {
        for (String privilegeAction : ALL_ACTIONS) {
          tPrivilege.setAction(privilegeAction);
          newPrivilege.setAction(privilegeAction);
          renamePrivilegeForAllEntities(pm, tPrivilege, newPrivilege);
        }
      } else {
        renamePrivilegeForAllEntities(pm, tPrivilege, newPrivilege);
      }
    } catch (JDODataStoreException e) {
      throw new SentryInvalidInputException("Failed to get privileges: "
          + e.getMessage());
    }
  }

  // Currently INSERT/SELECT/ALL are supported for Table and DB level privileges
  private boolean isMultiActionsSupported(TSentryPrivilege tPrivilege) {
    return tPrivilege.getDbName() != null;

  }
  // wrapper for dropOrRename
  private void renamePrivilegeForAllEntities(PersistenceManager pm,
      TSentryPrivilege tPrivilege,
      TSentryPrivilege newPrivilege) throws SentryNoSuchObjectException,
      SentryInvalidInputException {
    dropOrRenamePrivilegeForAllEntities(pm, tPrivilege, newPrivilege);
  }

  /**
   * Drop given privilege from all entities
   * @param tPrivilege
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  private void dropPrivilegeForAllEntities(PersistenceManager pm,
      TSentryPrivilege tPrivilege)
      throws SentryNoSuchObjectException, SentryInvalidInputException {
    dropOrRenamePrivilegeForAllEntities(pm, tPrivilege, null);
  }

  /**
   * Drop given privilege from all entities Create the new privilege if asked
   * @param tPrivilege
   * @param pm
   * @throws SentryNoSuchObjectException
   * @throws SentryInvalidInputException
   */
  private void dropOrRenamePrivilegeForAllEntities(PersistenceManager pm,
      TSentryPrivilege tPrivilege,
      TSentryPrivilege newTPrivilege) throws SentryNoSuchObjectException,
      SentryInvalidInputException {
    Collection<PrivilegePrincipal> entitySet = new HashSet<>();
    List<MSentryPrivilege> mPrivileges = getMSentryPrivileges(tPrivilege, pm);
    for (MSentryPrivilege mPrivilege : mPrivileges) {
      entitySet.addAll(ImmutableSet.copyOf(mPrivilege.getRoles()));
      entitySet.addAll(ImmutableSet.copyOf(mPrivilege.getUsers()));
    }
    // Dropping the privilege
    if (newTPrivilege == null) {
      for (PrivilegePrincipal principal : entitySet) {
        alterSentryRevokePrivilegeCore(pm, principal.getPrincipalType(), principal.getPrincipalName(), tPrivilege);
      }
      return;
    }
    // Renaming privilege
    MSentryPrivilege parent = getMSentryPrivilege(tPrivilege, pm);
    if (parent != null) {
      // When all the roles associated with that privilege are revoked, privilege
      // will be removed from the database.
      // parent is an JDO object which is associated with privilege data in the database.
      // When the associated row is deleted in database, JDO should be not be
      // dereferenced. If object has to be used even after that it should have been detached.
      parent = pm.detachCopy(parent);
    }
    for (PrivilegePrincipal principal : entitySet) {
      // When all the privilege associated for a user are revoked, user will be removed from the database.
      // JDO object should be not used when the associated database entry is removed. Application should use
      // a detached copy instead.
      PrivilegePrincipal detachedEntity = pm.detachCopy(principal);
      // 1. get privilege and child privileges
      Collection<MSentryPrivilege> privilegeGraph = new HashSet<>();
      if (parent != null) {
        privilegeGraph.add(parent);
        populateChildren(pm, detachedEntity.getPrincipalType(), Sets.newHashSet(detachedEntity.getPrincipalName()), parent, privilegeGraph);
      } else {
        populateChildren(pm, detachedEntity.getPrincipalType(), Sets.newHashSet(detachedEntity.getPrincipalName()), convertToMSentryPrivilege(tPrivilege),
          privilegeGraph);
      }
      // 2. revoke privilege and child privileges
      alterSentryRevokePrivilegeCore(pm, detachedEntity.getPrincipalType(), detachedEntity.getPrincipalName(), tPrivilege);
      // 3. add new privilege and child privileges with new tableName
      for (MSentryPrivilege mPriv : privilegeGraph) {
        TSentryPrivilege tPriv = convertToTSentryPrivilege(mPriv);
        if (newTPrivilege.getPrivilegeScope().equals(PrivilegeScope.DATABASE.name())) {
          tPriv.setDbName(newTPrivilege.getDbName());
        } else if (newTPrivilege.getPrivilegeScope().equals(PrivilegeScope.TABLE.name())) {
          // the DB name could change, so set its value
          tPriv.setDbName(newTPrivilege.getDbName());
          tPriv.setTableName(newTPrivilege.getTableName());
        }
        alterSentryGrantPrivilegeCore(pm, detachedEntity.getPrincipalType(), detachedEntity.getPrincipalName(), tPriv);
      }
    }
  }

  private TSentryPrivilege toSentryPrivilege(TSentryAuthorizable tAuthorizable)
      throws SentryInvalidInputException {
    TSentryPrivilege tSentryPrivilege = new TSentryPrivilege();
    tSentryPrivilege.setDbName(fromNULLCol(tAuthorizable.getDb()));
    tSentryPrivilege.setServerName(fromNULLCol(tAuthorizable.getServer()));
    tSentryPrivilege.setTableName(fromNULLCol(tAuthorizable.getTable()));
    tSentryPrivilege.setColumnName(fromNULLCol(tAuthorizable.getColumn()));
    tSentryPrivilege.setURI(fromNULLCol(tAuthorizable.getUri()));
    PrivilegeScope scope;
    if (!isNULL(tSentryPrivilege.getColumnName())) {
      scope = PrivilegeScope.COLUMN;
    } else if (!isNULL(tSentryPrivilege.getTableName())) {
      scope = PrivilegeScope.TABLE;
    } else if (!isNULL(tSentryPrivilege.getDbName())) {
      scope = PrivilegeScope.DATABASE;
    } else if (!isNULL(tSentryPrivilege.getURI())) {
      scope = PrivilegeScope.URI;
    } else {
      scope = PrivilegeScope.SERVER;
    }
    tSentryPrivilege.setPrivilegeScope(scope.name());
    tSentryPrivilege.setAction(AccessConstants.ALL);
    return tSentryPrivilege;
  }

  /**
   * <p>
   * Convert different forms of empty strings to @NULL_COL and return all other input strings unmodified.
   * <p>
   * Possible empty strings:
   * <ul>
   *   <li>null</li>
   *   <li>empty string ("")</li>
   * </ul>
   * <p>
   * This function is used to create proper MSentryPrivilege objects that are saved in the Sentry database from the user
   * supplied privileges (TSentryPrivilege). This function will ensure that the data we are putting into the database is
   * always consistent for various types of input from the user. Without this one can save a column as an empty string
   * or null or @NULL_COLL specifier.
   * <p>
   * @param s string input, and can be null.
   * @return original string if it is non-empty and @NULL_COL for empty strings.
   */
  public static String toNULLCol(String s) {
    return Strings.isNullOrEmpty(s) ? NULL_COL : s;
  }

  /**
   * <p>
   * Convert different forms of empty strings to an empty string("") and return all other input strings unmodified.
   * <p>
   * Possible empty strings:
   * <ul>
   *   <li>null</li>
   *   <li>empty string ("")</li>
   *   <li>@NULL_COLL</li>
   * </ul>
   * <p>
   * This function is used to create TSentryPrivilege objects and is essential in maintaining backward compatibility
   * for reading the data that is saved in the sentry database. And also to ensure the backward compatibility of read the
   * user passed column data (@see TSentryAuthorizable conversion to TSentryPrivilege)
   * <p>
   * @param s string input, and can be null.
   * @return original string if it is non-empty and "" for empty strings.
   */
  private static String fromNULLCol(String s) {
    return isNULL(s) ? "" : s;
  }

  /**
   * Retrieves an up-to-date sentry permission snapshot.
   * <p>
   * It reads hiveObj to &lt role, privileges &gt mapping from {@link MSentryPrivilege}
   * table and role to groups mapping from {@link MSentryGroup}.
   * It also gets the changeID of latest delta update, from {@link MSentryPathChange}, that
   * the snapshot corresponds to.
   *
   * @return a {@link PathsImage} contains the mapping of hiveObj to
   *         &lt role, privileges &gt and the mapping of role to &lt Groups &gt.
   *         For empty image returns
   *         {@link org.apache.sentry.core.common.utils.SentryConstants#EMPTY_CHANGE_ID}
   *         and empty maps.
   * @throws Exception
   */
  public PermissionsImage retrieveFullPermssionsImage() throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              // curChangeID could be 0, if Sentry server has been running before
              // enable SentryPlugin(HDFS Sync feature).
              long curChangeID = getLastProcessedChangeIDCore(pm, MSentryPermChange.class);
              Map<String, List<String>> roleImage = retrieveFullRoleImageCore(pm);
              Map<String, Map<TPrivilegePrincipal, String>> privilegeMap = retrieveFullPrivilegeImageCore(pm);

              return new PermissionsImage(roleImage, privilegeMap, curChangeID);
            });
  }

  /**
   * Retrieves an up-to-date sentry privileges snapshot from {@code MSentryPrivilege} table.
   * The snapshot is represented by mapping of hiveObj to role privileges.
   *
   * @param pm PersistenceManager
   * @return a mapping of hiveObj to &lt role, privileges &gt
   * @throws Exception
   */
   private Map<String, Map<TPrivilegePrincipal, String>> retrieveFullPrivilegeImageCore(PersistenceManager pm)
        throws Exception {
     pm.setDetachAllOnCommit(false); // No need to detach objects

    Map<String, Map<TPrivilegePrincipal, String>> retVal = new HashMap<>();
    Query query = pm.newQuery(MSentryPrivilege.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

    QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
    paramBuilder.addNotNull(SERVER_NAME)
                .addNotNull(DB_NAME)
                .addNull(URI);

    query.setFilter(paramBuilder.toString());
    query.setOrdering("serverName ascending, dbName ascending, tableName ascending");

    FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRolesUsers");
    grp.addMember("roles").addMember("users");
    pm.getFetchPlan().addGroup("fetchRolesUsers");

    @SuppressWarnings("unchecked")
    List<MSentryPrivilege> privileges =
            (List<MSentryPrivilege>) query.executeWithMap(paramBuilder.getArguments());
    for (MSentryPrivilege mPriv : privileges) {
      String authzObj = mPriv.getDbName();
      if (!isNULL(mPriv.getTableName())) {
        authzObj = authzObj + "." + mPriv.getTableName();
      }
      Map<TPrivilegePrincipal, String> pUpdate = retVal.get(authzObj);
      if (pUpdate == null) {
        pUpdate = new HashMap<>();
        retVal.put(authzObj, pUpdate);
      }
      for (MSentryRole mRole : mPriv.getRoles()) {
        pUpdate = addPrivilegeEntry (mPriv, TPrivilegePrincipalType.ROLE, mRole.getRoleName(), pUpdate);
      }
      for (MSentryUser mUser : mPriv.getUsers()) {
        pUpdate = addPrivilegeEntry (mPriv, TPrivilegePrincipalType.USER, mUser.getUserName(), pUpdate);
      }
    }
    query.closeAll();
    return retVal;
  }

  private static Map<TPrivilegePrincipal, String> addPrivilegeEntry(MSentryPrivilege mPriv, TPrivilegePrincipalType tEntityType,
    String principal, Map<TPrivilegePrincipal, String> update) {
    TPrivilegePrincipal tPrivilegePrincipal = new TPrivilegePrincipal(tEntityType, principal);
    String existingPriv = update.get(tPrivilegePrincipal);
    String action = mPriv.getAction().toUpperCase();
    String newAction = mPriv.getAction().toUpperCase();
    if(action.equals(AccessConstants.OWNER)) {
      // Translate owner privilege to actual privilege.
      newAction = AccessConstants.ACTION_ALL;
    }

    if (existingPriv == null) {
      update.put(tPrivilegePrincipal, newAction);
    } else {
      update.put(tPrivilegePrincipal, existingPriv + "," + newAction);
    }
    return update;
  }

  /**
   * Retrieves an up-to-date sentry role snapshot from {@code MSentryGroup} table.
   * The snapshot is represented by a role to groups map.
   *
   * @param pm PersistenceManager
   * @return a mapping of Role to &lt Groups &gt
   * @throws Exception
   */
  private Map<String, List<String>> retrieveFullRoleImageCore(PersistenceManager pm)
          throws Exception {
    pm.setDetachAllOnCommit(false); // No need to detach objects
    Query query = pm.newQuery(MSentryGroup.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

    FetchGroup grp = pm.getFetchGroup(MSentryGroup.class, "fetchRoles");
    grp.addMember("roles");
    pm.getFetchPlan().addGroup("fetchRoles");

    @SuppressWarnings("unchecked")
    List<MSentryGroup> groups = (List<MSentryGroup>) query.execute();
    if (groups.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, List<String>> retVal = new HashMap<>();
    for (MSentryGroup mGroup : groups) {
      for (MSentryRole role : mGroup.getRoles()) {
        List<String> rUpdate = retVal.get(role.getRoleName());
        if (rUpdate == null) {
          rUpdate = new ArrayList<>();
          retVal.put(role.getRoleName(), rUpdate);
        }
        rUpdate.add(mGroup.getGroupName());
      }
    }
    query.closeAll();
    return retVal;
  }

  /**
   * Retrieves an up-to-date hive paths snapshot.
   * The image only contains PathsDump in it.
   * <p>
   * It reads hiveObj to paths mapping from {@link MAuthzPathsMapping} table and
   * gets the changeID of latest delta update, from {@link MSentryPathChange}, that
   * the snapshot corresponds to.
   *
   * @param prefixes path of Sentry managed prefixes. Ignore any path outside the prefix.
   * @return an up-to-date hive paths snapshot contains mapping of hiveObj to &lt Paths &gt.
   *         For empty image return
   *         {@link org.apache.sentry.core.common.utils.SentryConstants#EMPTY_CHANGE_ID}
   *         and a empty map.
   * @throws Exception
   */
  public PathsUpdate retrieveFullPathsImageUpdate(final String[] prefixes) throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              long curImageID = getCurrentAuthzPathsSnapshotID(pm);
              long curChangeID = getLastProcessedChangeIDCore(pm, MSentryPathChange.class);
              PathsUpdate pathUpdate = new PathsUpdate(curChangeID, curImageID, true);
              // We ignore anything in the update and set it later to the assembled PathsDump
              UpdateableAuthzPaths authzPaths = new UpdateableAuthzPaths(prefixes);
              // Extract all paths and put them into authzPaths
              retrieveFullPathsImageCore(pm, curImageID, authzPaths);
              pathUpdate.toThrift().setPathsDump(authzPaths.getPathsDump().createPathsDump(true));
              return pathUpdate;
            });
  }

  /**
   * Extract all paths and convert them into HMSPaths obect
   * @param pm Persistence manager
   * @param currentSnapshotID Image ID we are interested in
   * @param pathUpdate Destination for result
   */
  private void retrieveFullPathsImageCore(PersistenceManager pm,
                                          long currentSnapshotID,
                                          UpdateableAuthzPaths pathUpdate) {
    // Query for all MAuthzPathsMapping objects matching the given image ID
    Query query = pm.newQuery(MAuthzPathsMapping.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setFilter("this.authzSnapshotID == currentSnapshotID");
    query.declareParameters("long currentSnapshotID");

    // Get path in batch to improve performance. The fectch groups are defined in package.jdo
    pm.getFetchPlan().addGroup("includingPaths");
    Collection<MAuthzPathsMapping> authzToPathsMappings =
        (Collection<MAuthzPathsMapping>) query.execute(currentSnapshotID);

    // Walk each MAuthzPathsMapping object, get set of paths and push them all
    // into HMSPaths object contained in UpdateableAuthzPaths.
    for (MAuthzPathsMapping authzToPaths : authzToPathsMappings) {
      String  objName = authzToPaths.getAuthzObjName();
      // Convert path strings to list of components
      for (String path: authzToPaths.getPathStrings()) {
        String[] pathComponents = PathUtils.splitPath(path);
        List<String> paths = new ArrayList<>(pathComponents.length);
        Collections.addAll(paths, pathComponents);
        pathUpdate.applyAddChanges(objName, Collections.singletonList(paths));
      }
    }
  }

  /**
   * Delete all stored HMS notifications starting from given ID.<p>
   *
   * The purpose of the function is to clean up notifications in cases
   * were we recover from HMS notifications resets.
   *
   * @param pm Persistent manager instance
   * @param id initial ID. All notifications starting from this ID and above are
   *          removed.
   */
  private void deleteNotificationsSince(PersistenceManager pm, long id) {
    Query query = pm.newQuery(MSentryHmsNotification.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setFilter("notificationId >= currentNotificationId");
    query.declareParameters("long currentNotificationId");
    long numDeleted = query.deletePersistentAll(id);
    if (numDeleted > 0) {
      LOGGER.info("Purged {} notification entries starting from {}",
              numDeleted, id);
    }
  }

  /**
   * Persist an up-to-date HMS snapshot into Sentry DB in a single transaction with its latest
   * notification ID
   *
   * @param authzPaths paths to be be persisted
   * @param notificationID the latest notificationID associated with the snapshot
   * @throws Exception
   */
  public void persistFullPathsImage(final Map<String, Collection<String>> authzPaths,
      final long notificationID) throws Exception {
    tm.executeTransactionWithRetry(
            pm -> {

              int totalNumberOfObjectsToPersist = authzPaths.size();
              int totalNumberOfPathsToPersist = authzPaths.values().stream().mapToInt(Collection::size).sum();
              int objectsPersistedCount = 0, pathsPersistedCount = 0;

              logPersistingFullSnapshotState(totalNumberOfObjectsToPersist,
                  totalNumberOfPathsToPersist, objectsPersistedCount, pathsPersistedCount);

              pm.setDetachAllOnCommit(false); // No need to detach objects
              deleteNotificationsSince(pm, notificationID + 1);
              // persist the notification ID
              pm.makePersistent(new MSentryHmsNotification(notificationID));

              // persist the full snapshot
              long snapshotID = getCurrentAuthzPathsSnapshotID(pm);
              long nextObjectId = getNextAuthzObjectID(pm);
              long nextSnapshotID = snapshotID + 1;
              pm.makePersistent(new MAuthzPathsSnapshotId(nextSnapshotID));
              LOGGER.info("Attempting to commit new HMS snapshot with ID = {}", nextSnapshotID);

              long lastProgressTime = System.currentTimeMillis();

              for (Map.Entry<String, Collection<String>> authzPath : authzPaths.entrySet()) {
                MAuthzPathsMapping mapping = new MAuthzPathsMapping(nextSnapshotID, nextObjectId++, authzPath.getKey(),
                        authzPath.getValue());
                mapping.makePersistent(pm);
                objectsPersistedCount++;
                pathsPersistedCount = pathsPersistedCount + authzPath.getValue().size();

                long currentTime = System.currentTimeMillis();
                if ((currentTime - lastProgressTime) > printSnapshotPersistTimeInterval) {

                  logPersistingFullSnapshotState(totalNumberOfObjectsToPersist,
                      totalNumberOfPathsToPersist, objectsPersistedCount, pathsPersistedCount);

                  lastProgressTime = currentTime;
                }
              }
              return null;
            });
  }

  public void logPersistingFullSnapshotState(int totalNumberOfObjectsToPersist,
      int totalNumberOfPathsToPersist, int objectsPersistedCount, int pathsPersistedCount) {

    LOGGER.info(String.format("Persisting HMS Paths on Snapshot: "
            + "authz_objs_persisted=%d(%.2f%%) authz_paths_persisted=%d(%.2f%%) "
            + "authz_objs_total=%d authz_paths_total=%d",
        objectsPersistedCount,
        totalNumberOfObjectsToPersist > 0 ? 100 * ((double) objectsPersistedCount
            / totalNumberOfObjectsToPersist) : 0,
        pathsPersistedCount, totalNumberOfPathsToPersist > 0 ? 100 * ((double) pathsPersistedCount
            / totalNumberOfPathsToPersist) : 0,
        totalNumberOfObjectsToPersist, totalNumberOfPathsToPersist));
  }

  /**
   * Get the Next object ID to be persisted
   * Always executed in the transaction context.
   *
   * @param pm The PersistenceManager object.
   * @return the Next object ID to be persisted. It returns 0 if no rows are found.
   */
  private static long getNextAuthzObjectID(PersistenceManager pm) {
    return getMaxPersistedIDCore(pm, MAuthzPathsMapping.class, "authzObjectId", EMPTY_PATHS_MAPPING_ID) + 1;
  }

  /**
   * Get the last authorization path snapshot ID persisted.
   * Always executed in the transaction context.
   *
   * @param pm The PersistenceManager object.
   * @return the last persisted snapshot ID. It returns 0 if no rows are found.
   */
  private static long getCurrentAuthzPathsSnapshotID(PersistenceManager pm) {
    return getMaxPersistedIDCore(pm, MAuthzPathsSnapshotId.class, "authzSnapshotID", EMPTY_PATHS_SNAPSHOT_ID);
  }


  /**
   * Get the last authorization path snapshot ID persisted.
   * Always executed in the non-transaction context.
   * This is used for metrics, so no retries are attempted.
   *
   * @return the last persisted snapshot ID. It returns 0 if no rows are found.
   */
  @VisibleForTesting
  long getCurrentAuthzPathsSnapshotID() throws Exception {
    return tm.executeTransaction(
            SentryStore::getCurrentAuthzPathsSnapshotID
    );
  }

  /**
   * Adds the authzObj and with a set of paths into the authzObj -> [Paths] mapping.
   * As well as persist the corresponding delta path change to MSentryPathChange
   * table in a single transaction.
   *
   * @param authzObj an authzObj
   * @param paths a set of paths need to be added into the authzObj -> [Paths] mapping
   * @param update the corresponding path delta update
   * @throws Exception
   */
  public void addAuthzPathsMapping(final String authzObj, final Collection<String> paths,
      final UniquePathsUpdate update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      addAuthzPathsMappingCore(pm, authzObj, paths);
      return null;
    });
  }

  /**
   * Adds the authzObj and with a set of paths into the authzObj -> [Paths] mapping.
   * If the given authzObj already exists in the mapping, only need to add the new paths
   * into its mapping.
   *
   * @param pm PersistenceManager
   * @param authzObj an authzObj
   * @param paths a set of paths need to be added into the authzObj -> [Paths] mapping
   */
  private void addAuthzPathsMappingCore(PersistenceManager pm, String authzObj,
        Collection<String> paths) {
    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.warn("AuthzObj: {} cannot be persisted if paths snapshot ID does not exist yet.", authzObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, authzObj);
    if (mAuthzPathsMapping == null) {
      mAuthzPathsMapping = new MAuthzPathsMapping(currentSnapshotID, getNextAuthzObjectID(pm), authzObj, paths);
    } else {
      mAuthzPathsMapping.addPathToPersist(paths);
    }
    mAuthzPathsMapping.makePersistent(pm);
  }

  /**
   * Deletes a set of paths belongs to given authzObj from the authzObj -> [Paths] mapping.
   * As well as persist the corresponding delta path change to MSentryPathChange
   * table in a single transaction.
   *
   * @param authzObj an authzObj
   * @param paths a set of paths need to be deleted from the authzObj -> [Paths] mapping
   * @param update the corresponding path delta update
   */
  public void deleteAuthzPathsMapping(final String authzObj, final Collection<String> paths,
      final UniquePathsUpdate update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      deleteAuthzPathsMappingCore(pm, authzObj, paths);
      return null;
    });
  }

  /**
   * Deletes a set of paths belongs to given authzObj from the authzObj -> [Paths] mapping.
   *
   * @param pm PersistenceManager
   * @param authzObj an authzObj
   * @param paths a set of paths need to be deleted from the authzObj -> [Paths] mapping.
   * @throws SentryNoSuchObjectException if cannot find the existing authzObj or path.
   */
  private void deleteAuthzPathsMappingCore(PersistenceManager pm, String authzObj,
                                           Collection<String> paths) {
    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.error("No paths snapshot ID is found. Cannot delete authzoObj: {}", authzObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, authzObj);
    if (mAuthzPathsMapping != null) {
      mAuthzPathsMapping.deletePersistent(pm, paths);
    } else {
      LOGGER.error("nonexistent authzObj: {} on current paths snapshot ID #{}",
          authzObj, currentSnapshotID);
    }
  }

  /**
   * Deletes all entries of the given authzObj from the authzObj -> [Paths] mapping.
   * As well as persist the corresponding delta path change to MSentryPathChange
   * table in a single transaction.
   *
   * @param authzObj an authzObj to be deleted
   * @param update the corresponding path delta update
   */
  public void deleteAllAuthzPathsMapping(final String authzObj, final UniquePathsUpdate update)
        throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      deleteAllAuthzPathsMappingCore(pm, authzObj);
      return null;
    });
  }

  /**
   * Deletes the entry of the given authzObj from the authzObj -> [Paths] mapping.
   *
   * @param pm PersistenceManager
   * @param authzObj an authzObj to be deleted
   * @throws SentryNoSuchObjectException if cannot find the existing authzObj
   */
  private void deleteAllAuthzPathsMappingCore(PersistenceManager pm, String authzObj) {
    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.error("No paths snapshot ID is found. Cannot delete authzoObj: {}", authzObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, authzObj);
    if (mAuthzPathsMapping != null) {
      pm.deletePersistent(mAuthzPathsMapping);
    } else {
      LOGGER.error("nonexistent authzObj: {} on current paths snapshot ID #{}",
          authzObj, currentSnapshotID);
    }
  }

  /**
   * Renames the existing authzObj to a new one in the authzObj -> [Paths] mapping.
   * And updates its existing path with a new path, while keeps the rest of its paths
   * untouched if there is any. As well as persist the corresponding delta path
   * change to MSentryPathChange table in a single transaction.
   *
   * @param oldObj the existing authzObj
   * @param newObj the new name to be changed to
   * @param oldPath a existing path of the given authzObj
   * @param newPath a new path to be changed to
   * @param update the corresponding path delta update
   */
  public void renameAuthzPathsMapping(final String oldObj, final String newObj,
      final String oldPath, final String newPath, final UniquePathsUpdate update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      renameAuthzPathsMappingCore(pm, oldObj, newObj, oldPath, newPath);
      return null;
    });
  }

  /**
   * Renames the existing authzObj to a new one in the authzObj -> [Paths] mapping.
   * And updates its existing path with a new path, while keeps the rest of its paths
   * untouched if there is any.
   *
   * @param pm PersistenceManager
   * @param oldObj the existing authzObj
   * @param newObj the new name to be changed to
   * @param oldPath a existing path of the given authzObj
   * @param newPath a new path to be changed to
   * @throws SentryNoSuchObjectException if cannot find the existing authzObj or path.
   */
  private void renameAuthzPathsMappingCore(PersistenceManager pm, String oldObj,
        String newObj, String oldPath, String newPath) {
    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.error("No paths snapshot ID is found. Cannot rename authzoObj: {}", oldObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, oldObj);
    if (mAuthzPathsMapping != null) {
      mAuthzPathsMapping.deletePersistent(pm,Collections.singleton(oldPath));
      mAuthzPathsMapping.setAuthzObjName(newObj);
      mAuthzPathsMapping.addPathToPersist(Collections.singleton(newPath));
      mAuthzPathsMapping.makePersistent(pm);
    } else {
      LOGGER.error("nonexistent authzObj: {} on current paths snapshot ID #{}",
          oldObj, currentSnapshotID);
    }
  }

  /**
   * Renames the existing authzObj to a new one in the authzObj -> [Paths] mapping,
   * but keeps its paths mapping as-is. As well as persist the corresponding delta path
   * change to MSentryPathChange table in a single transaction.
   *
   * @param oldObj the existing authzObj
   * @param newObj the new name to be changed to
   * @param update the corresponding path delta update
   */
  public void renameAuthzObj(final String oldObj, final String newObj,
      final UniquePathsUpdate update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      renameAuthzObjCore(pm, oldObj, newObj);
      return null;
    });
  }

  /**
   * Renames the existing authzObj to a new one in the authzObj -> [Paths] mapping,
   * but keeps its paths mapping as-is.
   *
   * @param pm PersistenceManager
   * @param oldObj the existing authzObj
   * @param newObj the new name to be changed to
   * @throws SentryNoSuchObjectException if cannot find the existing authzObj.
   */
  private void renameAuthzObjCore(PersistenceManager pm, String oldObj,
      String newObj) {
    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.error("No paths snapshot ID is found. Cannot rename authzoObj: {}", oldObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, oldObj);
    if (mAuthzPathsMapping != null) {
      mAuthzPathsMapping.setAuthzObjName(newObj);
      pm.makePersistent(mAuthzPathsMapping);
    } else {
      LOGGER.error("nonexistent authzObj: {} on current paths snapshot ID #{}",
          oldObj, currentSnapshotID);
    }
  }

  /**
   * Tells if there are any records in MAuthzPathsMapping
   *
   * @return true if there are no entries in <code>MAuthzPathsMapping</code>
   * false if there are entries
   * @throws Exception
   */
  public boolean isAuthzPathsMappingEmpty() throws Exception {
    return tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return isTableEmptyCore(pm, MAuthzPathsMapping.class);
            });
  }

  /**
   * Tells if there are any records in MSentryHmsNotification
   *
   * @return true if there are no entries in <code>MSentryHmsNotification</code>
   * false if there are entries
   * @throws Exception
   */
  public boolean isHmsNotificationEmpty() throws Exception {
    return tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return isTableEmptyCore(pm, MSentryHmsNotification.class);
            });
  }

  /**
   * Tells if there are any records in MAuthzPathsMapping
   *
   * @return true if there are no entries in <code>MAuthzPathsMapping</code>
   * false if there are entries
   * @throws Exception
   */
  public boolean isAuthzPathsSnapshotEmpty() throws Exception {
    return tm.executeTransactionWithRetry(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return isTableEmptyCore(pm, MAuthzPathsMapping.class);
            });
  }

  /**
   * Updates authzObj -> [Paths] mapping to replace an existing path with a new one
   * given an authzObj. As well as persist the corresponding delta path change to
   * MSentryPathChange table in a single transaction.
   *
   * @param authzObj an authzObj
   * @param oldPath the existing path maps to the given authzObj
   * @param newPath a new path to replace the existing one
   * @param update the corresponding path delta update
   * @throws Exception
   */
  public void updateAuthzPathsMapping(final String authzObj, final String oldPath,
        final String newPath, final UniquePathsUpdate update) throws Exception {
    execute(update, pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      updateAuthzPathsMappingCore(pm, authzObj, oldPath, newPath);
      return null;
    });
  }

  /**
   * Updates authzObj -> [Paths] mapping to replace an existing path with a new one
   * given an authzObj.
   *
   * @param pm PersistenceManager
   * @param authzObj an authzObj
   * @param oldPath the existing path maps to the given authzObj
   * @param newPath a non-empty path to replace the existing one
   * @throws SentryNoSuchObjectException if no such path found
   *        in the authzObj -> [Paths] mapping.
   */
  private void updateAuthzPathsMappingCore(PersistenceManager pm, String authzObj,
        String oldPath, String newPath) {

    long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);
    if (currentSnapshotID <= EMPTY_PATHS_SNAPSHOT_ID) {
      LOGGER.error("No paths snapshot ID is found. Cannot update authzoObj: {}", authzObj);
    }

    MAuthzPathsMapping mAuthzPathsMapping = getMAuthzPathsMappingCore(pm, currentSnapshotID, authzObj);
    if (mAuthzPathsMapping == null) {
      mAuthzPathsMapping = new MAuthzPathsMapping(currentSnapshotID, getNextAuthzObjectID(pm), authzObj,
              Collections.singleton(newPath));
    } else {
      mAuthzPathsMapping.deletePersistent(pm, Collections.singleton(oldPath));
      mAuthzPathsMapping.addPathToPersist(Collections.singleton(newPath));
    }
    mAuthzPathsMapping.makePersistent(pm);
  }

  /**
   * Get the Collection of MPath associated with snapshot id and authzObj
   * @param authzSnapshotID Snapshot ID
   * @param authzObj Object name
   * @return Path mapping for object provided.
   * @throws Exception
   */
  @VisibleForTesting
   Set<MPath> getMAuthzPaths(long authzSnapshotID, String authzObj) throws Exception {
    return tm.executeTransactionWithRetry( pm -> {
      MAuthzPathsMapping mapping = null;
      pm.setDetachAllOnCommit(true); // No need to detach objects
      mapping = getMAuthzPathsMappingCore(pm, authzSnapshotID, authzObj);
      if(mapping != null) {
        Set<MPath> paths = mapping.getPathsPersisted();
        return paths;
      } else {
        return Collections.emptySet();
      }
    });
  }

    /**
     * Get the MAuthzPathsMapping object from authzObj
     */
  private MAuthzPathsMapping getMAuthzPathsMappingCore(PersistenceManager pm,
        long authzSnapshotID, String authzObj) {
    Query query = pm.newQuery(MAuthzPathsMapping.class);
    query.setFilter("this.authzSnapshotID == authzSnapshotID && this.authzObjName == authzObjName");
    query.declareParameters("long authzSnapshotID, java.lang.String authzObjName");
    query.setUnique(true);
    return (MAuthzPathsMapping) query.execute(authzSnapshotID, authzObj);
  }

  /**
   * Checks if the table associated with class provided is empty
   *
   * @param pm PersistenceManager
   * @param clazz class
   * @return True is the table is empty
   * False if it not.
   */
  private boolean isTableEmptyCore(PersistenceManager pm, Class clazz) {
    Query query = pm.newQuery(clazz);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    // setRange is implemented efficiently for MySQL, Postgresql (using the LIMIT SQL keyword)
    // and Oracle (using the ROWNUM keyword), with the query only finding the objects required
    // by the user directly in the datastore. For other RDBMS the query will retrieve all
    // objects up to the "to" record, and will not pass any unnecessary objects that are before
    // the "from" record.
    query.setRange(0, 1);
    return ((List<?>) query.execute()).isEmpty();
  }

  /**
   * Generic method used to query the maximum number (or ID) of a column from a specified class.
   *
   * @param pm The PersistenceManager object.
   * @param clazz The class name to query.
   * @param columnName The column name to query.
   * @return the maximum number persisted on the class. It returns NULL if the class has no rows.
   */
  private static long getMaxPersistedIDCore(PersistenceManager pm, Class clazz, String columnName, long defaultValue) {
    Query query = pm.newQuery(clazz);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setResult(String.format("max(%s)", columnName));
    Long maxValue = (Long) query.execute();
    return (maxValue != null) ? maxValue : defaultValue;
  }

  @VisibleForTesting
  List<MPath> getMPaths() throws Exception {
    return tm.executeTransaction(pm -> {
      long currentSnapshotID = getCurrentAuthzPathsSnapshotID(pm);

      Query query = pm.newQuery("SQL",
          "SELECT p.PATH_NAME FROM AUTHZ_PATH p " +
             "JOIN AUTHZ_PATHS_MAPPING a ON a.AUTHZ_OBJ_ID = p.AUTHZ_OBJ_ID " +
             "WHERE a.AUTHZ_SNAPSHOT_ID = ?"
      );
      query.setResultClass(MPath.class);
      return (List<MPath>) query.execute(currentSnapshotID);
    });
  }

  /**
   * Get the total number of entries in AUTHZ_PATH table.
   * @return  number of entries in AUTHZ_PATH table.
   */
  @VisibleForTesting
   long getPathCount() {
    return getCount(MPath.class);
  }

  /**
   * Method detects orphaned privileges
   *
   * @return True, If there are orphan privileges
   * False, If orphan privileges are not found.
   * non-zero value if an orphan is found.
   * <p>
   * Method currently used only by tests.
   * <p>
   */

  @VisibleForTesting
  Boolean findOrphanedPrivileges() throws Exception {
    return tm.executeTransaction(
            pm -> findOrphanedPrivilegesCore(pm));
  }

  Boolean findOrphanedPrivilegesCore(PersistenceManager pm) {
    //Perform a SQL query to get things that look like orphans
    List<MSentryPrivilege> results = getAllMSentryPrivilegesCore(pm);
    List<Object> idList = new ArrayList<>(results.size());
    for (MSentryPrivilege orphan : results) {
      idList.add(pm.getObjectId(orphan));
    }
    if (idList.isEmpty()) {
      return false;
    }
    //For each potential orphan, verify it's really a orphan.
    // Moment an orphan is identified return 1 indicating an orphan is found.
    pm.refreshAll();  // Try to ensure we really have correct objects
    for (Object id : idList) {
      MSentryPrivilege priv = (MSentryPrivilege) pm.getObjectById(id);
      if (priv.getRoles().isEmpty()) {
        return true;
      }
    }
    return false;
  }

  /** get mapping datas for [group,role], [user,role] with the specific roles */
  @SuppressWarnings("unchecked")
  public List<Map<String, Set<String>>> getGroupUserRoleMapList(final Collection<String> roleNames)
          throws Exception {
      return tm.executeTransaction(
              pm -> {
                pm.setDetachAllOnCommit(false); // No need to detach objects

                Query query = pm.newQuery(MSentryRole.class);
                query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
                List<MSentryRole> mSentryRoles;

                FetchGroup grp = pm.getFetchGroup(MSentryRole.class, "fetchGroupsUsers");
                grp.addMember("groups").addMember("users");
                pm.getFetchPlan().addGroup("fetchGroupsUsers");

                if ((roleNames == null) || roleNames.isEmpty()) {
                  mSentryRoles = (List<MSentryRole>)query.execute();
                } else {
                  QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder(QueryParamBuilder.Op.OR);
                  paramBuilder.addSet("roleName == ", roleNames, true);
                  query.setFilter(paramBuilder.toString());
                  mSentryRoles =
                          (List<MSentryRole>) query.executeWithMap(paramBuilder.getArguments());
                }
                Map<String, Set<String>> groupRolesMap = getGroupRolesMap(mSentryRoles);
                Map<String, Set<String>> userRolesMap = getUserRolesMap(mSentryRoles);
                List<Map<String, Set<String>>> mapsList = new ArrayList<>();
                mapsList.add(INDEX_GROUP_ROLES_MAP, groupRolesMap);
                mapsList.add(INDEX_USER_ROLES_MAP, userRolesMap);
                return mapsList;
              });
  }

  private Map<String, Set<String>> getGroupRolesMap(Collection<MSentryRole> mSentryRoles) {
    if (mSentryRoles.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, Set<String>> groupRolesMap = new HashMap<>();
    // change the List<MSentryRole> -> Map<groupName, Set<roleName>>
    for (MSentryRole mSentryRole : mSentryRoles) {
      Set<MSentryGroup> groups = mSentryRole.getGroups();
      for (MSentryGroup group : groups) {
        String groupName = group.getGroupName();
        Set<String> rNames = groupRolesMap.get(groupName);
        if (rNames == null) {
          rNames = new HashSet<>();
        }
        rNames.add(mSentryRole.getRoleName());
        groupRolesMap.put(groupName, rNames);
      }
    }
    return groupRolesMap;
  }

  private Map<String, Set<String>> getUserRolesMap(Collection<MSentryRole> mSentryRoles) {
    if (mSentryRoles.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, Set<String>> userRolesMap = new HashMap<>();
    // change the List<MSentryRole> -> Map<userName, Set<roleName>>
    for (MSentryRole mSentryRole : mSentryRoles) {
      Set<MSentryUser> users = mSentryRole.getUsers();
      for (MSentryUser user : users) {
        String userName = user.getUserName();
        Set<String> rNames = userRolesMap.get(userName);
        if (rNames == null) {
          rNames = new HashSet<>();
        }
        rNames.add(mSentryRole.getRoleName());
        userRolesMap.put(userName, rNames);
      }
    }
    return userRolesMap;
  }

  // get all mapping data for [role,privilege]
  Map<String, Set<TSentryPrivilege>> getRoleNameTPrivilegesMap() throws Exception {
    return getRoleNameTPrivilegesMap(null, null);
  }

  /**
   * @return Privileges granted to Authoriable and it's children.
   * If the authorizable is server, returns all the privileges granted on that server
   * If the authorizable is database,returns all the privileges granted on that database and also the tables and
   * the columns in it.
   * If the authorizable is an URI, returns all the privileges granted on URI's with the given prefix.
   */
  public List<MSentryPrivilege> getPrivilegesForAuthorizables(List<TSentryAuthorizable> authHierarchyList) throws Exception {
    return tm.executeTransaction(
            pm -> getPrivilegesForAuthorizables(pm, authHierarchyList)
    );
  }

  /**
   * @return Privileges granted to Authoriables and it's children.
   * If the authorizable is server, returns all the privileges granted on that server
   * If the authorizable is database,returns all the privileges granted on that database and also the tables and
   * the columns in it.
   * If the authorizable is an URI, returns all the privileges granted on URI's with the given prefix.
   * If the authHierarchyList is Null or Empty, all the privileges in the sentry store are returned.
   */
  private List<MSentryPrivilege> getPrivilegesForAuthorizables(PersistenceManager pm,
      List<TSentryAuthorizable> authHierarchyList) throws Exception {
    List<MSentryPrivilege> mSentryPrivileges = Lists.newArrayList();
    pm.setDetachAllOnCommit(false); // No need to detach objects
    Query query = pm.newQuery(MSentryPrivilege.class);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchPrincipals");
    grp.addMember("roles");
    grp.addMember("users");
    pm.getFetchPlan().addGroup("fetchPrincipals");

    // When the list is empty or NULL return every thing.
    if(authHierarchyList == null || authHierarchyList.isEmpty()) {
      mSentryPrivileges.addAll((List<MSentryPrivilege>) query.execute());
      return mSentryPrivileges;
    }

    for (TSentryAuthorizable authHierarchy : authHierarchyList) {
      QueryParamBuilder authParamBuilder = QueryParamBuilder.newQueryParamBuilder(QueryParamBuilder.Op.AND);
      if (authHierarchy.getServer() != null) {
        authParamBuilder.add(SERVER_NAME, authHierarchy.getServer());
        if (authHierarchy.getDb() != null) {
          authParamBuilder.add(DB_NAME, authHierarchy.getDb()).addNull(URI);
          if (authHierarchy.getTable() != null) {
            authParamBuilder.add(TABLE_NAME, authHierarchy.getTable());
            if (authHierarchy.getColumn() != null) {
              authParamBuilder.add(COLUMN_NAME, authHierarchy.getColumn());
            }
          }
        } else if (authHierarchy.getUri() != null) {
          authParamBuilder.addNotNull(URI)
                  .addNotNull(URI)
                  .addNull(DB_NAME)
                  .addCustomParam("(URI.startsWith(:authURI))", "authURI", authHierarchy.getUri());
        }
      }

      query.setFilter(authParamBuilder.toString());
      mSentryPrivileges.addAll((List<MSentryPrivilege>) query.executeWithMap(authParamBuilder.getArguments()));
    }
    return mSentryPrivileges;
  }

  /**
   * @return mapping data for [role,privilege] with the specific auth object
   */
  public Map<String, Set<TSentryPrivilege>> getRoleNameTPrivilegesMap(final String dbName,
        final String tableName) throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              Query query = pm.newQuery(MSentryPrivilege.class);
              query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
              QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();

              if (!StringUtils.isEmpty(dbName)) {
                  paramBuilder.add(DB_NAME, dbName);
              }
              if (!StringUtils.isEmpty(tableName)) {
                  paramBuilder.add(TABLE_NAME, tableName);
              }
              query.setFilter(paramBuilder.toString());
              FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRoles");
              grp.addMember("roles");
              pm.getFetchPlan().addGroup("fetchRoles");

              @SuppressWarnings("unchecked")
              List<MSentryPrivilege> mSentryPrivileges =
                      (List<MSentryPrivilege>) query.
                              executeWithMap(paramBuilder.getArguments());
              return getRolePrivilegesMap(mSentryPrivileges);
            });
  }

  private Map<String, Set<TSentryPrivilege>> getRolePrivilegesMap(
          Collection<MSentryPrivilege> mSentryPrivileges) {
    if (mSentryPrivileges.isEmpty()) {
      return Collections.emptyMap();
    }

    // change the List<MSentryPrivilege> -> Map<roleName, Set<TSentryPrivilege>>
    Map<String, Set<TSentryPrivilege>> rolePrivilegesMap = new HashMap<>();
    for (MSentryPrivilege mSentryPrivilege : mSentryPrivileges) {
      TSentryPrivilege privilege = convertToTSentryPrivilege(mSentryPrivilege);
      for (MSentryRole mSentryRole : mSentryPrivilege.getRoles()) {
        String roleName = mSentryRole.getRoleName();
        Set<TSentryPrivilege> privileges = rolePrivilegesMap.get(roleName);
        if (privileges == null) {
          privileges = new HashSet<>();
        }
        privileges.add(privilege);
        rolePrivilegesMap.put(roleName, privileges);
      }
    }
    return rolePrivilegesMap;
  }

  /**
   * @return Set of all role names, or an empty set if no roles are defined
   */
  public Set<String> getAllRoleNames() throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return getAllRoleNamesCore(pm);
            });
  }

  /**
   * Get set of all role names
   * Should be executed inside transaction
   * @param pm PersistenceManager instance
   * @return Set of all role names, or an empty set if no roles are defined
   */
  private Set<String> getAllRoleNamesCore(PersistenceManager pm) {
    List<MSentryRole> mSentryRoles = getAllRoles(pm);
    if (mSentryRoles.isEmpty()) {
      return Collections.emptySet();
    }

    return rolesToRoleNames(mSentryRoles);
  }

  /**
   * Get all groups as a map from group name to group
   * @param pm PersistenceManager instance
   * @return map of group names to group data for each group
   */
  private Map<String, MSentryGroup> getGroupNameTGroupMap(PersistenceManager pm) {
    Query query = pm.newQuery(MSentryGroup.class);
    @SuppressWarnings("unchecked")
    List<MSentryGroup> mSentryGroups = (List<MSentryGroup>) query.execute();
    if (mSentryGroups.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, MSentryGroup> existGroupsMap = new HashMap<>(mSentryGroups.size());
    // change the List<MSentryGroup> -> Map<groupName, MSentryGroup>
    for (MSentryGroup mSentryGroup : mSentryGroups) {
      existGroupsMap.put(mSentryGroup.getGroupName(), mSentryGroup);
    }
    return existGroupsMap;
  }

  /**
   * Get all users as a map from user name to user
   * @param pm PersistenceManager instance
   * @return map of user names to user data for each user
   */
  private Map<String, MSentryUser> getUserNameToUserMap(PersistenceManager pm) {
    Query query = pm.newQuery(MSentryUser.class);
    @SuppressWarnings("unchecked")
    List<MSentryUser> users = (List<MSentryUser>) query.execute();
    if (users.isEmpty()) {
      return Collections.emptyMap();
    }
    Map<String, MSentryUser> existUsersMap = new HashMap<>(users.size());
    // change the List<MSentryUser> -> Map<userName, MSentryUser>
    for (MSentryUser user : users) {
      existUsersMap.put(user.getUserName(), user);
    }
    return existUsersMap;
  }

  @VisibleForTesting
  Map<String, MSentryRole> getRolesMap() throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              List<MSentryRole> mSentryRoles = getAllRoles(pm);
              if (mSentryRoles.isEmpty()) {
                return Collections.emptyMap();
              }
              Map<String, MSentryRole> existRolesMap =
                      new HashMap<>(mSentryRoles.size());
              // change the List<MSentryRole> -> Map<roleName, Set<MSentryRole>>
              for (MSentryRole mSentryRole : mSentryRoles) {
                existRolesMap.put(mSentryRole.getRoleName(), mSentryRole);
              }

              return existRolesMap;
            });
  }

  @VisibleForTesting
  Map<String, MSentryGroup> getGroupNameToGroupMap() throws Exception {
    return tm.executeTransaction(
            this::getGroupNameTGroupMap);
  }

  @VisibleForTesting
  Map<String, MSentryUser> getUserNameToUserMap() throws Exception {
    return tm.executeTransaction(
            this::getUserNameToUserMap);
  }

  @VisibleForTesting
  List<MSentryPrivilege> getPrivilegesList() throws Exception {
    return tm.executeTransaction(
            pm -> {
              Query query = pm.newQuery(MSentryPrivilege.class);
              return (List<MSentryPrivilege>) query.execute();
            });
  }

  /**
   * Import the sentry mapping data.
   *
   * @param tSentryMappingData
   *        Include 2 maps to save the mapping data, the following is the example of the data
   *        structure:
   *        for the following mapping data:
   *        user1=role1,role2
   *        user2=role2,role3
   *        group1=role1,role2
   *        group2=role2,role3
   *        role1=server=server1->db=db1
   *        role2=server=server1->db=db1->table=tbl1,server=server1->db=db1->table=tbl2
   *        role3=server=server1->url=hdfs://localhost/path
   *
   *        The GroupRolesMap in TSentryMappingData will be saved as:
   *        {
   *        TSentryGroup(group1)={role1, role2},
   *        TSentryGroup(group2)={role2, role3}
   *        }
   *        The UserRolesMap in TSentryMappingData will be saved as:
   *        {
   *        TSentryUser(user1)={role1, role2},
   *        TSentryGroup(user2)={role2, role3}
   *        }
   *        The RolePrivilegesMap in TSentryMappingData will be saved as:
   *        {
   *        role1={TSentryPrivilege(server=server1->db=db1)},
   *        role2={TSentryPrivilege(server=server1->db=db1->table=tbl1),
   *        TSentryPrivilege(server=server1->db=db1->table=tbl2)},
   *        role3={TSentryPrivilege(server=server1->url=hdfs://localhost/path)}
   *        }
   * @param isOverwriteForRole
   *        The option for merging or overwriting the existing data during import, true for
   *        overwriting, false for merging
   */
  public void importSentryMetaData(final TSentryMappingData tSentryMappingData,
      final boolean isOverwriteForRole) throws Exception {
    tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              TSentryMappingData mappingData = lowercaseRoleName(tSentryMappingData);
              Set<String> roleNames = getAllRoleNamesCore(pm);

              Map<String, Set<TSentryGroup>> importedRoleGroupsMap = covertToRoleNameTGroupsMap(mappingData
                  .getGroupRolesMap());
              Map<String, Set<String>> importedRoleUsersMap = covertToRoleUsersMap(mappingData
                  .getUserRolesMap());
              Set<String> importedRoleNames = importedRoleGroupsMap.keySet();
              // if import with overwrite role, drop the duplicated roles in current DB first.
              if (isOverwriteForRole) {
                dropDuplicatedRoleForImport(pm, roleNames, importedRoleNames);
                // refresh the roleNames for the drop role
                roleNames = getAllRoleNamesCore(pm);
              }

              // Empty roleNames is most likely the COllections.emptySet().
              // We are going to modify roleNames below, so create an actual set.
              if (roleNames.isEmpty()) {
                roleNames = new HashSet<>();
              }

              // import the mapping data for [role,privilege], the roleNames will be updated
              importRolePrivilegeMapping(pm, roleNames, mappingData.getRolePrivilegesMap());
              // import the mapping data for [role,group], the roleNames will be updated
              importRoleGroupMapping(pm, roleNames, importedRoleGroupsMap);
              // import the mapping data for [role,user], the roleNames will be updated
              importRoleUserMapping(pm, roleNames, importedRoleUsersMap);
              return null;
            });
  }

  // covert the Map[group->roles] to Map[role->groups]
  private Map<String, Set<TSentryGroup>> covertToRoleNameTGroupsMap(
      Map<String, Set<String>> groupRolesMap) {
    if (groupRolesMap == null || groupRolesMap.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, Set<TSentryGroup>> roleGroupsMap = Maps.newHashMap();
    for (Map.Entry<String, Set<String>> entry : groupRolesMap.entrySet()) {
      Set<String> roleNames = entry.getValue();
      if (roleNames != null) {
        for (String roleName : roleNames) {
          Set<TSentryGroup> tSentryGroups = roleGroupsMap.get(roleName);
          if (tSentryGroups == null) {
            tSentryGroups = new HashSet<>();
          }
          tSentryGroups.add(new TSentryGroup(entry.getKey()));
          roleGroupsMap.put(roleName, tSentryGroups);
        }
      }
    }
    return roleGroupsMap;
  }

  // covert the Map[user->roles] to Map[role->users]
  private Map<String, Set<String>> covertToRoleUsersMap(
      Map<String, Set<String>> userRolesMap) {
    if (userRolesMap == null || userRolesMap.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<String, Set<String>> roleUsersMap = new HashMap<>();
    for (Map.Entry<String, Set<String>> entry : userRolesMap.entrySet()) {
      Set<String> roleNames = entry.getValue();
      if (roleNames != null) {
        for (String roleName : roleNames) {
          Set<String> users = roleUsersMap.get(roleName);
          if (users == null) {
            users = new HashSet<>();
          }
          users.add(entry.getKey());
          roleUsersMap.put(roleName, users);
        }
      }
    }
    return roleUsersMap;
  }

  private void importRoleGroupMapping(PersistenceManager pm, Set<String> existRoleNames,
      Map<String, Set<TSentryGroup>> importedRoleGroupsMap) throws Exception {
    if (importedRoleGroupsMap == null || importedRoleGroupsMap.keySet() == null) {
      return;
    }
    for (Map.Entry<String, Set<TSentryGroup>> entry : importedRoleGroupsMap.entrySet()) {
      createRoleIfNotExist(pm, existRoleNames, entry.getKey());
      alterSentryRoleAddGroupsCore(pm, entry.getKey(), entry.getValue());
    }
  }

  private void importRoleUserMapping(PersistenceManager pm, Set<String> existRoleNames,
      Map<String, Set<String>> importedRoleUsersMap) throws Exception {
    if (importedRoleUsersMap == null || importedRoleUsersMap.keySet() == null) {
      return;
    }
    for (Map.Entry<String, Set<String>> entry : importedRoleUsersMap.entrySet()) {
      createRoleIfNotExist(pm, existRoleNames, entry.getKey());
      alterSentryRoleAddUsersCore(pm, entry.getKey(), entry.getValue());
    }
  }

  // drop all duplicated with the imported role
  private void dropDuplicatedRoleForImport(PersistenceManager pm, Set<String> existRoleNames,
      Set<String> importedRoleNames) throws Exception {
    Set<String> duplicatedRoleNames = Sets.intersection(existRoleNames, importedRoleNames);
    for (String droppedRoleName : duplicatedRoleNames) {
      dropSentryRoleCore(pm, droppedRoleName);
    }
  }

  // change all role name in lowercase
  private TSentryMappingData lowercaseRoleName(TSentryMappingData tSentryMappingData) {
    Map<String, Set<String>> sentryGroupRolesMap = tSentryMappingData.getGroupRolesMap();
    Map<String, Set<TSentryPrivilege>> sentryRolePrivilegesMap = tSentryMappingData
        .getRolePrivilegesMap();

    Map<String, Set<String>> newSentryGroupRolesMap = new HashMap<>();
    Map<String, Set<TSentryPrivilege>> newSentryRolePrivilegesMap = new HashMap<>();
    // for mapping data [group,role]
    for (Map.Entry<String, Set<String>> entry : sentryGroupRolesMap.entrySet()) {
      Collection<String> lowcaseRoles = Collections2.transform(entry.getValue(),
          new Function<String, String>() {
            @Override
            public String apply(String input) {
              return input.toLowerCase();
            }
          });
      newSentryGroupRolesMap.put(entry.getKey(), new HashSet<>(lowcaseRoles));
    }

    // for mapping data [role,privilege]
    for (Map.Entry<String,Set<TSentryPrivilege>> entry : sentryRolePrivilegesMap.entrySet()) {
      newSentryRolePrivilegesMap.put(entry.getKey().toLowerCase(), entry.getValue());
    }

    tSentryMappingData.setGroupRolesMap(newSentryGroupRolesMap);
    tSentryMappingData.setRolePrivilegesMap(newSentryRolePrivilegesMap);
    return tSentryMappingData;
  }

  // import the mapping data for [role,privilege]
  private void importRolePrivilegeMapping(PersistenceManager pm, Set<String> existRoleNames,
      Map<String, Set<TSentryPrivilege>> sentryRolePrivilegesMap) throws Exception {
    if (sentryRolePrivilegesMap != null) {
      for (Map.Entry<String, Set<TSentryPrivilege>> entry : sentryRolePrivilegesMap.entrySet()) {
        // if the rolenName doesn't exist, create it and add it to existRoleNames
        createRoleIfNotExist(pm, existRoleNames, entry.getKey());
        // get the privileges for the role
        Set<TSentryPrivilege> tSentryPrivileges = entry.getValue();
        for (TSentryPrivilege tSentryPrivilege : tSentryPrivileges) {
          alterSentryGrantPrivilegeCore(pm, SentryPrincipalType.ROLE, entry.getKey(), tSentryPrivilege);
        }
      }
    }
  }

  private void createRoleIfNotExist(PersistenceManager pm,
      Set<String> existRoleNames, String roleName) throws Exception {
    String lowerRoleName = trimAndLower(roleName);
    // if the rolenName doesn't exist, create it.
    if (!existRoleNames.contains(lowerRoleName)) {
      // update the exist role name set
      existRoleNames.add(lowerRoleName);
      // Create role in the persistent storage
      pm.makePersistent(new MSentryRole(trimAndLower(roleName)));
    }
  }

  /**
   * Return set of rolenames from a collection of roles
   * @param roles - collection of roles
   * @return set of role names for each role in collection
   */
  public static Set<String> rolesToRoleNames(final Iterable<MSentryRole> roles) {
    Set<String> roleNames = new HashSet<>();
    for (MSentryRole mSentryRole : roles) {
      roleNames.add(mSentryRole.getRoleName());
    }
    return roleNames;
  }

  /**
   * Return exception for nonexistent role
   * @param roleName Role name
   * @return SentryNoSuchObjectException with appropriate message
   */
  private static SentryNoSuchObjectException noSuchRole(String roleName) {
    return new SentryNoSuchObjectException("Role " + roleName);
  }

  /**
   * Return exception for nonexistent user
   * @param userName User name
   * @return SentryNoSuchObjectException with appropriate message
   */
  private static SentryNoSuchObjectException noSuchUser(String userName) {
    return new SentryNoSuchObjectException("nonexistent user " + userName);
  }

  /**
   * Return exception for nonexistent group
   * @param groupName Group name
   * @return SentryNoSuchObjectException with appropriate message
   */
  private static SentryNoSuchObjectException noSuchGroup(String groupName) {
    return new SentryNoSuchObjectException("Group " + groupName);

  }

  /**
   * Return exception for nonexistent update
   * @param changeID change ID
   * @return SentryNoSuchObjectException with appropriate message
   */
  private SentryNoSuchObjectException noSuchUpdate(final long changeID) {
    return new SentryNoSuchObjectException("nonexistent update + " + changeID);
  }

  /**
   * Gets the last processed change ID for perm/path delta changes.
   *
   * @param pm the PersistenceManager
   * @param changeCls the class of a delta c
   *
   * @return the last processed changedID for the delta changes. If no
   *         change found then return 0.
   */
  static <T extends MSentryChange> Long getLastProcessedChangeIDCore(
      PersistenceManager pm, Class<T> changeCls) {
    return getMaxPersistedIDCore(pm, changeCls, "changeID", EMPTY_CHANGE_ID);
  }

  /**
   * Gets the last processed Notification ID
   * <p>
   * As the table might have zero or one record, result of the query
   * might be null OR instance of MSentryHmsNotification.
   *
   * @param pm the PersistenceManager
   * @return EMPTY_NOTIFICATION_ID(0) when there are no notifications processed.
   * else  last NotificationID processed by HMSFollower
   */
  static Long getLastProcessedNotificationIDCore(
      PersistenceManager pm) {
    return getMaxPersistedIDCore(pm, MSentryHmsNotification.class, "notificationId", EMPTY_NOTIFICATION_ID);
  }

  /**
   * Set the notification ID of last processed HMS notification and remove all
   * subsequent notifications stored.
   */
  public void setLastProcessedNotificationID(final Long notificationId) throws Exception {
    LOGGER.debug("Persisting Last Processed Notification ID {}", notificationId);
    tm.executeTransaction(
            pm -> {
              deleteNotificationsSince(pm, notificationId + 1);
              return pm.makePersistent(new MSentryHmsNotification(notificationId));
            });
  }

  /**
   * Set the notification ID of last processed HMS notification.
   */
  public void persistLastProcessedNotificationID(final Long notificationId) throws Exception {
    LOGGER.debug("Persisting Last Processed Notification ID {}", notificationId);
    tm.executeTransaction(
            pm -> pm.makePersistent(new MSentryHmsNotification(notificationId)));
  }

  /**
   * Gets the last processed change ID for perm delta changes.
   *
   * Internally invoke {@link #getLastProcessedChangeIDCore(PersistenceManager, Class)}
   *
   * @return latest perm change ID.
   */
  public Long getLastProcessedPermChangeID() throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return getLastProcessedChangeIDCore(pm, MSentryPermChange.class);
            });
  }

  /**
   * Gets the last processed change ID for path delta changes.
   *
   * @return latest path change ID.
   */
  public Long getLastProcessedPathChangeID() throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return getLastProcessedChangeIDCore(pm, MSentryPathChange.class);
            });
  }

  /**
   * Get the notification ID of last processed path delta change.
   *
   * @return the notification ID of latest path change. If no change
   *         found then return 0.
   */
  public Long getLastProcessedNotificationID() throws Exception {
    long notificationId = tm.executeTransaction(
            pm -> {
              long notificationId1 =  getLastProcessedNotificationIDCore(pm);
              return notificationId1;
            });
    LOGGER.debug("Retrieving Last Processed Notification ID {}", notificationId);
    return notificationId;
  }

  /**
   * Gets the last processed HMS snapshot ID for path delta changes.
   *
   * @return latest path change ID.
   */
  public long getLastProcessedImageID() throws Exception {
    return tm.executeTransaction(pm -> {
      pm.setDetachAllOnCommit(false); // No need to detach objects
      return getCurrentAuthzPathsSnapshotID(pm);
    });
  }

  /**
   * Get the MSentryPermChange object by ChangeID.
   *
   * @param changeID the given changeID.
   * @return MSentryPermChange
   */
  public MSentryPermChange getMSentryPermChangeByID(final long changeID) throws Exception {
    return tm.executeTransaction(
            pm -> {
              Query query = pm.newQuery(MSentryPermChange.class);
              query.setFilter("this.changeID == id");
              query.declareParameters("long id");
              List<MSentryPermChange> permChanges = (List<MSentryPermChange>)query.execute(changeID);
              if (permChanges == null) {
                throw noSuchUpdate(changeID);
              }
              if (permChanges.size() > 1) {
                throw new Exception("Inconsistent permission delta: " + permChanges.size()
                    + " permissions for the same id, " + changeID);
              }

              return permChanges.get(0);
            });
  }

  /**
   * Fetch all {@link MSentryChange} in the database.
   *
   * @param cls the class of the Sentry delta change.
   * @return a list of Sentry delta changes.
   * @throws Exception
   */
  @SuppressWarnings("unchecked")
  private <T extends MSentryChange> List<T> getMSentryChanges(final Class<T> cls)
      throws Exception {
    return tm.executeTransaction(
            pm -> {
              Query query = pm.newQuery(cls);
              return (List<T>) query.execute();
            });
  }

  /**
   * Fetch all {@link MSentryPermChange} in the database. It should only be used in the tests.
   *
   * @return a list of permission changes.
   * @throws Exception
   */
  @VisibleForTesting
  List<MSentryPermChange> getMSentryPermChanges() throws Exception {
    return getMSentryChanges(MSentryPermChange.class);
  }

  /**
   * Fetch all {@link MSentryHmsNotification} in the database. It should only be used in the tests.
   *
   * @return a list of notifications ids.
   * @throws Exception
   */
  @VisibleForTesting
  List<MSentryHmsNotification> getMSentryHmsNotificationCore() throws Exception {
    return tm.executeTransaction(
            pm -> {
              Query query = pm.newQuery(MSentryHmsNotification.class);
              return (List<MSentryHmsNotification>) query.execute();
            });
  }

    /**
   * Checks if any MSentryChange object exists with the given changeID.
   *
   * @param pm PersistenceManager
   * @param changeCls class instance of type {@link MSentryChange}
   * @param changeID changeID
   * @return true if found the MSentryChange object, otherwise false.
   * @throws Exception
   */
  @SuppressWarnings("unchecked")
  private <T extends MSentryChange> Boolean changeExistsCore(
          PersistenceManager pm, Class<T> changeCls, final long changeID)
              throws Exception {
    Query query = pm.newQuery(changeCls);
    query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
    query.setFilter("this.changeID == id");
    query.declareParameters("long id");
    List<T> changes = (List<T>)query.execute(changeID);
    return !changes.isEmpty();
  }

  /**
   * Checks if any MSentryPermChange object exists with the given changeID.
   *
   * @param changeID
   * @return true if found the MSentryPermChange object, otherwise false.
   * @throws Exception
   */
  public Boolean permChangeExists(final long changeID) throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return changeExistsCore(pm, MSentryPermChange.class, changeID);
            });
  }

  /**
   * Checks if any MSentryPathChange object exists with the given changeID.
   *
   * @param changeID
   * @return true if found the MSentryPathChange object, otherwise false.
   * @throws Exception
   */
  public Boolean pathChangeExists(final long changeID) throws Exception {
    return tm.executeTransaction(
            pm -> {
              pm.setDetachAllOnCommit(false); // No need to detach objects
              return changeExistsCore(pm, MSentryPathChange.class, changeID);
            });
  }

  /**
   * Gets the MSentryPathChange object by ChangeID.
   *
   * @param changeID the given changeID
   * @return the MSentryPathChange object with corresponding changeID.
   * @throws Exception
   */
  public MSentryPathChange getMSentryPathChangeByID(final long changeID) throws Exception {
    return tm.executeTransaction(
            pm -> {
              Query query = pm.newQuery(MSentryPathChange.class);
              query.setFilter("this.changeID == id");
              query.declareParameters("long id");
              List<MSentryPathChange> pathChanges = (List<MSentryPathChange>)query.execute(changeID);
              if (pathChanges == null) {
                throw noSuchUpdate(changeID);
              }
              if (pathChanges.size() > 1) {
                throw new Exception("Inconsistent path delta: " + pathChanges.size()
                    + " paths for the same id, " + changeID);
              }

              return pathChanges.get(0);
            });
  }

  /**
   * Fetch all {@link MSentryPathChange} in the database. It should only be used in the tests.
   */
  @VisibleForTesting
  List<MSentryPathChange> getMSentryPathChanges() throws Exception {
    return getMSentryChanges(MSentryPathChange.class);
  }

  /**
   * Gets a list of MSentryChange objects greater than or equal to the given changeID.
   *
   * @param changeID
   * @return a list of MSentryChange objects. It can returns an empty list.
   * @throws Exception
   */
  @SuppressWarnings("unchecked")
  private <T extends MSentryChange> List<T> getMSentryChangesCore(PersistenceManager pm,
      Class<T> changeCls, final long changeID) throws Exception {
    Query query = pm.newQuery(changeCls);
    query.setFilter("this.changeID >= t");
    query.declareParameters("long t");
    query.setOrdering("this.changeID ascending");
    return (List<T>) query.execute(changeID);
  }

  /**
   * Gets a list of MSentryPathChange objects greater than or equal to the given changeID.
   * If there is any path delta missing in {@link MSentryPathChange} table, an empty list is returned.
   *
   * @param changeID  Requested changeID
   * @return a list of MSentryPathChange objects. May be empty.
   * @throws Exception
   */
  public List<MSentryPathChange> getMSentryPathChanges(final long changeID)
          throws Exception {
    return tm.executeTransaction(pm -> {
      // 1. We first rextrieve the entire list of latest delta changes since the changeID
      List<MSentryPathChange> pathChanges =
              getMSentryChangesCore(pm, MSentryPathChange.class, changeID);
      // 2. We then check for consistency issues with delta changes
      if (validateDeltaChanges(changeID, pathChanges)) {
        // If everything is in order, return the delta changes
        return pathChanges;
      }

      // Looks like delta change validation failed. Return an empty list.
      return Collections.emptyList();
    });
  }

  /**
   * Gets a list of MSentryPermChange objects greater than or equal to the given ChangeID.
   * If there is any path delta missing in {@link MSentryPermChange} table, an empty list is returned.
   *
   * @param changeID Requested changeID
   * @return a list of MSentryPathChange objects. May be empty.
   * @throws Exception
   */
  public List<MSentryPermChange> getMSentryPermChanges(final long changeID)
      throws Exception {
    return tm.executeTransaction(pm -> {
      // 1. We first retrieve the entire list of latest delta changes since the changeID
      List<MSentryPermChange> permChanges =
          getMSentryChangesCore(pm, MSentryPermChange.class, changeID);
      // 2. We then check for consistency issues with delta changes
      if (validateDeltaChanges(changeID, permChanges)) {
        // If everything is in order, return the delta changes
        return permChanges;
      }

      // Looks like delta change validation failed. Return an empty list.
      return Collections.emptyList();
    });
  }

  /**
   * Validate if the delta changes are consistent with the requested changeID.
   * <p>
   *   1. Checks if the first delta changeID matches the requested changeID
   *   (This verifies the delta table still has entries starting from the changeID) <br/>
   *   2. Checks if there are any holes in the list of delta changes <br/>
   * </p>
   * @param changeID Requested changeID
   * @param changes List of delta changes
   * @return True if the delta changes are all consistent otherwise returns False
   */
  public <T extends MSentryChange> boolean validateDeltaChanges(final long changeID, List<T> changes) {
    if (changes.isEmpty()) {
      // If database has nothing more recent than CHANGE_ID return True
      return true;
    }

    // The first delta change from the DB should match the changeID
    // If it doesn't, then it means the delta table no longer has entries starting from the
    // requested CHANGE_ID
    if (changes.get(0).getChangeID() != changeID) {
      LOGGER.debug(String.format("Starting delta change from %s is off from the requested id. " +
          "Requested changeID: %s, Missing delta count: %s",
          changes.get(0).getClass().getCanonicalName(), changeID, changes.get(0).getChangeID() - changeID));
      return false;
    }

    // Check for holes in the delta changes.
    if (!MSentryUtil.isConsecutive(changes)) {
      String pathChangesIds = MSentryUtil.collapseChangeIDsToString(changes);
      LOGGER.error(String.format("Certain delta is missing in %s! The table may get corrupted. " +
          "Start changeID %s, Current size of elements = %s. path changeID list: %s",
          changes.get(0).getClass().getCanonicalName(), changeID, changes.size(), pathChangesIds));
      return false;
    }

    return true;
  }

  /**
   * Execute actual Perm/Path action transaction, e.g dropSentryRole, and persist corresponding
   * Update in a single transaction if persistUpdateDeltas is true.
   * Note that this method only applies to TransactionBlock that
   * does not have any return value.
   * <p>
   * Failure in any TransactionBlock would cause the whole transaction
   * to fail.
   *
   * @param update
   * @param transactionBlock
   * @throws Exception
   */
  private void execute(Update update,
        TransactionBlock<Object> transactionBlock) throws Exception {
    execute(update != null ? Collections.singletonList(update) : Collections.emptyList(), transactionBlock);
  }


  /**
   * Execute multiple delta updates in a single transaction.
   * Note that this method only applies to TransactionBlock that
   * does not have any return value.
   * <p>
   * Failure in any TransactionBlock would cause the whole transaction
   * to fail.
   *
   * @param updates list of delta updates
   * @throws Exception
   */
  private void execute(List<Update> updates, TransactionBlock<Object> transactionBlock) throws Exception {
    // Currently this API is used to update the owner privilege. This needs two DeltaTransactionBlock's to record
    // revoking/granting owner privilege and one TransactionBlock to perform actual permission change.
    // Default size of tbs is picked accordingly.
    List<TransactionBlock<Object>> tbs = new ArrayList<>(3);
    if (persistUpdateDeltas && updates != null && updates.size() > 0) {
      for (Update update : updates) {
        tbs.add(new DeltaTransactionBlock(update));
      }
    }
    tbs.add(transactionBlock);
    tm.executeTransactionBlocksWithRetry(tbs);
  }

  /**
   * Checks if a notification was already processed by searching for the hash value
   * on the MSentryPathChange table.
   *
   * @param hash A SHA-1 hex hash that represents a unique notification
   * @return True if the notification was already processed; False otherwise
   */
  public boolean isNotificationProcessed(final String hash) throws Exception {
    return tm.executeTransactionWithRetry(pm -> {
      pm.setDetachAllOnCommit(false);
      Query query = pm.newQuery(MSentryPathChange.class);
      query.setFilter("this.notificationHash == hash");
      query.setUnique(true);
      query.declareParameters("java.lang.String hash");
      MSentryPathChange changes = (MSentryPathChange) query.execute(hash);

      return changes != null;
    });
  }

  /**
   * Get a single principal with the given name and type inside a transaction
   * @param pm Persistence Manager instance
   * @param name Role/user name (should not be null)
   * @param type Type of principal
   * @return single PrivilegePrincipal with the given name and type
   */
  public PrivilegePrincipal getEntity(PersistenceManager pm, String name, SentryPrincipalType type) {
    Query query;

    if(type == SentryPrincipalType.ROLE) {
      query = pm.newQuery(MSentryRole.class);
      query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
      query.setFilter("this.roleName == :roleName");
      query.setUnique(true);

      FetchGroup grp = pm.getFetchGroup(MSentryRole.class, "fetchPrivileges");
      grp.addMember("privileges");
      pm.getFetchPlan().addGroup("fetchPrivileges");
    } else {
      query = pm.newQuery(MSentryUser.class);
      query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");
      query.setFilter("this.userName == :userName");
      query.setUnique(true);

      FetchGroup grp = pm.getFetchGroup(MSentryUser.class, "fetchPrivileges");
      grp.addMember("privileges");
      pm.getFetchPlan().addGroup("fetchPrivileges");
    }
    return (PrivilegePrincipal) query.execute(name);
  }

  /**
   * Returns all roles and privileges found on the Sentry database.
   *
   * @return A mapping between role and privileges in the form [roleName, set<privileges>].
   *         If a role does not have privileges, then an empty set is returned for that role.
   *         If no roles are found, then an empty map object is returned.
   */
  @Override
  public Map<String, Set<TSentryPrivilege>> getAllRolesPrivileges() throws Exception {
    return tm.executeTransaction(
      pm -> {
        // No need to detach objects
        pm.setDetachAllOnCommit(false);

        Query query = pm.newQuery(MSentryRole.class);
        query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

        FetchGroup grp = pm.getFetchGroup(MSentryRole.class, "fetchPrivileges");
        grp.addMember("privileges");
        pm.getFetchPlan().addGroup("fetchPrivileges");

        List<MSentryRole> mSentryRoles = (List<MSentryRole>)query.execute();
        if (mSentryRoles == null || mSentryRoles.isEmpty()) {
          return Collections.emptyMap();
        }

        // Transform the list of privileges to a map [roleName, set<privileges>]
        Map<String, Set<TSentryPrivilege>> allRolesPrivileges = Maps.newHashMap();
        for (MSentryRole mSentryRole : mSentryRoles) {
          // convertToTSentryPrivileges returns an empty set in case is null
          Set<TSentryPrivilege> tPrivileges = convertToTSentryPrivileges(mSentryRole.getPrivileges());
          allRolesPrivileges.put(mSentryRole.getRoleName(), tPrivileges);
        }

        return allRolesPrivileges;
      }
    );
  }

  /**
   * Returns all users and privileges found on the Sentry database.
   *
   * @return A mapping between user and privileges in the form [userName, set<privileges>].
   *         If a user does not have privileges, then an empty set is returned for that user.
   *         If no users are found, then an empty map object is returned.
   */
  @Override
  public Map<String, Set<TSentryPrivilege>> getAllUsersPrivileges() throws Exception {
    return tm.executeTransaction(
      pm -> {
        // No need to detach objects
        pm.setDetachAllOnCommit(false);

        Query query = pm.newQuery(MSentryUser.class);
        query.addExtension(LOAD_RESULTS_AT_COMMIT, "false");

        FetchGroup grp = pm.getFetchGroup(MSentryUser.class, "fetchPrivileges");
        grp.addMember("privileges");
        pm.getFetchPlan().addGroup("fetchPrivileges");

        List<MSentryUser> mSentryUsers = (List<MSentryUser>)query.execute();
        if (mSentryUsers == null || mSentryUsers.isEmpty()) {
          return Collections.emptyMap();
        }

        // Transform the list of privileges to a map [userName, set<privileges>]
        Map<String, Set<TSentryPrivilege>> allUsersPrivileges = Maps.newHashMap();
        for (MSentryUser mSentryUser : mSentryUsers) {
          // convertToTSentryPrivileges returns an empty set in case is null
          Set<TSentryPrivilege> tPrivileges = convertToTSentryPrivileges(mSentryUser.getPrivileges());
          allUsersPrivileges.put(mSentryUser.getUserName(), tPrivileges);
        }

        return allUsersPrivileges;
      }
    );
  }
}
