| /* |
| * Copyright 2013-present Facebook, Inc. |
| * |
| * 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.facebook.buck.dalvik; |
| |
| import com.facebook.buck.io.ProjectFilesystem; |
| import com.facebook.buck.java.classes.ClasspathTraversal; |
| import com.facebook.buck.java.classes.DefaultClasspathTraverser; |
| import com.facebook.buck.java.classes.FileLike; |
| import com.facebook.buck.java.classes.FileLikes; |
| import com.facebook.buck.step.ExecutionContext; |
| import com.facebook.buck.step.Step; |
| import com.google.common.annotations.VisibleForTesting; |
| import com.google.common.base.Preconditions; |
| import com.google.common.base.Supplier; |
| |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.util.Collections; |
| |
| public class EstimateLinearAllocStep implements Step, Supplier<Integer> { |
| |
| @VisibleForTesting |
| static interface LinearAllocEstimator { |
| public int getEstimate(FileLike fileLike) throws IOException; |
| } |
| |
| /** |
| * This is a linear alloc estimator that uses the size of the {@code .class} file as the |
| * estimate. This should be used when speed is more important than accuracy. If accuracy is a |
| * priority, an estimator based on {@link DalvikStatsTool#getEstimate(java.io.InputStream)} should |
| * be used instead. |
| */ |
| private static final LinearAllocEstimator DEFAULT_LINEAR_ALLOC_ESTIMATOR = |
| new LinearAllocEstimator() { |
| @Override |
| public int getEstimate(FileLike fileLike) throws IOException { |
| return (int) fileLike.getSize(); |
| } |
| }; |
| |
| private final Path pathToJarOrClassesDirectory; |
| private final LinearAllocEstimator linearAllocEstimator; |
| |
| private int linearAllocEstimate = -1; |
| |
| /** |
| * This uses a linear alloc estimator that uses the size of the {@code .class} file as the |
| * estimate. This should be used when speed is more important than accuracy. If accuracy is a |
| * priority, an estimator based on {@link DalvikStatsTool#getEstimate(java.io.InputStream)} should |
| * be used instead. |
| */ |
| public EstimateLinearAllocStep(Path pathToJarOrClassesDirectory) { |
| this(pathToJarOrClassesDirectory, DEFAULT_LINEAR_ALLOC_ESTIMATOR); |
| } |
| |
| @VisibleForTesting |
| EstimateLinearAllocStep(Path pathToJarOrClassesDirectory, |
| LinearAllocEstimator linearAllocEstimator) { |
| this.pathToJarOrClassesDirectory = pathToJarOrClassesDirectory; |
| this.linearAllocEstimator = linearAllocEstimator; |
| } |
| |
| @Override |
| public int execute(ExecutionContext context) { |
| ProjectFilesystem filesystem = context.getProjectFilesystem(); |
| Path path = filesystem.resolve(pathToJarOrClassesDirectory); |
| ClasspathTraversal traversal = new ClasspathTraversal(Collections.singleton(path), filesystem) { |
| |
| private int totalLinearAllocEstimate = 0; |
| |
| @Override |
| public void visit(FileLike fileLike) throws IOException { |
| // When traversing a JAR file, it may have resources or directory entries that do not end |
| // in .class, which should be ignored. |
| if (!FileLikes.isClassFile(fileLike)) { |
| return; |
| } |
| |
| totalLinearAllocEstimate += linearAllocEstimator.getEstimate(fileLike); |
| } |
| |
| @Override |
| public Integer getResult() { |
| return totalLinearAllocEstimate; |
| } |
| }; |
| |
| try { |
| new DefaultClasspathTraverser().traverse(traversal); |
| } catch (IOException e) { |
| context.logError(e, "Error accumulating class names for %s.", pathToJarOrClassesDirectory); |
| return 1; |
| } |
| |
| this.linearAllocEstimate = (Integer) traversal.getResult(); |
| return 0; |
| } |
| |
| @Override |
| public Integer get() { |
| Preconditions.checkState(linearAllocEstimate >= 0, "If less than zero, was not set."); |
| return linearAllocEstimate; |
| } |
| |
| @Override |
| public String getShortName() { |
| return "estimate_linear_alloc"; |
| } |
| |
| @Override |
| public String getDescription(ExecutionContext context) { |
| return "estimate_linear_alloc"; |
| } |
| |
| @VisibleForTesting |
| public void setLinearAllocEstimateForTesting(int linearAllocEstimate) { |
| this.linearAllocEstimate = linearAllocEstimate; |
| } |
| } |