/*******************************************************************************
* Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de>
*
* 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
*******************************************************************************/
package org.eclipse.egit.core.internal.indexdiff;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
/**
* Job used to collect pending paths before starting actual index update. The
* same job instance is intended to be used repeatedly, reducing management cost
* and memory consumption.
*/
abstract class IndexDiffUpdateJob extends Job {
private final long defaultDelay;
private Object lock = new Object();
private Set<String> files;
private Set<IResource> resources;
/**
* @param name
* non null job name
* @param delay
* default delay in milliseconds for job scheduling
*/
public IndexDiffUpdateJob(String name, long delay) {
super(name);
setSystem(true);
defaultDelay = delay;
cleanup();
}
/**
* Updates index diff on given resources
*
* @param filesToUpdate
* non null paths set
* @param resourcesToUpdate
* non null resources set
* @param monitor
* non null progress callback
* @return non null status
*/
abstract IStatus updateIndexDiff(Collection<String> filesToUpdate,
Collection<IResource> resourcesToUpdate, IProgressMonitor monitor);
@Override
protected final IStatus run(IProgressMonitor monitor) {
Collection<String> filesToUpdate;
Collection<IResource> resourcesToUpdate;
synchronized (lock) {
filesToUpdate = files;
resourcesToUpdate = resources;
cleanup();
if (monitor.isCanceled() || filesToUpdate.isEmpty()) {
return Status.CANCEL_STATUS;
}
}
return updateIndexDiff(filesToUpdate, resourcesToUpdate, monitor);
}
/**
* Adds files to update and schedules the job to run after default delay
*
* @param filesToUpdate
* non null repo relative paths to update
* @param resourcesToUpdate
* non null resources to update
*/
protected void addChanges(Collection<String> filesToUpdate,
Collection<IResource> resourcesToUpdate) {
synchronized (lock) {
files.addAll(filesToUpdate);
resources.addAll(resourcesToUpdate);
}
if (!filesToUpdate.isEmpty()) {
schedule(defaultDelay);
}
}
@Override
protected void canceling() {
// always run cleanup on cancel
cleanup();
}
void cleanupAndCancel() {
// we must always run cleanup here because framework may not call
// canceling() if the job was not started yet
cleanup();
cancel();
}
private void cleanup() {
synchronized (lock) {
files = new HashSet<String>();
resources = new HashSet<IResource>();
}
}
}