Repository: sentry
Updated Branches:
  refs/heads/master 2c5723e15 -> 8028cef7e


SENTRY-2307: Avoid HMS event synchronization while sentry is fetching full 
snapshot (Kalyan Kumar Kalvagadda reviewed by Lina li)


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/8028cef7
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/8028cef7
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/8028cef7

Branch: refs/heads/master
Commit: 8028cef7efb6c1a2e8c493ed1d1566aae176912d
Parents: 2c5723e
Author: Kalyan Kumar Kalvagadda <kkal...@cloudera.com>
Authored: Wed Aug 22 11:50:34 2018 -0500
Committer: Kalyan Kumar Kalvagadda <kkal...@cloudera.com>
Committed: Wed Aug 22 11:51:47 2018 -0500

----------------------------------------------------------------------
 .../thrift/SentryPolicyStoreProcessor.java      | 11 ++++-
 .../thrift/FullUpdateInitializerState.java      | 42 +++++++++++++++++++
 .../sentry/service/thrift/SentryHMSClient.java  |  3 ++
 .../sentry/service/thrift/SentryStateBank.java  | 24 +++++++++++
 .../thrift/TestSentryPolicyStoreProcessor.java  | 43 ++++++++++++++++++++
 .../service/thrift/TestSentryHMSClient.java     | 25 +++++++++++-
 6 files changed, 146 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyStoreProcessor.java
 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyStoreProcessor.java
index 36b635a..008a48e 100644
--- 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyStoreProcessor.java
+++ 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyStoreProcessor.java
@@ -63,6 +63,8 @@ import 
org.apache.sentry.service.common.ServiceConstants.ConfUtilties;
 import org.apache.sentry.service.common.ServiceConstants.SentryPrincipalType;
 import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
 import org.apache.sentry.api.common.Status;
+import org.apache.sentry.service.thrift.FullUpdateInitializerState;
+import org.apache.sentry.service.thrift.SentryStateBank;
 import org.apache.sentry.service.thrift.TSentryResponseStatus;
 import org.apache.thrift.TException;
 import org.apache.log4j.Logger;
@@ -1631,7 +1633,14 @@ public class SentryPolicyStoreProcessor implements 
SentryPolicyService.Iface {
    */
   long syncEventId(long eventId) {
     try {
-      return sentryStore.getCounterWait().waitFor(eventId);
+        if (!SentryStateBank.isEnabled(FullUpdateInitializerState.COMPONENT,
+            FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS)) {
+          return sentryStore.getCounterWait().waitFor(eventId);
+        } else {
+          LOGGER.info("HMS event synchronization is disabled temporarily as 
sentry is in the process of " +
+                  "fetching full snapshot. No action needed");
+          return eventId;
+        }
     } catch (InterruptedException e) {
       String msg = String.format("wait request for id %d is interrupted",
               eventId);

http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/FullUpdateInitializerState.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/FullUpdateInitializerState.java
 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/FullUpdateInitializerState.java
new file mode 100644
index 0000000..8f423a4
--- /dev/null
+++ 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/FullUpdateInitializerState.java
@@ -0,0 +1,42 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.service.thrift;
+
+/**
+ * States for the FullUpdateInitializer
+ */
+public enum FullUpdateInitializerState implements SentryState {
+  /**
+   * If the FullUpdateInitializer is in the process of taking full snapshot
+   */
+  FULL_SNAPSHOT_INPROGRESS;
+
+  /**
+   * The component name this state is for.
+   */
+  public static final String COMPONENT = "FullUpdateInitializer";
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public long getValue() {
+    return 1 << this.ordinal();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryHMSClient.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryHMSClient.java
 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryHMSClient.java
index cfb0d78..4baeb67 100644
--- 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryHMSClient.java
+++ 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryHMSClient.java
@@ -250,6 +250,7 @@ public class SentryHMSClient implements AutoCloseable {
     try (FullUpdateInitializer updateInitializer =
              new FullUpdateInitializer(hiveConnectionFactory, conf);
          Context context = updateTimer.time()) {
+      
SentryStateBank.enableState(FullUpdateInitializerState.COMPONENT,FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS);
       Map<String, Collection<String>> pathsUpdate = 
updateInitializer.getFullHMSSnapshot();
       logMessage = "Obtained full HMS snapshot";
       LOGGER.info(logMessage);
@@ -259,6 +260,8 @@ public class SentryHMSClient implements AutoCloseable {
       failedSnapshotsCount.inc();
       LOGGER.error("Snapshot created failed ", exception);
       throw exception;
+    } finally {
+      
SentryStateBank.disableState(FullUpdateInitializerState.COMPONENT,FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryStateBank.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryStateBank.java
 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryStateBank.java
index 2c05d49..2afe919 100644
--- 
a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryStateBank.java
+++ 
b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/service/thrift/SentryStateBank.java
@@ -67,6 +67,7 @@ public final class SentryStateBank {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(SentryStateBank.class);
   private static final AtomicLongMap<String> states = AtomicLongMap.create();
+  private static final AtomicLongMap<String> allStates = 
AtomicLongMap.create();
   private static final ReentrantReadWriteLock lock = new 
ReentrantReadWriteLock();
 
   protected SentryStateBank() {
@@ -75,12 +76,14 @@ public final class SentryStateBank {
   @VisibleForTesting
   static void clearAllStates() {
     states.clear();
+    allStates.clear();
     LOGGER.debug("All states have been cleared.");
   }
 
   @VisibleForTesting
   static void resetComponentState(String component) {
     states.remove(component);
+    allStates.remove(component);
     LOGGER.debug("All states have been cleared for component {}", component);
   }
 
@@ -94,6 +97,7 @@ public final class SentryStateBank {
     lock.writeLock().lock();
     try {
       states.put(component, states.get(component) | state.getValue());
+      allStates.put(component, states.get(component) | state.getValue());
       if (LOGGER.isDebugEnabled()) {
         LOGGER.debug("{} entered state {}", component, state.toString());
       }
@@ -156,4 +160,24 @@ public final class SentryStateBank {
       lock.readLock().unlock();
     }
   }
+
+  /**
+   * Checks if all of the states passed in were enabled
+   *
+   * @param component The component for the states
+   * @param passedStates the SentryStates to check
+   */
+  public static boolean wereStatesEnabled(String component, Set<SentryState> 
passedStates) {
+    lock.readLock().lock();
+    try {
+      long value = 0L;
+
+      for (SentryState state : passedStates) {
+        value += state.getValue();
+      }
+      return (allStates.get(component) & value) == value;
+    } finally {
+      lock.readLock().unlock();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/api/service/thrift/TestSentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/api/service/thrift/TestSentryPolicyStoreProcessor.java
 
b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/api/service/thrift/TestSentryPolicyStoreProcessor.java
index 2de6253..c23b385 100644
--- 
a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/api/service/thrift/TestSentryPolicyStoreProcessor.java
+++ 
b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/api/service/thrift/TestSentryPolicyStoreProcessor.java
@@ -40,6 +40,8 @@ import 
org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
 import org.apache.sentry.provider.db.service.persistent.SentryStore;
 import org.apache.sentry.service.common.ServiceConstants.SentryPrincipalType;
 import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
+import org.apache.sentry.service.thrift.FullUpdateInitializerState;
+import org.apache.sentry.service.thrift.SentryStateBank;
 import org.junit.After;
 import org.junit.Assert;
 
@@ -419,6 +421,47 @@ public class TestSentryPolicyStoreProcessor {
   }
 
   @Test
+  public void testNotificationSync() throws Exception {
+
+    SentryPolicyStoreProcessor sentryServiceHandler =
+            new 
SentryPolicyStoreProcessor(ApiConstants.SentryPolicyServiceConstants.SENTRY_POLICY_SERVICE_NAME,
+                    conf, sentryStore);
+    TSentryAuthorizable authorizable = new TSentryAuthorizable();
+    authorizable.setDb(DBNAME);
+
+    TSentryHmsEventNotification notification = new 
TSentryHmsEventNotification();
+    notification.setId(1L);
+    notification.setOwnerType(TSentryPrincipalType.ROLE);
+    notification.setOwnerName(OWNER);
+    notification.setAuthorizable(authorizable);
+    notification.setEventType(EventType.CREATE_DATABASE.toString());
+
+    sentryServiceHandler.sentry_notify_hms_event(notification);
+
+    // Verify that synchronization is attempted
+    Mockito.verify(
+            sentryStore, Mockito.times(1)
+    ).getCounterWait();
+
+    Mockito.verify(counterWait, Mockito.times(1)).waitFor(1L);
+
+    SentryStateBank.enableState(FullUpdateInitializerState.COMPONENT,
+        FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS);
+
+    sentryServiceHandler.sentry_notify_hms_event(notification);
+
+    // Verify that synchronization is not attempted because
+    // full snapshot is in progress
+    Mockito.reset(sentryStore);
+    Mockito.reset(counterWait);
+    Mockito.verify(
+            sentryStore, Mockito.times(0)
+    ).getCounterWait();
+    Mockito.verify(counterWait, Mockito.times(0)).waitFor(1L);
+
+  }
+
+  @Test
   public void testAlterTableEventProcessing() throws Exception {
 
     conf.set(SENTRY_DB_POLICY_STORE_OWNER_AS_PRIVILEGE, 
SentryOwnerPrivilegeType.ALL.toString());

http://git-wip-us.apache.org/repos/asf/sentry/blob/8028cef7/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/service/thrift/TestSentryHMSClient.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/service/thrift/TestSentryHMSClient.java
 
b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/service/thrift/TestSentryHMSClient.java
index 38668ca..04e562f 100644
--- 
a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/service/thrift/TestSentryHMSClient.java
+++ 
b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/service/thrift/TestSentryHMSClient.java
@@ -25,6 +25,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.HashSet;
+import java.util.Arrays;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
 import org.apache.hadoop.hive.metastore.api.CurrentNotificationEventId;
@@ -36,6 +38,7 @@ import org.apache.hadoop.hive.metastore.api.Table;
 import org.apache.sentry.provider.db.service.persistent.PathsImage;
 import org.apache.thrift.TException;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -107,6 +110,11 @@ public class TestSentryHMSClient {
     client = new SentryHMSClient(conf, 
(HiveConnectionFactory)hiveConnectionFactory);
   }
 
+  @Before
+  public void setUp() {
+    SentryStateBank.clearAllStates();
+  }
+
   /**
    * Creating snapshot when SentryHMSClient is not connected to HMS
    */
@@ -116,6 +124,10 @@ public class TestSentryHMSClient {
     Assert.assertFalse(client.isConnected());
     PathsImage snapshotInfo = client.getFullSnapshot();
     Assert.assertTrue(snapshotInfo.getPathImage().isEmpty());
+    Assert.assertFalse("FullUpdateInitializer is not expected to be in 
progress",
+            SentryStateBank.isEnabled(FullUpdateInitializerState.COMPONENT, 
FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS));
+    
Assert.assertFalse(SentryStateBank.wereStatesEnabled(FullUpdateInitializerState.COMPONENT,
 new HashSet<SentryState>(
+            
Arrays.asList(FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS))));
   }
 
   /**
@@ -129,6 +141,10 @@ public class TestSentryHMSClient {
     Assert.assertTrue(client.isConnected());
     PathsImage snapshotInfo = client.getFullSnapshot();
     Assert.assertTrue(snapshotInfo.getPathImage().isEmpty());
+    Assert.assertFalse("FullUpdateInitializer is not expected to be in 
progress",
+            SentryStateBank.isEnabled(FullUpdateInitializerState.COMPONENT, 
FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS));
+    
Assert.assertTrue(SentryStateBank.wereStatesEnabled(FullUpdateInitializerState.COMPONENT,
 new HashSet<SentryState>(
+            
Arrays.asList(FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS))));
   }
 
   /**
@@ -164,6 +180,10 @@ public class TestSentryHMSClient {
 
     snapshotInfo = client.getFullSnapshot();
     Assert.assertTrue(snapshotInfo.getPathImage().isEmpty());
+    Assert.assertFalse("FullUpdateInitializer is not expected to be in 
progress",
+            SentryStateBank.isEnabled(FullUpdateInitializerState.COMPONENT, 
FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS));
+    
Assert.assertTrue(SentryStateBank.wereStatesEnabled(FullUpdateInitializerState.COMPONENT,
 new HashSet<SentryState>(
+            
Arrays.asList(FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS))));
   }
 
   /**
@@ -194,7 +214,10 @@ public class TestSentryHMSClient {
         snapshotInfo.getPathImage().get("db2.tab21"));
     Assert.assertEquals(Sets.newHashSet("db3/tab31"), 
snapshotInfo.getPathImage().get("db3.tab31"));
     Assert.assertEquals(snapshotInfo.getId(), mockClient.eventId);
-
+    Assert.assertFalse("FullUpdateInitializer is not expected to be in 
progress",
+            SentryStateBank.isEnabled(FullUpdateInitializerState.COMPONENT, 
FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS));
+    
Assert.assertTrue(SentryStateBank.wereStatesEnabled(FullUpdateInitializerState.COMPONENT,
 new HashSet<SentryState>(
+            
Arrays.asList(FullUpdateInitializerState.FULL_SNAPSHOT_INPROGRESS))));
   }
 
   /**

Reply via email to