blob: 915f8eef25610c6aefe6ee76e6524cf60e4db5d7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Google, Inc 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:
* Stefan Xenos (Google) - Initial implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core.search.indexing;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.index.DiskIndex;
import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.Util;
public class IndexNamesRegistry {
private final File savedIndexNamesFile;
private final Job writeJob;
private final IPath javaPluginWorkingLocation;
private final Object queueMutex = new Object();
/**
* Outstanding write that is waiting to be processed. Null if there are no outstanding writes. Synchronize on
* queueMutex before accessing.
*/
private char[][] pendingWrite;
public IndexNamesRegistry(File savedIndexNamesFile, IPath javaPluginWorkingLocation) {
super();
this.savedIndexNamesFile = savedIndexNamesFile;
this.writeJob = Job.create("Updating index names", this::save); //$NON-NLS-1$
this.writeJob.setSystem(true);
this.javaPluginWorkingLocation = javaPluginWorkingLocation;
}
public void write(char[][] newContents) {
synchronized (this.queueMutex) {
this.pendingWrite = newContents;
}
this.writeJob.schedule();
}
/**
* Returns the contents of the index names registry.
*/
public char[][] read(IProgressMonitor monitor) {
// If there is currently a write in progress, return the contents that are about to be written to disk.
char[][] newContents;
synchronized (this.queueMutex) {
newContents = this.pendingWrite;
}
if (newContents != null) {
return newContents;
}
// Otherwise, read fresh contents from disk
try {
char[] savedIndexNames = org.eclipse.jdt.internal.compiler.util.Util
.getFileCharContent(this.savedIndexNamesFile, null);
if (savedIndexNames.length > 0) {
char[][] names = CharOperation.splitOn('\n', savedIndexNames);
if (names.length > 1) {
// First line is DiskIndex signature + saved plugin working location (see writeSavedIndexNamesFile())
String savedSignature = DiskIndex.SIGNATURE + "+" + this.javaPluginWorkingLocation.toOSString(); //$NON-NLS-1$
if (savedSignature.equals(new String(names[0])))
return names;
}
}
} catch (IOException ignored) {
if (JobManager.VERBOSE)
Util.verbose("Failed to read saved index file names"); //$NON-NLS-1$
}
return null;
}
private void save(IProgressMonitor monitor) {
SubMonitor subMonitor = SubMonitor.convert(monitor);
char[][] newContents;
synchronized (this.queueMutex) {
newContents = this.pendingWrite;
}
if (newContents == null) {
return;
}
subMonitor.setWorkRemaining(newContents.length);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(this.savedIndexNamesFile))) {
writer.write(DiskIndex.SIGNATURE);
writer.write('+');
writer.write(this.javaPluginWorkingLocation.toOSString());
writer.write('\n');
for (char[] next : newContents) {
subMonitor.split(1);
writer.write(next);
writer.write('\n');
}
} catch (IOException ignored) {
if (JobManager.VERBOSE)
Util.verbose("Failed to write saved index file names", System.err); //$NON-NLS-1$
}
synchronized (this.queueMutex) {
if (this.pendingWrite == newContents) {
this.pendingWrite = null;
}
}
}
public void delete() {
synchronized (this.queueMutex) {
this.pendingWrite = null;
}
this.writeJob.cancel();
try {
this.writeJob.join();
} catch (InterruptedException e) {
// Nothing to do
}
synchronized (this.queueMutex) {
this.pendingWrite = null;
}
this.savedIndexNamesFile.delete();
}
}