/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.visualvm.modules.tracer.impl.timeline;
import com.sun.tools.visualvm.modules.tracer.ProbeItemDescriptor;
import com.sun.tools.visualvm.modules.tracer.impl.timeline.items.ValueItemDescriptor;
import java.util.ArrayList;
import java.util.List;
import org.netbeans.lib.profiler.charts.Timeline;
import org.netbeans.lib.profiler.charts.xy.synchronous.SynchronousXYItem;
/**
* All methods must be invoked from the EDT.
*
* @author Jiri Sedlacek
*/
final class TimelineModel implements Timeline {
private static final int STORAGE_BUFFER_STEP = 50;
private int bufferStep;
private int valuesCount;
private long[] timestamps;
private long[][] values;
private final List<TimelineXYItem> items = new ArrayList();
TimelineModel() {
this(STORAGE_BUFFER_STEP);
}
private TimelineModel(int bufferStep) {
this.bufferStep = bufferStep;
reset();
}
int getItemsCount() {
return items.size();
}
TimelineXYItem[] createItems(ProbeItemDescriptor[] itemDescriptors) {
int itemsCount = values == null ? 0 : values.length;
int addedItemsCount = itemDescriptors.length;
TimelineXYItem[] itemsArr = new TimelineXYItem[addedItemsCount];
for (int i = 0; i < addedItemsCount; i++) {
if (itemDescriptors[i] instanceof ValueItemDescriptor) {
ValueItemDescriptor d = (ValueItemDescriptor)itemDescriptors[i];
itemsArr[i] = new TimelineXYItem(d.getName(), d.getMinValue(),
d.getMaxValue(), itemsCount + i) {
public long getYValue(int valueIndex) {
return values[getIndex()][valueIndex];
}
};
} else {
// Reserved for non-value items
}
items.add(itemsArr[i]);
}
addItemsImpl(addedItemsCount);
return itemsArr;
}
void removeItems(SynchronousXYItem[] removed) {
removeItemsImpl(removed.length);
int firstRemovedIndex = ((TimelineXYItem)removed[0]).getIndex();
for (SynchronousXYItem item : removed)
items.remove(firstRemovedIndex);
for (int i = firstRemovedIndex; i < items.size(); i++)
items.get(i).setIndex(i);
}
void addValues(long timestamp, long[] newValues) {
updateStorage();
// Check last timestamp whether greater than the new one
long lastTimestamp = valuesCount == 0 ? -1 : timestamps[valuesCount - 1];
// Silently increase timestamp, JVM was busy - timer out of sync
if (lastTimestamp >= timestamp) timestamp = lastTimestamp + 1;
timestamps[valuesCount] = timestamp;
for (int i = 0; i < values.length; i++)
values[i][valuesCount] = newValues[i];
valuesCount++;
}
void reset() {
valuesCount = 0;
timestamps = null;
if (values != null) {
if (values.length == 0) {
values = null;
} else {
for (int i = 0; i < values.length; i++)
values[i] = new long[0];
}
}
}
private void addItemsImpl(int addedItemsCount) {
int newItemsCount = (values == null ? 0 : values.length) + addedItemsCount;
values = new long[newItemsCount][];
reset();
}
private void removeItemsImpl(int removedItemsCount) {
values = new long[values.length - removedItemsCount][];
reset();
}
public int getTimestampsCount() {
return valuesCount;
}
public long getTimestamp(int index) {
return timestamps[index];
}
private void updateStorage() {
if (timestamps == null) {
timestamps = new long[bufferStep];
for (int i = 0; i < values.length; i++)
values[i] = new long[bufferStep];
} else if (valuesCount == timestamps.length) {
timestamps = extendArray(timestamps, bufferStep);
for (int i = 0; i < values.length; i++)
values[i] = extendArray(values[i], bufferStep);
}
}
private static long[] extendArray(long[] array, int extraLength) {
int originalLength = array.length;
long[] newArray = new long[originalLength + extraLength];
System.arraycopy(array, 0, newArray, 0, originalLength);
return newArray;
}
}