View | Details | Raw Unified | Return to bug 138309 | Differences between
and this patch

Collapse All | Expand All

(-)search/org/eclipse/jdt/internal/core/index/DiskIndex.java (-50 / +46 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 19-28 Link Here
19
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
19
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
20
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
20
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
21
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
21
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
22
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
22
23
23
public class DiskIndex {
24
public class DiskIndex {
24
25
25
String fileName;
26
File indexFile;
26
27
27
private int headerInfoOffset;
28
private int headerInfoOffset;
28
private int numberOfChunks;
29
private int numberOfChunks;
Lines 45-50 Link Here
45
46
46
private static final int CHUNK_SIZE = 100;
47
private static final int CHUNK_SIZE = 100;
47
48
49
private static final SimpleSetOfCharArray INTERNED_CATEGORY_NAMES = new SimpleSetOfCharArray(20);
50
48
static class IntList {
51
static class IntList {
49
52
50
int size;
53
int size;
Lines 71-77 Link Here
71
74
72
75
73
DiskIndex(String fileName) {
76
DiskIndex(String fileName) {
74
	this.fileName = fileName;
77
	if (fileName == null)
78
		throw new java.lang.IllegalArgumentException();
79
	this.indexFile = new File(fileName);
75
80
76
	// clear cached items
81
	// clear cached items
77
	this.headerInfoOffset = -1;
82
	this.headerInfoOffset = -1;
Lines 204-210 Link Here
204
private void cacheDocumentNames() throws IOException {
209
private void cacheDocumentNames() throws IOException {
205
	// will need all document names so get them now
210
	// will need all document names so get them now
206
	this.cachedChunks = new String[this.numberOfChunks][];
211
	this.cachedChunks = new String[this.numberOfChunks][];
207
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), this.numberOfChunks > 5 ? 4096 : 2048));
212
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(this.indexFile), this.numberOfChunks > 5 ? 4096 : 2048));
208
	try {
213
	try {
209
		stream.skip(this.chunkOffsets[0]);
214
		stream.skip(this.chunkOffsets[0]);
210
		for (int i = 0; i < this.numberOfChunks; i++) {
215
		for (int i = 0; i < this.numberOfChunks; i++) {
Lines 335-350 Link Here
335
		}
340
		}
336
	}
341
	}
337
}
342
}
338
File getIndexFile() {
339
	if (this.fileName == null) return null;
340
341
	return new File(this.fileName);
342
}
343
void initialize(boolean reuseExistingFile) throws IOException {
343
void initialize(boolean reuseExistingFile) throws IOException {
344
	File indexFile = getIndexFile();
344
	if (this.indexFile.exists()) {
345
	if (indexFile.exists()) {
346
		if (reuseExistingFile) {
345
		if (reuseExistingFile) {
347
			RandomAccessFile file = new RandomAccessFile(this.fileName, "r"); //$NON-NLS-1$
346
			RandomAccessFile file = new RandomAccessFile(this.indexFile, "r"); //$NON-NLS-1$
348
			try {
347
			try {
349
				String signature = file.readUTF();
348
				String signature = file.readUTF();
350
				if (!signature.equals(SIGNATURE))
349
				if (!signature.equals(SIGNATURE))
Lines 358-371 Link Here
358
			}
357
			}
359
			return;
358
			return;
360
		}
359
		}
361
		if (!indexFile.delete()) {
360
		if (!this.indexFile.delete()) {
362
			if (DEBUG)
361
			if (DEBUG)
363
				System.out.println("initialize - Failed to delete index " + this.fileName); //$NON-NLS-1$
362
				System.out.println("initialize - Failed to delete index " + this.indexFile); //$NON-NLS-1$
364
			throw new IOException("Failed to delete index " + this.fileName); //$NON-NLS-1$
363
			throw new IOException("Failed to delete index " + this.indexFile); //$NON-NLS-1$
365
		}
364
		}
366
	}
365
	}
367
	if (indexFile.createNewFile()) {
366
	if (this.indexFile.createNewFile()) {
368
		RandomAccessFile file = new RandomAccessFile(this.fileName, "rw"); //$NON-NLS-1$
367
		RandomAccessFile file = new RandomAccessFile(this.indexFile, "rw"); //$NON-NLS-1$
369
		try {
368
		try {
370
			file.writeUTF(SIGNATURE);
369
			file.writeUTF(SIGNATURE);
371
			file.writeInt(-1); // file is empty
370
			file.writeInt(-1); // file is empty
Lines 374-391 Link Here
374
		}
373
		}
375
	} else {
374
	} else {
376
		if (DEBUG)
375
		if (DEBUG)
377
			System.out.println("initialize - Failed to create new index " + this.fileName); //$NON-NLS-1$
376
			System.out.println("initialize - Failed to create new index " + this.indexFile); //$NON-NLS-1$
378
		throw new IOException("Failed to create new index " + this.fileName); //$NON-NLS-1$
377
		throw new IOException("Failed to create new index " + this.indexFile); //$NON-NLS-1$
379
	}
378
	}
380
}
379
}
381
private void initializeFrom(DiskIndex diskIndex, File newIndexFile) throws IOException {
380
private void initializeFrom(DiskIndex diskIndex, File newIndexFile) throws IOException {
382
	if (newIndexFile.exists() && !newIndexFile.delete()) { // delete the temporary index file
381
	if (newIndexFile.exists() && !newIndexFile.delete()) { // delete the temporary index file
383
		if (DEBUG)
382
		if (DEBUG)
384
			System.out.println("initializeFrom - Failed to delete temp index " + this.fileName); //$NON-NLS-1$
383
			System.out.println("initializeFrom - Failed to delete temp index " + this.indexFile); //$NON-NLS-1$
385
	} else if (!newIndexFile.createNewFile()) {
384
	} else if (!newIndexFile.createNewFile()) {
386
		if (DEBUG)
385
		if (DEBUG)
387
			System.out.println("initializeFrom - Failed to create temp index " + this.fileName); //$NON-NLS-1$
386
			System.out.println("initializeFrom - Failed to create temp index " + this.indexFile); //$NON-NLS-1$
388
		throw new IOException("Failed to create temp index " + this.fileName); //$NON-NLS-1$
387
		throw new IOException("Failed to create temp index " + this.indexFile); //$NON-NLS-1$
389
	}
388
	}
390
389
391
	int size = diskIndex.categoryOffsets == null ? 8 : diskIndex.categoryOffsets.elementSize;
390
	int size = diskIndex.categoryOffsets == null ? 8 : diskIndex.categoryOffsets.elementSize;
Lines 465-480 Link Here
465
		if (previousLength == 0) return this; // nothing to do... memory index contained deleted documents that had never been saved
464
		if (previousLength == 0) return this; // nothing to do... memory index contained deleted documents that had never been saved
466
465
467
		// index is now empty since all the saved documents were removed
466
		// index is now empty since all the saved documents were removed
468
		DiskIndex newDiskIndex = new DiskIndex(this.fileName);
467
		DiskIndex newDiskIndex = new DiskIndex(this.indexFile.getPath());
469
		newDiskIndex.initialize(false);
468
		newDiskIndex.initialize(false);
470
		return newDiskIndex;
469
		return newDiskIndex;
471
	}
470
	}
472
471
473
	DiskIndex newDiskIndex = new DiskIndex(this.fileName + ".tmp"); //$NON-NLS-1$
472
	DiskIndex newDiskIndex = new DiskIndex(this.indexFile.getPath() + ".tmp"); //$NON-NLS-1$
474
	File newIndexFile = newDiskIndex.getIndexFile();
475
	try {
473
	try {
476
		newDiskIndex.initializeFrom(this, newIndexFile);
474
		newDiskIndex.initializeFrom(this, newDiskIndex.indexFile);
477
		DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newIndexFile, false), 2048));
475
		DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newDiskIndex.indexFile, false), 2048));
478
		int offsetToHeader = -1;
476
		int offsetToHeader = -1;
479
		try {
477
		try {
480
			newDiskIndex.writeAllDocumentNames(docNames, stream);
478
			newDiskIndex.writeAllDocumentNames(docNames, stream);
Lines 487-494 Link Here
487
				for (int i = 0, l = names.length; i < l; i++)
485
				for (int i = 0, l = names.length; i < l; i++)
488
					if (names[i] != null)
486
					if (names[i] != null)
489
						newDiskIndex.copyQueryResults(
487
						newDiskIndex.copyQueryResults(
490
							(HashtableOfObject) memoryIndex.docsToReferences.get(names[i]),
488
							(HashtableOfObject) memoryIndex.docsToReferences.get(names[i]), ((Integer) integerPositions[i]).intValue());
491
							((Integer) integerPositions[i]).intValue());
492
			}
489
			}
493
			indexedDocuments = null; // free up the space
490
			indexedDocuments = null; // free up the space
494
491
Lines 506-537 Link Here
506
		newDiskIndex.writeOffsetToHeader(offsetToHeader);
503
		newDiskIndex.writeOffsetToHeader(offsetToHeader);
507
504
508
		// rename file by deleting previous index file & renaming temp one
505
		// rename file by deleting previous index file & renaming temp one
509
		File old = getIndexFile();
506
		if (this.indexFile.exists() && !this.indexFile.delete()) {
510
		if (old.exists() && !old.delete()) {
511
			if (DEBUG)
507
			if (DEBUG)
512
				System.out.println("mergeWith - Failed to delete " + this.fileName); //$NON-NLS-1$
508
				System.out.println("mergeWith - Failed to delete " + this.indexFile); //$NON-NLS-1$
513
			throw new IOException("Failed to delete index file " + this.fileName); //$NON-NLS-1$
509
			throw new IOException("Failed to delete index file " + this.indexFile); //$NON-NLS-1$
514
		}
510
		}
515
		if (!newIndexFile.renameTo(old)) {
511
		if (!newDiskIndex.indexFile.renameTo(this.indexFile)) {
516
			if (DEBUG)
512
			if (DEBUG)
517
				System.out.println("mergeWith - Failed to rename " + this.fileName); //$NON-NLS-1$
513
				System.out.println("mergeWith - Failed to rename " + this.indexFile); //$NON-NLS-1$
518
			throw new IOException("Failed to rename index file " + this.fileName); //$NON-NLS-1$
514
			throw new IOException("Failed to rename index file " + this.indexFile); //$NON-NLS-1$
519
		}
515
		}
520
	} catch (IOException e) {
516
	} catch (IOException e) {
521
		if (newIndexFile.exists() && !newIndexFile.delete())
517
		if (newDiskIndex.indexFile.exists() && !newDiskIndex.indexFile.delete())
522
			if (DEBUG)
518
			if (DEBUG)
523
				System.out.println("mergeWith - Failed to delete temp index " + newDiskIndex.fileName); //$NON-NLS-1$
519
				System.out.println("mergeWith - Failed to delete temp index " + newDiskIndex.indexFile); //$NON-NLS-1$
524
		throw e;
520
		throw e;
525
	}
521
	}
526
522
527
	newDiskIndex.fileName = this.fileName;
523
	newDiskIndex.indexFile = this.indexFile;
528
	return newDiskIndex;
524
	return newDiskIndex;
529
}
525
}
530
private synchronized String[] readAllDocumentNames() throws IOException {
526
private synchronized String[] readAllDocumentNames() throws IOException {
531
	if (this.numberOfChunks <= 0)
527
	if (this.numberOfChunks <= 0)
532
		return CharOperation.NO_STRINGS;
528
		return CharOperation.NO_STRINGS;
533
529
534
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), this.numberOfChunks > 5 ? 4096 : 2048));
530
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(this.indexFile), this.numberOfChunks > 5 ? 4096 : 2048));
535
	try {
531
	try {
536
		stream.skip(this.chunkOffsets[0]);
532
		stream.skip(this.chunkOffsets[0]);
537
		int lastIndex = this.numberOfChunks - 1;
533
		int lastIndex = this.numberOfChunks - 1;
Lines 564-570 Link Here
564
		}
560
		}
565
	}
561
	}
566
562
567
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
563
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(this.indexFile), 2048));
568
	HashtableOfObject categoryTable = null;
564
	HashtableOfObject categoryTable = null;
569
	char[][] matchingWords = null;
565
	char[][] matchingWords = null;
570
	int count = 0;
566
	int count = 0;
Lines 575-581 Link Here
575
		try {
571
		try {
576
			if (size < 0) { // DEBUG
572
			if (size < 0) { // DEBUG
577
				System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
573
				System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
578
				System.err.println("file = "+getIndexFile()); //$NON-NLS-1$
574
				System.err.println("file = "+this.indexFile); //$NON-NLS-1$
579
				System.err.println("offset = "+offset); //$NON-NLS-1$
575
				System.err.println("offset = "+offset); //$NON-NLS-1$
580
				System.err.println("size = "+size); //$NON-NLS-1$
576
				System.err.println("size = "+size); //$NON-NLS-1$
581
				System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
577
				System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
Lines 585-591 Link Here
585
			// DEBUG
581
			// DEBUG
586
			oom.printStackTrace();
582
			oom.printStackTrace();
587
			System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
583
			System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
588
			System.err.println("file = "+getIndexFile()); //$NON-NLS-1$
584
			System.err.println("file = "+this.indexFile); //$NON-NLS-1$
589
			System.err.println("offset = "+offset); //$NON-NLS-1$
585
			System.err.println("offset = "+offset); //$NON-NLS-1$
590
			System.err.println("size = "+size); //$NON-NLS-1$
586
			System.err.println("size = "+size); //$NON-NLS-1$
591
			System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
587
			System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
Lines 615-630 Link Here
615
				categoryTable.put(word, new Integer(arrayOffset)); // offset to array in the file
611
				categoryTable.put(word, new Integer(arrayOffset)); // offset to array in the file
616
			}
612
			}
617
		}
613
		}
618
		this.categoryTables.put(categoryName, categoryTable);
614
		this.categoryTables.put(INTERNED_CATEGORY_NAMES.get(categoryName), categoryTable);
619
		// cache the table as long as its not too big
615
		// cache the table as long as its not too big
620
		// in practice, some tables can be greater than 500K when they contain more than 10K elements
616
		// in practice, some tables can be greater than 500K when they contain more than 10K elements
621
		this.cachedCategoryName = categoryTable.elementSize < 10000 ? categoryName : null;
617
		this.cachedCategoryName = categoryTable.elementSize < 20000 ? categoryName : null;
622
	} finally {
618
	} finally {
623
		stream.close();
619
		stream.close();
624
	}
620
	}
625
621
626
	if (matchingWords != null && count > 0) {
622
	if (matchingWords != null && count > 0) {
627
		stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
623
		stream = new DataInputStream(new BufferedInputStream(new FileInputStream(this.indexFile), 2048));
628
		try {
624
		try {
629
			stream.skip(firstOffset);
625
			stream.skip(firstOffset);
630
			for (int i = 0; i < count; i++) // each array follows the previous one
626
			for (int i = 0; i < count; i++) // each array follows the previous one
Lines 688-694 Link Here
688
		if (numberOfBytes < 0)
684
		if (numberOfBytes < 0)
689
			throw new IllegalArgumentException();
685
			throw new IllegalArgumentException();
690
		byte[] bytes = new byte[numberOfBytes];
686
		byte[] bytes = new byte[numberOfBytes];
691
		FileInputStream file = new FileInputStream(getIndexFile());
687
		FileInputStream file = new FileInputStream(this.indexFile);
692
		try {
688
		try {
693
			file.skip(start);
689
			file.skip(start);
694
			if (file.read(bytes, 0, numberOfBytes) != numberOfBytes)
690
			if (file.read(bytes, 0, numberOfBytes) != numberOfBytes)
Lines 708-714 Link Here
708
	if (arrayOffset instanceof int[])
704
	if (arrayOffset instanceof int[])
709
		return (int[]) arrayOffset;
705
		return (int[]) arrayOffset;
710
706
711
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
707
	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(this.indexFile), 2048));
712
	try {
708
	try {
713
		stream.skip(((Integer) arrayOffset).intValue());
709
		stream.skip(((Integer) arrayOffset).intValue());
714
		return readDocumentArray(stream, stream.readInt());
710
		return readDocumentArray(stream, stream.readInt());
Lines 733-739 Link Here
733
	int size = file.readInt();
729
	int size = file.readInt();
734
	this.categoryOffsets = new HashtableOfIntValues(size);
730
	this.categoryOffsets = new HashtableOfIntValues(size);
735
	for (int i = 0; i < size; i++)
731
	for (int i = 0; i < size; i++)
736
		this.categoryOffsets.put(Util.readUTF(file), file.readInt()); // cache offset to category table
732
		this.categoryOffsets.put(INTERNED_CATEGORY_NAMES.get(Util.readUTF(file)), file.readInt()); // cache offset to category table
737
	this.categoryTables = new HashtableOfObject(3);
733
	this.categoryTables = new HashtableOfObject(3);
738
}
734
}
739
synchronized void startQuery() {
735
synchronized void startQuery() {
Lines 909-915 Link Here
909
}
905
}
910
private void writeOffsetToHeader(int offsetToHeader) throws IOException {
906
private void writeOffsetToHeader(int offsetToHeader) throws IOException {
911
	if (offsetToHeader > 0) {
907
	if (offsetToHeader > 0) {
912
		RandomAccessFile file = new RandomAccessFile(this.fileName, "rw"); //$NON-NLS-1$
908
		RandomAccessFile file = new RandomAccessFile(this.indexFile, "rw"); //$NON-NLS-1$
913
		try {
909
		try {
914
			file.seek(this.headerInfoOffset); // offset to position in header
910
			file.seek(this.headerInfoOffset); // offset to position in header
915
			file.writeInt(offsetToHeader);
911
			file.writeInt(offsetToHeader);
(-)search/org/eclipse/jdt/internal/core/index/Index.java (-4 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 105-113 Link Here
105
	return documentPath.substring(index + 1);
105
	return documentPath.substring(index + 1);
106
}
106
}
107
public File getIndexFile() {
107
public File getIndexFile() {
108
	if (this.diskIndex == null) return null;
108
	return this.diskIndex == null ? null : this.diskIndex.indexFile;
109
110
	return this.diskIndex.getIndexFile();
111
}
109
}
112
public boolean hasChanged() {
110
public boolean hasChanged() {
113
	return this.memoryIndex.hasChanged();
111
	return this.memoryIndex.hasChanged();
(-)search/org/eclipse/jdt/internal/core/search/IndexSelector.java (-3 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-17 Link Here
11
package org.eclipse.jdt.internal.core.search;
11
package org.eclipse.jdt.internal.core.search;
12
12
13
import org.eclipse.core.runtime.IPath;
13
import org.eclipse.core.runtime.IPath;
14
import org.eclipse.core.runtime.Path;
15
import org.eclipse.jdt.core.IClasspathEntry;
14
import org.eclipse.jdt.core.IClasspathEntry;
16
import org.eclipse.jdt.core.IJavaElement;
15
import org.eclipse.jdt.core.IJavaElement;
17
import org.eclipse.jdt.core.IJavaModel;
16
import org.eclipse.jdt.core.IJavaModel;
Lines 197-203 Link Here
197
	int count = 0;
196
	int count = 0;
198
	for (int i = values.length; --i >= 0;)
197
	for (int i = values.length; --i >= 0;)
199
		if (values[i] != null)
198
		if (values[i] != null)
200
			this.indexLocations[count++] = new Path((String) values[i]);
199
			this.indexLocations[count++] = (IPath) values[i];
201
}
200
}
202
public IPath[] getIndexLocations() {
201
public IPath[] getIndexLocations() {
203
	if (this.indexLocations == null) {
202
	if (this.indexLocations == null) {
(-)search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 85-91 Link Here
85
	for (int i = 0; i < length; i++) {
85
	for (int i = 0; i < length; i++) {
86
		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
86
		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
87
		// may trigger some index recreation work
87
		// may trigger some index recreation work
88
		String indexLocation = indexLocations[i].toOSString();
88
		IPath indexLocation = indexLocations[i];
89
		Index index = indexManager.getIndex(indexLocation);
89
		Index index = indexManager.getIndex(indexLocation);
90
		if (index == null) {
90
		if (index == null) {
91
			// only need containerPath if the index must be built
91
			// only need containerPath if the index must be built
(-)search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java (-157 / +162 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 26-33 Link Here
26
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
26
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
27
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
27
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
28
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
28
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
29
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
29
import org.eclipse.jdt.internal.core.*;
30
import org.eclipse.jdt.internal.core.*;
30
import org.eclipse.jdt.internal.core.index.Index;
31
import org.eclipse.jdt.internal.core.index.*;
31
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
32
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
32
import org.eclipse.jdt.internal.core.search.PatternSearchJob;
33
import org.eclipse.jdt.internal.core.search.PatternSearchJob;
33
import org.eclipse.jdt.internal.core.search.processing.IJob;
34
import org.eclipse.jdt.internal.core.search.processing.IJob;
Lines 37-47 Link Here
37
38
38
public class IndexManager extends JobManager implements IIndexConstants {
39
public class IndexManager extends JobManager implements IIndexConstants {
39
40
41
	// key = containerPath, value = indexLocation path
42
	// indexLocation path is created by appending an index file name to the getJavaPluginWorkingLocation() path
40
	public SimpleLookupTable indexLocations = new SimpleLookupTable();
43
	public SimpleLookupTable indexLocations = new SimpleLookupTable();
41
	/*
44
	// key = indexLocation path, value = an index
42
	 * key = an IPath, value = an Index
45
	private SimpleLookupTable indexes = new SimpleLookupTable();
43
	 */
44
	private Map indexes = new HashMap(5);
45
46
46
	/* need to save ? */
47
	/* need to save ? */
47
	private boolean needToSave = false;
48
	private boolean needToSave = false;
Lines 49-57 Link Here
49
	private IPath javaPluginLocation = null;
50
	private IPath javaPluginLocation = null;
50
51
51
	/* can only replace a current state if its less than the new one */
52
	/* can only replace a current state if its less than the new one */
53
	// key = indexLocation path, value = index state integer
52
	private SimpleLookupTable indexStates = null;
54
	private SimpleLookupTable indexStates = null;
53
	private File savedIndexNamesFile =
55
	private File savedIndexNamesFile = new File(getSavedIndexesDirectory(), "savedIndexNames.txt"); //$NON-NLS-1$
54
		new File(getJavaPluginWorkingLocation().append("savedIndexNames.txt").toOSString()); //$NON-NLS-1$
55
	public static Integer SAVED_STATE = new Integer(0);
56
	public static Integer SAVED_STATE = new Integer(0);
56
	public static Integer UPDATING_STATE = new Integer(1);
57
	public static Integer UPDATING_STATE = new Integer(1);
57
	public static Integer UNKNOWN_STATE = new Integer(2);
58
	public static Integer UNKNOWN_STATE = new Integer(2);
Lines 60-66 Link Here
60
public synchronized void aboutToUpdateIndex(IPath containerPath, Integer newIndexState) {
61
public synchronized void aboutToUpdateIndex(IPath containerPath, Integer newIndexState) {
61
	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
62
	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
62
	// must tag the index as inconsistent, in case we exit before the update job is started
63
	// must tag the index as inconsistent, in case we exit before the update job is started
63
	String indexLocation = computeIndexLocation(containerPath);
64
	IPath indexLocation = computeIndexLocation(containerPath);
64
	Object state = getIndexStates().get(indexLocation);
65
	Object state = getIndexStates().get(indexLocation);
65
	Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
66
	Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
66
	if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index
67
	if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index
Lines 82-88 Link Here
82
	if (JavaCore.getPlugin() == null) return;	
83
	if (JavaCore.getPlugin() == null) return;	
83
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
84
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
84
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
85
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
85
	String indexLocation = computeIndexLocation(containerPath);
86
	IPath indexLocation = computeIndexLocation(containerPath);
86
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
87
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
87
}
88
}
88
/**
89
/**
Lines 94-149 Link Here
94
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
95
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
95
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
96
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
96
	((InternalSearchDocument) document).parser = parser;
97
	((InternalSearchDocument) document).parser = parser;
97
	String indexLocation = computeIndexLocation(containerPath);
98
	IPath indexLocation = computeIndexLocation(containerPath);
98
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
99
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
99
}
100
}
100
/*
101
/*
101
 * Removes unused indexes from disk.
102
 * Removes unused indexes from disk.
102
 */
103
 */
103
public void cleanUpIndexes() {
104
public void cleanUpIndexes() {
104
	SimpleLookupTable knownPaths = new SimpleLookupTable();
105
	SimpleSet knownPaths = new SimpleSet();
105
	IJavaSearchScope scope = BasicSearchEngine.createWorkspaceScope();
106
	IJavaSearchScope scope = BasicSearchEngine.createWorkspaceScope();
106
	PatternSearchJob job = new PatternSearchJob(null, SearchEngine.getDefaultSearchParticipant(), scope, null);
107
	PatternSearchJob job = new PatternSearchJob(null, SearchEngine.getDefaultSearchParticipant(), scope, null);
107
	Index[] selectedIndexes = job.getIndexes(null);
108
	Index[] selectedIndexes = job.getIndexes(null);
108
	for (int j = 0, max = selectedIndexes.length; j < max; j++) {
109
	for (int i = 0, l = selectedIndexes.length; i < l; i++) {
109
		// TODO should use getJavaPluginWorkingLocation()+index simple name to avoid bugs such as https://bugs.eclipse.org/bugs/show_bug.cgi?id=62267
110
		String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
110
		String path = selectedIndexes[j].getIndexFile().getAbsolutePath();
111
		knownPaths.add(path);
111
		knownPaths.put(path, path);
112
	}
112
	}
113
113
114
	if (indexStates != null) {
114
	if (this.indexStates != null) {
115
		Object[] keys = indexStates.keyTable;
115
		Object[] keys = this.indexStates.keyTable;
116
		int keysLength = keys.length;
116
		IPath[] locations = new IPath[this.indexStates.elementSize];
117
		int updates = 0;
117
		int count = 0;
118
		String locations[] = new String[keysLength];
119
		for (int i = 0, l = keys.length; i < l; i++) {
118
		for (int i = 0, l = keys.length; i < l; i++) {
120
			String key = (String) keys[i];
119
			IPath key = (IPath) keys[i];
121
			if (key != null && !knownPaths.containsKey(key)) {
120
			if (key != null && !knownPaths.includes(key.toOSString()))
122
				locations[updates++] = key;
121
				locations[count++] = key;
123
			}
124
		}
122
		}
125
		if (updates > 0) {
123
		if (count > 0)
126
			removeIndexesState(locations);
124
			removeIndexesState(locations);
127
		}
128
	}
129
130
	File indexesDirectory = new File(getJavaPluginWorkingLocation().toOSString());
131
	if (indexesDirectory.isDirectory()) {
132
		File[] indexesFiles = indexesDirectory.listFiles();
133
		if (indexesFiles != null) {
134
			for (int i = 0, indexesFilesLength = indexesFiles.length; i < indexesFilesLength; i++) {
135
				String fileName = indexesFiles[i].getAbsolutePath();
136
				if (!knownPaths.containsKey(fileName) && fileName.toLowerCase().endsWith(".index")) { //$NON-NLS-1$
137
					if (VERBOSE)
138
						Util.verbose("Deleting index file " + indexesFiles[i]); //$NON-NLS-1$
139
					indexesFiles[i].delete();
140
				}
141
			}
142
		}
143
	}
125
	}
126
	deleteIndexFiles(knownPaths);
144
}
127
}
145
public String computeIndexLocation(IPath containerPath) {
128
public IPath computeIndexLocation(IPath containerPath) {
146
	String indexLocation = (String) this.indexLocations.get(containerPath);
129
	IPath indexLocation = (IPath) this.indexLocations.get(containerPath);
147
	if (indexLocation == null) {
130
	if (indexLocation == null) {
148
		String pathString = containerPath.toOSString();
131
		String pathString = containerPath.toOSString();
149
		checksumCalculator.reset();
132
		checksumCalculator.reset();
Lines 151-165 Link Here
151
		String fileName = Long.toString(checksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
134
		String fileName = Long.toString(checksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
152
		if (VERBOSE)
135
		if (VERBOSE)
153
			Util.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
136
			Util.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
154
		indexLocation = getJavaPluginWorkingLocation().append(fileName).toOSString();
137
		// to share the indexLocation between the indexLocations and indexStates tables, get the key from the indexStates table
138
		indexLocation = (IPath) getIndexStates().getKey(getJavaPluginWorkingLocation().append(fileName));
155
		this.indexLocations.put(containerPath, indexLocation);
139
		this.indexLocations.put(containerPath, indexLocation);
156
	}
140
	}
157
	return indexLocation;
141
	return indexLocation;
158
}
142
}
143
private void deleteIndexFiles(SimpleSet pathsToKeep) {
144
	File[] indexesFiles = getSavedIndexesDirectory().listFiles();
145
	if (indexesFiles == null) return;
146
147
	for (int i = 0, l = indexesFiles.length; i < l; i++) {
148
		String fileName = indexesFiles[i].getAbsolutePath();
149
		if (pathsToKeep != null && pathsToKeep.includes(fileName)) continue;
150
		String suffix = ".index"; //$NON-NLS-1$
151
		if (fileName.regionMatches(true, fileName.length() - suffix.length(), suffix, 0, suffix.length())) {
152
			if (VERBOSE)
153
				Util.verbose("Deleting index file " + indexesFiles[i]); //$NON-NLS-1$
154
			indexesFiles[i].delete();
155
		}
156
	}
157
}
159
/*
158
/*
160
 * Creates an empty index at the given location, for the given container path, if none exist.
159
 * Creates an empty index at the given location, for the given container path, if none exist.
161
 */
160
 */
162
public void ensureIndexExists(String indexLocation, IPath containerPath) {
161
public void ensureIndexExists(IPath indexLocation, IPath containerPath) {
163
	SimpleLookupTable states = getIndexStates();
162
	SimpleLookupTable states = getIndexStates();
164
	Object state = states.get(indexLocation);
163
	Object state = states.get(indexLocation);
165
	if (state == null) {
164
	if (state == null) {
Lines 196-202 Link Here
196
 * Warning: Does not check whether index is consistent (not being used)
195
 * Warning: Does not check whether index is consistent (not being used)
197
 */
196
 */
198
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
197
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
199
	String indexLocation = computeIndexLocation(containerPath);
198
	IPath indexLocation = computeIndexLocation(containerPath);
200
	return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
199
	return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
201
}
200
}
202
/**
201
/**
Lines 207-215 Link Here
207
 * 
206
 * 
208
 * Warning: Does not check whether index is consistent (not being used)
207
 * Warning: Does not check whether index is consistent (not being used)
209
 */
208
 */
210
public synchronized Index getIndex(IPath containerPath, String indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
209
public synchronized Index getIndex(IPath containerPath, IPath indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
211
	// Path is already canonical per construction
210
	// Path is already canonical per construction
212
	Index index = (Index) indexes.get(indexLocation);
211
	Index index = getIndex(indexLocation);
213
	if (index == null) {
212
	if (index == null) {
214
		Object state = getIndexStates().get(indexLocation);
213
		Object state = getIndexStates().get(indexLocation);
215
		Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
214
		Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
Lines 222-239 Link Here
222
221
223
		// index isn't cached, consider reusing an existing index file
222
		// index isn't cached, consider reusing an existing index file
224
		String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
223
		String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
224
		String indexLocationString = indexLocation.toOSString();
225
		if (reuseExistingFile) {
225
		if (reuseExistingFile) {
226
			File indexFile = new File(indexLocation);
226
			File indexFile = new File(indexLocationString);
227
			if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
227
			if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
228
				try {
228
				try {
229
					index = new Index(indexLocation, containerPathString, true /*reuse index file*/);
229
					index = new Index(indexLocationString, containerPathString, true /*reuse index file*/);
230
					indexes.put(indexLocation, index);
230
					this.indexes.put(indexLocation, index);
231
					return index;
231
					return index;
232
				} catch (IOException e) {
232
				} catch (IOException e) {
233
					// failed to read the existing file or its no longer compatible
233
					// failed to read the existing file or its no longer compatible
234
					if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
234
					if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
235
						if (VERBOSE)
235
						if (VERBOSE)
236
							Util.verbose("-> cannot reuse existing index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
236
							Util.verbose("-> cannot reuse existing index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
237
						rebuildIndex(indexLocation, containerPath);
237
						rebuildIndex(indexLocation, containerPath);
238
						return null;
238
						return null;
239
					} 
239
					} 
Lines 249-261 Link Here
249
		if (createIfMissing) {
249
		if (createIfMissing) {
250
			try {
250
			try {
251
				if (VERBOSE)
251
				if (VERBOSE)
252
					Util.verbose("-> create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
252
					Util.verbose("-> create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
253
				index = new Index(indexLocation, containerPathString, false /*do not reuse index file*/);
253
				index = new Index(indexLocationString, containerPathString, false /*do not reuse index file*/);
254
				indexes.put(indexLocation, index);
254
				this.indexes.put(indexLocation, index);
255
				return index;
255
				return index;
256
			} catch (IOException e) {
256
			} catch (IOException e) {
257
				if (VERBOSE)
257
				if (VERBOSE)
258
					Util.verbose("-> unable to create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
258
					Util.verbose("-> unable to create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
259
				// The file could not be created. Possible reason: the project has been deleted.
259
				// The file could not be created. Possible reason: the project has been deleted.
260
				return null;
260
				return null;
261
			}
261
			}
Lines 264-312 Link Here
264
	//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());	
264
	//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());	
265
	return index;
265
	return index;
266
}
266
}
267
public synchronized Index getIndex(String indexLocation) {
267
public synchronized Index getIndex(IPath indexLocation) {
268
	return (Index) indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
268
	return (Index) this.indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
269
}
269
}
270
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
270
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
271
	String indexLocation = computeIndexLocation(containerPath);
271
	IPath indexLocation = computeIndexLocation(containerPath);
272
	if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
272
	if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
273
		return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
273
		return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
274
274
275
	return null; // abort the job since the index has been removed from the REBUILDING_STATE
275
	return null; // abort the job since the index has been removed from the REBUILDING_STATE
276
}
276
}
277
private SimpleLookupTable getIndexStates() {
277
private SimpleLookupTable getIndexStates() {
278
	if (indexStates != null) return indexStates;
278
	if (this.indexStates != null) return this.indexStates;
279
279
280
	this.indexStates = new SimpleLookupTable();
280
	this.indexStates = new SimpleLookupTable();
281
	char[] savedIndexNames = readIndexState();
281
	IPath indexesDirectoryPath = getJavaPluginWorkingLocation();
282
	if (savedIndexNames.length > 0) {
282
	char[][] savedNames = readIndexState(indexesDirectoryPath.toOSString());
283
		char[][] names = CharOperation.splitOn('\n', savedIndexNames);
283
	if (savedNames != null) {
284
		if (names.length > 0) {
284
		for (int i = 1, l = savedNames.length; i < l; i++) { // first name is saved signature, see readIndexState()
285
			// check to see if workspace has moved, if so then do not trust saved indexes
285
			char[] savedName = savedNames[i];
286
			File indexesDirectory = new File(getJavaPluginWorkingLocation().toOSString());
286
			if (savedName.length > 0) {
287
			char[] dirName = indexesDirectory.getAbsolutePath().toCharArray();
287
				IPath indexLocation = indexesDirectoryPath.append(new String(savedName)); // shares indexesDirectoryPath's segments
288
			int delimiterPos = dirName.length;
288
				if (VERBOSE)
289
			if (CharOperation.match(names[0], 0, delimiterPos, dirName, 0, delimiterPos, true)) {
289
					Util.verbose("Reading saved index file " + indexLocation); //$NON-NLS-1$
290
				for (int i = 0, l = names.length; i < l; i++) {
290
				this.indexStates.put(indexLocation, SAVED_STATE);
291
					char[] name = names[i];
292
					if (name.length > 0)
293
						this.indexStates.put(new String(name), SAVED_STATE);
294
				}
295
			} else {
296
				savedIndexNamesFile.delete(); // forget saved indexes & delete each index file
297
				File[] files = indexesDirectory.listFiles();
298
				if (files != null) {
299
					for (int i = 0, l = files.length; i < l; i++) {
300
						String fileName = files[i].getAbsolutePath();
301
						if (fileName.toLowerCase().endsWith(".index")) { //$NON-NLS-1$
302
							if (VERBOSE)
303
								Util.verbose("Deleting index file " + files[i]); //$NON-NLS-1$
304
							files[i].delete();
305
						}
306
					}
307
				}
308
			}
291
			}
309
		}
292
		}
293
	} else {
294
		this.savedIndexNamesFile.delete(); // forget saved indexes & delete each index file
295
		deleteIndexFiles(null);
310
	}
296
	}
311
	return this.indexStates;
297
	return this.indexStates;
312
}
298
}
Lines 316-321 Link Here
316
	IPath stateLocation = JavaCore.getPlugin().getStateLocation();
302
	IPath stateLocation = JavaCore.getPlugin().getStateLocation();
317
	return this.javaPluginLocation = stateLocation;
303
	return this.javaPluginLocation = stateLocation;
318
}
304
}
305
private File getSavedIndexesDirectory() {
306
	return new File(getJavaPluginWorkingLocation().toOSString());
307
}
319
public void indexDocument(SearchDocument searchDocument, SearchParticipant searchParticipant, Index index, IPath indexLocation) {
308
public void indexDocument(SearchDocument searchDocument, SearchParticipant searchParticipant, Index index, IPath indexLocation) {
320
	try {
309
	try {
321
		((InternalSearchDocument) searchDocument).index = index;
310
		((InternalSearchDocument) searchDocument).index = index;
Lines 365-372 Link Here
365
	IndexRequest request = null;
354
	IndexRequest request = null;
366
	if (target instanceof IFile) {
355
	if (target instanceof IFile) {
367
		request = new AddJarFileToIndex((IFile) target, this);
356
		request = new AddJarFileToIndex((IFile) target, this);
368
	} else if (target instanceof java.io.File) {
357
	} else if (target instanceof File) {
369
		if (((java.io.File) target).isFile()) {
358
		if (((File) target).isFile()) {
370
			request = new AddJarFileToIndex(path, this);
359
			request = new AddJarFileToIndex(path, this);
371
		} else {
360
		} else {
372
			return;
361
			return;
Lines 394-405 Link Here
394
383
395
	this.request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
384
	this.request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
396
}
385
}
397
public void jobWasCancelled(IPath containerPath) {
386
public synchronized void jobWasCancelled(IPath containerPath) {
398
	String indexLocation = computeIndexLocation(containerPath);
387
	IPath indexLocation = computeIndexLocation(containerPath);
399
	Object o = this.indexes.get(indexLocation);
388
	Index index = getIndex(indexLocation);
400
	if (o instanceof Index) {
389
	if (index != null) {
401
		((Index) o).monitor = null;
390
		index.monitor = null;
402
		this.indexes.remove(indexLocation);
391
		this.indexes.removeKey(indexLocation);
403
	}
392
	}
404
	updateIndexState(indexLocation, UNKNOWN_STATE);
393
	updateIndexState(indexLocation, UNKNOWN_STATE);
405
}
394
}
Lines 424-437 Link Here
424
public String processName(){
413
public String processName(){
425
	return Messages.process_name; 
414
	return Messages.process_name; 
426
}
415
}
427
private void rebuildIndex(String indexLocation, IPath containerPath) {
416
private void rebuildIndex(IPath indexLocation, IPath containerPath) {
428
	IWorkspace workspace = ResourcesPlugin.getWorkspace();
417
	IWorkspace workspace = ResourcesPlugin.getWorkspace();
429
	if (workspace == null) return;
418
	if (workspace == null) return;
430
	Object target = JavaModel.getTarget(workspace.getRoot(), containerPath, true);
419
	Object target = JavaModel.getTarget(workspace.getRoot(), containerPath, true);
431
	if (target == null) return;
420
	if (target == null) return;
432
421
433
	if (VERBOSE)
422
	if (VERBOSE)
434
		Util.verbose("-> request to rebuild index: "+indexLocation+" path: "+containerPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
423
		Util.verbose("-> request to rebuild index: "+indexLocation+" path: "+containerPath); //$NON-NLS-1$ //$NON-NLS-2$
435
424
436
	updateIndexState(indexLocation, REBUILDING_STATE);
425
	updateIndexState(indexLocation, REBUILDING_STATE);
437
	IndexRequest request = null;
426
	IndexRequest request = null;
Lines 443-449 Link Here
443
		request = new IndexBinaryFolder((IFolder) target, this);
432
		request = new IndexBinaryFolder((IFolder) target, this);
444
	} else if (target instanceof IFile) {
433
	} else if (target instanceof IFile) {
445
		request = new AddJarFileToIndex((IFile) target, this);
434
		request = new AddJarFileToIndex((IFile) target, this);
446
	} else if (target instanceof java.io.File) {
435
	} else if (target instanceof File) {
447
		request = new AddJarFileToIndex(containerPath, this);
436
		request = new AddJarFileToIndex(containerPath, this);
448
	}
437
	}
449
	if (request != null)
438
	if (request != null)
Lines 459-472 Link Here
459
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
448
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
460
	try {
449
	try {
461
		// Path is already canonical
450
		// Path is already canonical
462
		String indexLocation = computeIndexLocation(containerPath);
451
		IPath indexLocation = computeIndexLocation(containerPath);
463
		
452
		Index index = getIndex(indexLocation);
464
		Index index = (Index) this.indexes.get(indexLocation);
465
		ReadWriteMonitor monitor = index == null ? null : index.monitor;
453
		ReadWriteMonitor monitor = index == null ? null : index.monitor;
466
454
467
		if (VERBOSE)
455
		if (VERBOSE)
468
			Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
456
			Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
469
		index = new Index(indexLocation, containerPathString, false /*reuse index file*/);
457
		index = new Index(indexLocation.toOSString(), containerPathString, false /*reuse index file*/);
470
		this.indexes.put(indexLocation, index);
458
		this.indexes.put(indexLocation, index);
471
		index.monitor = monitor;
459
		index.monitor = monitor;
472
		return index;
460
		return index;
Lines 493-538 Link Here
493
public synchronized void removeIndex(IPath containerPath) {
481
public synchronized void removeIndex(IPath containerPath) {
494
	if (VERBOSE)
482
	if (VERBOSE)
495
		Util.verbose("removing index " + containerPath); //$NON-NLS-1$
483
		Util.verbose("removing index " + containerPath); //$NON-NLS-1$
496
	String indexLocation = computeIndexLocation(containerPath);
484
	IPath indexLocation = computeIndexLocation(containerPath);
497
	File indexFile = new File(indexLocation);
485
	Index index = getIndex(indexLocation);
486
	File indexFile = null;
487
	if (index != null) {
488
		index.monitor = null;
489
		indexFile = index.getIndexFile();
490
	}
491
	if (indexFile == null)
492
		indexFile = new File(indexLocation.toOSString()); // index is not cached yet, but still want to delete the file
498
	if (indexFile.exists())
493
	if (indexFile.exists())
499
		indexFile.delete();
494
		indexFile.delete();
500
	Object o = this.indexes.get(indexLocation);
495
	this.indexes.removeKey(indexLocation);
501
	if (o instanceof Index)
502
		((Index) o).monitor = null;
503
	this.indexes.remove(indexLocation);
504
	updateIndexState(indexLocation, null);
496
	updateIndexState(indexLocation, null);
505
}
497
}
506
/**
498
/**
507
 * Removes all indexes whose paths start with (or are equal to) the given path. 
499
 * Removes all indexes whose paths start with (or are equal to) the given path. 
508
 */
500
 */
509
public synchronized void removeIndexPath(IPath path) {
501
public synchronized void removeIndexPath(IPath path) {
510
	Set entrySet = this.indexes.entrySet();
502
	Object[] keyTable = this.indexes.keyTable;
511
	Iterator entries = entrySet.iterator();
503
	Object[] valueTable = this.indexes.valueTable;
512
	String[] locations = null;
504
	IPath[] locations = null;
513
	int max = entrySet.size();
505
	int max = this.indexes.elementSize;
514
	int ptr = 0;
506
	int count = 0;
515
	while (entries.hasNext()) {
507
	for (int i = 0, l = keyTable.length; i < l; i++) {
516
		Map.Entry entry = (Map.Entry) entries.next();
508
		IPath indexLocation = (IPath) keyTable[i];
517
		String indexLocation = (String) entry.getKey();
509
		if (indexLocation == null)
518
		IPath indexPath = new Path(indexLocation);
510
			continue;
519
		if (path.isPrefixOf(indexPath)) {
511
		if (path.isPrefixOf(indexLocation)) {
520
			Index index = (Index) entry.getValue();
512
			Index index = (Index) valueTable[i];
521
			if (index != null) index.monitor = null;
513
			index.monitor = null;
522
			if (locations == null) locations = new String[max];
514
			if (locations == null)
523
			locations[ptr++] = indexLocation;
515
				locations = new IPath[max];
524
			File indexFile = new File(indexLocation);
516
			locations[count++] = indexLocation;
525
			if (indexFile.exists()) {
517
			File indexFile = index.getIndexFile();
518
			if (indexFile.exists())
526
				indexFile.delete();
519
				indexFile.delete();
527
			}
520
		} else {
528
		} else if (locations == null) {
529
			max--;
521
			max--;
530
		}
522
		}
531
	}
523
	}
532
	if (locations != null) {
524
	if (locations != null) {
533
		for (int i=0; i<ptr; i++) {
525
		for (int i = 0; i < count; i++)
534
			this.indexes.remove(locations[i]);
526
			this.indexes.removeKey(locations[i]);
535
		}
536
		removeIndexesState(locations);
527
		removeIndexesState(locations);
537
	}
528
	}
538
}
529
}
Lines 575-581 Link Here
575
public synchronized void reset() {
566
public synchronized void reset() {
576
	super.reset();
567
	super.reset();
577
	if (this.indexes != null) {
568
	if (this.indexes != null) {
578
		this.indexes = new HashMap(5);
569
		this.indexes = new SimpleLookupTable();
579
		this.indexStates = null;
570
		this.indexStates = null;
580
	}
571
	}
581
	this.indexLocations = new SimpleLookupTable();
572
	this.indexLocations = new SimpleLookupTable();
Lines 588-608 Link Here
588
			Util.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
579
			Util.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
589
		index.save();
580
		index.save();
590
	}
581
	}
591
	// TODO should use getJavaPluginWorkingLocation()+index simple name to avoid bugs such as https://bugs.eclipse.org/bugs/show_bug.cgi?id=62267
582
	synchronized (this) {
592
	String indexLocation = index.getIndexFile().getPath();
583
		IPath containerPath = new Path(index.containerPath);
593
	if (this.jobEnd > this.jobStart) {
584
		if (this.jobEnd > this.jobStart) {
594
		Object containerPath = this.indexLocations.keyForValue(indexLocation);
585
			for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
595
		if (containerPath != null) {
586
				IJob job = this.awaitingJobs[i];
596
			synchronized(this) {
587
				if (job instanceof IndexRequest)
597
				for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
588
					if (((IndexRequest) job).containerPath.equals(containerPath)) return;
598
					IJob job = this.awaitingJobs[i];
599
					if (job instanceof IndexRequest)
600
						if (((IndexRequest) job).containerPath.equals(containerPath)) return;
601
				}
602
			}
589
			}
603
		}
590
		}
591
		IPath indexLocation = computeIndexLocation(containerPath);
592
		updateIndexState(indexLocation, SAVED_STATE);
604
	}
593
	}
605
	updateIndexState(indexLocation, SAVED_STATE);
606
}
594
}
607
/**
595
/**
608
 * Commit all index memory changes to disk
596
 * Commit all index memory changes to disk
Lines 611-620 Link Here
611
	// only save cached indexes... the rest were not modified
599
	// only save cached indexes... the rest were not modified
612
	ArrayList toSave = new ArrayList();
600
	ArrayList toSave = new ArrayList();
613
	synchronized(this) {
601
	synchronized(this) {
614
		for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
602
		Object[] valueTable = this.indexes.valueTable;
615
			Object o = iter.next();
603
		for (int i = 0, l = valueTable.length; i < l; i++) {
616
			if (o instanceof Index)
604
			Index index = (Index) valueTable[i];
617
				toSave.add(o);
605
			if (index != null)
606
				toSave.add(index);
618
		}
607
		}
619
	}
608
	}
620
609
Lines 650-656 Link Here
650
	}
639
	}
651
	this.needToSave = !allSaved;
640
	this.needToSave = !allSaved;
652
}
641
}
653
public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final String indexLocation, final SearchParticipant searchParticipant) {
642
public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IPath indexLocation, final SearchParticipant searchParticipant) {
654
	request(new IndexRequest(container, this) {
643
	request(new IndexRequest(container, this) {
655
		public boolean execute(IProgressMonitor progressMonitor) {
644
		public boolean execute(IProgressMonitor progressMonitor) {
656
			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
645
			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
Lines 663-669 Link Here
663
			
652
			
664
			try {
653
			try {
665
				monitor.enterWrite(); // ask permission to write
654
				monitor.enterWrite(); // ask permission to write
666
				indexDocument(searchDocument, searchParticipant, index, new Path(indexLocation));
655
				indexDocument(searchDocument, searchParticipant, index, indexLocation);
667
			} finally {
656
			} finally {
668
				monitor.exitWrite(); // free write lock
657
				monitor.exitWrite(); // free write lock
669
			}
658
			}
Lines 680-701 Link Here
680
	buffer.append(super.toString());
669
	buffer.append(super.toString());
681
	buffer.append("In-memory indexes:\n"); //$NON-NLS-1$
670
	buffer.append("In-memory indexes:\n"); //$NON-NLS-1$
682
	int count = 0;
671
	int count = 0;
683
	for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
672
	Object[] valueTable = this.indexes.valueTable;
684
		buffer.append(++count).append(" - ").append(iter.next().toString()).append('\n'); //$NON-NLS-1$
673
	for (int i = 0, l = valueTable.length; i < l; i++) {
674
		Index index = (Index) valueTable[i];
675
		if (index != null)
676
			buffer.append(++count).append(" - ").append(index.toString()).append('\n'); //$NON-NLS-1$
685
	}
677
	}
686
	return buffer.toString();
678
	return buffer.toString();
687
}
679
}
688
680
689
private char[] readIndexState() {
681
private char[][] readIndexState(String dirOSString) {
690
	try {
682
	try {
691
		return org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(savedIndexNamesFile, null);
683
		char[] savedIndexNames = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(savedIndexNamesFile, null);
684
		if (savedIndexNames.length > 0) {
685
			char[][] names = CharOperation.splitOn('\n', savedIndexNames);
686
			if (names.length > 1) {
687
				// First line is DiskIndex signature + saved plugin working location (see writeSavedIndexNamesFile())
688
				String savedSignature = DiskIndex.SIGNATURE + "+" + dirOSString; //$NON-NLS-1$
689
				if (savedSignature.equals(new String(names[0])))
690
					return names;
691
			}
692
		}
692
	} catch (IOException ignored) {
693
	} catch (IOException ignored) {
693
		if (VERBOSE)
694
		if (VERBOSE)
694
			Util.verbose("Failed to read saved index file names"); //$NON-NLS-1$
695
			Util.verbose("Failed to read saved index file names"); //$NON-NLS-1$
695
		return CharOperation.NO_CHAR;
696
	}
696
	}
697
	return null;
697
}
698
}
698
private synchronized void removeIndexesState(String[] locations) {
699
private synchronized void removeIndexesState(IPath[] locations) {
699
	getIndexStates(); // ensure the states are initialized
700
	getIndexStates(); // ensure the states are initialized
700
	int length = locations.length;
701
	int length = locations.length;
701
	boolean changed = false;
702
	boolean changed = false;
Lines 712-718 Link Here
712
713
713
	writeSavedIndexNamesFile();
714
	writeSavedIndexNamesFile();
714
}
715
}
715
private synchronized void updateIndexState(String indexLocation, Integer indexState) {
716
private synchronized void updateIndexState(IPath indexLocation, Integer indexState) {
716
	getIndexStates(); // ensure the states are initialized
717
	getIndexStates(); // ensure the states are initialized
717
	if (indexState != null) {
718
	if (indexState != null) {
718
		if (indexState.equals(indexStates.get(indexLocation))) return; // not changed
719
		if (indexState.equals(indexStates.get(indexLocation))) return; // not changed
Lines 737-747 Link Here
737
	BufferedWriter writer = null;
738
	BufferedWriter writer = null;
738
	try {
739
	try {
739
		writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
740
		writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
741
		writer.write(DiskIndex.SIGNATURE);
742
		writer.write('+');
743
		writer.write(getJavaPluginWorkingLocation().toOSString());
744
		writer.write('\n');
740
		Object[] keys = indexStates.keyTable;
745
		Object[] keys = indexStates.keyTable;
741
		Object[] states = indexStates.valueTable;
746
		Object[] states = indexStates.valueTable;
742
		for (int i = 0, l = states.length; i < l; i++) {
747
		for (int i = 0, l = states.length; i < l; i++) {
743
			if (states[i] == SAVED_STATE) {
748
			if (states[i] == SAVED_STATE) {
744
				writer.write((String) keys[i]);
749
				writer.write(((IPath) keys[i]).lastSegment());
745
				writer.write('\n');
750
				writer.write('\n');
746
			}
751
			}
747
		}
752
		}
(-)compiler/org/eclipse/jdt/internal/compiler/util/SimpleSetOfCharArray.java (-1 / +16 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
2
 * Copyright (c) 2006, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 76-81 Link Here
76
	return result;
76
	return result;
77
}
77
}
78
78
79
public char[] get(char[] object) {
80
	int length = this.values.length;
81
	int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length;
82
	char[] current;
83
	while ((current = this.values[index]) != null) {
84
		if (CharOperation.equals(current, object)) return current;
85
		if (++index == length) index = 0;
86
	}
87
	this.values[index] = object;
88
89
	// assumes the threshold is never equal to the size of the table
90
	if (++this.elementSize > this.threshold) rehash();
91
	return object;
92
}
93
79
public boolean includes(char[] object) {
94
public boolean includes(char[] object) {
80
	int length = values.length;
95
	int length = values.length;
81
	int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length;
96
	int index = (CharOperation.hashCode(object) & 0x7FFFFFFF) % length;
(-)compiler/org/eclipse/jdt/internal/compiler/util/SimpleLookupTable.java (-1 / +12 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 74-79 Link Here
74
	return null;
74
	return null;
75
}
75
}
76
76
77
public Object getKey(Object key) {
78
	int length = keyTable.length;
79
	int index = (key.hashCode() & 0x7FFFFFFF) % length;
80
	Object currentKey;
81
	while ((currentKey = keyTable[index]) != null) {
82
		if (currentKey.equals(key)) return currentKey;
83
		if (++index == length) index = 0;
84
	}
85
	return key;
86
}
87
77
public Object keyForValue(Object valueToMatch) {
88
public Object keyForValue(Object valueToMatch) {
78
	if (valueToMatch != null)
89
	if (valueToMatch != null)
79
		for (int i = 0, l = keyTable.length; i < l; i++)
90
		for (int i = 0, l = keyTable.length; i < l; i++)
(-)search/org/eclipse/jdt/core/search/SearchParticipant.java (-4 / +3 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 205-214 Link Here
205
			containerPath = documentPath.removeLastSegments(documentPath.segmentCount()-1);
205
			containerPath = documentPath.removeLastSegments(documentPath.segmentCount()-1);
206
		}
206
		}
207
		IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
207
		IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
208
		String osIndexLocation = indexLocation.toOSString();
209
		// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
208
		// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
210
		manager.ensureIndexExists(osIndexLocation, containerPath);
209
		manager.ensureIndexExists(indexLocation, containerPath);
211
		manager.scheduleDocumentIndexing(document, containerPath, osIndexLocation, this);
210
		manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this);
212
	}
211
	}
213
212
214
	/**
213
	/**

Return to bug 138309