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

Collapse All | Expand All

(-)search/org/eclipse/jdt/internal/core/index/CategoryTable.java (-76 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core.index;
12
13
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
14
15
16
/**
17
 * Hashtable of {char[] --> Object } typically used for the category table
18
 * stored in the {@link DiskIndex disk index}.
19
 * <p>
20
 * This is a more specific {@link HashtableOfObject hashtable of objects} where
21
 * the hash code is computed by using twice more characters than the hash
22
 * code computation of the {@link HashtableOfObject original hashtable}.
23
 * </p><p>
24
 * This is typically important for type declaration category table for which the
25
 * key postfix might have more than 16 identical characters...
26
 * </p>
27
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=289057"
28
 */
29
public final class CategoryTable extends HashtableOfObject {
30
31
	public CategoryTable() {
32
		super();
33
	}
34
	public CategoryTable(int size) {
35
		super(size);
36
	}
37
	
38
	/* (non-Javadoc)
39
	 * 
40
	 * The hash code computation is done by using half of the 32 characters last
41
	 * characters of the given array instead of only half of the 16 last ones for the
42
	 * super implementation...
43
	 * 
44
	 * @see org.eclipse.jdt.internal.compiler.util.HashtableOfObject#hashCode(char[])
45
	 */
46
	protected int hashCode(char[] array) {
47
		int length = array.length;
48
		int hash = length == 0 ? 31 : array[0];
49
		if (length < 16) {
50
			for (int i = length; --i > 0;)
51
				hash = (hash * 31) + array[i];
52
		} else {
53
			// 16 characters is enough to compute a decent hash code, don't waste time examining every character
54
			for (int i = length - 1, last = i > 32 ? i - 32 : 0; i > last; i -= 2)
55
				hash = (hash * 31) + array[i];
56
			
57
		}
58
		return hash & 0x7FFFFFFF;
59
		
60
	}
61
62
	/* (non-Javadoc)
63
	 * @see org.eclipse.jdt.internal.compiler.util.HashtableOfObject#rehash()
64
	 */
65
	protected void rehash() {
66
		CategoryTable newHashtable = new CategoryTable(this.elementSize * 2);		// double the number of expected elements
67
		char[] currentKey;
68
		for (int i = this.keyTable.length; --i >= 0;)
69
			if ((currentKey = this.keyTable[i]) != null)
70
				newHashtable.putUnsafely(currentKey, this.valueTable[i]);
71
	
72
		this.keyTable = newHashtable.keyTable;
73
		this.valueTable = newHashtable.valueTable;
74
		this.threshold = newHashtable.threshold;
75
	}
76
}
(-)search/org/eclipse/jdt/internal/core/index/DiskIndex.java (-24 / +28 lines)
Lines 132-151 Link Here
132
	}
132
	}
133
	return results;
133
	return results;
134
}
134
}
135
private HashtableOfObject addQueryResult(HashtableOfObject results, char[] word, CategoryTable wordsToDocNumbers, MemoryIndex memoryIndex, boolean prevResults) throws IOException {
135
private HashtableOfObject addQueryResult(HashtableOfObject results, char[] word, Object docs, MemoryIndex memoryIndex, boolean prevResults) throws IOException {
136
	// must skip over documents which have been added/changed/deleted in the memory index
136
	// must skip over documents which have been added/changed/deleted in the memory index
137
	if (results == null)
137
	if (results == null)
138
		results = new HashtableOfObject(13);
138
		results = new HashtableOfObject(13);
139
	EntryResult result = prevResults ? (EntryResult) results.get(word) : null;
139
	EntryResult result = prevResults ? (EntryResult) results.get(word) : null;
140
	if (memoryIndex == null) {
140
	if (memoryIndex == null) {
141
		if (result == null)
141
		if (result == null)
142
			results.putUnsafely(word, new EntryResult(word, wordsToDocNumbers));
142
			results.putUnsafely(word, new EntryResult(word, docs));
143
		else
143
		else
144
			result.addDocumentTable(wordsToDocNumbers);
144
			result.addDocumentTable(docs);
145
	} else {
145
	} else {
146
		SimpleLookupTable docsToRefs = memoryIndex.docsToReferences;
146
		SimpleLookupTable docsToRefs = memoryIndex.docsToReferences;
147
		if (result == null) result = new EntryResult(word, null);
147
		if (result == null) result = new EntryResult(word, null);
148
		int[] docNumbers = readDocumentNumbers(wordsToDocNumbers.get(word));
148
		int[] docNumbers = readDocumentNumbers(docs);
149
		for (int i = 0, l = docNumbers.length; i < l; i++) {
149
		for (int i = 0, l = docNumbers.length; i < l; i++) {
150
			String docName = readDocumentName(docNumbers[i]);
150
			String docName = readDocumentName(docNumbers[i]);
151
			if (!docsToRefs.containsKey(docName))
151
			if (!docsToRefs.containsKey(docName))
Lines 167-180 Link Here
167
	boolean prevResults = false;
167
	boolean prevResults = false;
168
	if (key == null) {
168
	if (key == null) {
169
		for (int i = 0, l = categories.length; i < l; i++) {
169
		for (int i = 0, l = categories.length; i < l; i++) {
170
			CategoryTable wordsToDocNumbers = readCategoryTable(categories[i], true); // cache if key is null since its a definite match
170
			HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], true); // cache if key is null since its a definite match
171
			if (wordsToDocNumbers != null) {
171
			if (wordsToDocNumbers != null) {
172
				char[][] words = wordsToDocNumbers.keyTable;
172
				char[][] words = wordsToDocNumbers.keyTable;
173
				Object[] values = wordsToDocNumbers.valueTable;
173
				if (results == null)
174
				if (results == null)
174
					results = new HashtableOfObject(wordsToDocNumbers.elementSize);
175
					results = new HashtableOfObject(wordsToDocNumbers.elementSize);
175
				for (int j = 0, m = words.length; j < m; j++)
176
				for (int j = 0, m = words.length; j < m; j++)
176
					if (words[j] != null)
177
					if (words[j] != null)
177
						results = addQueryResult(results, words[j], wordsToDocNumbers, memoryIndex, prevResults);
178
						results = addQueryResult(results, words[j], values[j], memoryIndex, prevResults);
178
			}
179
			}
179
			prevResults = results != null;
180
			prevResults = results != null;
180
		}
181
		}
Lines 184-204 Link Here
184
		switch (matchRule) {
185
		switch (matchRule) {
185
			case SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE:
186
			case SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE:
186
				for (int i = 0, l = categories.length; i < l; i++) {
187
				for (int i = 0, l = categories.length; i < l; i++) {
187
					CategoryTable wordsToDocNumbers = readCategoryTable(categories[i], false);
188
					HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], false);
188
					if (wordsToDocNumbers != null && wordsToDocNumbers.containsKey(key))
189
					Object value;
189
						results = addQueryResult(results, key, wordsToDocNumbers, memoryIndex, prevResults);
190
					if (wordsToDocNumbers != null && (value = wordsToDocNumbers.get(key)) != null)
191
						results = addQueryResult(results, key, value, memoryIndex, prevResults);
190
					prevResults = results != null;
192
					prevResults = results != null;
191
				}
193
				}
192
				break;
194
				break;
193
			case SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE:
195
			case SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE:
194
				for (int i = 0, l = categories.length; i < l; i++) {
196
				for (int i = 0, l = categories.length; i < l; i++) {
195
					CategoryTable wordsToDocNumbers = readCategoryTable(categories[i], false);
197
					HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], false);
196
					if (wordsToDocNumbers != null) {
198
					if (wordsToDocNumbers != null) {
197
						char[][] words = wordsToDocNumbers.keyTable;
199
						char[][] words = wordsToDocNumbers.keyTable;
200
						Object[] values = wordsToDocNumbers.valueTable;
198
						for (int j = 0, m = words.length; j < m; j++) {
201
						for (int j = 0, m = words.length; j < m; j++) {
199
							char[] word = words[j];
202
							char[] word = words[j];
200
							if (word != null && key[0] == word[0] && CharOperation.prefixEquals(key, word))
203
							if (word != null && key[0] == word[0] && CharOperation.prefixEquals(key, word))
201
								results = addQueryResult(results, word, wordsToDocNumbers, memoryIndex, prevResults);
204
								results = addQueryResult(results, word, values[j], memoryIndex, prevResults);
202
						}
205
						}
203
					}
206
					}
204
					prevResults = results != null;
207
					prevResults = results != null;
Lines 206-218 Link Here
206
				break;
209
				break;
207
			default:
210
			default:
208
				for (int i = 0, l = categories.length; i < l; i++) {
211
				for (int i = 0, l = categories.length; i < l; i++) {
209
					CategoryTable wordsToDocNumbers = readCategoryTable(categories[i], false);
212
					HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], false);
210
					if (wordsToDocNumbers != null) {
213
					if (wordsToDocNumbers != null) {
211
						char[][] words = wordsToDocNumbers.keyTable;
214
						char[][] words = wordsToDocNumbers.keyTable;
215
						Object[] values = wordsToDocNumbers.valueTable;
212
						for (int j = 0, m = words.length; j < m; j++) {
216
						for (int j = 0, m = words.length; j < m; j++) {
213
							char[] word = words[j];
217
							char[] word = words[j];
214
							if (word != null && Index.isMatch(key, word, matchRule))
218
							if (word != null && Index.isMatch(key, word, matchRule))
215
								results = addQueryResult(results, word, wordsToDocNumbers, memoryIndex, prevResults);
219
								results = addQueryResult(results, word, values[j], memoryIndex, prevResults);
216
						}
220
						}
217
					}
221
					}
218
					prevResults = results != null;
222
					prevResults = results != null;
Lines 344-352 Link Here
344
		char[] categoryName = categoryNames[i];
348
		char[] categoryName = categoryNames[i];
345
		if (categoryName != null) {
349
		if (categoryName != null) {
346
			SimpleWordSet wordSet = (SimpleWordSet) wordSets[i];
350
			SimpleWordSet wordSet = (SimpleWordSet) wordSets[i];
347
			CategoryTable wordsToDocs = (CategoryTable) this.categoryTables.get(categoryName);
351
			HashtableOfObject wordsToDocs = (HashtableOfObject) this.categoryTables.get(categoryName);
348
			if (wordsToDocs == null)
352
			if (wordsToDocs == null)
349
				this.categoryTables.put(categoryName, wordsToDocs = new CategoryTable(wordSet.elementSize));
353
				this.categoryTables.put(categoryName, wordsToDocs = new HashtableOfObject(wordSet.elementSize));
350
354
351
			char[][] words = wordSet.words;
355
			char[][] words = wordSet.words;
352
			for (int j = 0, m = words.length; j < m; j++) {
356
			for (int j = 0, m = words.length; j < m; j++) {
Lines 450-460 Link Here
450
	this.categoryTables = null;
454
	this.categoryTables = null;
451
}
455
}
452
private void mergeCategory(char[] categoryName, DiskIndex onDisk, int[] positions, FileOutputStream stream) throws IOException {
456
private void mergeCategory(char[] categoryName, DiskIndex onDisk, int[] positions, FileOutputStream stream) throws IOException {
453
	CategoryTable wordsToDocs = (CategoryTable) this.categoryTables.get(categoryName);
457
	HashtableOfObject wordsToDocs = (HashtableOfObject) this.categoryTables.get(categoryName);
454
	if (wordsToDocs == null)
458
	if (wordsToDocs == null)
455
		wordsToDocs = new CategoryTable(3);
459
		wordsToDocs = new HashtableOfObject(3);
456
460
457
	CategoryTable oldWordsToDocs = onDisk.readCategoryTable(categoryName, true);
461
	HashtableOfObject oldWordsToDocs = onDisk.readCategoryTable(categoryName, true);
458
	if (oldWordsToDocs != null) {
462
	if (oldWordsToDocs != null) {
459
		char[][] oldWords = oldWordsToDocs.keyTable;
463
		char[][] oldWords = oldWordsToDocs.keyTable;
460
		Object[] oldArrayOffsets = oldWordsToDocs.valueTable;
464
		Object[] oldArrayOffsets = oldWordsToDocs.valueTable;
Lines 588-594 Link Here
588
		this.streamBuffer = null;
592
		this.streamBuffer = null;
589
	}
593
	}
590
}
594
}
591
private synchronized CategoryTable readCategoryTable(char[] categoryName, boolean readDocNumbers) throws IOException {
595
private synchronized HashtableOfObject readCategoryTable(char[] categoryName, boolean readDocNumbers) throws IOException {
592
	// result will be null if categoryName is unknown
596
	// result will be null if categoryName is unknown
593
	int offset = this.categoryOffsets.get(categoryName);
597
	int offset = this.categoryOffsets.get(categoryName);
594
	if (offset == HashtableOfIntValues.NO_VALUE) {
598
	if (offset == HashtableOfIntValues.NO_VALUE) {
Lines 598-604 Link Here
598
	if (this.categoryTables == null) {
602
	if (this.categoryTables == null) {
599
		this.categoryTables = new HashtableOfObject(3);
603
		this.categoryTables = new HashtableOfObject(3);
600
	} else {
604
	} else {
601
		CategoryTable cachedTable = (CategoryTable) this.categoryTables.get(categoryName);
605
		HashtableOfObject cachedTable = (HashtableOfObject) this.categoryTables.get(categoryName);
602
		if (cachedTable != null) {
606
		if (cachedTable != null) {
603
			if (readDocNumbers) { // must cache remaining document number arrays
607
			if (readDocNumbers) { // must cache remaining document number arrays
604
				Object[] arrayOffsets = cachedTable.valueTable;
608
				Object[] arrayOffsets = cachedTable.valueTable;
Lines 611-617 Link Here
611
	}
615
	}
612
616
613
	FileInputStream stream = new FileInputStream(this.indexFile);
617
	FileInputStream stream = new FileInputStream(this.indexFile);
614
	CategoryTable categoryTable = null;
618
	HashtableOfObject categoryTable = null;
615
	char[][] matchingWords = null;
619
	char[][] matchingWords = null;
616
	int count = 0;
620
	int count = 0;
617
	int firstOffset = -1;
621
	int firstOffset = -1;
Lines 629-635 Link Here
629
				System.err.println("size = "+size); //$NON-NLS-1$
633
				System.err.println("size = "+size); //$NON-NLS-1$
630
				System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
634
				System.err.println("--------------------   END   --------------------"); //$NON-NLS-1$
631
			}
635
			}
632
			categoryTable = new CategoryTable(size);
636
			categoryTable = new HashtableOfObject(size);
633
		} catch (OutOfMemoryError oom) {
637
		} catch (OutOfMemoryError oom) {
634
			// DEBUG
638
			// DEBUG
635
			oom.printStackTrace();
639
			oom.printStackTrace();
Lines 1038-1047 Link Here
1038
	Object[] tables = this.categoryTables.valueTable;
1042
	Object[] tables = this.categoryTables.valueTable;
1039
	for (int i = 0, l = categoryNames.length; i < l; i++)
1043
	for (int i = 0, l = categoryNames.length; i < l; i++)
1040
		if (categoryNames[i] != null)
1044
		if (categoryNames[i] != null)
1041
			writeCategoryTable(categoryNames[i], (CategoryTable) tables[i], stream);
1045
			writeCategoryTable(categoryNames[i], (HashtableOfObject) tables[i], stream);
1042
	this.categoryTables = null;
1046
	this.categoryTables = null;
1043
}
1047
}
1044
private void writeCategoryTable(char[] categoryName, CategoryTable wordsToDocs, FileOutputStream stream) throws IOException {
1048
private void writeCategoryTable(char[] categoryName, HashtableOfObject wordsToDocs, FileOutputStream stream) throws IOException {
1045
	// the format of a category table is as follows:
1049
	// the format of a category table is as follows:
1046
	// any document number arrays with >= 256 elements are written before the table (the offset to each array is remembered)
1050
	// any document number arrays with >= 256 elements are written before the table (the offset to each array is remembered)
1047
	// then the number of word->int[] pairs in the table is written
1051
	// then the number of word->int[] pairs in the table is written
(-)search/org/eclipse/jdt/internal/core/index/EntryResult.java (-9 / +8 lines)
Lines 11-42 Link Here
11
package org.eclipse.jdt.internal.core.index;
11
package org.eclipse.jdt.internal.core.index;
12
12
13
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
15
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
14
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
16
15
17
public class EntryResult {
16
public class EntryResult {
18
17
19
private char[] word;
18
private char[] word;
20
private HashtableOfObject[] documentTables;
19
private Object[] documentTables;
21
private SimpleSet documentNames;
20
private SimpleSet documentNames;
22
21
23
public EntryResult(char[] word, HashtableOfObject table) {
22
public EntryResult(char[] word, Object table) {
24
	this.word = word;
23
	this.word = word;
25
	if (table != null)
24
	if (table != null)
26
		this.documentTables = new HashtableOfObject[] {table};
25
		this.documentTables = new Object[] {table};
27
}
26
}
28
public void addDocumentName(String documentName) {
27
public void addDocumentName(String documentName) {
29
	if (this.documentNames == null)
28
	if (this.documentNames == null)
30
		this.documentNames = new SimpleSet(3);
29
		this.documentNames = new SimpleSet(3);
31
	this.documentNames.add(documentName);
30
	this.documentNames.add(documentName);
32
}
31
}
33
public void addDocumentTable(HashtableOfObject table) {
32
public void addDocumentTable(Object table) {
34
	if (this.documentTables != null) {
33
	if (this.documentTables != null) {
35
		int length = this.documentTables.length;
34
		int length = this.documentTables.length;
36
		System.arraycopy(this.documentTables, 0, this.documentTables = new HashtableOfObject[length + 1], 0, length);
35
		System.arraycopy(this.documentTables, 0, this.documentTables = new Object[length + 1], 0, length);
37
		this.documentTables[length] = table;
36
		this.documentTables[length] = table;
38
	} else {
37
	} else {
39
		this.documentTables = new HashtableOfObject[] {table};
38
		this.documentTables = new Object[] {table};
40
	}
39
	}
41
}
40
}
42
public char[] getWord() {
41
public char[] getWord() {
Lines 46-52 Link Here
46
	if (this.documentTables != null) {
45
	if (this.documentTables != null) {
47
		int length = this.documentTables.length;
46
		int length = this.documentTables.length;
48
		if (length == 1 && this.documentNames == null) { // have a single table
47
		if (length == 1 && this.documentNames == null) { // have a single table
49
			Object offset = this.documentTables[0].get(this.word);
48
			Object offset = this.documentTables[0];
50
			int[] numbers = index.diskIndex.readDocumentNumbers(offset);
49
			int[] numbers = index.diskIndex.readDocumentNumbers(offset);
51
			String[] names = new String[numbers.length];
50
			String[] names = new String[numbers.length];
52
			for (int i = 0, l = numbers.length; i < l; i++)
51
			for (int i = 0, l = numbers.length; i < l; i++)
Lines 55-61 Link Here
55
		}
54
		}
56
55
57
		for (int i = 0; i < length; i++) {
56
		for (int i = 0; i < length; i++) {
58
			Object offset = this.documentTables[i].get(this.word);
57
			Object offset = this.documentTables[i];
59
			int[] numbers = index.diskIndex.readDocumentNumbers(offset);
58
			int[] numbers = index.diskIndex.readDocumentNumbers(offset);
60
			for (int j = 0, k = numbers.length; j < k; j++)
59
			for (int j = 0, k = numbers.length; j < k; j++)
61
				addDocumentName(index.diskIndex.readDocumentName(numbers[j]));
60
				addDocumentName(index.diskIndex.readDocumentName(numbers[j]));

Return to bug 306170