/**
* 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.waveprotocol.box.stat;
import com.google.gwt.core.shared.GWT;
/**
* Class that helps build a hierarchical tree of timers.
*
* @author akaplanov@gmail.com (A. Kaplanov)
*/
public class ExecutionTree implements RequestScope.Value {
private static final int DEFAULT_THRESHOLD = 500;
private final ExecutionNode root;
private ExecutionNode currentNode;
public ExecutionTree() {
root = new ExecutionNode(null, null, "", false, 0);
currentNode = root;
}
private ExecutionTree(ExecutionNode root, ExecutionNode currentNode) {
this.root = root;
this.currentNode = currentNode;
}
/**
* Push a new timer node.
*/
Timer start(String name) {
return start(name, false, DEFAULT_THRESHOLD);
}
/**
* Push a new timer node.
*/
Timer start(String name, int threshold) {
return start(name, false, threshold);
}
/**
* Push a new timer node.
*/
Timer startRequest(String name) {
return start(name, true, DEFAULT_THRESHOLD);
}
/**
* Push a new timer node.
*/
Timer startRequest(String name, int threshold) {
return start(name, true, threshold);
}
/**
* Push a new timer node.
*/
Timer start(String name, boolean isRequest, int threshold) {
ExecutionNode node = currentNode.newChild(name, getModuleName(), isRequest, threshold);
currentNode = node;
Timer timer = new Timer(node);
timer.start();
return timer;
}
/**
* Pop the timer node.
*/
void pop(ExecutionNode node) {
while (currentNode != node && currentNode.getParent() != null) {
currentNode = currentNode.getParent();
}
if (node == currentNode && currentNode.getParent() != null) {
currentNode = currentNode.getParent();
}
}
/**
* Record statistics.
*/
void record(String name, int interval) {
record(name, false, interval, DEFAULT_THRESHOLD);
}
/**
* Record statistics.
*/
void record(String name, int interval, int threshold) {
record(name, false, interval, threshold);
}
/**
* Record statistics.
*/
void recordRequest(String name, int interval) {
record(name, true, interval, DEFAULT_THRESHOLD);
}
/**
* Record statistics.
*/
void recordRequest(String name, int interval, int threshold) {
record(name, true, interval, threshold);
}
@Override
public RequestScope.Value clone() {
return new ExecutionTree(root, currentNode);
}
/**
* Record statistics.
*/
void record(String name, boolean isRequest, int interval, int threshold) {
ExecutionNode node = currentNode.newChild(name, getModuleName(), isRequest, threshold);
record(node, interval);
}
/**
* Record statistics.
*/
void record(ExecutionNode node, int interval) {
node.sample(interval);
Timing.getStatsRecorder().record(node.getName(), node.getModule(), interval, node.getMeasurement().getThreshold());
if (node.isRequest()) {
Timing.getStatsRecorder().recordRequest(node);
}
}
ExecutionNode getRoot() {
return root;
}
ExecutionNode getCurrent() {
return currentNode;
}
private String getModuleName() {
if (GWT.isClient()) {
return com.google.gwt.core.client.GWT.getModuleName();
}
return "";
}
}