Hi Vel,

This commit breaks the JDK7 compatibility (due to import java.util.stream
.Collectors;).

Colm.
---------- Forwarded message ----------
From: <[email protected]>
Date: Thu, Dec 7, 2017 at 1:31 PM
Subject: ranger git commit: RANGER-1827 microbenchmark for
RangerPolicyEngine
To: [email protected]


Repository: ranger
Updated Branches:
  refs/heads/master 291bb3e9c -> c806d1777


RANGER-1827 microbenchmark for RangerPolicyEngine

Change-Id: Ie4cfd8e021a6e08ddcb1e6d58012f186c6732ccb

Signed-off-by: Velmurugan Periasamy <[email protected]>


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

Branch: refs/heads/master
Commit: c806d17779144df3d0c60402a03cb167e69c1582
Parents: 291bb3e
Author: Endre Zoltan Kovacs <[email protected]>
Authored: Tue Oct 3 14:44:18 2017 +0200
Committer: Velmurugan Periasamy <[email protected]>
Committed: Thu Dec 7 08:31:47 2017 -0500

----------------------------------------------------------------------
 .../ranger/plugin/util/PerfDataRecorder.java    |  43 +++-
 ranger-tools/pom.xml                            |  21 ++
 .../ranger/policyengine/PerfTestClient.java     |  32 +--
 .../RangerAccessRequestDeserializer.java        |  52 ++++
 .../RangerResourceDeserializer.java             |  50 ++++
 .../perftest/v2/RangerPolicyFactory.java        | 256 +++++++++++++++++++
 .../RangerPolicyEnginePerformanceTest.java      | 224 ++++++++++++++++
 .../src/test/resources/log4j.properties         |   2 +
 .../testdata/performance-chart.template         |  44 ++++
 .../testdata/single-policy-template.json        |  83 ++++++
 .../testdata/single-request-template.json       |  16 ++
 11 files changed, 788 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/agents-common/src/main/java/org/apache/ranger/
plugin/util/PerfDataRecorder.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/PerfDataRecorder.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/
PerfDataRecorder.java
index 25f5334..2816369 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/
PerfDataRecorder.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/
PerfDataRecorder.java
@@ -23,6 +23,8 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;

+import com.google.common.collect.ImmutableMap;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -80,15 +82,15 @@ public class PerfDataRecorder {
                        long averageTimeSpent = 0L;

                        if (perfStatistic.numberOfInvocations.get() != 0L) {
-                               averageTimeSpent = perfStatistic.
millisecondsSpent.get()/perfStatistic.numberOfInvocations.get();
+                               averageTimeSpent = perfStatistic.
microSecondsSpent.get()/perfStatistic.numberOfInvocations.get();
                        }

                        String logMsg = "[" + tag + "]" +
-                             " execCount:" +
perfStatistic.numberOfInvocations.get()
+
-                             ", totalTimeTaken:" +
perfStatistic.millisecondsSpent.get()
+
-                             ", maxTimeTaken:" +
perfStatistic.maxTimeSpent.get() +
-                             ", minTimeTaken:" +
perfStatistic.minTimeSpent.get() +
-                             ", avgTimeTaken:" + averageTimeSpent;
+                             " execCount: " +
perfStatistic.numberOfInvocations.get()
+
+                             ", totalTimeTaken: " +
perfStatistic.microSecondsSpent.get()
+ " μs" +
+                             ", maxTimeTaken: " +
perfStatistic.maxTimeSpent.get() + " μs" +
+                             ", minTimeTaken: " +
perfStatistic.minTimeSpent.get() + " μs" +
+                             ", avgTimeTaken: " + averageTimeSpent + " μs";

                        LOG.info(logMsg);
                        PERF.debug(logMsg);
@@ -125,15 +127,22 @@ public class PerfDataRecorder {
                }
        }

-       private static class PerfStatistic {
+       public static Map<String, PerfStatistic> exposeStatistics() {
+               if (instance != null) {
+                       return ImmutableMap.copyOf(instance.perfStatistics);
+               }
+               return ImmutableMap.of();
+       }
+
+       public static class PerfStatistic {
                private AtomicLong numberOfInvocations = new AtomicLong(0L);
-               private AtomicLong millisecondsSpent = new AtomicLong(0L);
+               private AtomicLong microSecondsSpent = new AtomicLong(0L);
                private AtomicLong minTimeSpent = new
AtomicLong(Long.MAX_VALUE);
                private AtomicLong maxTimeSpent = new
AtomicLong(Long.MIN_VALUE);

                void addPerfDataItem(final long timeTaken) {
                        numberOfInvocations.getAndIncrement();
-                       millisecondsSpent.getAndAdd(timeTaken);
+                       microSecondsSpent.getAndAdd(timeTaken);

                        long min = minTimeSpent.get();
                        if(timeTaken < min) {
@@ -145,5 +154,21 @@ public class PerfDataRecorder {
                                maxTimeSpent.compareAndSet(max, timeTaken);
                        }
                }
+
+               public long getNumberOfInvocations() {
+                       return numberOfInvocations.get();
+               }
+
+               public long getMicroSecondsSpent() {
+                       return microSecondsSpent.get();
+               }
+
+               public long getMinTimeSpent() {
+                       return minTimeSpent.get();
+               }
+
+               public long getMaxTimeSpent() {
+                       return maxTimeSpent.get();
+               }
        }
 }

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/pom.xml
----------------------------------------------------------------------
diff --git a/ranger-tools/pom.xml b/ranger-tools/pom.xml
index ff37fb3..c6db1f2 100644
--- a/ranger-tools/pom.xml
+++ b/ranger-tools/pom.xml
@@ -58,5 +58,26 @@
             <artifactId>ranger-plugins-common</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+                       <groupId>be.ceau</groupId>
+                       <artifactId>chart</artifactId>
+                       <version>2.2.0</version>
+               </dependency>
     </dependencies>
+    <build>
+        <pluginManagement>
+            <plugins>
+            <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.20</version>
+                    <configuration>
+                    <excludes>
+                        <exclude>**/RangerPolicyEnginePerformanceT
est*</exclude>
+                    </excludes>
+                    </configuration>
+            </plugin>
+            </plugins>
+        </pluginManagement>
+        </build>
 </project>

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/main/java/org/apache/ranger/
policyengine/PerfTestClient.java
----------------------------------------------------------------------
diff --git a/ranger-tools/src/main/java/org/apache/ranger/
policyengine/PerfTestClient.java b/ranger-tools/src/main/java/
org/apache/ranger/policyengine/PerfTestClient.java
index e6095cb..5bdb783 100644
--- a/ranger-tools/src/main/java/org/apache/ranger/
policyengine/PerfTestClient.java
+++ b/ranger-tools/src/main/java/org/apache/ranger/
policyengine/PerfTestClient.java
@@ -42,14 +42,14 @@ public class PerfTestClient extends Thread {
        final int maxCycles;

        List<RequestData> requests = null;
-       static Gson gsonBuilder  = null;
+       private static Gson gson  = null;

        static {
-
-               gsonBuilder = new GsonBuilder().setDateFormat("
yyyyMMdd-HH:mm:ss.SSS-Z")
+               GsonBuilder builder = new GsonBuilder().setDateFormat("
yyyyMMdd-HH:mm:ss.SSS-Z");
+               gson = builder
                                .setPrettyPrinting()
-                               .registerTypeAdapter(RangerAccessRequest.class,
new RangerAccessRequestDeserializer())
-
.registerTypeAdapter(RangerAccessResource.class,
new RangerResourceDeserializer())
+                               .registerTypeAdapter(RangerAccessRequest.class,
new RangerAccessRequestDeserializer(builder))
+
.registerTypeAdapter(RangerAccessResource.class,
new RangerResourceDeserializer(builder))
                                .create();
        }

@@ -89,7 +89,7 @@ public class PerfTestClient extends Thread {
                        Type listType = new TypeToken<List<RequestData>>() {
                        }.getType();

-                       requests = gsonBuilder.fromJson(reader, listType);
+                       requests = gson.fromJson(reader, listType);

                        ret = true;
                }
@@ -156,24 +156,4 @@ public class PerfTestClient extends Thread {
                public void setRequest(RangerAccessRequest request) {
this.request = request;}
                public void setResult(RangerAccessResult result) {
this.result = result;}
        }
-
-       static class RangerAccessRequestDeserializer implements
JsonDeserializer<RangerAccessRequest> {
-               @Override
-               public RangerAccessRequest deserialize(JsonElement jsonObj,
Type type,
-
                JsonDeserializationContext context) throws
JsonParseException {
-                       RangerAccessRequestImpl ret =
gsonBuilder.fromJson(jsonObj, RangerAccessRequestImpl.class);
-
-                       ret.setAccessType(ret.getAccessType()); // to force
computation of isAccessTypeAny and isAccessTypeDelegatedAdmin
-
-                       return ret;
-               }
-       }
-
-       static class RangerResourceDeserializer implements
JsonDeserializer<RangerAccessResource>
{
-               @Override
-               public RangerAccessResource deserialize(JsonElement
jsonObj, Type type,
-
                     JsonDeserializationContext context) throws
JsonParseException {
-                       return gsonBuilder.fromJson(jsonObj,
RangerAccessResourceImpl.class);
-               }
-       }
 }

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerAccessRequestDeserializer.java
----------------------------------------------------------------------
diff --git a/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerAccessRequestDeserializer.java b/ranger-tools/src/main/java/
org/apache/ranger/policyengine/RangerAccessRequestDeserializer.java
new file mode 100644
index 0000000..fd7762d
--- /dev/null
+++ b/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerAccessRequestDeserializer.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ranger.policyengine;
+
+import java.lang.reflect.Type;
+
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+/**
+ * {@link JsonDeserializer} to assist {@link Gson} with selecting proper
type
+ * when encountering RangerAccessRequest interface in the source json.
+ */
+public class RangerAccessRequestDeserializer implements
JsonDeserializer<RangerAccessRequest>
{
+
+       private GsonBuilder gsonBuilder;
+
+       public RangerAccessRequestDeserializer(final GsonBuilder builder) {
+               this.gsonBuilder = builder;
+       }
+
+       @Override
+       public RangerAccessRequest deserialize(JsonElement jsonObj, Type
type, JsonDeserializationContext context) throws JsonParseException {
+               RangerAccessRequestImpl ret =
gsonBuilder.create().fromJson(jsonObj,
RangerAccessRequestImpl.class);
+               ret.setAccessType(ret.getAccessType()); // to force
computation of isAccessTypeAny and isAccessTypeDelegatedAdmin
+               return ret;
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerResourceDeserializer.java
----------------------------------------------------------------------
diff --git a/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerResourceDeserializer.java b/ranger-tools/src/main/java/
org/apache/ranger/policyengine/RangerResourceDeserializer.java
new file mode 100644
index 0000000..da549f1
--- /dev/null
+++ b/ranger-tools/src/main/java/org/apache/ranger/policyengine/
RangerResourceDeserializer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ranger.policyengine;
+
+import java.lang.reflect.Type;
+
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+/**
+ * {@link JsonDeserializer} to assist {@link Gson} with selecting proper
type
+ * when encountering RangerAccessResource interface in the source json.
+ */
+public class RangerResourceDeserializer implements
JsonDeserializer<RangerAccessResource>
{
+
+       private GsonBuilder gsonBuilder;
+
+       public RangerResourceDeserializer(final GsonBuilder builder) {
+               this.gsonBuilder = builder;
+       }
+
+       @Override
+       public RangerAccessResource deserialize(JsonElement jsonObj, Type
type, JsonDeserializationContext context) throws JsonParseException {
+               return gsonBuilder.create().fromJson(jsonObj,
RangerAccessResourceImpl.class);
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/main/java/org/apache/ranger/
policyengine/perftest/v2/RangerPolicyFactory.java
----------------------------------------------------------------------
diff --git a/ranger-tools/src/main/java/org/apache/ranger/
policyengine/perftest/v2/RangerPolicyFactory.java
b/ranger-tools/src/main/java/org/apache/ranger/policyengine/perftest/v2/
RangerPolicyFactory.java
new file mode 100644
index 0000000..29b57d0
--- /dev/null
+++ b/ranger-tools/src/main/java/org/apache/ranger/policyengine/perftest/v2/
RangerPolicyFactory.java
@@ -0,0 +1,256 @@
+/*
+ * 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.ranger.policyengine.perftest.v2;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.File;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
+import org.apache.ranger.plugin.util.ServicePolicies;
+import org.apache.ranger.policyengine.RangerAccessRequestDeserializer;
+import org.apache.ranger.policyengine.RangerResourceDeserializer;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * Factory for creating and wiring the object graph of {@link
ServicePolicies} and {@link RangerAccessRequest}.
+ */
+public class RangerPolicyFactory {
+
+       private static final double SUCCESSFUL_ACCESS_RATE = 0.7d;
+
+       private static final Random RANDOM = new Random();
+
+       private static final List<String> KNOWN_DATABASES =
createList("database", 10);
+
+       private static final List<String> KNOWN_TABLES =
createList("tables", 100);
+
+       private static final List<String> KNOWN_COLUMNS =
createList("column", 1000);
+
+       private static final List<String> KNOWN_USERS = createList("user",
1000);
+
+       private static final List<String> RANDOM_VALUES =
createList("random", 100);
+
+       private static final List<String> ALWAYS_ALLOWED_ACCESS_TYPES =
Arrays.asList("create", "select", "drop");
+
+       /**
+        * Returns a {@link ServicePolicies service policy} instance with
containing the specified number of generated policies.
+        * @param numberOfPolicies
+        * @return
+        */
+       public static ServicePolicies createServicePolicy(int
numberOfPolicies) {
+               ServicePolicies servicePolicies =
loadTemplate("/testdata/test_servicepolicies_hive.json", new
TypeToken<ServicePolicies>(){}.getType());
+               mutate(servicePolicies, numberOfPolicies);
+               return servicePolicies;
+       }
+
+       private static void mutate(ServicePolicies servicePolicies, int
numberOfPolicies) {
+               servicePolicies.getPolicies().clear(); // reset
+               servicePolicies.setPolicies(createPolicies(
numberOfPolicies));
+       }
+
+       private static List<RangerPolicy> createPolicies(int
numberOfPolicies) {
+               List<RangerPolicy> policies = Lists.newArrayList();
+               String template = readResourceFile("/testdata/
single-policy-template.json");
+               for (int i = 0; i < numberOfPolicies; i++) {
+                       policies.add(createPolicyFromTemplate(template, i,
isAllowed()));
+               }
+               return policies;
+       }
+
+       private static RangerPolicy createPolicyFromTemplate(String
template, long policyId, boolean isAllowed) {
+               RangerPolicy rangerPolicy = buildGson().fromJson(template,
RangerPolicy.class);
+               rangerPolicy.setId(policyId);
+               rangerPolicy.setName(String.format("generated policyname
#%s", policyId));
+               rangerPolicy.setResources(createRangerPolicyResourceMap(
isAllowed));
+               rangerPolicy.setPolicyItems(createPolicyItems(isAllowed));
+               return rangerPolicy;
+       }
+
+       private static Map<String, RangerPolicyResource>
createRangerPolicyResourceMap(boolean isAllowed) {
+               RangerPolicyResource db = new
RangerPolicyResource(isAllowed ? pickFewRandomly(KNOWN_DATABASES):
RANDOM_VALUES, false, false);
+               RangerPolicyResource table = new
RangerPolicyResource(isAllowed ? pickFewRandomly(KNOWN_TABLES) :
RANDOM_VALUES, false, false);
+               RangerPolicyResource column = new
RangerPolicyResource(isAllowed ? pickFewRandomly(KNOWN_COLUMNS) :
RANDOM_VALUES, false, false);
+               return ImmutableMap.of("database", db, "table", table,
"column", column);
+       }
+
+
+       private static List<RangerPolicyItem> createPolicyItems(boolean
isAllowed) {
+               List<RangerPolicyItem> policyItems = Lists.newArrayList();
+               for (int i = 0; i < 15; i++) {
+                       policyItems.add(createPolicyItem(isAllowed));
+               }
+               return policyItems;
+       }
+
+       private static RangerPolicyItem createPolicyItem(boolean isAllowed)
{
+               RangerPolicyItem rangerPolicyItem = new RangerPolicyItem();
+               rangerPolicyItem.setDelegateAdmin(false);
+               rangerPolicyItem.setUsers(isAllowed ? KNOWN_USERS :
RANDOM_VALUES);
+               rangerPolicyItem.setAccesses(createAccesses(isAllowed));
+               return rangerPolicyItem;
+       }
+
+       private static List<RangerPolicyItemAccess> createAccesses(boolean
isAllowed) {
+               List<RangerPolicyItemAccess> results = Lists.newArrayList();
+               results.addAll(Lists.transform(isAllowed ?
ALWAYS_ALLOWED_ACCESS_TYPES : RANDOM_VALUES, new Function<String,
RangerPolicyItemAccess>() {
+                       @Override
+                       public RangerPolicyItemAccess apply(String input) {
+                               return new RangerPolicyItemAccess(input,
true);
+                       }
+               }));
+               return results;
+       }
+
+       /**
+        * Generates and returns a list of {@link RangerAccessRequest
requests}
+        * @param nubmerOfRequests the number of requests to generate.
+        * @return
+        */
+       public static List<RangerAccessRequest> createAccessRequests(int
nubmerOfRequests) {
+               List<RangerAccessRequest> result = Lists.newArrayList();
+               Gson gson = buildGson();
+               String template = readResourceFile("/testdata/
single-request-template.json");
+               for (int i = 0; i < nubmerOfRequests; i++) {
+                       RangerAccessRequestImpl accessRequest =
gson.fromJson(template, RangerAccessRequestImpl.class);
+                       result.add(mutate(accessRequest, isAllowed()));
+               }
+               return result;
+       }
+
+       /**
+        * @return 10% of the time returns <code>true</code>, in which case
the generated request policy should evaluate to true.
+        */
+       private static boolean isAllowed() {
+               return RANDOM.nextDouble() < SUCCESSFUL_ACCESS_RATE;
+       }
+
+       private static RangerAccessRequest mutate(RangerAccessRequest
template, boolean shouldEvaluateToTrue) {
+               RangerAccessRequestImpl accessRequest =
(RangerAccessRequestImpl) template;
+               accessRequest.setResource(new RangerAccessResourceImpl(
createResourceElements(shouldEvaluateToTrue)));
+
accessRequest.setAccessType(pickOneRandomly(ALWAYS_ALLOWED_ACCESS_TYPES
));
+               accessRequest.setRequestData(null);
+               accessRequest.setUser(pickOneRandomly(KNOWN_USERS));
+               return accessRequest;
+       }
+
+       private static ImmutableMap<String, String>
createResourceElements(boolean shouldEvaluateToTrue) {
+               String database = String.format("db_%s", System.nanoTime());
+               String table = String.format("table_%s", System.nanoTime());
+               String column = String.format("column_%s",
System.nanoTime());
+
+               if (shouldEvaluateToTrue) {
+                       database = pickOneRandomly(KNOWN_DATABASES);
+                       table = pickOneRandomly(KNOWN_TABLES);
+                       column = pickOneRandomly(KNOWN_COLUMNS);
+               }
+               return ImmutableMap.of("database", database, "table",
table, "column", column);
+       }
+
+       private static List<String> createList(String name, int n) {
+               List<String> results = Lists.newArrayList();
+               for (int i = 0; i < n; i++) {
+                       results.add(String.format("%s_%s",name, i));
+               }
+               return results;
+       }
+
+       private static String pickOneRandomly(Collection<String> list) {
+               return Iterables.get(list, RANDOM.nextInt(list.size()));
+       }
+
+       private static List<String> pickFewRandomly(final List<String>
list) {
+               int resultSize = RANDOM.nextInt(list.size());
+
+               Set<String> results = RANDOM.ints(resultSize, 0,
list.size()).boxed().map(new java.util.function.Function<Integer, String>()
{
+                       @Override
+                       public String apply(Integer index) {
+                               return list.get(index);
+                       }
+               }).collect(Collectors.<String>toSet());
+
+               return ImmutableList.copyOf(results);
+
+       }
+
+       private static <T> T loadTemplate(String file, Type targetType) {
+               try {
+                       T model = buildGson().fromJson(readResourceFile(file),
targetType);
+                       return model;
+               } catch (Exception e) {
+                       throw Throwables.propagate(e);
+               }
+       }
+
+       private static Gson buildGson() {
+               GsonBuilder gsonBuilder = new GsonBuilder().setDateFormat("
yyyyMMdd-HH:mm:ss.SSS-Z");
+               return gsonBuilder
+                               .registerTypeAdapter(RangerAccessRequest.class,
new RangerAccessRequestDeserializer(gsonBuilder))
+
.registerTypeAdapter(RangerAccessResource.class,
new RangerResourceDeserializer(gsonBuilder))
+                               .setPrettyPrinting().create();
+       }
+
+       public static String readResourceFile(String fileName) {
+               try {
+                       File f = new File(RangerPolicyFactory.
class.getResource(fileName).toURI());
+                       checkState(f.exists() && f.isFile() && f.canRead());
+                       return Files.toString(f, Charsets.UTF_8);
+               } catch (Exception e) {
+                       throw Throwables.propagate(e);
+               }
+       }
+
+       public static RangerPolicyEngineOptions createPolicyEngineOption() {
+               RangerPolicyEngineOptions policyEngineOptions = new
RangerPolicyEngineOptions();
+               policyEngineOptions.disableTagPolicyEvaluation = false;
+               policyEngineOptions.evaluatorType = RangerPolicyEvaluator.
EVALUATOR_TYPE_OPTIMIZED;
+               policyEngineOptions.cacheAuditResults = false;
+               policyEngineOptions.disableTrieLookupPrefilter = true;
+               return policyEngineOptions;
+       }
+}

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/test/java/org/apache/ranger/policyengine/
RangerPolicyEnginePerformanceTest.java
----------------------------------------------------------------------
diff --git a/ranger-tools/src/test/java/org/apache/ranger/policyengine/
RangerPolicyEnginePerformanceTest.java b/ranger-tools/src/test/java/
org/apache/ranger/policyengine/RangerPolicyEnginePerformanceTest.java
new file mode 100644
index 0000000..82f5c1f
--- /dev/null
+++ b/ranger-tools/src/test/java/org/apache/ranger/policyengine/
RangerPolicyEnginePerformanceTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.ranger.policyengine;
+
+import static com.google.common.collect.Iterables.get;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+import org.apache.ranger.plugin.util.PerfDataRecorder;
+import org.apache.ranger.plugin.util.PerfDataRecorder.PerfStatistic;
+import org.apache.ranger.plugin.util.ServicePolicies;
+import org.apache.ranger.policyengine.perftest.v2.RangerPolicyFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import com.google.common.collect.TreeBasedTable;
+import com.google.common.io.Files;
+
+import be.ceau.chart.LineChart;
+import be.ceau.chart.color.Color;
+import be.ceau.chart.data.LineData;
+import be.ceau.chart.dataset.LineDataset;
+
+/**
+ * A parameterized JUnit test that tests the performance of
RangerPolicyEngine, under increasing load of number of policies and
concurrent calls.
+ * A cross product of the input parameters are generated and fed into the
test method.
+ * This microbenchmark includes a warm-up phase so that any of the JIT
performance optimizations happen before the measurement of the policy
engine's performance.
+ */
+@RunWith(Parameterized.class)
+public class RangerPolicyEnginePerformanceTest {
+
+       private static final String STATISTICS_KEY__ACCESS_ALLOWED =
"RangerPolicyEngine.isAccessAllowed";
+
+       /* pre-warming unit-under-test's method with this many call
iterations, so all possible JIT optimization happen before measuring
performance */
+       private static final int WARM_UP__ITERATIONS = 30_000;
+
+       private static LoadingCache<Integer, List<RangerAccessRequest>>
requestsCache = CacheBuilder.newBuilder().build(
createAccessRequestsCacheLoader());
+
+       private static LoadingCache<Integer, ServicePolicies>
servicePoliciesCache = CacheBuilder.newBuilder().build(
createServicePoliciesCacheLoader());
+
+       @Parameter(0)
+       public Integer numberOfPolicies;
+
+       @Parameter(1)
+       public Integer concurrency;
+
+       /**
+        * Generates a cross product of number-of-policies X concurrency
parameter sets.
+        * @returns a collection of "tuples" (Object[]) of numberOfPolicies
and concurrency for the given test run
+        */
+       @Parameters(name = "{index}: isAccessAllowed(policies: {0},
concurrent calls: {1})")
+       public static Iterable<Object[]> data() {
+               // tree set for maintaining natural ordering
+               Set<Integer> policies = Sets.newTreeSet(Lists.newArrayList(5,
50, 100, 250, 500, 1_000, 2_000, 3_000, 4_000, 5_000));
+               Set<Integer> concurrency =
Sets.newTreeSet(Lists.newArrayList(1,
5, 10, 20, 30, 40, 50, 100));
+
+               return Iterables.transform(Sets.cartesianProduct(policies,
concurrency), new Function<List<Integer>, Object[]>() {
+                       @Override
+                       public Object[] apply(List<Integer> input) {
+                               return input.toArray();
+                       }
+               });
+       }
+
+       @BeforeClass
+       public static void init() throws IOException {
+               PerfDataRecorder.initialize(Arrays.asList("")); // dummy
value initializes PerfDataRecorder
+
Files.write("policies;concurrency;average;min;max;total-time-spent;\n",
outputFile(), Charsets.UTF_8);
+       }
+
+       @AfterClass
+       public static void chartResults() throws IOException {
+               // row: policies
+               // column: concurrency
+               // value: average
+               LineChart chart = buildChart(parsePerformanceTable());
+               String chartMarkup = StrSubstitutor.replace(
RangerPolicyFactory.readResourceFile("/testdata/performance-chart.template"),
ImmutableMap.of("data", chart.toJson()));
+               Files.write(chartMarkup, new File("target",
"performance-chart.html"), Charsets.UTF_8);
+       }
+
+       @Before
+       public void before() throws Exception {
+               PerfDataRecorder.clearStatistics();
+       }
+
+       @After
+       public void after() throws IOException {
+               Map<String, PerfStatistic> exposeStatistics =
PerfDataRecorder.exposeStatistics();
+               PerfStatistic stat = exposeStatistics.get(
STATISTICS_KEY__ACCESS_ALLOWED);
+               long average = stat.getNumberOfInvocations() > 0 ?
(stat.getMicroSecondsSpent() / stat.getNumberOfInvocations()) : 0;
+               Files.append(String.format("%s;%s;%s;%s;%s;%s;\n",
numberOfPolicies, concurrency, average, stat.getMinTimeSpent(),
stat.getMaxTimeSpent(), stat.getMicroSecondsSpent()), outputFile(),
Charsets.UTF_8);
+               PerfDataRecorder.printStatistics();
+               PerfDataRecorder.clearStatistics();
+       }
+
+       @Test
+       public void policyEngineTest() throws InterruptedException {
+               List<RangerAccessRequest> requests =
requestsCache.getUnchecked(concurrency);
+               ServicePolicies servicePolicies = servicePoliciesCache.
getUnchecked(numberOfPolicies);
+
+               final RangerPolicyEngineImpl rangerPolicyEngine = new
RangerPolicyEngineImpl("perf-test", servicePolicies, RangerPolicyFactory.
createPolicyEngineOption());
+               rangerPolicyEngine.preProcess(requests);
+
+               for (int iterations = 0; iterations < WARM_UP__ITERATIONS;
iterations++) {
+                       // using return value of 'isAccessAllowed' with a
cheap operation: System#identityHashCode so JIT wont remove it as dead code
+                       System.identityHashCode(rangerPolicyEngine.
isAccessAllowed(requests.get(iterations % concurrency), null));
+                       PerfDataRecorder.clearStatistics();
+               }
+
+               final CountDownLatch latch = new
CountDownLatch(concurrency);
+               for (int i = 0; i < concurrency; i++) {
+                       final RangerAccessRequest rangerAccessRequest =
requests.get(i);
+                       new Thread(new Runnable() {
+                               @Override
+                               public void run() {
+                                       System.identityHashCode(
rangerPolicyEngine.isAccessAllowed(rangerAccessRequest, null));
+                                       latch.countDown();
+                               }
+                       }, String.format("Client #%s", i)).start();
+               }
+               latch.await();
+       }
+
+       private static File outputFile() {
+               return new File("target", "ranger-policy-engine-
performance.csv");
+       }
+
+       private static CacheLoader<Integer, List<RangerAccessRequest>>
createAccessRequestsCacheLoader() {
+               return new CacheLoader<Integer, List<RangerAccessRequest>>
() {
+                       @Override
+                       public List<RangerAccessRequest> load(Integer
numberOfRequests) throws Exception {
+                               return RangerPolicyFactory.
createAccessRequests(numberOfRequests);
+                       }
+               };
+       }
+
+       private static CacheLoader<Integer, ServicePolicies>
createServicePoliciesCacheLoader() {
+               return new CacheLoader<Integer, ServicePolicies>() {
+                       @Override
+                       public ServicePolicies load(Integer
numberOfPolicies) throws Exception {
+                               return RangerPolicyFactory.
createServicePolicy(numberOfPolicies);
+                       }
+               };
+       }
+
+       private static LineChart buildChart(Table<Long, Long, BigDecimal>
policyConcurrencyValueTable) {
+               LineData lineData = new LineData();
+               LineChart chart = new LineChart(lineData);
+               for (Entry<Long, Map<Long, BigDecimal>>
concurrencyKeyedEntry : policyConcurrencyValueTable.columnMap().entrySet())
{
+                       LineDataset dataset = new LineDataset()
+                                       .setBackgroundColor(Color.
TRANSPARENT)
+                                       .setBorderColor(Color.random())
+                                       .setLabel(String.format("%s
client(s)", concurrencyKeyedEntry.getKey()))
+                                       .setData(concurrencyKeyedEntry.
getValue().values());
+                       lineData.addDataset(dataset);
+               }
+
+               for (Long policies : policyConcurrencyValueTable.rowKeySet())
{
+                       lineData.addLabels(String.format("Policies %s",
policies));
+               }
+               return chart;
+       }
+
+       private static Table<Long, Long, BigDecimal>
parsePerformanceTable() throws IOException {
+               Table<Long, Long, BigDecimal> policyConcurrencyValueTable =
TreeBasedTable.create();
+               List<String> lines = Files.readLines(outputFile(),
Charsets.UTF_8).stream().skip(1).collect(Collectors.<String>toList());
+               Splitter splitter = Splitter.on(";");
+               for (String line : lines) {
+                       Iterable<String> values = splitter.split(line);
+                       Long policies = Long.valueOf(get(values, 0));
+                       Long concurrency = Long.valueOf(get(values, 1));
+                       BigDecimal averageValue = new
BigDecimal(get(values, 2));
+                       policyConcurrencyValueTable.put(policies,
concurrency, averageValue);
+               }
+               return policyConcurrencyValueTable;
+       }
+}

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ranger-tools/src/test/resources/log4j.properties
b/ranger-tools/src/test/resources/log4j.properties
index 4ea9d85..0bc879a 100644
--- a/ranger-tools/src/test/resources/log4j.properties
+++ b/ranger-tools/src/test/resources/log4j.properties
@@ -42,6 +42,8 @@ ranger.perf.log.file=${java.io.tmpdir}/ranger-perf-test.
log

 log4j.logger.org.apache.ranger.perf=${ranger.perf.logger}
 log4j.additivity.org.apache.ranger.perf=false
+log4j.logger.org.apache.ranger.plugin.policyengine.
RangerPolicyEngineImpl=OFF
+log4j.additivity.org.apache.ranger.plugin.policyengine.
RangerPolicyEngineImpl=false

 log4j.appender.PERF=org.apache.log4j.DailyRollingFileAppender
 log4j.appender.PERF.File=${ranger.perf.log.file}

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/test/resources/testdata/performance-chart.template
----------------------------------------------------------------------
diff --git a/ranger-tools/src/test/resources/testdata/performance-chart.template
b/ranger-tools/src/test/resources/testdata/performance-chart.template
new file mode 100644
index 0000000..0366fb6
--- /dev/null
+++ b/ranger-tools/src/test/resources/testdata/performance-chart.template
@@ -0,0 +1,44 @@
+{{!--
+  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.
+--}}
+<!doctype html>
+<html>
+<head>
+    <title>Performance Chart</title>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/
Chart.min.js"></script>
+    <style>
+    canvas{
+        -moz-user-select: none;
+        -webkit-user-select: none;
+        -ms-user-select: none;
+    }
+    </style>
+</head>
+
+<body>
+    <div style="width:90%;">
+        <canvas id="canvas"></canvas>
+    </div>
+    <script>
+               var config = ${data};
+
+        window.onload = function() {
+            var ctx = document.getElementById("canvas").getContext("2d");
+            window.myLine = new Chart(ctx, config);
+        };
+    </script>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/test/resources/testdata/
single-policy-template.json
----------------------------------------------------------------------
diff --git 
a/ranger-tools/src/test/resources/testdata/single-policy-template.json
b/ranger-tools/src/test/resources/testdata/single-policy-template.json
new file mode 100644
index 0000000..c030803
--- /dev/null
+++ b/ranger-tools/src/test/resources/testdata/single-policy-template.json
@@ -0,0 +1,83 @@
+{
+       "service": "cl1_hive",
+       "name": "cl1_hive-1-20151212014502",
+       "isAuditEnabled": false,
+       "resources": {
+               "database": {
+                       "values": [
+                               "*"
+                       ],
+                       "isExcludes": false,
+                       "isRecursive": false
+               },
+               "column": {
+                       "values": [
+                               "*"
+                       ],
+                       "isExcludes": false,
+                       "isRecursive": false
+               },
+               "table": {
+                       "values": [
+                               "*"
+                       ],
+                       "isExcludes": false,
+                       "isRecursive": false
+               }
+       },
+       "policyItems": [
+               {
+                       "accesses": [
+                               {
+                                       "type": "select",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "update",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "create",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "drop",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "alter",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "index",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "lock",
+                                       "isAllowed": true
+                               },
+                               {
+                                       "type": "all",
+                                       "isAllowed": true
+                               }
+                       ],
+                       "users": [
+                               "ambari-qa"
+                       ],
+                       "groups": [
+                       ],
+                       "conditions": [
+                       ],
+                       "delegateAdmin": true,
+                       "isEnabled": true
+               }
+       ],
+       "denyPolicyItems": [
+       ],
+       "allowExceptions": [
+       ],
+       "denyExceptions": [
+       ],
+       "id": 2,
+       "isEnabled": true
+}

http://git-wip-us.apache.org/repos/asf/ranger/blob/
c806d177/ranger-tools/src/test/resources/testdata/
single-request-template.json
----------------------------------------------------------------------
diff --git 
a/ranger-tools/src/test/resources/testdata/single-request-template.json
b/ranger-tools/src/test/resources/testdata/single-request-template.json
new file mode 100644
index 0000000..1bc409d
--- /dev/null
+++ b/ranger-tools/src/test/resources/testdata/single-request-template.json
@@ -0,0 +1,16 @@
+{
+       "request": {
+               "resource": {
+                       "elements": {
+                               "database": "default",
+                               "table": "tbl-0",
+                               "column": "col-2"
+                       }
+               },
+               "accessType": "select",
+               "user": "hrt_1",
+               "userGroups": [
+               ],
+               "requestData": "use default"
+       }
+}




-- 
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

Reply via email to