Skip to main content
summaryrefslogtreecommitdiffstats
blob: 915f8eef25610c6aefe6ee76e6524cf60e4db5d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*******************************************************************************
 * 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(); 
	}
}

Back to the top