blob: fb77faf894544fd4ccf0ec31c04bebfc7892e994 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* James Blackburn (Broadcom Corp.) - ongoing development
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
*******************************************************************************/
package org.eclipse.core.internal.resources;
import java.util.*;
import org.eclipse.core.runtime.IPath;
/**
* The notification mechanism can request marker deltas for several overlapping intervals
* of time. This class maintains a history of marker deltas, and upon request can
* generate a map of marker deltas for any interval. This is done by maintaining
* batches of marker deltas keyed by the change Id at the start of that batch.
* When the delta factory requests a delta, it specifies the start generation, and
* this class assembles the deltas for all generations between then and the most
* recent delta.
*/
class MarkerDeltaManager {
private static final int DEFAULT_SIZE = 10;
private long[] startIds = new long[DEFAULT_SIZE];
@SuppressWarnings("unchecked")
private Map<IPath, MarkerSet>[] batches = new Map[DEFAULT_SIZE];
private int nextFree = 0;
/**
* Returns the deltas from the given start id up until the present. Returns null
* if there are no deltas for that interval.
*/
protected Map<IPath, MarkerSet> assembleDeltas(long start) {
Map<IPath, MarkerSet> result = null;
for (int i = 0; i < nextFree; i++)
if (startIds[i] >= start)
result = MarkerDelta.merge(result, batches[i]);
return result;
}
/**
* Flushes all delta batches up to but not including the given start Id.
*/
@SuppressWarnings("unchecked")
protected void resetDeltas(long startId) {
//find offset of first batch to keep
int startOffset = 0;
for (; startOffset < nextFree; startOffset++)
if (startIds[startOffset] >= startId)
break;
if (startOffset == 0)
return;
long[] newIds = startIds;
Map<IPath, MarkerSet>[] newBatches = batches;
//shrink the arrays if it has grown too large
if (startIds.length > DEFAULT_SIZE && (nextFree - startOffset < DEFAULT_SIZE)) {
newIds = new long[DEFAULT_SIZE];
newBatches = new Map[DEFAULT_SIZE];
}
//copy and compact into the new array
int remaining = nextFree - startOffset;
System.arraycopy(startIds, startOffset, newIds, 0, remaining);
System.arraycopy(batches, startOffset, newBatches, 0, remaining);
//clear the end of the array
Arrays.fill(startIds, remaining, startIds.length, 0);
Arrays.fill(batches, remaining, startIds.length, null);
startIds = newIds;
batches = newBatches;
nextFree = remaining;
}
@SuppressWarnings("unchecked")
protected Map<IPath, MarkerSet> newGeneration(long start) {
int len = startIds.length;
if (nextFree >= len) {
long[] newIds = new long[len * 2];
Map<IPath, MarkerSet>[] newBatches = new Map[len * 2];
System.arraycopy(startIds, 0, newIds, 0, len);
System.arraycopy(batches, 0, newBatches, 0, len);
startIds = newIds;
batches = newBatches;
}
startIds[nextFree] = start;
batches[nextFree] = new HashMap<>(11);
return batches[nextFree++];
}
}