/******************************************************************************* * Copyright (c) 2003, 2011 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 *******************************************************************************/ 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<IPath, MarkerSet>(11); return batches[nextFree++]; } }