summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorRyan Campbell <ryanjcampbell@google.com>2017-10-10 11:00:05 -0700
committerRyan Campbell <ryanjcampbell@google.com>2017-10-13 09:06:09 -0700
commit83c69d93b55bc790c97b2863ad8cae84115658f7 (patch)
treec720413538e5152cc52b96185a9072897a63990e /src/main
parent2c96b51cbec1dc08a38ed5c2ad5b682b64482335 (diff)
downloaddashboard-83c69d93b55bc790c97b2863ad8cae84115658f7.tar.gz
Break out branches and targets into entities.
Move branch and build target information into separate entities to speed up querying for auto-complete (in the search dropdowns). Instead of querying this from the test runs, which can become inefficient as the number of test runs increases, this can be made O(1) with respect to test runs. Test: staging Bug: 67635355 Change-Id: I79d81e25a0b47a69ecfbe419b86ef007861d6f98
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/android/vts/entity/BranchEntity.java61
-rw-r--r--src/main/java/com/android/vts/entity/BuildTargetEntity.java61
-rw-r--r--src/main/java/com/android/vts/servlet/ShowGraphServlet.java4
-rw-r--r--src/main/java/com/android/vts/util/DatastoreHelper.java71
4 files changed, 147 insertions, 50 deletions
diff --git a/src/main/java/com/android/vts/entity/BranchEntity.java b/src/main/java/com/android/vts/entity/BranchEntity.java
new file mode 100644
index 0000000..f1b5a4c
--- /dev/null
+++ b/src/main/java/com/android/vts/entity/BranchEntity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.android.vts.entity;
+
+import com.google.appengine.api.datastore.Entity;
+import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.datastore.KeyFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** Entity describing a branch. */
+public class BranchEntity implements DashboardEntity {
+ protected static final Logger logger = Logger.getLogger(BranchEntity.class.getName());
+
+ public static final String KIND = "Branch"; // The entity kind.
+
+ public Key key; // The key for the entity in the database.
+
+ /**
+ * Create a BranchEntity object.
+ *
+ * @param branchName The name of the branch.
+ */
+ public BranchEntity(String branchName) {
+ this.key = KeyFactory.createKey(KIND, branchName);
+ }
+
+ @Override
+ public Entity toEntity() {
+ return new Entity(this.key);
+ }
+
+ /**
+ * Convert an Entity object to a BranchEntity.
+ *
+ * @param e The entity to process.
+ * @return BranchEntity object with the properties from e, or null if incompatible.
+ */
+ public static BranchEntity fromEntity(Entity e) {
+ if (!e.getKind().equals(KIND) || e.getKey().getName() == null) {
+ logger.log(Level.WARNING, "Missing branch attributes in entity: " + e.toString());
+ return null;
+ }
+ String branchName = e.getKey().getName();
+ return new BranchEntity(branchName);
+ }
+}
diff --git a/src/main/java/com/android/vts/entity/BuildTargetEntity.java b/src/main/java/com/android/vts/entity/BuildTargetEntity.java
new file mode 100644
index 0000000..ddcd4f8
--- /dev/null
+++ b/src/main/java/com/android/vts/entity/BuildTargetEntity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.android.vts.entity;
+
+import com.google.appengine.api.datastore.Entity;
+import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.datastore.KeyFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** Entity describing a build target. */
+public class BuildTargetEntity implements DashboardEntity {
+ protected static final Logger logger = Logger.getLogger(BuildTargetEntity.class.getName());
+
+ public static final String KIND = "BuildTarget"; // The entity kind.
+
+ public Key key; // The key for the entity in the database.
+
+ /**
+ * Create a BuildTargetEntity object.
+ *
+ * @param targetName The name of the build target.
+ */
+ public BuildTargetEntity(String targetName) {
+ this.key = KeyFactory.createKey(KIND, targetName);
+ }
+
+ @Override
+ public Entity toEntity() {
+ return new Entity(this.key);
+ }
+
+ /**
+ * Convert an Entity object to a BuildTargetEntity.
+ *
+ * @param e The entity to process.
+ * @return BuildTargetEntity object with the properties from e, or null if incompatible.
+ */
+ public static BuildTargetEntity fromEntity(Entity e) {
+ if (!e.getKind().equals(KIND) || e.getKey().getName() == null) {
+ logger.log(Level.WARNING, "Missing build target attributes in entity: " + e.toString());
+ return null;
+ }
+ String targetName = e.getKey().getName();
+ return new BuildTargetEntity(targetName);
+ }
+}
diff --git a/src/main/java/com/android/vts/servlet/ShowGraphServlet.java b/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
index 4ef709b..05496ef 100644
--- a/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
+++ b/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
@@ -144,7 +144,7 @@ public class ShowGraphServlet extends BaseServlet {
Long startTime = endTime - TimeUnit.DAYS.toMicros(1);
// Set of device names
- List<String> devices = DatastoreHelper.getAllProducts();
+ List<String> devices = DatastoreHelper.getAllBuildFlavors();
if (!devices.contains(selectedDevice)) selectedDevice = null;
Map<String, Graph> graphMap = new HashMap<>();
@@ -182,7 +182,7 @@ public class ShowGraphServlet extends BaseServlet {
Query.CompositeFilterOperator.and(
deviceFilter,
new Query.FilterPredicate(
- DeviceInfoEntity.PRODUCT,
+ DeviceInfoEntity.BUILD_FLAVOR,
Query.FilterOperator.EQUAL,
selectedDevice));
}
diff --git a/src/main/java/com/android/vts/util/DatastoreHelper.java b/src/main/java/com/android/vts/util/DatastoreHelper.java
index d741115..7891329 100644
--- a/src/main/java/com/android/vts/util/DatastoreHelper.java
+++ b/src/main/java/com/android/vts/util/DatastoreHelper.java
@@ -13,6 +13,8 @@
*/
package com.android.vts.util;
+import com.android.vts.entity.BranchEntity;
+import com.android.vts.entity.BuildTargetEntity;
import com.android.vts.entity.CoverageEntity;
import com.android.vts.entity.DeviceInfoEntity;
import com.android.vts.entity.ProfilingPointRunEntity;
@@ -43,7 +45,6 @@ import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
-import com.google.appengine.api.datastore.PropertyProjection;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
@@ -113,53 +114,18 @@ public class DatastoreHelper {
}
/**
- * Determines if any entities match the provided query.
- *
- * @param query The query to test.
- * @return true if entities match the query.
- */
- public static boolean hasEntities(Query query) {
- DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
- FetchOptions limitOne = FetchOptions.Builder.withLimit(1);
- return datastore.prepare(query).countEntities(limitOne) > 0;
- }
-
- /**
- * Get all of the target product names.
- *
- * @return a list of all device product names.
- */
- public static List<String> getAllProducts() {
- DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
- Query query =
- new Query(DeviceInfoEntity.KIND)
- .addProjection(
- new PropertyProjection(DeviceInfoEntity.PRODUCT, String.class))
- .setDistinct(true);
- List<String> devices = new ArrayList<>();
- for (Entity e : datastore.prepare(query).asIterable()) {
- devices.add((String) e.getProperty(DeviceInfoEntity.PRODUCT));
- }
- return devices;
- }
-
- /**
* Get all of the devices branches.
*
* @return a list of all branches.
*/
public static List<String> getAllBranches() {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
- Query query =
- new Query(DeviceInfoEntity.KIND)
- .addProjection(
- new PropertyProjection(DeviceInfoEntity.BRANCH, String.class))
- .setDistinct(true);
- List<String> devices = new ArrayList<>();
- for (Entity e : datastore.prepare(query).asIterable()) {
- devices.add((String) e.getProperty(DeviceInfoEntity.BRANCH));
+ Query query = new Query(BranchEntity.KIND).setKeysOnly();
+ List<String> branches = new ArrayList<>();
+ for (Entity e : datastore.prepare(query).asIterable(getLargeBatchOptions())) {
+ branches.add(e.getKey().getName());
}
- return devices;
+ return branches;
}
/**
@@ -169,14 +135,10 @@ public class DatastoreHelper {
*/
public static List<String> getAllBuildFlavors() {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
- Query query =
- new Query(DeviceInfoEntity.KIND)
- .addProjection(
- new PropertyProjection(DeviceInfoEntity.BUILD_FLAVOR, String.class))
- .setDistinct(true);
+ Query query = new Query(BuildTargetEntity.KIND).setKeysOnly();
List<String> devices = new ArrayList<>();
- for (Entity e : datastore.prepare(query).asIterable()) {
- devices.add((String) e.getProperty(DeviceInfoEntity.BUILD_FLAVOR));
+ for (Entity e : datastore.prepare(query).asIterable(getLargeBatchOptions())) {
+ devices.add(e.getKey().getName());
}
return devices;
}
@@ -215,6 +177,9 @@ public class DatastoreHelper {
long coveredLineCount = 0;
long totalLineCount = 0;
+ Set<Key> buildTargetKeys = new HashSet<>();
+ Set<Key> branchKeys = new HashSet<>();
+ List<Entity> buildPuts = new ArrayList<>();
List<TestCaseRunEntity> testCases = new ArrayList<>();
List<Key> profilingPointKeys = new ArrayList<>();
List<String> links = new ArrayList<>();
@@ -267,6 +232,8 @@ public class DatastoreHelper {
testCaseEntity.addTestCase(testCaseName, result.getNumber());
}
+ datastore.put(buildPuts);
+
List<Entity> testCasePuts = new ArrayList<>();
for (TestCaseRunEntity testCaseEntity : testCases) {
testCasePuts.add(testCaseEntity.toEntity());
@@ -296,6 +263,14 @@ public class DatastoreHelper {
testRunType = TestRunType.OTHER;
}
puts.add(deviceInfoEntity.toEntity());
+ BuildTargetEntity target = new BuildTargetEntity(deviceInfoEntity.buildFlavor);
+ if (buildTargetKeys.add(target.key)) {
+ buildPuts.add(target.toEntity());
+ }
+ BranchEntity branch = new BranchEntity(deviceInfoEntity.branch);
+ if (branchKeys.add(branch.key)) {
+ buildPuts.add(branch.toEntity());
+ }
}
// Overall run type should be determined by the device builds unless test build is OTHER