Copyright (c) 2000, 2017 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.team.internal.core.subscribers; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.ResourceVariantByteStore;
A ResourceVariantByteStore that optimizes the memory footprint of a remote resource variant tree by only storing those bytes that differ from a base resource variant tree. This class should only be used for cases where the base and remote are on the same line-of-descent. For example, when the remote tree represents the current state of a branch and the base represents the state of the same branch when the local workspace as last refreshed.

This class also contains the logic that allows subclasses to determine if bytes stored in the remote tree are on a different line-of-descent than the base. This is necessary because it is possible for the base tree to change in ways that invalidate the stored remote variants. For example, if the local resources are moved from the main trunk to a branch, any cached remote resource variants would be stale.

Since:3.0
/** * A <code>ResourceVariantByteStore</code> that optimizes the memory footprint * of a remote resource variant tree by only storing those bytes that differ * from a base resource variant tree. This class should only be used for cases * where the base and remote are on the same line-of-descent. For example, when * the remote tree represents the current state of a branch and the base * represents the state of the same branch when the local workspace as last * refreshed. * <p> * This class also contains the logic that allows subclasses to determine if * bytes stored in the remote tree are on a different line-of-descent than the * base. This is necessary because it is possible for the base tree to change in * ways that invalidate the stored remote variants. For example, if the local * resources are moved from the main trunk to a branch, any cached remote * resource variants would be stale. * * @since 3.0 */
public abstract class DescendantResourceVariantByteStore extends ResourceVariantByteStore { ResourceVariantByteStore baseStore, remoteStore; public DescendantResourceVariantByteStore(ResourceVariantByteStore baseCache, ResourceVariantByteStore remoteCache) { this.baseStore = baseCache; this.remoteStore = remoteCache; }
This method will dispose the remote cache but not the base cache.
See Also:
  • dispose.dispose()
/** * This method will dispose the remote cache but not the base cache. * @see org.eclipse.team.core.variants.ResourceVariantByteStore#dispose() */
@Override public void dispose() { remoteStore.dispose(); } @Override public byte[] getBytes(IResource resource) throws TeamException { byte[] remoteBytes = remoteStore.getBytes(resource); byte[] baseBytes = baseStore.getBytes(resource); if (baseBytes == null) { // There is no base so use the remote bytes return remoteBytes; } if (remoteBytes == null) { if (isVariantKnown(resource)) { // The remote is known to not exist // TODO: The check for NO_REMOTE does not take into consideration the line-of-descent return remoteBytes; } else { // The remote was either never queried or was the same as the base. // In either of these cases, the base bytes are used. return baseBytes; } } if (isDescendant(resource, baseBytes, remoteBytes)) { // Only use the remote bytes if they are later on the same line-of-descent as the base return remoteBytes; } // Use the base sbytes since the remote bytes must be stale (i.e. are // not on the same line-of-descent return baseBytes; } @Override public boolean setBytes(IResource resource, byte[] bytes) throws TeamException { byte[] baseBytes = baseStore.getBytes(resource); if (baseBytes != null && equals(baseBytes, bytes)) { // Remove the existing bytes so the base will be used (thus saving space) return remoteStore.flushBytes(resource, IResource.DEPTH_ZERO); } else { return remoteStore.setBytes(resource, bytes); } } @Override public boolean flushBytes(IResource resource, int depth) throws TeamException { return remoteStore.flushBytes(resource, depth); }
Return true if the variant associated with the given local resource has been cached. This method is useful for those cases when there are no bytes for a resource variant and the client wants to know if this means that the remote does exist (i.e. this method returns true) or the remote has not been fetched (i.e. this method returns false).
Params:
  • resource – the local resource
Throws:
Returns:true if the variant associated with the given local resource has been cached.
/** * Return <code>true</code> if the variant associated with the given local * resource has been cached. This method is useful for those cases when * there are no bytes for a resource variant and the client wants to * know if this means that the remote does exist (i.e. this method returns * <code>true</code>) or the remote has not been fetched (i.e. this method returns * <code>false</code>). * @param resource the local resource * @return <code>true</code> if the variant associated with the given local * resource has been cached. * @throws TeamException */
public abstract boolean isVariantKnown(IResource resource) throws TeamException;
This method indicates whether the remote bytes are a later revision or version on the same line-of-descent as the base. A line of descent may be a branch or a fork (depending on the terminology used by the versioing server). If this method returns false then the remote bytes will be ignored by this tree.
Params:
  • resource – the local resource
  • baseBytes – the base bytes for the local resoource
  • remoteBytes – the remote bytes for the local resoource
Returns:whether the remote bytes are later on the same line-of-descent as the base bytes
/** * This method indicates whether the remote bytes are a later revision or version * on the same line-of-descent as the base. A line of descent may be a branch or a fork * (depending on the terminology used by the versioing server). If this method returns * <code>false</code> then the remote bytes will be ignored by this tree. * @param resource the local resource * @param baseBytes the base bytes for the local resoource * @param remoteBytes the remote bytes for the local resoource * @return whether the remote bytes are later on the same line-of-descent as the base bytes */
protected abstract boolean isDescendant(IResource resource, byte[] baseBytes, byte[] remoteBytes) throws TeamException; @Override public boolean deleteBytes(IResource resource) throws TeamException { return remoteStore.deleteBytes(resource); }
Return the base tree from which the remote is descendant.
Returns:Returns the base tree.
/** * Return the base tree from which the remote is descendant. * @return Returns the base tree. */
protected ResourceVariantByteStore getBaseStore() { return baseStore; }
Return the remote tree which contains bytes only for the resource variants that differ from those in the base tree.
Returns:Returns the remote tree.
/** * Return the remote tree which contains bytes only for the resource variants * that differ from those in the base tree. * @return Returns the remote tree. */
protected ResourceVariantByteStore getRemoteStore() { return remoteStore; } @Override public IResource[] members(IResource resource) throws TeamException { IResource[] remoteMembers = getRemoteStore().members(resource); IResource[] baseMembers = getBaseStore().members(resource); Set<IResource> members = new HashSet<>(); Collections.addAll(members, remoteMembers); for (IResource member : baseMembers) { // Add the base only if the remote does not know about it // (i.e. hasn't marked it as deleted if (!isVariantKnown(member)) { members.add(member); } } return members.toArray(new IResource[members.size()]); } @Override public void run(IResource root, IWorkspaceRunnable runnable, IProgressMonitor monitor) throws TeamException { remoteStore.run(root, runnable, monitor); } }