/* * Copyright (C) 2015 The Android Open Source Project * * 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.builder.profile; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.google.common.base.Objects; import java.util.List; import java.util.concurrent.Callable; /** * A {@link ExecutionRecord} recorder for a block execution. * * A block is some code that produces a result and may throw exceptions. */ public interface Recorder { /** * Abstraction of a block of code that produces a result of type T and may throw exceptions. Any * exception thrown by {@link Callable#call()} will be passed to the {@link * #handleException(Exception)} method. Default implementation of this method is to repackage * the exception as {@link RuntimeException} unless it already is one. * * @param <T> the type of result produced by executing this block of code. */ abstract class Block<T> implements Callable<T> { /** * Notification that an exception was raised during the {@link #call()} method invocation. * Default behavior is to repackage as a {@link RuntimeException}, subclasses can choose * differently including swallowing the exception. Swallowing the exception will make the * {@link Recorder#record(ExecutionType, Block, Property...)} return null. * * @param e the exception raised during the {@link #call()} execution. */ public void handleException(@NonNull Exception e) { // by default we rethrow as a runtime exception, subclasses should override for more // precise handling. throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e); } } Block<Void> EmptyBlock = new Block<Void>() { @Override public Void call() throws Exception { return null; } }; /** * Free formed name/value property pair that will be saved along the execution record for a * particular block. */ final class Property { @NonNull final String name; @NonNull final String value; public Property(@NonNull String name, @NonNull String value) { this.name = name; this.value = value; } @NonNull public String getName() { return name; } @NonNull public String getValue() { return value; } @Override public String toString() { return Objects.toStringHelper(this) .add("name", name) .add("value", value) .toString(); } } /** * Records the time elapsed while executing a {@link Block} and saves the resulting {@link * ExecutionRecord} to {@link ProcessRecorder}. * * @param executionType the task type, so aggregation can be performed. * @param block the block of code to execution and measure. * @param properties optional list of free formed properties to save in the {@link * ExecutionRecord} * @param <T> the type of the returned value from the block. * @return the value returned from the block (including null) or null if the block execution * raised an exception which was subsequently swallowed by {@link Block#handleException(Exception)} */ @Nullable <T> T record(@NonNull ExecutionType executionType, @NonNull Block<T> block, Property... properties); /** * Records the time elapsed while executing a {@link Block} and saves the resulting {@link * ExecutionRecord} to {@link ProcessRecorder}. * * @param executionType the task type, so aggregation can be performed. * @param block the block of code to execution and measure. * @param properties optional list of free formed properties to save in the {@link * ExecutionRecord} * @param <T> the type of the returned value from the block. * @return the value returned from the block (including null) or null if the block execution * raised an exception which was subsequently swallowed by {@link Block#handleException(Exception)} */ @Nullable <T> T record(@NonNull ExecutionType executionType, @NonNull Block<T> block, @NonNull List<Property> properties); /** * Allocate a new recordId that can be used to create a {@link ExecutionRecord} and record * an execution span. This method is useful when the code span to measure cannot be expressed * as a {@link Block} and therefore cannot directly use the * {@link #record(ExecutionType, Block, Property...)} method. * * @return the unique record id for this process. */ long allocationRecordId(); /** * Closes an execution span measurement using the allocated record id obtained from * {@link #allocationRecordId()} method. * * @param record the span execution record, fully populated. */ void closeRecord(ExecutionRecord record); }