mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Patch for Bogdan Gheorghe:
- The initial framework for the new indexer. - Added a checkbox to the Indexer tab on the C/C++ Projects settings dialog to turn on the indexing on a per project basis.
This commit is contained in:
parent
728848ffc6
commit
afbe575516
70 changed files with 11247 additions and 140 deletions
|
@ -6,6 +6,7 @@
|
|||
<classpathentry kind="src" path="parser/"/>
|
||||
<classpathentry kind="src" path="resources/"/>
|
||||
<classpathentry kind="src" path="suite/"/>
|
||||
<classpathentry kind="src" path="indexer"/>
|
||||
<classpathentry kind="src" path="/org.apache.xerces"/>
|
||||
<classpathentry kind="src" path="/org.eclipse.core.resources"/>
|
||||
<classpathentry kind="src" path="/org.eclipse.core.runtime"/>
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 Rational Software Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
***********************************************************************/
|
||||
/*
|
||||
* Created on Jun 19, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.core.indexer.tests;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.CProjectNature;
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IProjectDescription;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IWorkspace;
|
||||
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/**
|
||||
* @author bgheorgh
|
||||
*/
|
||||
public class IndexManagerTest extends TestCase {
|
||||
IFile file;
|
||||
IFileDocument fileDoc;
|
||||
IProject testProject;
|
||||
NullProgressMonitor monitor;
|
||||
IndexManager indexManager;
|
||||
/**
|
||||
* Constructor for IndexManagerTest.
|
||||
* @param name
|
||||
*/
|
||||
public IndexManagerTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
/*
|
||||
* @see TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
//Create temp project
|
||||
testProject = createProject("IndexerTestProject");
|
||||
if (testProject==null)
|
||||
fail("Unable to create project");
|
||||
//Add a file to the project
|
||||
importFile("mail.cpp","resources/indexer/mail.cpp");
|
||||
//Start up the index manager
|
||||
//indexManager = new IndexManager();
|
||||
//indexManager.reset();
|
||||
}
|
||||
/*
|
||||
* @see TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
//Delete project
|
||||
//testProject.delete(true,monitor);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return new TestSuite(IndexManagerTest.class);
|
||||
}
|
||||
/*
|
||||
* Utils
|
||||
*/
|
||||
private IProject createProject(String projectName) throws CoreException
|
||||
{
|
||||
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
|
||||
IProject project= root.getProject(projectName);
|
||||
if (!project.exists()) {
|
||||
project.create(null);
|
||||
} else {
|
||||
project.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||
}
|
||||
if (!project.isOpen()) {
|
||||
project.open(null);
|
||||
}
|
||||
if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
|
||||
addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
|
||||
}
|
||||
//Fill out a project description
|
||||
IPath defaultPath = Platform.getLocation();
|
||||
IPath newPath = project.getFullPath();
|
||||
if (defaultPath.equals(newPath))
|
||||
newPath = null;
|
||||
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||
IProjectDescription description = workspace.newProjectDescription(project.getName());
|
||||
description.setLocation(newPath);
|
||||
//Create the project
|
||||
IProject cproject = CCorePlugin.getDefault().createCProject(description,project,monitor,CCorePlugin.PLUGIN_ID + ".make"); //.getCoreModel().create(project);
|
||||
|
||||
return cproject;
|
||||
}
|
||||
|
||||
private void importFile(String fileName, String resourceLocation)throws Exception{
|
||||
//Obtain file handle
|
||||
file = testProject.getProject().getFile(fileName);
|
||||
String pluginRoot=org.eclipse.core.runtime.Platform.getPlugin("org.eclipse.cdt.core.tests").find(new Path("/")).getFile();
|
||||
//Create file input stream
|
||||
monitor = new NullProgressMonitor();
|
||||
if (!file.exists()){
|
||||
file.create(new FileInputStream(pluginRoot + resourceLocation),false,monitor);
|
||||
}
|
||||
fileDoc = new IFileDocument(file);
|
||||
}
|
||||
|
||||
private void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
|
||||
IProjectDescription description = proj.getDescription();
|
||||
String[] prevNatures= description.getNatureIds();
|
||||
String[] newNatures= new String[prevNatures.length + 1];
|
||||
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
|
||||
newNatures[prevNatures.length]= natureId;
|
||||
description.setNatureIds(newNatures);
|
||||
proj.setDescription(description, monitor);
|
||||
}
|
||||
/*
|
||||
* Start of tests
|
||||
*/
|
||||
public void testIndexAll() throws Exception {
|
||||
//Enable indexing on the created project
|
||||
//By doing this, we force the Index Manager to indexAll()
|
||||
indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||
indexManager.setEnabled(testProject,true);
|
||||
|
||||
Thread.sleep(15000);
|
||||
IIndex ind = indexManager.getIndex(testProject.getFullPath(),true,true);
|
||||
char[] prefix = "typeDecl/".toCharArray();
|
||||
IQueryResult[] qresults = ind.queryPrefix(prefix);
|
||||
IEntryResult[] eresults = ind.queryEntries(prefix);
|
||||
String [] queryResultModel = {"IndexedFile(1: /IndexerTestProject/mail.cpp)"};
|
||||
String [] entryResultModel ={"EntryResult: word=typeDecl/C/Mail/, refs={ 1 }", "EntryResult: word=typeDecl/C/Unknown/, refs={ 1 }", "EntryResult: word=typeDecl/C/container/, refs={ 1 }", "EntryResult: word=typeDecl/C/first_class/, refs={ 1 }", "EntryResult: word=typeDecl/C/postcard/, refs={ 1 }"};
|
||||
|
||||
if (qresults.length != queryResultModel.length)
|
||||
fail("Query Result length different from model");
|
||||
|
||||
if (eresults.length != entryResultModel.length)
|
||||
fail("Entry Result length different from model");
|
||||
|
||||
|
||||
for (int i=0; i<qresults.length;i++)
|
||||
{
|
||||
assertEquals(queryResultModel[i],qresults[i].toString());
|
||||
}
|
||||
|
||||
for (int i=0;i<eresults.length; i++)
|
||||
{
|
||||
assertEquals(entryResultModel[i],eresults[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
98
core/org.eclipse.cdt.core.tests/resources/indexer/mail.cpp
Normal file
98
core/org.eclipse.cdt.core.tests/resources/indexer/mail.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <iostream.h>
|
||||
#include <stdlib.h>
|
||||
#include <alloc.h>
|
||||
#include <iomanip.h>
|
||||
|
||||
class Mail
|
||||
{
|
||||
public:
|
||||
Mail(){}
|
||||
virtual void print()=0; //Pure Virtual Function, forces redefinition
|
||||
protected:
|
||||
float postage;
|
||||
char *type;
|
||||
friend ostream& operator << (ostream& os, Mail *m);
|
||||
};
|
||||
|
||||
class postcard : public Mail
|
||||
{
|
||||
public:
|
||||
postcard(): Mail(){postage = 0.20; type = "Postcard";}
|
||||
void print(){cout << type << ": $" << setiosflags(ios::fixed)
|
||||
<<setprecision(2) << postage <<endl;}
|
||||
};
|
||||
|
||||
class first_class : public Mail
|
||||
{
|
||||
public:
|
||||
first_class() : Mail(){postage = 0.32; type = "First Class";}
|
||||
void print(){cout << type << ": $" <<setiosflags(ios::fixed)
|
||||
<< setprecision(2) << postage <<endl;}
|
||||
|
||||
};
|
||||
|
||||
class Unknown : public postcard, first_class // ??? Multiple Inheritance
|
||||
{
|
||||
public:
|
||||
Unknown(): postcard(), first_class()
|
||||
{
|
||||
postcard::postage = 1.50; // MUST disambiguate
|
||||
postcard::type = "Unknown";
|
||||
}
|
||||
void print(){cout << postcard::type << ": $" <<setiosflags(ios::fixed)
|
||||
<<setprecision(2)<<postcard::postage <<endl;}
|
||||
};
|
||||
|
||||
class container
|
||||
{
|
||||
private:
|
||||
Mail **array;
|
||||
int index;
|
||||
int sz;
|
||||
public:
|
||||
container(){array = 0;}
|
||||
~container(){
|
||||
for(int x = 0; x <sz; x++)
|
||||
delete array[x];
|
||||
free(array);
|
||||
}
|
||||
int size() {return sz;}
|
||||
Mail* operator[](int index);
|
||||
Mail* operator = (Mail* mail);
|
||||
};
|
||||
|
||||
main()
|
||||
{
|
||||
container PO_Box;
|
||||
PO_Box = new postcard;
|
||||
PO_Box = new first_class;
|
||||
PO_Box = new parcel_Post;
|
||||
//PO_Box = new Unknown;
|
||||
//one way of printing information
|
||||
for(int x =0; x <3; x++){
|
||||
PO_Box[x]->print();
|
||||
}
|
||||
//Overloaded <<
|
||||
for(int x =0; x <PO_Box.size(); x++){
|
||||
cout << PO_Box[x];
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator << (ostream &os, Mail *m)
|
||||
{
|
||||
os <<setiosflags(ios::fixed) << setprecision(2)<< m->type
|
||||
<< ": $" << m->postage <<endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
Mail* container::operator[](int index) {return array[index];}
|
||||
Mail* container::operator = (Mail* mail)
|
||||
{
|
||||
int size = sizeof(Mail*) * (++sz);
|
||||
int temp = sz -1;
|
||||
array = (Mail**)realloc(array, size);
|
||||
array[temp] = mail;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -9,6 +9,17 @@
|
|||
Added new constant for comma-separated lists
|
||||
* src/org/eclipse/cdt/core/resources/IBuildInfo.java
|
||||
|
||||
2003-06-25 Bogdan Gheorghe
|
||||
|
||||
* src/org/eclipse/cdt/core/CCorePlugin.java
|
||||
Start the new indexer thread on startup
|
||||
* src/org/eclipse/cdt/core/model/CoreModel.java
|
||||
Added some methods to access the IndexManager
|
||||
* src/org/eclipse/cdt/internal/core/model/CModelManager.java
|
||||
Added some methods to access the IndexManager
|
||||
* src/org/eclipse/cdt/internal/core/model/DeltaProcessor.java
|
||||
Added IndexManager member
|
||||
|
||||
2003-06-24 Alain Magloire
|
||||
|
||||
Patch form ando@park.ruru.ne.jp, to deal
|
||||
|
|
60
core/org.eclipse.cdt.core/index/ChangeLog
Normal file
60
core/org.eclipse.cdt.core/index/ChangeLog
Normal file
|
@ -0,0 +1,60 @@
|
|||
2003-06-25 Bogdan Gheorghe
|
||||
|
||||
Added new Indexer framework:
|
||||
|
||||
* index/org/eclipse/cdt/internal/core/index/IDocument.java
|
||||
* index/org/eclipse/cdt/internal/core/index/IEntryResult.java
|
||||
* index/org/eclipse/cdt/internal/core/index/IIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/index/IIndexer.java
|
||||
* index/org/eclipse/cdt/internal/core/index/IIndexerOutput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/IQueryResult.java
|
||||
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/Block.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexOutput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/CodeByteStream.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/Field.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/GammaCompressedIndexBlock.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IIndexConstants.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/Index.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexedFile.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexedFileHashedArray.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexerOutput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexInput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexOutput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/InMemoryIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/Int.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/MergeFactory.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/PropertyDocument.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/SafeRandomAccessFile.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/SimpleIndexInput.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/Util.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java
|
||||
* index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java
|
||||
|
||||
* index/org/eclipse/cdt/internal/core/search/CharOperation.java
|
||||
* index/org/eclipse/cdt/internal/core/search/HashtableOfInt.java
|
||||
* index/org/eclipse/cdt/internal/core/search/SimpleLookupTable.java
|
||||
* index/org/eclipse/cdt/internal/core/search/Util.java
|
||||
* index/org/eclipse/cdt/internal/core/search/message.properties
|
||||
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/AddFileToIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/IIndexConstants.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/IndexRequest.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/ReadWriteMonitor.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/RemoveFromIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/SaveIndex.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/SourceIndexer.java
|
||||
* index/org/eclipse/cdt/internal/core/search/indexing/SourceIndexerRequestor.java
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An <code>IDocument</code> represent a data source, e.g. a <code>File</code> (<code>FileDocument</code>),
|
||||
* an <code>IFile</code> (<code>IFileDocument</code>),
|
||||
* or other kinds of data sources (URL, ...). An <code>IIndexer</code> indexes an<code>IDocument</code>.
|
||||
*/
|
||||
|
||||
public interface IDocument {
|
||||
/**
|
||||
* Returns the content of the document, in a byte array.
|
||||
*/
|
||||
byte[] getByteContent() throws IOException;
|
||||
/**
|
||||
* Returns the content of the document, in a char array.
|
||||
*/
|
||||
char[] getCharContent() throws IOException;
|
||||
/**
|
||||
* Returns the encoding for this document
|
||||
*/
|
||||
String getEncoding();
|
||||
/**
|
||||
* returns the name of the document (e.g. its path for a <code>File</code>, or its relative path
|
||||
* in the workbench for an <code>IFile</code>).
|
||||
*/
|
||||
String getName();
|
||||
/**
|
||||
* Returns the content of the document, as a String.
|
||||
*/
|
||||
public String getStringContent() throws IOException;
|
||||
/**
|
||||
* Returns the type of the document.
|
||||
*/
|
||||
String getType();
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
public interface IEntryResult {
|
||||
public int[] getFileReferences();
|
||||
public char[] getWord();
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An IIndex is the interface used to generate an index file, and to make queries on
|
||||
* this index.
|
||||
*/
|
||||
|
||||
public interface IIndex {
|
||||
/**
|
||||
* Adds the given document to the index.
|
||||
*/
|
||||
void add(IDocument document, IIndexer indexer) throws IOException;
|
||||
/**
|
||||
* Empties the index.
|
||||
*/
|
||||
void empty() throws IOException;
|
||||
/**
|
||||
* Returns the index file on the disk.
|
||||
*/
|
||||
File getIndexFile();
|
||||
/**
|
||||
* Returns the number of documents indexed.
|
||||
*/
|
||||
int getNumDocuments() throws IOException;
|
||||
/**
|
||||
* Returns the number of unique words indexed.
|
||||
*/
|
||||
int getNumWords() throws IOException;
|
||||
/**
|
||||
* Returns the path corresponding to a given document number
|
||||
*/
|
||||
String getPath(int documentNumber) throws IOException;
|
||||
/**
|
||||
* Ansers true if has some changes to save.
|
||||
*/
|
||||
boolean hasChanged();
|
||||
/**
|
||||
* Returns the paths of the documents containing the given word.
|
||||
*/
|
||||
IQueryResult[] query(String word) throws IOException;
|
||||
/**
|
||||
* Returns all entries for a given word.
|
||||
*/
|
||||
IEntryResult[] queryEntries(char[] pattern) throws IOException;
|
||||
/**
|
||||
* Returns the paths of the documents whose names contain the given word.
|
||||
*/
|
||||
IQueryResult[] queryInDocumentNames(String word) throws IOException;
|
||||
/**
|
||||
* Returns the paths of the documents containing the given word prefix.
|
||||
*/
|
||||
IQueryResult[] queryPrefix(char[] prefix) throws IOException;
|
||||
/**
|
||||
* Removes the corresponding document from the index.
|
||||
*/
|
||||
void remove(String documentName) throws IOException;
|
||||
/**
|
||||
* Saves the index on the disk.
|
||||
*/
|
||||
void save() throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
/**
|
||||
* An <code>IIndexer</code> indexes ONE document at each time. It adds the document names and
|
||||
* the words references to an IIndex. Each IIndexer can index certain types of document, and should
|
||||
* not index the other files.
|
||||
*/
|
||||
public interface IIndexer {
|
||||
/**
|
||||
* Returns the file types the <code>IIndexer</code> handles.
|
||||
*/
|
||||
|
||||
String[] getFileTypes();
|
||||
/**
|
||||
* Indexes the given document, adding the document name and the word references
|
||||
* to this document to the given <code>IIndex</code>.The caller should use
|
||||
* <code>shouldIndex()</code> first to determine whether this indexer handles
|
||||
* the given type of file, and only call this method if so.
|
||||
*/
|
||||
|
||||
void index(IDocument document, IIndexerOutput output) throws java.io.IOException;
|
||||
/**
|
||||
* Sets the document types the <code>IIndexer</code> handles.
|
||||
*/
|
||||
|
||||
public void setFileTypes(String[] fileTypes);
|
||||
/**
|
||||
* Returns whether the <code>IIndexer</code> can index the given document or not.
|
||||
*/
|
||||
|
||||
public boolean shouldIndex(IDocument document);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
/**
|
||||
* This class represents the output from an indexer to an index
|
||||
* for a single document.
|
||||
*/
|
||||
|
||||
public interface IIndexerOutput {
|
||||
public void addDocument(IDocument document);
|
||||
public void addRef(char[] word);
|
||||
public void addRef(String word);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
public interface IQueryResult {
|
||||
String getPath();
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* A block is a container that can hold information (a list of file names, a list of
|
||||
* words, ...), be saved on the disk and loaded in memory.
|
||||
*/
|
||||
|
||||
public abstract class Block {
|
||||
/**
|
||||
* Size of the block
|
||||
*/
|
||||
protected int blockSize;
|
||||
|
||||
/**
|
||||
* Field in which the information is stored
|
||||
*/
|
||||
protected Field field;
|
||||
|
||||
public Block(int blockSize) {
|
||||
this.blockSize= blockSize;
|
||||
field= new Field(blockSize);
|
||||
}
|
||||
/**
|
||||
* Empties the block.
|
||||
*/
|
||||
public void clear() {
|
||||
field.clear();
|
||||
}
|
||||
/**
|
||||
* Flushes the block
|
||||
*/
|
||||
public void flush() {
|
||||
}
|
||||
/**
|
||||
* Loads the block with the given number in memory, reading it from a RandomAccessFile.
|
||||
*/
|
||||
public void read(RandomAccessFile raf, int blockNum) throws IOException {
|
||||
raf.seek(blockNum * (long) blockSize);
|
||||
raf.readFully(field.buffer());
|
||||
}
|
||||
/**
|
||||
* Writes the block in a RandomAccessFile, giving it a block number.
|
||||
*/
|
||||
public void write(RandomAccessFile raf, int blockNum) throws IOException {
|
||||
raf.seek(blockNum * (long) blockSize);
|
||||
raf.write(field.buffer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
import org.eclipse.cdt.internal.core.search.Util;
|
||||
import org.eclipse.cdt.internal.core.util.LRUCache;
|
||||
|
||||
/**
|
||||
* This input is used for reading indexes saved using a BlocksIndexOutput.
|
||||
*/
|
||||
public class BlocksIndexInput extends IndexInput {
|
||||
public static final int CACHE_SIZE= 16; // Cache 16 blocks of 8K each, for a cache size of 128K
|
||||
protected FileListBlock currentFileListBlock;
|
||||
protected int currentFileListBlockNum;
|
||||
protected int currentIndexBlockNum;
|
||||
protected IndexBlock currentIndexBlock;
|
||||
private RandomAccessFile raf;
|
||||
protected File indexFile;
|
||||
protected LRUCache blockCache;
|
||||
protected boolean opened= false;
|
||||
protected IndexSummary summary;
|
||||
|
||||
public BlocksIndexInput(File inputFile) {
|
||||
this.indexFile= inputFile;
|
||||
blockCache= new LRUCache(CACHE_SIZE);
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#clearCache()
|
||||
*/
|
||||
public void clearCache() {
|
||||
blockCache= new LRUCache(CACHE_SIZE);
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (opened) {
|
||||
summary= null;
|
||||
opened= false;
|
||||
if (raf != null)
|
||||
raf.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getCurrentFile()
|
||||
*/
|
||||
public IndexedFile getCurrentFile() throws IOException {
|
||||
if (!hasMoreFiles())
|
||||
return null;
|
||||
IndexedFile file= null;
|
||||
if ((file= currentFileListBlock.getFile(filePosition)) == null) {
|
||||
currentFileListBlockNum= summary.getBlockNumForFileNum(filePosition);
|
||||
currentFileListBlock= getFileListBlock(currentFileListBlockNum);
|
||||
file= currentFileListBlock.getFile(filePosition);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
/**
|
||||
* Returns the entry corresponding to the given word.
|
||||
*/
|
||||
protected WordEntry getEntry(char[] word) throws IOException {
|
||||
int blockNum= summary.getBlockNumForWord(word);
|
||||
if (blockNum == -1) return null;
|
||||
IndexBlock block= getIndexBlock(blockNum);
|
||||
return block.findExactEntry(word);
|
||||
}
|
||||
/**
|
||||
* Returns the FileListBlock with the given number.
|
||||
*/
|
||||
protected FileListBlock getFileListBlock(int blockNum) throws IOException {
|
||||
Integer key= new Integer(blockNum);
|
||||
Block block= (Block) blockCache.get(key);
|
||||
if (block != null && block instanceof FileListBlock)
|
||||
return (FileListBlock) block;
|
||||
FileListBlock fileListBlock= new FileListBlock(IIndexConstants.BLOCK_SIZE);
|
||||
fileListBlock.read(raf, blockNum);
|
||||
blockCache.put(key, fileListBlock);
|
||||
return fileListBlock;
|
||||
}
|
||||
/**
|
||||
* Returns the IndexBlock (containing words) with the given number.
|
||||
*/
|
||||
protected IndexBlock getIndexBlock(int blockNum) throws IOException {
|
||||
Integer key= new Integer(blockNum);
|
||||
Block block= (Block) blockCache.get(key);
|
||||
if (block != null && block instanceof IndexBlock)
|
||||
return (IndexBlock) block;
|
||||
IndexBlock indexBlock= new GammaCompressedIndexBlock(IIndexConstants.BLOCK_SIZE);
|
||||
indexBlock.read(raf, blockNum);
|
||||
blockCache.put(key, indexBlock);
|
||||
return indexBlock;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getIndexedFile(int)
|
||||
*/
|
||||
public IndexedFile getIndexedFile(int fileNum) throws IOException {
|
||||
int blockNum= summary.getBlockNumForFileNum(fileNum);
|
||||
if (blockNum == -1)
|
||||
return null;
|
||||
FileListBlock block= getFileListBlock(blockNum);
|
||||
return block.getFile(fileNum);
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getIndexedFile(IDocument)
|
||||
*/
|
||||
public IndexedFile getIndexedFile(IDocument document) throws java.io.IOException {
|
||||
setFirstFile();
|
||||
String name= document.getName();
|
||||
while (hasMoreFiles()) {
|
||||
IndexedFile file= getCurrentFile();
|
||||
String path= file.getPath();
|
||||
if (path.equals(name))
|
||||
return file;
|
||||
moveToNextFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the list of numbers of files containing the given word.
|
||||
*/
|
||||
|
||||
protected int[] getMatchingFileNumbers(char[] word) throws IOException {
|
||||
int blockNum= summary.getBlockNumForWord(word);
|
||||
if (blockNum == -1)
|
||||
return new int[0];
|
||||
IndexBlock block= getIndexBlock(blockNum);
|
||||
WordEntry entry= block.findExactEntry(word);
|
||||
return entry == null ? new int[0] : entry.getRefs();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getNumFiles()
|
||||
*/
|
||||
public int getNumFiles() {
|
||||
return summary.getNumFiles();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getNumWords()
|
||||
*/
|
||||
public int getNumWords() {
|
||||
return summary.getNumWords();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getSource()
|
||||
*/
|
||||
public Object getSource() {
|
||||
return indexFile;
|
||||
}
|
||||
/**
|
||||
* Initialises the blocksIndexInput
|
||||
*/
|
||||
protected void init() throws IOException {
|
||||
clearCache();
|
||||
setFirstFile();
|
||||
setFirstWord();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#moveToNextFile()
|
||||
*/
|
||||
public void moveToNextFile() throws IOException {
|
||||
filePosition++;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#moveToNextWordEntry()
|
||||
*/
|
||||
public void moveToNextWordEntry() throws IOException {
|
||||
wordPosition++;
|
||||
if (!hasMoreWords()) {
|
||||
return;
|
||||
}
|
||||
//if end of the current block, we load the next one.
|
||||
boolean endOfBlock= !currentIndexBlock.nextEntry(currentWordEntry);
|
||||
if (endOfBlock) {
|
||||
currentIndexBlock= getIndexBlock(++currentIndexBlockNum);
|
||||
currentIndexBlock.nextEntry(currentWordEntry);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#open()
|
||||
*/
|
||||
|
||||
public void open() throws IOException {
|
||||
if (!opened) {
|
||||
raf= new SafeRandomAccessFile(indexFile, "r"); //$NON-NLS-1$
|
||||
String sig= raf.readUTF();
|
||||
if (!sig.equals(IIndexConstants.SIGNATURE))
|
||||
throw new IOException(Util.bind("exception.wrongFormat")); //$NON-NLS-1$
|
||||
int summaryBlockNum= raf.readInt();
|
||||
raf.seek(summaryBlockNum * (long) IIndexConstants.BLOCK_SIZE);
|
||||
summary= new IndexSummary();
|
||||
summary.read(raf);
|
||||
init();
|
||||
opened= true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#query(String)
|
||||
*/
|
||||
public IQueryResult[] query(String word) throws IOException {
|
||||
open();
|
||||
int[] fileNums= getMatchingFileNumbers(word.toCharArray());
|
||||
int size= fileNums.length;
|
||||
IQueryResult[] files= new IQueryResult[size];
|
||||
for (int i= 0; i < size; ++i) {
|
||||
files[i]= getIndexedFile(fileNums[i]);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
/**
|
||||
* If no prefix is provided in the pattern, then this operation will have to walk
|
||||
* all the entries of the whole index.
|
||||
*/
|
||||
public IEntryResult[] queryEntriesMatching(char[] pattern/*, boolean isCaseSensitive*/) throws IOException {
|
||||
open();
|
||||
|
||||
if (pattern == null || pattern.length == 0) return null;
|
||||
int[] blockNums = null;
|
||||
int firstStar = CharOperation.indexOf('*', pattern);
|
||||
switch (firstStar){
|
||||
case -1 :
|
||||
WordEntry entry = getEntry(pattern);
|
||||
if (entry == null) return null;
|
||||
return new IEntryResult[]{ new EntryResult(entry.getWord(), entry.getRefs()) };
|
||||
case 0 :
|
||||
blockNums = summary.getAllBlockNums();
|
||||
break;
|
||||
default :
|
||||
char[] prefix = CharOperation.subarray(pattern, 0, firstStar);
|
||||
blockNums = summary.getBlockNumsForPrefix(prefix);
|
||||
}
|
||||
if (blockNums == null || blockNums.length == 0) return null;
|
||||
|
||||
IEntryResult[] entries = new IEntryResult[5];
|
||||
int count = 0;
|
||||
for (int i = 0, max = blockNums.length; i < max; i++) {
|
||||
IndexBlock block = getIndexBlock(blockNums[i]);
|
||||
block.reset();
|
||||
boolean found = false;
|
||||
WordEntry entry = new WordEntry();
|
||||
while (block.nextEntry(entry)) {
|
||||
if (CharOperation.match(entry.getWord(), pattern, true)) {
|
||||
if (count == entries.length){
|
||||
System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
|
||||
}
|
||||
entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
|
||||
found = true;
|
||||
} else {
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count != entries.length){
|
||||
System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
|
||||
open();
|
||||
|
||||
int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
|
||||
if (blockLoc < 0) return null;
|
||||
|
||||
IEntryResult[] entries = new IEntryResult[5];
|
||||
int count = 0;
|
||||
while(blockLoc >= 0){
|
||||
IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
|
||||
block.reset();
|
||||
boolean found = false;
|
||||
WordEntry entry = new WordEntry();
|
||||
while (block.nextEntry(entry)) {
|
||||
if (CharOperation.prefixEquals(prefix, entry.getWord())) {
|
||||
if (count == entries.length){
|
||||
System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
|
||||
}
|
||||
entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
|
||||
found = true;
|
||||
} else {
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
/* consider next block ? */
|
||||
blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);
|
||||
}
|
||||
if (count == 0) return null;
|
||||
if (count != entries.length){
|
||||
System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
|
||||
open();
|
||||
|
||||
int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
|
||||
if (blockLoc < 0) return null;
|
||||
|
||||
// each filename must be returned already once
|
||||
org.eclipse.cdt.internal.core.search.HashtableOfInt fileMatches = new org.eclipse.cdt.internal.core.search.HashtableOfInt(20);
|
||||
int count = 0;
|
||||
while(blockLoc >= 0){
|
||||
IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
|
||||
block.reset();
|
||||
boolean found = false;
|
||||
WordEntry entry = new WordEntry();
|
||||
while (block.nextEntry(entry)) {
|
||||
if (CharOperation.prefixEquals(prefix, entry.getWord()/*, isCaseSensitive*/)) {
|
||||
int [] refs = entry.getRefs();
|
||||
for (int i = 0, max = refs.length; i < max; i++){
|
||||
int ref = refs[i];
|
||||
if (!fileMatches.containsKey(ref)){
|
||||
count++;
|
||||
fileMatches.put(ref, getIndexedFile(ref));
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
} else {
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
/* consider next block ? */
|
||||
blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);
|
||||
}
|
||||
/* extract indexed files */
|
||||
IQueryResult[] files = new IQueryResult[count];
|
||||
Object[] indexedFiles = fileMatches.valueTable;
|
||||
for (int i = 0, index = 0, max = indexedFiles.length; i < max; i++){
|
||||
IndexedFile indexedFile = (IndexedFile) indexedFiles[i];
|
||||
if (indexedFile != null){
|
||||
files[index++] = indexedFile;
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#queryInDocumentNames(String)
|
||||
*/
|
||||
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||
open();
|
||||
ArrayList matches= new ArrayList();
|
||||
setFirstFile();
|
||||
while (hasMoreFiles()) {
|
||||
IndexedFile file= getCurrentFile();
|
||||
if (file.getPath().indexOf(word) != -1)
|
||||
matches.add(file);
|
||||
moveToNextFile();
|
||||
}
|
||||
IQueryResult[] match= new IQueryResult[matches.size()];
|
||||
matches.toArray(match);
|
||||
return match;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#setFirstFile()
|
||||
*/
|
||||
|
||||
protected void setFirstFile() throws IOException {
|
||||
filePosition= 1;
|
||||
if (getNumFiles() > 0) {
|
||||
currentFileListBlockNum= summary.getBlockNumForFileNum(1);
|
||||
currentFileListBlock= getFileListBlock(currentFileListBlockNum);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#setFirstWord()
|
||||
*/
|
||||
|
||||
protected void setFirstWord() throws IOException {
|
||||
wordPosition= 1;
|
||||
if (getNumWords() > 0) {
|
||||
currentIndexBlockNum= summary.getFirstWordBlockNum();
|
||||
currentIndexBlock= getIndexBlock(currentIndexBlockNum);
|
||||
currentWordEntry= new WordEntry();
|
||||
currentIndexBlock.reset();
|
||||
currentIndexBlock.nextEntry(currentWordEntry);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* A blocksIndexOutput is used to save an index in a file with the given structure:<br>
|
||||
* - Signature of the file;<br>
|
||||
* - FileListBlocks;<br>
|
||||
* - IndexBlocks;<br>
|
||||
* - Summary of the index.
|
||||
*/
|
||||
|
||||
public class BlocksIndexOutput extends IndexOutput {
|
||||
protected RandomAccessFile indexOut;
|
||||
protected int blockNum;
|
||||
protected boolean opened= false;
|
||||
protected File indexFile;
|
||||
protected FileListBlock fileListBlock;
|
||||
protected IndexBlock indexBlock;
|
||||
protected int numWords= 0;
|
||||
protected IndexSummary summary;
|
||||
protected int numFiles= 0;
|
||||
protected boolean firstInBlock;
|
||||
protected boolean firstIndexBlock;
|
||||
protected boolean firstFileListBlock;
|
||||
|
||||
public BlocksIndexOutput(File indexFile) {
|
||||
this.indexFile= indexFile;
|
||||
summary= new IndexSummary();
|
||||
blockNum= 1;
|
||||
firstInBlock= true;
|
||||
firstIndexBlock= true;
|
||||
firstFileListBlock= true;
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#addFile
|
||||
*/
|
||||
public void addFile(IndexedFile indexedFile) throws IOException {
|
||||
if (firstFileListBlock) {
|
||||
firstInBlock= true;
|
||||
fileListBlock= new FileListBlock(IIndexConstants.BLOCK_SIZE);
|
||||
firstFileListBlock= false;
|
||||
}
|
||||
if (fileListBlock.addFile(indexedFile)) {
|
||||
if (firstInBlock) {
|
||||
summary.addFirstFileInBlock(indexedFile, blockNum);
|
||||
firstInBlock= false;
|
||||
}
|
||||
numFiles++;
|
||||
} else {
|
||||
if (fileListBlock.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
flushFiles();
|
||||
addFile(indexedFile);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#addWord
|
||||
*/
|
||||
public void addWord(WordEntry entry) throws IOException {
|
||||
if (firstIndexBlock) {
|
||||
indexBlock= new GammaCompressedIndexBlock(IIndexConstants.BLOCK_SIZE);
|
||||
firstInBlock= true;
|
||||
firstIndexBlock= false;
|
||||
}
|
||||
if (entry.getNumRefs() == 0)
|
||||
return;
|
||||
if (indexBlock.addEntry(entry)) {
|
||||
if (firstInBlock) {
|
||||
summary.addFirstWordInBlock(entry.getWord(), blockNum);
|
||||
firstInBlock= false;
|
||||
}
|
||||
numWords++;
|
||||
} else {
|
||||
if (indexBlock.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
flushWords();
|
||||
addWord(entry);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#close
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (opened) {
|
||||
indexOut.close();
|
||||
summary= null;
|
||||
numFiles= 0;
|
||||
opened= false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#flush
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
|
||||
summary.setNumFiles(numFiles);
|
||||
summary.setNumWords(numWords);
|
||||
indexOut.seek(blockNum * (long) IIndexConstants.BLOCK_SIZE);
|
||||
summary.write(indexOut);
|
||||
indexOut.seek(0);
|
||||
indexOut.writeUTF(IIndexConstants.SIGNATURE);
|
||||
indexOut.writeInt(blockNum);
|
||||
}
|
||||
/**
|
||||
* Writes the current fileListBlock on the disk and initialises it
|
||||
* (when it's full or it's the end of the index).
|
||||
*/
|
||||
protected void flushFiles() throws IOException {
|
||||
if (!firstFileListBlock
|
||||
&& fileListBlock != null) {
|
||||
fileListBlock.flush();
|
||||
fileListBlock.write(indexOut, blockNum++);
|
||||
fileListBlock.clear();
|
||||
firstInBlock= true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Writes the current indexBlock on the disk and initialises it
|
||||
* (when it's full or it's the end of the index).
|
||||
*/
|
||||
protected void flushWords() throws IOException {
|
||||
if (!firstInBlock
|
||||
&& indexBlock != null) { // could have added a document without any indexed word, no block created yet
|
||||
indexBlock.flush();
|
||||
indexBlock.write(indexOut, blockNum++);
|
||||
indexBlock.clear();
|
||||
firstInBlock= true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#getDestination
|
||||
*/
|
||||
public Object getDestination() {
|
||||
return indexFile;
|
||||
}
|
||||
/**
|
||||
* @see IndexOutput#open
|
||||
*/
|
||||
public void open() throws IOException {
|
||||
if (!opened) {
|
||||
summary= new IndexSummary();
|
||||
numFiles= 0;
|
||||
numWords= 0;
|
||||
blockNum= 1;
|
||||
firstInBlock= true;
|
||||
firstIndexBlock= true;
|
||||
firstFileListBlock= true;
|
||||
indexOut= new SafeRandomAccessFile(this.indexFile, "rw"); //$NON-NLS-1$
|
||||
opened= true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.UTFDataFormatException;
|
||||
|
||||
public class CodeByteStream {
|
||||
protected byte[] bytes;
|
||||
protected int byteOffset= 0;
|
||||
protected int bitOffset= 0;
|
||||
protected int markByteOffset= -1;
|
||||
protected int markBitOffset= -1;
|
||||
|
||||
public CodeByteStream() {
|
||||
this(16);
|
||||
}
|
||||
public CodeByteStream(byte[] bytes) {
|
||||
this.bytes= bytes;
|
||||
}
|
||||
public CodeByteStream(int initialByteLength) {
|
||||
bytes= new byte[initialByteLength];
|
||||
}
|
||||
public int byteLength() {
|
||||
return (bitOffset + 7) / 8 + byteOffset;
|
||||
}
|
||||
public byte[] getBytes(int startOffset, int endOffset) {
|
||||
int byteLength= byteLength();
|
||||
if (startOffset > byteLength || endOffset > byteLength || startOffset > endOffset)
|
||||
throw new IndexOutOfBoundsException();
|
||||
int length= endOffset - startOffset;
|
||||
byte[] result= new byte[length];
|
||||
System.arraycopy(bytes, startOffset, result, 0, length);
|
||||
if (endOffset == byteLength && bitOffset != 0) {
|
||||
int mask= (1 << bitOffset) - 1;
|
||||
result[length - 1] &= (mask << 8 - bitOffset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected void grow() {
|
||||
byte[] newBytes= new byte[bytes.length * 2 + 1];
|
||||
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
|
||||
bytes= newBytes;
|
||||
}
|
||||
public void mark() {
|
||||
markByteOffset= byteOffset;
|
||||
markBitOffset= bitOffset;
|
||||
}
|
||||
/**
|
||||
* Reads a single bit (value == 0 or == 1).
|
||||
*/
|
||||
public int readBit() {
|
||||
int value= (bytes[byteOffset] >> (7 - bitOffset)) & 1;
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
++byteOffset;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Read up to 32 bits from the stream.
|
||||
*/
|
||||
public int readBits(int numBits) {
|
||||
int value= 0;
|
||||
while (numBits > 0) {
|
||||
int bitsToRead= 8 - bitOffset;
|
||||
if (bitsToRead > numBits)
|
||||
bitsToRead= numBits;
|
||||
int mask= (1 << bitsToRead) - 1;
|
||||
value |= ((bytes[byteOffset] >> (8 - bitOffset - bitsToRead)) & mask) << (numBits - bitsToRead);
|
||||
numBits -= bitsToRead;
|
||||
bitOffset += bitsToRead;
|
||||
if (bitOffset >= 8) {
|
||||
bitOffset -= 8;
|
||||
byteOffset += 1;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
public final int readByte() {
|
||||
|
||||
// no need to rebuild byte value from bit sequences
|
||||
if (bitOffset == 0) return bytes[byteOffset++] & 255;
|
||||
|
||||
int value= 0;
|
||||
int numBits = 8;
|
||||
while (numBits > 0) {
|
||||
int bitsToRead= 8 - bitOffset;
|
||||
if (bitsToRead > numBits)
|
||||
bitsToRead= numBits;
|
||||
int mask= (1 << bitsToRead) - 1;
|
||||
value |= ((bytes[byteOffset] >> (8 - bitOffset - bitsToRead)) & mask) << (numBits - bitsToRead);
|
||||
numBits -= bitsToRead;
|
||||
bitOffset += bitsToRead;
|
||||
if (bitOffset >= 8) {
|
||||
bitOffset -= 8;
|
||||
byteOffset += 1;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Reads a value using Gamma coding.
|
||||
*/
|
||||
public int readGamma() {
|
||||
int numBits= readUnary();
|
||||
return readBits(numBits - 1) | (1 << (numBits - 1));
|
||||
}
|
||||
public char[] readUTF() throws UTFDataFormatException {
|
||||
int utflen= readByte();
|
||||
if (utflen == 255) {
|
||||
// long UTF
|
||||
int high = readByte();
|
||||
int low = readByte();
|
||||
utflen = (high << 8) + low;
|
||||
}
|
||||
char str[]= new char[utflen];
|
||||
int count= 0;
|
||||
int strlen= 0;
|
||||
while (count < utflen) {
|
||||
int c= readByte();
|
||||
int char2, char3;
|
||||
switch (c >> 4) {
|
||||
case 0 :
|
||||
case 1 :
|
||||
case 2 :
|
||||
case 3 :
|
||||
case 4 :
|
||||
case 5 :
|
||||
case 6 :
|
||||
case 7 :
|
||||
// 0xxxxxxx
|
||||
count++;
|
||||
str[strlen++]= (char) c;
|
||||
break;
|
||||
case 12 :
|
||||
case 13 :
|
||||
// 110x xxxx 10xx xxxx
|
||||
count += 2;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= readByte();
|
||||
if ((char2 & 0xC0) != 0x80)
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14 :
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
count += 3;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= readByte();
|
||||
char3= readByte();
|
||||
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||
break;
|
||||
default :
|
||||
// 10xx xxxx, 1111 xxxx
|
||||
throw new UTFDataFormatException();
|
||||
}
|
||||
}
|
||||
if (strlen < utflen)
|
||||
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* Reads a value in unary.
|
||||
*/
|
||||
public int readUnary() {
|
||||
int value= 1;
|
||||
int mask= 1 << (7 - bitOffset);
|
||||
while ((bytes[byteOffset] & mask) != 0) {
|
||||
++value;
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
++byteOffset;
|
||||
mask= 0x80;
|
||||
} else {
|
||||
mask >>>= 1;
|
||||
}
|
||||
}
|
||||
// skip the 0 bit
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
++byteOffset;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
public void reset() {
|
||||
byteOffset= bitOffset= 0;
|
||||
markByteOffset= markBitOffset= -1;
|
||||
}
|
||||
public void reset(byte[] bytes) {
|
||||
this.bytes= bytes;
|
||||
reset();
|
||||
}
|
||||
public void reset(byte[] bytes, int byteOffset) {
|
||||
reset(bytes);
|
||||
this.byteOffset= byteOffset;
|
||||
}
|
||||
public boolean resetToMark() {
|
||||
if (markByteOffset == -1)
|
||||
return false;
|
||||
byteOffset= markByteOffset;
|
||||
bitOffset= markBitOffset;
|
||||
markByteOffset= markBitOffset= -1;
|
||||
return true;
|
||||
}
|
||||
public void skipBits(int numBits) {
|
||||
int newOffset= byteOffset * 8 + bitOffset + numBits;
|
||||
if (newOffset < 0 || (newOffset + 7) / 8 >= bytes.length)
|
||||
throw new IllegalArgumentException();
|
||||
byteOffset= newOffset / 8;
|
||||
bitOffset= newOffset % 8;
|
||||
}
|
||||
public byte[] toByteArray() {
|
||||
return getBytes(0, byteLength());
|
||||
}
|
||||
/**
|
||||
* Writes a single bit (value == 0 or == 1).
|
||||
*/
|
||||
public void writeBit(int value) {
|
||||
bytes[byteOffset] |= (value & 1) << (7 - bitOffset);
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
if (++byteOffset >= bytes.length)
|
||||
grow();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Write up to 32 bits to the stream.
|
||||
* The least significant numBits bits of value are written.
|
||||
*/
|
||||
public void writeBits(int value, int numBits) {
|
||||
while (numBits > 0) {
|
||||
int bitsToWrite= 8 - bitOffset;
|
||||
if (bitsToWrite > numBits)
|
||||
bitsToWrite= numBits;
|
||||
int shift= 8 - bitOffset - bitsToWrite;
|
||||
int mask= ((1 << bitsToWrite) - 1) << shift;
|
||||
bytes[byteOffset]= (byte) ((bytes[byteOffset] & ~mask) | (((value >>> (numBits - bitsToWrite)) << shift) & mask));
|
||||
numBits -= bitsToWrite;
|
||||
bitOffset += bitsToWrite;
|
||||
if (bitOffset >= 8) {
|
||||
bitOffset -= 8;
|
||||
if (++byteOffset >= bytes.length)
|
||||
grow();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void writeByte(int value) {
|
||||
writeBits(value, 8);
|
||||
}
|
||||
/**
|
||||
* Writes the given value using Gamma coding, in which positive integer x
|
||||
* is represented by coding floor(log2(x) in unary followed by the value
|
||||
* of x - 2**floor(log2(x)) in binary.
|
||||
* The value must be >= 1.
|
||||
*/
|
||||
public void writeGamma(int value) {
|
||||
if (value < 1)
|
||||
throw new IllegalArgumentException();
|
||||
int temp= value;
|
||||
int numBits= 0;
|
||||
while (temp != 0) {
|
||||
temp >>>= 1;
|
||||
++numBits;
|
||||
}
|
||||
writeUnary(numBits);
|
||||
writeBits(value, numBits - 1);
|
||||
}
|
||||
public void writeUTF(char[] str, int start, int end) {
|
||||
int utflen= 0;
|
||||
for (int i= start; i < end; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
if (utflen < 255) {
|
||||
writeByte(utflen & 0xFF);
|
||||
} else if (utflen > 65535) {
|
||||
throw new IllegalArgumentException();
|
||||
} else {
|
||||
writeByte(255); // marker for long UTF
|
||||
writeByte((utflen >>> 8) & 0xFF); // high byte
|
||||
writeByte((utflen >>> 0) & 0xFF); // low byte
|
||||
}
|
||||
for (int i= start; i < end; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
writeByte(c);
|
||||
} else if (c > 0x07FF) {
|
||||
writeByte(0xE0 | ((c >> 12) & 0x0F));
|
||||
writeByte(0x80 | ((c >> 6) & 0x3F));
|
||||
writeByte(0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
writeByte(0xC0 | ((c >> 6) & 0x1F));
|
||||
writeByte(0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Write the given value in unary. The value must be >= 1.
|
||||
*/
|
||||
public void writeUnary(int value) {
|
||||
if (value < 1)
|
||||
throw new IllegalArgumentException();
|
||||
int mask= 1 << (7 - bitOffset);
|
||||
// write N-1 1-bits
|
||||
while (--value > 0) {
|
||||
bytes[byteOffset] |= mask;
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
if (++byteOffset >= bytes.length)
|
||||
grow();
|
||||
mask= 0x80;
|
||||
} else {
|
||||
mask >>>= 1;
|
||||
}
|
||||
}
|
||||
// write a 0-bit
|
||||
bytes[byteOffset] &= ~mask;
|
||||
if (++bitOffset >= 8) {
|
||||
bitOffset= 0;
|
||||
if (++byteOffset >= bytes.length)
|
||||
grow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
|
||||
public class EntryResult implements IEntryResult {
|
||||
private char[] word;
|
||||
private int[] fileRefs;
|
||||
|
||||
public EntryResult(char[] word, int[] refs) {
|
||||
this.word = word;
|
||||
this.fileRefs = refs;
|
||||
}
|
||||
public boolean equals(Object anObject){
|
||||
|
||||
if (this == anObject) {
|
||||
return true;
|
||||
}
|
||||
if ((anObject != null) && (anObject instanceof EntryResult)) {
|
||||
EntryResult anEntryResult = (EntryResult) anObject;
|
||||
if (!CharOperation.equals(this.word, anEntryResult.word)) return false;
|
||||
|
||||
int length;
|
||||
int[] refs, otherRefs;
|
||||
if ((length = (refs = this.fileRefs).length) != (otherRefs = anEntryResult.fileRefs).length) return false;
|
||||
for (int i = 0; i < length; i++){
|
||||
if (refs[i] != otherRefs[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
public int[] getFileReferences() {
|
||||
return fileRefs;
|
||||
}
|
||||
public char[] getWord() {
|
||||
return word;
|
||||
}
|
||||
public int hashCode(){
|
||||
return CharOperation.hashCode(word);
|
||||
}
|
||||
public String toString(){
|
||||
StringBuffer buffer = new StringBuffer(word.length * 2);
|
||||
buffer.append("EntryResult: word="); //$NON-NLS-1$
|
||||
buffer.append(word);
|
||||
buffer.append(", refs={"); //$NON-NLS-1$
|
||||
for (int i = 0; i < fileRefs.length; i++){
|
||||
if (i > 0) buffer.append(',');
|
||||
buffer.append(' ');
|
||||
buffer.append(fileRefs[i]);
|
||||
}
|
||||
buffer.append(" }"); //$NON-NLS-1$
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.UTFDataFormatException;
|
||||
|
||||
public class Field {
|
||||
protected byte[] buffer; // contents
|
||||
protected int offset; // offset of the field within the byte array
|
||||
protected int length; // length of the field
|
||||
|
||||
/**
|
||||
* ByteSegment constructor comment.
|
||||
*/
|
||||
public Field(byte[] bytes) {
|
||||
this.buffer= bytes;
|
||||
this.offset= 0;
|
||||
this.length= bytes.length;
|
||||
}
|
||||
/**
|
||||
* ByteSegment constructor comment.
|
||||
*/
|
||||
public Field(byte[] bytes, int length) {
|
||||
this.buffer= bytes;
|
||||
this.offset= 0;
|
||||
this.length= length;
|
||||
}
|
||||
/**
|
||||
* ByteSegment constructor comment.
|
||||
*/
|
||||
public Field(byte[] bytes, int offset, int length) {
|
||||
this.buffer= bytes;
|
||||
this.offset= offset;
|
||||
this.length= length;
|
||||
}
|
||||
/**
|
||||
* Creates a new field containing an empty buffer of the given length.
|
||||
*/
|
||||
public Field(int length) {
|
||||
this.buffer= new byte[length];
|
||||
this.offset= 0;
|
||||
this.length= length;
|
||||
}
|
||||
public byte[] buffer() {
|
||||
return buffer;
|
||||
}
|
||||
public Field buffer(byte[] buffer) {
|
||||
this.buffer= buffer;
|
||||
return this;
|
||||
}
|
||||
public Field clear() {
|
||||
clear(buffer, offset, length);
|
||||
return this;
|
||||
}
|
||||
protected static void clear(byte[] buffer, int offset, int length) {
|
||||
int n= offset;
|
||||
for (int i= 0; i < length; i++) {
|
||||
buffer[n]= 0;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
public Field clear(int length) {
|
||||
clear(buffer, offset, length);
|
||||
return this;
|
||||
}
|
||||
public Field clear(int offset, int length) {
|
||||
clear(buffer, this.offset + offset, length);
|
||||
return this;
|
||||
}
|
||||
protected static int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
|
||||
int n= Math.min(length1, length2);
|
||||
for (int i= 0; i < n; i++) {
|
||||
int j1= buffer1[offset1 + i] & 255;
|
||||
int j2= buffer2[offset2 + i] & 255;
|
||||
if (j1 > j2)
|
||||
return 1;
|
||||
if (j1 < j2)
|
||||
return -1;
|
||||
}
|
||||
if (length1 > n) {
|
||||
for (int i= n; i < length1; i++)
|
||||
if (buffer1[offset1 + i] != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
for (int i= n; i < length2; i++)
|
||||
if (buffer2[offset2 + i] != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
public static int compare(Field f1, Field f2) {
|
||||
return compare(f1.buffer, f1.offset, f1.length, f2.buffer, f2.offset, f2.length);
|
||||
}
|
||||
// copy bytes from one offset to another within the field
|
||||
public Field copy(int fromOffset, int toOffset, int length) {
|
||||
System.arraycopy(buffer, offset + fromOffset, buffer, offset + toOffset, length);
|
||||
return this;
|
||||
}
|
||||
public Field dec(int n) {
|
||||
offset -= n;
|
||||
return this;
|
||||
}
|
||||
public byte[] get() {
|
||||
byte[] result= new byte[length];
|
||||
System.arraycopy(buffer, offset, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
public byte[] get(int offset, int length) {
|
||||
byte[] result= new byte[length];
|
||||
System.arraycopy(buffer, this.offset + offset, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
public Field getField(int offset, int length) {
|
||||
return new Field(buffer, this.offset + offset, length);
|
||||
}
|
||||
public int getInt1() {
|
||||
return buffer[this.offset];
|
||||
}
|
||||
public int getInt1(int offset) {
|
||||
return buffer[this.offset + offset];
|
||||
}
|
||||
public int getInt2() {
|
||||
int i= this.offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getInt2(int offset) {
|
||||
int i= this.offset + offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getInt3() {
|
||||
int i= this.offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getInt3(int offset) {
|
||||
int i= this.offset + offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getInt4() {
|
||||
int i= this.offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getInt4(int offset) {
|
||||
int i= this.offset + offset;
|
||||
int v= buffer[i++];
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getUInt1() {
|
||||
return buffer[this.offset] & 255;
|
||||
}
|
||||
public int getUInt1(int offset) {
|
||||
return buffer[this.offset + offset] & 255;
|
||||
}
|
||||
public int getUInt2() {
|
||||
int i= this.offset;
|
||||
int v= (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getUInt2(int offset) {
|
||||
int i= this.offset + offset;
|
||||
int v= (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getUInt3() {
|
||||
int i= this.offset;
|
||||
int v= (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public int getUInt3(int offset) {
|
||||
int i= this.offset + offset;
|
||||
int v= (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
v= (v << 8) | (buffer[i++] & 255);
|
||||
return v;
|
||||
}
|
||||
public char[] getUTF(int offset) throws UTFDataFormatException {
|
||||
int pos= this.offset + offset;
|
||||
int utflen= getUInt2(pos);
|
||||
pos += 2;
|
||||
char str[]= new char[utflen];
|
||||
int count= 0;
|
||||
int strlen= 0;
|
||||
while (count < utflen) {
|
||||
int c= buffer[pos++] & 0xFF;
|
||||
int char2, char3;
|
||||
switch (c >> 4) {
|
||||
case 0 :
|
||||
case 1 :
|
||||
case 2 :
|
||||
case 3 :
|
||||
case 4 :
|
||||
case 5 :
|
||||
case 6 :
|
||||
case 7 :
|
||||
// 0xxxxxxx
|
||||
count++;
|
||||
str[strlen++]= (char) c;
|
||||
break;
|
||||
case 12 :
|
||||
case 13 :
|
||||
// 110x xxxx 10xx xxxx
|
||||
count += 2;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= buffer[pos++] & 0xFF;
|
||||
if ((char2 & 0xC0) != 0x80)
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14 :
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
count += 3;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= buffer[pos++] & 0xFF;
|
||||
char3= buffer[pos++] & 0xFF;
|
||||
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||
break;
|
||||
default :
|
||||
// 10xx xxxx, 1111 xxxx
|
||||
throw new UTFDataFormatException();
|
||||
}
|
||||
}
|
||||
if (strlen < utflen)
|
||||
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||
return str;
|
||||
}
|
||||
public Field inc(int n) {
|
||||
offset += n;
|
||||
return this;
|
||||
}
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
public Field length(int length) {
|
||||
this.length= length;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
Returns the offset into the underlying byte array that this field is defined over.
|
||||
*/
|
||||
public int offset() {
|
||||
return offset;
|
||||
}
|
||||
public Field offset(int offset) {
|
||||
this.offset= offset;
|
||||
return this;
|
||||
}
|
||||
public Field pointTo(int offset) {
|
||||
return new Field(buffer, this.offset + offset, 0);
|
||||
}
|
||||
public Field put(byte[] b) {
|
||||
return put(0, b);
|
||||
}
|
||||
public Field put(int offset, byte[] b) {
|
||||
System.arraycopy(b, 0, buffer, this.offset + offset, b.length);
|
||||
return this;
|
||||
}
|
||||
public Field put(int offset, Field f) {
|
||||
System.arraycopy(f.buffer, f.offset, buffer, this.offset + offset, f.length);
|
||||
return this;
|
||||
}
|
||||
public Field put(Field f) {
|
||||
System.arraycopy(f.buffer, f.offset, buffer, offset, f.length);
|
||||
return this;
|
||||
}
|
||||
public Field putInt1(int n) {
|
||||
buffer[offset]= (byte) (n);
|
||||
return this;
|
||||
}
|
||||
public Field putInt1(int offset, int n) {
|
||||
buffer[this.offset + offset]= (byte) (n);
|
||||
return this;
|
||||
}
|
||||
public Field putInt2(int n) {
|
||||
int i= offset;
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public Field putInt2(int offset, int n) {
|
||||
int i= this.offset + offset;
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public Field putInt3(int n) {
|
||||
int i= offset;
|
||||
buffer[i++]= (byte) (n >> 16);
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public Field putInt3(int offset, int n) {
|
||||
int i= this.offset + offset;
|
||||
buffer[i++]= (byte) (n >> 16);
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public Field putInt4(int n) {
|
||||
int i= offset;
|
||||
buffer[i++]= (byte) (n >> 24);
|
||||
buffer[i++]= (byte) (n >> 16);
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public Field putInt4(int offset, int n) {
|
||||
int i= this.offset + offset;
|
||||
buffer[i++]= (byte) (n >> 24);
|
||||
buffer[i++]= (byte) (n >> 16);
|
||||
buffer[i++]= (byte) (n >> 8);
|
||||
buffer[i++]= (byte) (n >> 0);
|
||||
return this;
|
||||
}
|
||||
public int putUTF(int offset, char[] str) {
|
||||
int strlen= str.length;
|
||||
int utflen= 0;
|
||||
for (int i= 0; i < strlen; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
if (utflen > 65535)
|
||||
throw new IllegalArgumentException();
|
||||
int pos= this.offset + offset;
|
||||
buffer[pos++]= (byte) ((utflen >>> 8) & 0xFF);
|
||||
buffer[pos++]= (byte) ((utflen >>> 0) & 0xFF);
|
||||
for (int i= 0; i < strlen; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
buffer[pos++]= ((byte) c);
|
||||
} else if (c > 0x07FF) {
|
||||
buffer[pos++]= ((byte) (0xE0 | ((c >> 12) & 0x0F)));
|
||||
buffer[pos++]= ((byte) (0x80 | ((c >> 6) & 0x3F)));
|
||||
buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F)));
|
||||
} else {
|
||||
buffer[pos++]= ((byte) (0xC0 | ((c >> 6) & 0x1F)));
|
||||
buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F)));
|
||||
}
|
||||
}
|
||||
return 2 + utflen;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FileListBlock extends Block {
|
||||
|
||||
protected int offset= 0;
|
||||
protected String prevPath= null;
|
||||
protected String[] paths= null;
|
||||
|
||||
public FileListBlock(int blockSize) {
|
||||
super(blockSize);
|
||||
}
|
||||
/**
|
||||
* add the name of the indexedfile to the buffr of the field.
|
||||
* The name is not the entire name of the indexedfile, but the
|
||||
* difference between its name and the name of the previous indexedfile ...
|
||||
*/
|
||||
public boolean addFile(IndexedFile indexedFile) {
|
||||
int offset= this.offset;
|
||||
if (isEmpty()) {
|
||||
field.putInt4(offset, indexedFile.getFileNumber());
|
||||
offset += 4;
|
||||
}
|
||||
String path= indexedFile.getPath();
|
||||
int prefixLen= prevPath == null ? 0 : Util.prefixLength(prevPath, path);
|
||||
int sizeEstimate= 2 + 2 + (path.length() - prefixLen) * 3;
|
||||
if (offset + sizeEstimate > blockSize - 2)
|
||||
return false;
|
||||
field.putInt2(offset, prefixLen);
|
||||
offset += 2;
|
||||
char[] chars= new char[path.length() - prefixLen];
|
||||
path.getChars(prefixLen, path.length(), chars, 0);
|
||||
offset += field.putUTF(offset, chars);
|
||||
this.offset= offset;
|
||||
prevPath= path;
|
||||
return true;
|
||||
}
|
||||
public void clear() {
|
||||
reset();
|
||||
super.clear();
|
||||
}
|
||||
public void flush() {
|
||||
if (offset > 0) {
|
||||
field.putInt2(offset, 0);
|
||||
field.putInt2(offset + 2, 0);
|
||||
offset= 0;
|
||||
}
|
||||
}
|
||||
public IndexedFile getFile(int fileNum) throws IOException {
|
||||
IndexedFile resp= null;
|
||||
try {
|
||||
String[] paths= getPaths();
|
||||
int i= fileNum - field.getInt4(0);
|
||||
resp= new IndexedFile(paths[i], fileNum);
|
||||
} catch (Exception e) {
|
||||
//fileNum too big
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
/**
|
||||
* Creates a vector of paths reading the buffer of the field.
|
||||
*/
|
||||
protected String[] getPaths() throws IOException {
|
||||
if (paths == null) {
|
||||
ArrayList v= new ArrayList();
|
||||
int offset= 4;
|
||||
char[] prevPath= null;
|
||||
for (;;) {
|
||||
int prefixLen= field.getUInt2(offset);
|
||||
offset += 2;
|
||||
int utfLen= field.getUInt2(offset);
|
||||
char[] path= field.getUTF(offset);
|
||||
offset += 2 + utfLen;
|
||||
if (prefixLen != 0) {
|
||||
char[] temp= new char[prefixLen + path.length];
|
||||
System.arraycopy(prevPath, 0, temp, 0, prefixLen);
|
||||
System.arraycopy(path, 0, temp, prefixLen, path.length);
|
||||
path= temp;
|
||||
}
|
||||
if (path.length == 0)
|
||||
break;
|
||||
v.add(new String(path));
|
||||
prevPath= path;
|
||||
}
|
||||
paths= new String[v.size()];
|
||||
v.toArray(paths);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
public boolean isEmpty() {
|
||||
return offset == 0;
|
||||
}
|
||||
public void reset() {
|
||||
offset= 0;
|
||||
prevPath= null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.UTFDataFormatException;
|
||||
|
||||
/**
|
||||
* Uses prefix coding on words, and gamma coding of document numbers differences.
|
||||
*/
|
||||
public class GammaCompressedIndexBlock extends IndexBlock {
|
||||
CodeByteStream writeCodeStream= new CodeByteStream();
|
||||
CodeByteStream readCodeStream;
|
||||
char[] prevWord= null;
|
||||
int offset= 0;
|
||||
|
||||
public GammaCompressedIndexBlock(int blockSize) {
|
||||
super(blockSize);
|
||||
readCodeStream= new CodeByteStream(field.buffer());
|
||||
}
|
||||
/**
|
||||
* @see IndexBlock#addEntry
|
||||
*/
|
||||
public boolean addEntry(WordEntry entry) {
|
||||
writeCodeStream.reset();
|
||||
encodeEntry(entry, prevWord, writeCodeStream);
|
||||
if (offset + writeCodeStream.byteLength() > this.blockSize - 2) {
|
||||
return false;
|
||||
}
|
||||
byte[] bytes= writeCodeStream.toByteArray();
|
||||
field.put(offset, bytes);
|
||||
offset += bytes.length;
|
||||
prevWord= entry.getWord();
|
||||
return true;
|
||||
}
|
||||
protected void encodeEntry(WordEntry entry, char[] prevWord, CodeByteStream codeStream) {
|
||||
char[] word= entry.getWord();
|
||||
int prefixLen= prevWord == null ? 0 : Util.prefixLength(prevWord, word);
|
||||
codeStream.writeByte(prefixLen);
|
||||
codeStream.writeUTF(word, prefixLen, word.length);
|
||||
int n= entry.getNumRefs();
|
||||
codeStream.writeGamma(n);
|
||||
int prevRef= 0;
|
||||
for (int i= 0; i < n; ++i) {
|
||||
int ref= entry.getRef(i);
|
||||
if (ref <= prevRef)
|
||||
throw new IllegalArgumentException();
|
||||
codeStream.writeGamma(ref - prevRef);
|
||||
prevRef= ref;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexBlock#flush
|
||||
*/
|
||||
public void flush() {
|
||||
if (offset > 0) {
|
||||
field.putInt2(offset, 0);
|
||||
offset= 0;
|
||||
prevWord= null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexBlock#isEmpty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return offset == 0;
|
||||
}
|
||||
/**
|
||||
* @see IndexBlock#nextEntry
|
||||
*/
|
||||
public boolean nextEntry(WordEntry entry) {
|
||||
try {
|
||||
readCodeStream.reset(field.buffer(), offset);
|
||||
int prefixLength= readCodeStream.readByte();
|
||||
char[] word= readCodeStream.readUTF();
|
||||
if (prevWord != null && prefixLength > 0) {
|
||||
char[] temp= new char[prefixLength + word.length];
|
||||
System.arraycopy(prevWord, 0, temp, 0, prefixLength);
|
||||
System.arraycopy(word, 0, temp, prefixLength, word.length);
|
||||
word= temp;
|
||||
}
|
||||
if (word.length == 0) {
|
||||
return false;
|
||||
}
|
||||
entry.reset(word);
|
||||
int n= readCodeStream.readGamma();
|
||||
int prevRef= 0;
|
||||
for (int i= 0; i < n; ++i) {
|
||||
int ref= prevRef + readCodeStream.readGamma();
|
||||
if (ref < prevRef)
|
||||
throw new InternalError();
|
||||
entry.addRef(ref);
|
||||
prevRef= ref;
|
||||
}
|
||||
offset= readCodeStream.byteLength();
|
||||
prevWord= word;
|
||||
return true;
|
||||
} catch (UTFDataFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexBlock#reset
|
||||
*/
|
||||
public void reset() {
|
||||
super.reset();
|
||||
offset= 0;
|
||||
prevWord= null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
|
||||
/**
|
||||
* An <code>IFileDocument</code> represents an IFile.
|
||||
*/
|
||||
|
||||
public class IFileDocument extends PropertyDocument {
|
||||
protected IFile file;
|
||||
|
||||
// cached contents if needed - only one of them is used at a time
|
||||
protected char[] charContents;
|
||||
protected byte[] byteContents;
|
||||
/**
|
||||
* IFileDocument constructor comment.
|
||||
*/
|
||||
public IFileDocument(IFile file) {
|
||||
this(file, (char[])null);
|
||||
}
|
||||
/**
|
||||
* IFileDocument constructor comment.
|
||||
*/
|
||||
public IFileDocument(IFile file, byte[] byteContents) {
|
||||
this.file= file;
|
||||
this.byteContents= byteContents;
|
||||
}
|
||||
/**
|
||||
* IFileDocument constructor comment.
|
||||
*/
|
||||
public IFileDocument(IFile file, char[] charContents) {
|
||||
this.file= file;
|
||||
this.charContents= charContents;
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
|
||||
*/
|
||||
public byte[] getByteContent() throws IOException {
|
||||
if (byteContents != null) return byteContents;
|
||||
IPath location = file.getLocation();
|
||||
if (location == null) return new byte[0];
|
||||
return byteContents = org.eclipse.cdt.internal.core.search.Util.getFileByteContent(location.toFile());
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
|
||||
*/
|
||||
public char[] getCharContent() throws IOException {
|
||||
if (charContents != null) return charContents;
|
||||
IPath location = file.getLocation();
|
||||
if (location == null) return CharOperation.NO_CHAR;
|
||||
return charContents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(
|
||||
location.toFile(),
|
||||
getEncoding());
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
|
||||
*/
|
||||
public String getEncoding() {
|
||||
//TODO: Indexer - get encoding
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return file.getFullPath().toString();
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getStringContent()
|
||||
*/
|
||||
public String getStringContent() throws java.io.IOException {
|
||||
return new String(getCharContent());
|
||||
}
|
||||
/**
|
||||
* @see org.eclipse.jdt.internal.core.index.IDocument#getType()
|
||||
*/
|
||||
public String getType() {
|
||||
String extension= file.getFileExtension();
|
||||
if (extension == null)
|
||||
return ""; //$NON-NLS-1$
|
||||
return extension;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
/**
|
||||
* This interface provides constants used by the search engine.
|
||||
*/
|
||||
public interface IIndexConstants {
|
||||
/**
|
||||
* The signature of the index file.
|
||||
*/
|
||||
public static final String SIGNATURE= "INDEX FILE 0.012"; //$NON-NLS-1$
|
||||
/**
|
||||
* The separator for files in the index file.
|
||||
*/
|
||||
public static final char FILE_SEPARATOR= '/';
|
||||
/**
|
||||
* The size of a block for a <code>Block</code>.
|
||||
*/
|
||||
public static final int BLOCK_SIZE= 8192;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
/**
|
||||
* This index stores the document names in an <code>ObjectVector</code>, and the words in
|
||||
* an <code>HashtableOfObjects</code>.
|
||||
*/
|
||||
|
||||
public class InMemoryIndex {
|
||||
|
||||
/**
|
||||
* hashtable of WordEntrys = words+numbers of the files they appear in.
|
||||
*/
|
||||
protected WordEntryHashedArray words;
|
||||
/**
|
||||
* List of IndexedFiles = file name + a unique number.
|
||||
*/
|
||||
protected IndexedFileHashedArray files;
|
||||
/**
|
||||
* Size of the index.
|
||||
*/
|
||||
protected long footprint;
|
||||
|
||||
private WordEntry[] sortedWordEntries;
|
||||
private IndexedFile[] sortedFiles;
|
||||
public InMemoryIndex() {
|
||||
init();
|
||||
}
|
||||
|
||||
public IndexedFile addDocument(IDocument document) {
|
||||
IndexedFile indexedFile= this.files.add(document);
|
||||
this.footprint += indexedFile.footprint() + 4;
|
||||
this.sortedFiles = null;
|
||||
return indexedFile;
|
||||
}
|
||||
/**
|
||||
* Adds the references of the word to the index (reference = number of the file the word belongs to).
|
||||
*/
|
||||
protected void addRef(char[] word, int[] references) {
|
||||
int size= references.length;
|
||||
int i= 0;
|
||||
while (i < size) {
|
||||
if (references[i] != 0)
|
||||
addRef(word, references[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Looks if the word already exists in the index and add the fileNum to this word.
|
||||
* If the word does not exist, it adds it in the index.
|
||||
*/
|
||||
protected void addRef(char[] word, int fileNum) {
|
||||
WordEntry entry= (WordEntry) this.words.get(word);
|
||||
if (entry == null) {
|
||||
entry= new WordEntry(word);
|
||||
entry.addRef(fileNum);
|
||||
this.words.add(entry);
|
||||
this.sortedWordEntries= null;
|
||||
this.footprint += entry.footprint();
|
||||
} else {
|
||||
this.footprint += entry.addRef(fileNum);
|
||||
}
|
||||
}
|
||||
|
||||
public void addRef(IndexedFile indexedFile, char[] word) {
|
||||
addRef(word, indexedFile.getFileNumber());
|
||||
}
|
||||
|
||||
public void addRef(IndexedFile indexedFile, String word) {
|
||||
addRef(word.toCharArray(), indexedFile.getFileNumber());
|
||||
}
|
||||
/**
|
||||
* Returns the footprint of the index.
|
||||
*/
|
||||
public long getFootprint() {
|
||||
return this.footprint;
|
||||
}
|
||||
/**
|
||||
* Returns the indexed file with the given path, or null if such file does not exist.
|
||||
*/
|
||||
public IndexedFile getIndexedFile(String path) {
|
||||
return files.get(path);
|
||||
}
|
||||
/**
|
||||
* @see IIndex#getNumDocuments()
|
||||
*/
|
||||
public int getNumFiles() {
|
||||
return files.size();
|
||||
}
|
||||
/**
|
||||
* @see IIndex#getNumWords()
|
||||
*/
|
||||
public int getNumWords() {
|
||||
return words.elementSize;
|
||||
}
|
||||
/**
|
||||
* Returns the words contained in the hashtable of words, sorted by alphabetical order.
|
||||
*/
|
||||
protected IndexedFile[] getSortedFiles() {
|
||||
if (this.sortedFiles == null) {
|
||||
IndexedFile[] indexedFiles= files.asArray();
|
||||
Util.sort(indexedFiles);
|
||||
this.sortedFiles= indexedFiles;
|
||||
}
|
||||
return this.sortedFiles;
|
||||
}
|
||||
/**
|
||||
* Returns the word entries contained in the hashtable of words, sorted by alphabetical order.
|
||||
*/
|
||||
protected WordEntry[] getSortedWordEntries() {
|
||||
if (this.sortedWordEntries == null) {
|
||||
WordEntry[] words= this.words.asArray();
|
||||
Util.sort(words);
|
||||
this.sortedWordEntries= words;
|
||||
}
|
||||
return this.sortedWordEntries;
|
||||
}
|
||||
/**
|
||||
* Returns the word entry corresponding to the given word.
|
||||
*/
|
||||
protected WordEntry getWordEntry(char[] word) {
|
||||
return (WordEntry) words.get(word);
|
||||
}
|
||||
/**
|
||||
* Initialises the fields of the index
|
||||
*/
|
||||
public void init() {
|
||||
words= new WordEntryHashedArray(501);
|
||||
files= new IndexedFileHashedArray(101);
|
||||
footprint= 0;
|
||||
sortedWordEntries= null;
|
||||
sortedFiles= null;
|
||||
}
|
||||
/**
|
||||
* Saves the index in the given file.
|
||||
* Structure of the saved Index :
|
||||
* - IndexedFiles in sorted order.
|
||||
* + example:
|
||||
* "c:/com/a.cpp 1"
|
||||
* "c:/com/b.cpp 2"
|
||||
* - References with the words in sorted order
|
||||
* + example:
|
||||
* "classDecl/a 1"
|
||||
* "classDecl/b 2"
|
||||
* "ref/String 1 2"
|
||||
*/
|
||||
public void save(File file) throws IOException {
|
||||
BlocksIndexOutput output= new BlocksIndexOutput(file);
|
||||
save(output);
|
||||
}
|
||||
/**
|
||||
* Saves the index in the given IndexOutput.
|
||||
* Structure of the saved Index :
|
||||
* - IndexedFiles in sorted order.
|
||||
* + example:
|
||||
* "c:/com/a.cpp 1"
|
||||
* "c:/com/b.cpp 2"
|
||||
* - References with the words in sorted order
|
||||
* + example:
|
||||
* "classDecl/a 1"
|
||||
* "classDecl/b 2"
|
||||
* "ref/String 1 2"
|
||||
*/
|
||||
protected void save(IndexOutput output) throws IOException {
|
||||
boolean ok= false;
|
||||
try {
|
||||
output.open();
|
||||
IndexedFile[] indexedFiles= files.asArray();
|
||||
for (int i= 0, length = indexedFiles.length; i < length; ++i)
|
||||
output.addFile(indexedFiles[i]); // written out in order BUT not alphabetical
|
||||
getSortedWordEntries(); // init the slot
|
||||
for (int i= 0, numWords= sortedWordEntries.length; i < numWords; ++i)
|
||||
output.addWord(sortedWordEntries[i]);
|
||||
output.flush();
|
||||
output.close();
|
||||
ok= true;
|
||||
} finally {
|
||||
if (!ok && output != null)
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexer;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
|
||||
/**
|
||||
* An Index is used to create an index on the disk, and to make queries. It uses a set of
|
||||
* indexers and a mergeFactory. The index fills an inMemoryIndex up
|
||||
* to it reaches a certain size, and then merges it with a main index on the disk.
|
||||
* <br> <br>
|
||||
* The changes are only taken into account by the queries after a merge.
|
||||
*/
|
||||
|
||||
public class Index implements IIndex {
|
||||
/**
|
||||
* Maximum size of the index in memory.
|
||||
*/
|
||||
public static final int MAX_FOOTPRINT= 10000000;
|
||||
|
||||
/**
|
||||
* Index in memory, who is merged with mainIndex each times it
|
||||
* reaches a certain size.
|
||||
*/
|
||||
protected InMemoryIndex addsIndex;
|
||||
protected IndexInput addsIndexInput;
|
||||
|
||||
/**
|
||||
* State of the indexGenerator: addsIndex empty <=> MERGED, or
|
||||
* addsIndex not empty <=> CAN_MERGE
|
||||
*/
|
||||
protected int state;
|
||||
|
||||
/**
|
||||
* Files removed form the addsIndex.
|
||||
*/
|
||||
protected Map removedInAdds;
|
||||
|
||||
/**
|
||||
* Files removed form the oldIndex.
|
||||
*/
|
||||
protected Map removedInOld;
|
||||
protected static final int CAN_MERGE= 0;
|
||||
protected static final int MERGED= 1;
|
||||
private File indexFile;
|
||||
|
||||
/**
|
||||
* String representation of this index.
|
||||
*/
|
||||
public String toString;
|
||||
|
||||
public Index(File indexDirectory, boolean reuseExistingFile) throws IOException {
|
||||
this(indexDirectory,".index", reuseExistingFile); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public Index(File indexDirectory, String indexName, boolean reuseExistingFile) throws IOException {
|
||||
super();
|
||||
state= MERGED;
|
||||
indexFile= new File(indexDirectory, indexName);
|
||||
initialize(reuseExistingFile);
|
||||
}
|
||||
|
||||
public Index(String indexName, boolean reuseExistingFile) throws IOException {
|
||||
this(indexName, null, reuseExistingFile);
|
||||
}
|
||||
|
||||
public Index(String indexName, String toString, boolean reuseExistingFile) throws IOException {
|
||||
super();
|
||||
state= MERGED;
|
||||
indexFile= new File(indexName);
|
||||
this.toString = toString;
|
||||
initialize(reuseExistingFile);
|
||||
}
|
||||
/**
|
||||
* Indexes the given document, using the appropriate indexer registered in the indexerRegistry.
|
||||
* If the document already exists in the index, it overrides the previous one. The changes will be
|
||||
* taken into account after a merge.
|
||||
*/
|
||||
public void add(IDocument document, IIndexer indexer) throws IOException {
|
||||
if (timeToMerge()) {
|
||||
merge();
|
||||
}
|
||||
IndexedFile indexedFile= addsIndex.getIndexedFile(document.getName());
|
||||
if (indexedFile != null /*&& removedInAdds.get(document.getName()) == null*/
|
||||
)
|
||||
remove(indexedFile, MergeFactory.ADDS_INDEX);
|
||||
IndexerOutput output= new IndexerOutput(addsIndex);
|
||||
indexer.index(document, output);
|
||||
state= CAN_MERGE;
|
||||
}
|
||||
/**
|
||||
* Returns true if the index in memory is not empty, so
|
||||
* merge() can be called to fill the mainIndex with the files and words
|
||||
* contained in the addsIndex.
|
||||
*/
|
||||
protected boolean canMerge() {
|
||||
return state == CAN_MERGE;
|
||||
}
|
||||
/**
|
||||
* Initialises the indexGenerator.
|
||||
*/
|
||||
public void empty() throws IOException {
|
||||
|
||||
if (indexFile.exists()){
|
||||
indexFile.delete();
|
||||
//initialisation of mainIndex
|
||||
InMemoryIndex mainIndex= new InMemoryIndex();
|
||||
IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
|
||||
if (!indexFile.exists())
|
||||
mainIndex.save(mainIndexOutput);
|
||||
}
|
||||
|
||||
//initialisation of addsIndex
|
||||
addsIndex= new InMemoryIndex();
|
||||
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||
|
||||
//vectors who keep track of the removed Files
|
||||
removedInAdds= new HashMap(11);
|
||||
removedInOld= new HashMap(11);
|
||||
}
|
||||
/**
|
||||
* @see IIndex#getIndexFile
|
||||
*/
|
||||
public File getIndexFile() {
|
||||
return indexFile;
|
||||
}
|
||||
/**
|
||||
* @see IIndex#getNumDocuments
|
||||
*/
|
||||
public int getNumDocuments() throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
input.open();
|
||||
return input.getNumFiles();
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IIndex#getNumWords
|
||||
*/
|
||||
public int getNumWords() throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
input.open();
|
||||
return input.getNumWords();
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the path corresponding to a given document number
|
||||
*/
|
||||
public String getPath(int documentNumber) throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
input.open();
|
||||
IndexedFile file = input.getIndexedFile(documentNumber);
|
||||
if (file == null) return null;
|
||||
return file.getPath();
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* see IIndex.hasChanged
|
||||
*/
|
||||
public boolean hasChanged() {
|
||||
return canMerge();
|
||||
}
|
||||
/**
|
||||
* Initialises the indexGenerator.
|
||||
*/
|
||||
public void initialize(boolean reuseExistingFile) throws IOException {
|
||||
//initialisation of addsIndex
|
||||
addsIndex= new InMemoryIndex();
|
||||
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||
|
||||
//vectors who keep track of the removed Files
|
||||
removedInAdds= new HashMap(11);
|
||||
removedInOld= new HashMap(11);
|
||||
|
||||
// check whether existing index file can be read
|
||||
if (reuseExistingFile && indexFile.exists()) {
|
||||
IndexInput mainIndexInput= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
mainIndexInput.open();
|
||||
} catch(IOException e) {
|
||||
BlocksIndexInput input = (BlocksIndexInput)mainIndexInput;
|
||||
try {
|
||||
input.opened = true;
|
||||
input.close();
|
||||
} finally {
|
||||
input.opened = false;
|
||||
}
|
||||
indexFile.delete();
|
||||
mainIndexInput = null;
|
||||
throw e;
|
||||
}
|
||||
mainIndexInput.close();
|
||||
} else {
|
||||
InMemoryIndex mainIndex= new InMemoryIndex();
|
||||
IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
|
||||
mainIndex.save(mainIndexOutput);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Merges the in memory index and the index on the disk, and saves the results on the disk.
|
||||
*/
|
||||
protected void merge() throws IOException {
|
||||
//initialisation of tempIndex
|
||||
File tempFile= new File(indexFile.getAbsolutePath() + "TempVA"); //$NON-NLS-1$
|
||||
|
||||
IndexInput mainIndexInput= new BlocksIndexInput(indexFile);
|
||||
BlocksIndexOutput tempIndexOutput= new BlocksIndexOutput(tempFile);
|
||||
|
||||
try {
|
||||
//invoke a mergeFactory
|
||||
new MergeFactory(
|
||||
mainIndexInput,
|
||||
addsIndexInput,
|
||||
tempIndexOutput,
|
||||
removedInOld,
|
||||
removedInAdds).merge();
|
||||
|
||||
//rename the file created to become the main index
|
||||
File mainIndexFile= (File) mainIndexInput.getSource();
|
||||
File tempIndexFile= (File) tempIndexOutput.getDestination();
|
||||
mainIndexFile.delete();
|
||||
tempIndexFile.renameTo(mainIndexFile);
|
||||
} finally {
|
||||
//initialise remove vectors and addsindex, and change the state
|
||||
removedInAdds.clear();
|
||||
removedInOld.clear();
|
||||
addsIndex.init();
|
||||
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||
state= MERGED;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IIndex#query
|
||||
*/
|
||||
public IQueryResult[] query(String word) throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
return input.query(word);
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
public IEntryResult[] queryEntries(char[] prefix) throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
return input.queryEntriesPrefixedBy(prefix);
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IIndex#queryInDocumentNames
|
||||
*/
|
||||
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
return input.queryInDocumentNames(word);
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IIndex#queryPrefix
|
||||
*/
|
||||
public IQueryResult[] queryPrefix(char[] prefix) throws IOException {
|
||||
//save();
|
||||
IndexInput input= new BlocksIndexInput(indexFile);
|
||||
try {
|
||||
return input.queryFilesReferringToPrefix(prefix);
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IIndex#remove
|
||||
*/
|
||||
public void remove(String documentName) throws IOException {
|
||||
IndexedFile file= addsIndex.getIndexedFile(documentName);
|
||||
if (file != null) {
|
||||
//the file is in the adds Index, we remove it from this one
|
||||
Int lastRemoved= (Int) removedInAdds.get(documentName);
|
||||
if (lastRemoved != null) {
|
||||
int fileNum= file.getFileNumber();
|
||||
if (lastRemoved.value < fileNum)
|
||||
lastRemoved.value= fileNum;
|
||||
} else
|
||||
removedInAdds.put(documentName, new Int(file.getFileNumber()));
|
||||
} else {
|
||||
//we remove the file from the old index
|
||||
removedInOld.put(documentName, new Int(1));
|
||||
}
|
||||
state= CAN_MERGE;
|
||||
}
|
||||
/**
|
||||
* Removes the given document from the given index (MergeFactory.ADDS_INDEX for the
|
||||
* in memory index, MergeFactory.OLD_INDEX for the index on the disk).
|
||||
*/
|
||||
protected void remove(IndexedFile file, int index) throws IOException {
|
||||
String name= file.getPath();
|
||||
if (index == MergeFactory.ADDS_INDEX) {
|
||||
Int lastRemoved= (Int) removedInAdds.get(name);
|
||||
if (lastRemoved != null) {
|
||||
if (lastRemoved.value < file.getFileNumber())
|
||||
lastRemoved.value= file.getFileNumber();
|
||||
} else
|
||||
removedInAdds.put(name, new Int(file.getFileNumber()));
|
||||
} else if (index == MergeFactory.OLD_INDEX)
|
||||
removedInOld.put(name, new Int(1));
|
||||
else
|
||||
throw new Error();
|
||||
state= CAN_MERGE;
|
||||
}
|
||||
/**
|
||||
* @see IIndex#save
|
||||
*/
|
||||
public void save() throws IOException {
|
||||
if (canMerge())
|
||||
merge();
|
||||
}
|
||||
/**
|
||||
* Returns true if the in memory index reaches a critical size,
|
||||
* to merge it with the index on the disk.
|
||||
*/
|
||||
protected boolean timeToMerge() {
|
||||
return (addsIndex.getFootprint() >= MAX_FOOTPRINT);
|
||||
}
|
||||
public String toString() {
|
||||
String str = this.toString;
|
||||
if (str == null) str = super.toString();
|
||||
str += "(length: "+ getIndexFile().length() +")"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return str;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
/**
|
||||
* An indexBlock stores wordEntries.
|
||||
*/
|
||||
public abstract class IndexBlock extends Block {
|
||||
|
||||
public IndexBlock(int blockSize) {
|
||||
super(blockSize);
|
||||
}
|
||||
/**
|
||||
* Adds the given wordEntry to the indexBlock.
|
||||
*/
|
||||
public abstract boolean addEntry(WordEntry entry);
|
||||
/**
|
||||
* @see Block#clear()
|
||||
*/
|
||||
public void clear() {
|
||||
reset();
|
||||
super.clear();
|
||||
}
|
||||
public WordEntry findEntryMatching(char[] pattern, boolean isCaseSensitive) {
|
||||
reset();
|
||||
WordEntry entry= new WordEntry();
|
||||
while (nextEntry(entry)) {
|
||||
if (CharOperation.match(pattern, entry.getWord(), isCaseSensitive)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public WordEntry findEntryPrefixedBy(char[] word, boolean isCaseSensitive) {
|
||||
reset();
|
||||
WordEntry entry= new WordEntry();
|
||||
while (nextEntry(entry)) {
|
||||
if (CharOperation.prefixEquals(entry.getWord(), word, isCaseSensitive)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public WordEntry findExactEntry(char[] word) {
|
||||
reset();
|
||||
WordEntry entry= new WordEntry();
|
||||
while (nextEntry(entry)) {
|
||||
if (CharOperation.equals(entry.getWord(), word)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns whether the block is empty or not (if it doesn't contain any wordEntry).
|
||||
*/
|
||||
public abstract boolean isEmpty();
|
||||
/**
|
||||
* Finds the next wordEntry and stores it in the given entry.
|
||||
*/
|
||||
public abstract boolean nextEntry(WordEntry entry);
|
||||
public void reset() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
|
||||
|
||||
/**
|
||||
* This class provides an input on an index, after it has been generated.
|
||||
* You can access all the files of an index via getNextFile(), getCurrentFile()
|
||||
* and moveToNextFile() (idem for the word entries).
|
||||
* The usage is the same for every subclass: creation (constructor), opening
|
||||
* (the open() method), usage, and closing (the close() method), to release the
|
||||
* data source used by this input.
|
||||
*/
|
||||
public abstract class IndexInput {
|
||||
protected int filePosition;
|
||||
protected WordEntry currentWordEntry;
|
||||
protected int wordPosition;
|
||||
|
||||
|
||||
public IndexInput() {
|
||||
super();
|
||||
wordPosition= 1;
|
||||
filePosition= 1;
|
||||
}
|
||||
/**
|
||||
* clears the cache of this indexInput, if it keeps track of the information already read.
|
||||
*/
|
||||
public abstract void clearCache();
|
||||
/**
|
||||
* Closes the IndexInput. For example, if the input is on a RandomAccessFile,
|
||||
* it calls the close() method of RandomAccessFile.
|
||||
*/
|
||||
public abstract void close() throws IOException;
|
||||
/**
|
||||
* Returns the current file the indexInput is pointing to in the index.
|
||||
*/
|
||||
public abstract IndexedFile getCurrentFile() throws IOException;
|
||||
/**
|
||||
* Returns the current file the indexInput is pointing to in the index.
|
||||
*/
|
||||
public WordEntry getCurrentWordEntry() throws IOException {
|
||||
if (!hasMoreWords())
|
||||
return null;
|
||||
return currentWordEntry;
|
||||
}
|
||||
/**
|
||||
* Returns the position of the current file the input is pointing to in the index.
|
||||
*/
|
||||
public int getFilePosition() {
|
||||
return filePosition;
|
||||
}
|
||||
/**
|
||||
* Returns the indexedFile corresponding to the given document number in the index the input
|
||||
* reads in, or null if such indexedFile does not exist.
|
||||
*/
|
||||
public abstract IndexedFile getIndexedFile(int fileNum) throws IOException;
|
||||
/**
|
||||
* Returns the indexedFile corresponding to the given document in the index the input
|
||||
* reads in (e.g. the indexedFile with the same path in this index), or null if such
|
||||
* indexedFile does not exist.
|
||||
*/
|
||||
public abstract IndexedFile getIndexedFile(IDocument document) throws IOException;
|
||||
/**
|
||||
* Returns the number of files in the index.
|
||||
*/
|
||||
public abstract int getNumFiles();
|
||||
/**
|
||||
* Returns the number of unique words in the index.
|
||||
*/
|
||||
public abstract int getNumWords();
|
||||
/**
|
||||
* Returns the Object the input is reading from. It can be an IIndex,
|
||||
* a File, ...
|
||||
*/
|
||||
public abstract Object getSource();
|
||||
/**
|
||||
* Returns true if the input has not reached the end of the index for the files.
|
||||
*/
|
||||
public boolean hasMoreFiles() {
|
||||
return getFilePosition() <= getNumFiles();
|
||||
}
|
||||
/**
|
||||
* Returns true if the input has not reached the end of the index for the files.
|
||||
*/
|
||||
public boolean hasMoreWords() {
|
||||
return wordPosition <= getNumWords();
|
||||
}
|
||||
/**
|
||||
* Moves the pointer on the current file to the next file in the index.
|
||||
*/
|
||||
public abstract void moveToNextFile() throws IOException;
|
||||
/**
|
||||
* Moves the pointer on the current word to the next file in the index.
|
||||
*/
|
||||
public abstract void moveToNextWordEntry() throws IOException;
|
||||
/**
|
||||
* Open the Source where the input gets the information from.
|
||||
*/
|
||||
public abstract void open() throws IOException;
|
||||
/**
|
||||
* Returns the list of the files containing the given word in the index.
|
||||
*/
|
||||
public abstract IQueryResult[] query(String word) throws IOException;
|
||||
public abstract IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException;
|
||||
public abstract IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException;
|
||||
/**
|
||||
* Returns the list of the files whose name contain the given word in the index.
|
||||
*/
|
||||
public abstract IQueryResult[] queryInDocumentNames(String word) throws IOException;
|
||||
/**
|
||||
* Set the pointer on the current file to the first file of the index.
|
||||
*/
|
||||
protected abstract void setFirstFile() throws IOException;
|
||||
/**
|
||||
* Set the pointer on the current word to the first word of the index.
|
||||
*/
|
||||
protected abstract void setFirstWord() throws IOException;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An indexOutput is used to write an index into a different object (a File, ...).
|
||||
*/
|
||||
public abstract class IndexOutput {
|
||||
/**
|
||||
* Adds a File to the destination.
|
||||
*/
|
||||
public abstract void addFile(IndexedFile file) throws IOException;
|
||||
/**
|
||||
* Adds a word to the destination.
|
||||
*/
|
||||
public abstract void addWord(WordEntry word) throws IOException;
|
||||
/**
|
||||
* Closes the output, releasing the resources it was using.
|
||||
*/
|
||||
public abstract void close() throws IOException;
|
||||
/**
|
||||
* Flushes the output.
|
||||
*/
|
||||
public abstract void flush() throws IOException;
|
||||
/**
|
||||
* Returns the Object the output is writing to. It can be a file, another type of index, ...
|
||||
*/
|
||||
public abstract Object getDestination();
|
||||
/**
|
||||
* Opens the output, before writing any information.
|
||||
*/
|
||||
public abstract void open() throws IOException;
|
||||
}
|
|
@ -0,0 +1,315 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
/**
|
||||
* An indexSummary is used when saving an index into a BlocksIndexOuput or
|
||||
* reading it from a BlocksIndexInput. It contains basic informations about
|
||||
* an index: first files/words in each block, number of files/words.
|
||||
*/
|
||||
|
||||
public class IndexSummary {
|
||||
/**
|
||||
* First file for each block.
|
||||
*/
|
||||
protected ArrayList firstFilesInBlocks= new ArrayList();
|
||||
/**
|
||||
* First word for each block.
|
||||
*/
|
||||
protected ArrayList firstWordsInBlocks= new ArrayList();
|
||||
/**
|
||||
* Number of files in the index.
|
||||
*/
|
||||
protected int numFiles;
|
||||
/**
|
||||
* Number of words in the index.
|
||||
*/
|
||||
protected int numWords;
|
||||
|
||||
static class FirstFileInBlock {
|
||||
IndexedFile indexedFile;
|
||||
int blockNum;
|
||||
}
|
||||
|
||||
static class FirstWordInBlock {
|
||||
char[] word;
|
||||
int blockNum;
|
||||
public String toString(){
|
||||
return "FirstWordInBlock: " + new String(word) + ", blockNum: " + blockNum; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
||||
protected int firstWordBlockNum;
|
||||
protected boolean firstWordAdded= true;
|
||||
/**
|
||||
* Adds the given file as the first file for the given Block number.
|
||||
*/
|
||||
public void addFirstFileInBlock(IndexedFile indexedFile, int blockNum) {
|
||||
FirstFileInBlock entry= new FirstFileInBlock();
|
||||
entry.indexedFile= indexedFile;
|
||||
entry.blockNum= blockNum;
|
||||
firstFilesInBlocks.add(entry);
|
||||
}
|
||||
/**
|
||||
* Adds the given word as the first word for the given Block number.
|
||||
*/
|
||||
public void addFirstWordInBlock(char[] word, int blockNum) {
|
||||
if (firstWordAdded) {
|
||||
firstWordBlockNum= blockNum;
|
||||
firstWordAdded= false;
|
||||
}
|
||||
FirstWordInBlock entry= new FirstWordInBlock();
|
||||
entry.word= word;
|
||||
entry.blockNum= blockNum;
|
||||
firstWordsInBlocks.add(entry);
|
||||
}
|
||||
/**
|
||||
* Returns the numbers of all the blocks
|
||||
*/
|
||||
public int[] getAllBlockNums() {
|
||||
|
||||
int max = firstWordsInBlocks.size();
|
||||
int[] blockNums = new int[max];
|
||||
for (int i = 0; i < max; i++){
|
||||
blockNums[i] = ((FirstWordInBlock)firstWordsInBlocks.get(i)).blockNum;
|
||||
}
|
||||
return blockNums;
|
||||
}
|
||||
public int getBlockNum(int blockLocation) {
|
||||
return ((FirstWordInBlock) firstWordsInBlocks.get(blockLocation)).blockNum;
|
||||
}
|
||||
/**
|
||||
* Returns the number of the Block containing the file with the given number.
|
||||
*/
|
||||
public int getBlockNumForFileNum(int fileNum) {
|
||||
int min= 0;
|
||||
int max= firstFilesInBlocks.size() - 1;
|
||||
while (min <= max) {
|
||||
int mid= (min + max) / 2;
|
||||
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(mid);
|
||||
int compare= fileNum - entry.indexedFile.getFileNumber();
|
||||
if (compare == 0)
|
||||
return entry.blockNum;
|
||||
if (compare < 0)
|
||||
max= mid - 1;
|
||||
else
|
||||
min= mid + 1;
|
||||
}
|
||||
if (max < 0)
|
||||
return -1;
|
||||
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(max);
|
||||
return entry.blockNum;
|
||||
}
|
||||
/**
|
||||
* Returns the number of the Block containing the given word.
|
||||
*/
|
||||
public int getBlockNumForWord(char[] word) {
|
||||
int min= 0;
|
||||
int max= firstWordsInBlocks.size() - 1;
|
||||
while (min <= max) {
|
||||
int mid= (min + max) / 2;
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||
int compare= Util.compare(word, entry.word);
|
||||
if (compare == 0)
|
||||
return entry.blockNum;
|
||||
if (compare < 0)
|
||||
max= mid - 1;
|
||||
else
|
||||
min= mid + 1;
|
||||
}
|
||||
if (max < 0)
|
||||
return -1;
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(max);
|
||||
return entry.blockNum;
|
||||
}
|
||||
public int[] getBlockNumsForPrefix(char[] prefix) {
|
||||
int min= 0;
|
||||
int size= firstWordsInBlocks.size();
|
||||
int max= size - 1;
|
||||
int match= -1;
|
||||
while (min <= max && match < 0) {
|
||||
int mid= (min + max) / 2;
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||
int compare= CharOperation.compareWith(entry.word, prefix);
|
||||
if (compare == 0) {
|
||||
match= mid;
|
||||
break;
|
||||
}
|
||||
if (compare >= 0)
|
||||
max= mid - 1;
|
||||
else
|
||||
min= mid + 1;
|
||||
}
|
||||
if (max < 0)
|
||||
return new int[0];
|
||||
|
||||
if (match < 0)
|
||||
match= max;
|
||||
|
||||
int firstBlock= match - 1;
|
||||
// Look if previous blocks are affected
|
||||
for (; firstBlock >= 0; firstBlock--) {
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(firstBlock);
|
||||
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||
break;
|
||||
}
|
||||
if (firstBlock < 0)
|
||||
firstBlock= 0;
|
||||
|
||||
// Look if next blocks are affected
|
||||
int firstNotIncludedBlock= match + 1;
|
||||
for (; firstNotIncludedBlock < size; firstNotIncludedBlock++) {
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(firstNotIncludedBlock);
|
||||
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||
break;
|
||||
}
|
||||
|
||||
int numberOfBlocks= firstNotIncludedBlock - firstBlock;
|
||||
int[] result= new int[numberOfBlocks];
|
||||
int pos= firstBlock;
|
||||
for (int i= 0; i < numberOfBlocks; i++, pos++) {
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(pos);
|
||||
result[i]= entry.blockNum;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public int getFirstBlockLocationForPrefix(char[] prefix) {
|
||||
int min = 0;
|
||||
int size = firstWordsInBlocks.size();
|
||||
int max = size - 1;
|
||||
int match = -1;
|
||||
while (min <= max) {
|
||||
int mid = (min + max) / 2;
|
||||
FirstWordInBlock entry = (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||
int compare = CharOperation.compareWith(entry.word, prefix);
|
||||
if (compare == 0) {
|
||||
match = mid;
|
||||
break;
|
||||
}
|
||||
if (compare >= 0) {
|
||||
max = mid - 1;
|
||||
} else {
|
||||
match = mid; // not perfect match, but could be inside
|
||||
min = mid + 1;
|
||||
}
|
||||
}
|
||||
if (max < 0) return -1;
|
||||
|
||||
// no match at all, might be some matching entries inside max block
|
||||
if (match < 0){
|
||||
match = max;
|
||||
} else {
|
||||
// look for possible matches inside previous blocks
|
||||
while (match > 0){
|
||||
FirstWordInBlock entry = (FirstWordInBlock) firstWordsInBlocks.get(match);
|
||||
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||
break;
|
||||
match--;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
/**
|
||||
* Returns the number of the first IndexBlock (containing words).
|
||||
*/
|
||||
public int getFirstWordBlockNum() {
|
||||
return firstWordBlockNum;
|
||||
}
|
||||
/**
|
||||
* Blocks are contiguous, so the next one is a potential candidate if its first word starts with
|
||||
* the given prefix
|
||||
*/
|
||||
public int getNextBlockLocationForPrefix(char[] prefix, int blockLoc) {
|
||||
if (++blockLoc < firstWordsInBlocks.size()){
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(blockLoc);
|
||||
if (CharOperation.prefixEquals(prefix, entry.word)) return blockLoc;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* Returns the number of files contained in the index.
|
||||
*/
|
||||
public int getNumFiles() {
|
||||
return numFiles;
|
||||
}
|
||||
/**
|
||||
* Returns the number of words contained in the index.
|
||||
*/
|
||||
public int getNumWords() {
|
||||
return numWords;
|
||||
}
|
||||
/**
|
||||
* Loads the summary in memory.
|
||||
*/
|
||||
public void read(RandomAccessFile raf) throws IOException {
|
||||
numFiles= raf.readInt();
|
||||
numWords= raf.readInt();
|
||||
firstWordBlockNum= raf.readInt();
|
||||
int numFirstFiles= raf.readInt();
|
||||
for (int i= 0; i < numFirstFiles; ++i) {
|
||||
FirstFileInBlock entry= new FirstFileInBlock();
|
||||
String path= raf.readUTF();
|
||||
int fileNum= raf.readInt();
|
||||
entry.indexedFile= new IndexedFile(path, fileNum);
|
||||
entry.blockNum= raf.readInt();
|
||||
firstFilesInBlocks.add(entry);
|
||||
}
|
||||
int numFirstWords= raf.readInt();
|
||||
for (int i= 0; i < numFirstWords; ++i) {
|
||||
FirstWordInBlock entry= new FirstWordInBlock();
|
||||
entry.word= raf.readUTF().toCharArray();
|
||||
entry.blockNum= raf.readInt();
|
||||
firstWordsInBlocks.add(entry);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the number of files of the index.
|
||||
*/
|
||||
|
||||
public void setNumFiles(int numFiles) {
|
||||
this.numFiles= numFiles;
|
||||
}
|
||||
/**
|
||||
* Sets the number of words of the index.
|
||||
*/
|
||||
|
||||
public void setNumWords(int numWords) {
|
||||
this.numWords= numWords;
|
||||
}
|
||||
/**
|
||||
* Saves the summary on the disk.
|
||||
*/
|
||||
public void write(RandomAccessFile raf) throws IOException {
|
||||
raf.writeInt(numFiles);
|
||||
raf.writeInt(numWords);
|
||||
raf.writeInt(firstWordBlockNum);
|
||||
raf.writeInt(firstFilesInBlocks.size());
|
||||
for (int i= 0, size= firstFilesInBlocks.size(); i < size; ++i) {
|
||||
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(i);
|
||||
raf.writeUTF(entry.indexedFile.getPath());
|
||||
raf.writeInt(entry.indexedFile.getFileNumber());
|
||||
raf.writeInt(entry.blockNum);
|
||||
}
|
||||
raf.writeInt(firstWordsInBlocks.size());
|
||||
for (int i= 0, size= firstWordsInBlocks.size(); i < size; ++i) {
|
||||
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(i);
|
||||
raf.writeUTF(new String(entry.word));
|
||||
raf.writeInt(entry.blockNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
/**
|
||||
* An indexedFile associates a number to a document path, and document properties.
|
||||
* It is what we add into an index, and the result of a query.
|
||||
*/
|
||||
|
||||
public class IndexedFile implements IQueryResult {
|
||||
protected String path;
|
||||
protected int fileNumber;
|
||||
|
||||
public IndexedFile(String path, int fileNum) {
|
||||
if (fileNum < 1)
|
||||
throw new IllegalArgumentException();
|
||||
this.fileNumber= fileNum;
|
||||
this.path= path;
|
||||
}
|
||||
public IndexedFile(IDocument document, int fileNum) {
|
||||
if (fileNum < 1)
|
||||
throw new IllegalArgumentException();
|
||||
this.path= document.getName();
|
||||
this.fileNumber= fileNum;
|
||||
}
|
||||
/**
|
||||
* Returns the size of the indexedFile.
|
||||
*/
|
||||
public int footprint() {
|
||||
//object+ 2 slots + size of the string (header + 4 slots + char[])
|
||||
return 8 + (2 * 4) + (8 + (4 * 4) + 8 + path.length() * 2);
|
||||
}
|
||||
/**
|
||||
* Returns the file number.
|
||||
*/
|
||||
public int getFileNumber() {
|
||||
return fileNumber;
|
||||
}
|
||||
/**
|
||||
* Returns the path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
/**
|
||||
* Sets the file number.
|
||||
*/
|
||||
public void setFileNumber(int fileNumber) {
|
||||
this.fileNumber= fileNumber;
|
||||
}
|
||||
public String toString() {
|
||||
return "IndexedFile(" + fileNumber + ": " + path + ")"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
public final class IndexedFileHashedArray {
|
||||
|
||||
private IndexedFile elements[];
|
||||
private int elementSize; // number of elements in the table
|
||||
private int threshold;
|
||||
private int lastId;
|
||||
private ArrayList replacedElements;
|
||||
|
||||
public IndexedFileHashedArray(int size) {
|
||||
if (size < 7) size = 7;
|
||||
this.elements = new IndexedFile[2 * size + 1];
|
||||
this.elementSize = 0;
|
||||
this.threshold = size + 1; // size is the expected number of elements
|
||||
this.lastId = 0;
|
||||
this.replacedElements = null;
|
||||
}
|
||||
|
||||
public IndexedFile add(IDocument document) {
|
||||
return add(new IndexedFile(document, ++lastId));
|
||||
}
|
||||
|
||||
private IndexedFile add(IndexedFile file) {
|
||||
int length = elements.length;
|
||||
String path = file.getPath();
|
||||
int index = (path.hashCode() & 0x7FFFFFFF) % length;
|
||||
IndexedFile current;
|
||||
while ((current = elements[index]) != null) {
|
||||
if (current.getPath().equals(path)) {
|
||||
if (replacedElements == null) replacedElements = new ArrayList(5);
|
||||
replacedElements.add(current);
|
||||
return elements[index] = file;
|
||||
}
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
elements[index] = file;
|
||||
|
||||
// assumes the threshold is never equal to the size of the table
|
||||
if (++elementSize > threshold) grow();
|
||||
return file;
|
||||
}
|
||||
|
||||
public IndexedFile[] asArray() {
|
||||
IndexedFile[] array = new IndexedFile[lastId];
|
||||
for (int i = 0, length = elements.length; i < length; i++) {
|
||||
IndexedFile current = elements[i];
|
||||
if (current != null)
|
||||
array[current.fileNumber - 1] = current;
|
||||
}
|
||||
if (replacedElements != null) {
|
||||
for (int i = 0, length = replacedElements.size(); i < length; i++) {
|
||||
IndexedFile current = (IndexedFile) replacedElements.get(i);
|
||||
array[current.fileNumber - 1] = current;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public IndexedFile get(String path) {
|
||||
int length = elements.length;
|
||||
int index = (path.hashCode() & 0x7FFFFFFF) % length;
|
||||
IndexedFile current;
|
||||
while ((current = elements[index]) != null) {
|
||||
if (current.getPath().equals(path)) return current;
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
IndexedFileHashedArray newArray = new IndexedFileHashedArray(elementSize * 2); // double the number of expected elements
|
||||
for (int i = 0, length = elements.length; i < length; i++)
|
||||
if (elements[i] != null)
|
||||
newArray.add(elements[i]);
|
||||
|
||||
// leave replacedElements as is
|
||||
this.elements = newArray.elements;
|
||||
this.elementSize = newArray.elementSize;
|
||||
this.threshold = newArray.threshold;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return elementSize + (replacedElements == null ? 0 : replacedElements.size());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = ""; //$NON-NLS-1$
|
||||
IndexedFile[] files = asArray();
|
||||
for (int i = 0, length = files.length; i < length; i++)
|
||||
s += files[i].toString() + "\n"; //$NON-NLS-1$
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IIndexerOutput;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
/**
|
||||
* An indexerOutput is used by an indexer to add documents and word references to
|
||||
* an inMemoryIndex. It keeps track of the document being indexed and add the
|
||||
* word references to this document (so you do not need to precise the document
|
||||
* each time you add a word).
|
||||
*/
|
||||
|
||||
public class IndexerOutput implements IIndexerOutput {
|
||||
protected InMemoryIndex index;
|
||||
protected IndexedFile indexedFile;
|
||||
protected IDocument document;
|
||||
/**
|
||||
* IndexerOutput constructor comment.
|
||||
*/
|
||||
public IndexerOutput(InMemoryIndex index) {
|
||||
this.index= index;
|
||||
}
|
||||
/**
|
||||
* Adds the given document to the inMemoryIndex.
|
||||
*/
|
||||
public void addDocument(IDocument document) {
|
||||
if (indexedFile == null) {
|
||||
indexedFile= index.addDocument(document);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Adds a reference to the given word to the inMemoryIndex.
|
||||
*/
|
||||
public void addRef(char[] word) {
|
||||
if (indexedFile == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
index.addRef(indexedFile, word);
|
||||
}
|
||||
/**
|
||||
* Adds a reference to the given word to the inMemoryIndex.
|
||||
*/
|
||||
public void addRef(String word) {
|
||||
addRef(word.toCharArray());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
public class Int {
|
||||
public int value;
|
||||
/**
|
||||
* Int constructor comment.
|
||||
*/
|
||||
public Int(int i) {
|
||||
value= i;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A mergeFactory is used to merge 2 indexes into one. One of the indexes
|
||||
* (oldIndex) is on the disk and the other(addsIndex) is in memory.
|
||||
* The merge respects the following rules: <br>
|
||||
* - The files are sorted in alphabetical order;<br>
|
||||
* - if a file is in oldIndex and addsIndex, the one which is added
|
||||
* is the one in the addsIndex.<br>
|
||||
*/
|
||||
public class MergeFactory {
|
||||
/**
|
||||
* Input on the addsIndex.
|
||||
*/
|
||||
protected IndexInput addsInput;
|
||||
/**
|
||||
* Input on the oldIndex.
|
||||
*/
|
||||
protected IndexInput oldInput;
|
||||
/**
|
||||
* Output to write the result of the merge in.
|
||||
*/
|
||||
protected BlocksIndexOutput mergeOutput;
|
||||
/**
|
||||
* Files removed from oldIndex.
|
||||
*/
|
||||
protected Map removedInOld;
|
||||
/**
|
||||
* Files removed from addsIndex.
|
||||
*/
|
||||
protected Map removedInAdds;
|
||||
protected int[] mappingOld;
|
||||
protected int[] mappingAdds;
|
||||
public static final int ADDS_INDEX= 0;
|
||||
public static final int OLD_INDEX= 1;
|
||||
/**
|
||||
* MergeFactory constructor comment.
|
||||
* @param directory java.io.File
|
||||
*/
|
||||
public MergeFactory(IndexInput oldIndexInput, IndexInput addsIndexInput, BlocksIndexOutput mergeIndexOutput, Map removedInOld, Map removedInAdds) {
|
||||
oldInput= oldIndexInput;
|
||||
addsInput= addsIndexInput;
|
||||
mergeOutput= mergeIndexOutput;
|
||||
this.removedInOld= removedInOld;
|
||||
this.removedInAdds= removedInAdds;
|
||||
}
|
||||
/**
|
||||
* Initialise the merge.
|
||||
*/
|
||||
protected void init() {
|
||||
mappingOld= new int[oldInput.getNumFiles() + 1];
|
||||
mappingAdds= new int[addsInput.getNumFiles() + 1];
|
||||
|
||||
}
|
||||
/**
|
||||
* Merges the 2 indexes into a new one on the disk.
|
||||
*/
|
||||
public void merge() throws IOException {
|
||||
try {
|
||||
//init
|
||||
addsInput.open();
|
||||
oldInput.open();
|
||||
mergeOutput.open();
|
||||
init();
|
||||
//merge
|
||||
//findChanges();
|
||||
mergeFiles();
|
||||
mergeReferences();
|
||||
mergeOutput.flush();
|
||||
} finally {
|
||||
//closes everything
|
||||
oldInput.close();
|
||||
addsInput.close();
|
||||
mergeOutput.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Merges the files of the 2 indexes in the new index, removes the files
|
||||
* to be removed, and records the changes made to propagate them to the
|
||||
* word references.
|
||||
*/
|
||||
|
||||
protected void mergeFiles() throws IOException {
|
||||
int positionInMerge= 1;
|
||||
int compare;
|
||||
while (oldInput.hasMoreFiles() || addsInput.hasMoreFiles()) {
|
||||
IndexedFile file1= oldInput.getCurrentFile();
|
||||
IndexedFile file2= addsInput.getCurrentFile();
|
||||
|
||||
//if the file has been removed we don't take it into account
|
||||
while (file1 != null && wasRemoved(file1, OLD_INDEX)) {
|
||||
oldInput.moveToNextFile();
|
||||
file1= oldInput.getCurrentFile();
|
||||
}
|
||||
while (file2 != null && wasRemoved(file2, ADDS_INDEX)) {
|
||||
addsInput.moveToNextFile();
|
||||
file2= addsInput.getCurrentFile();
|
||||
}
|
||||
|
||||
//the addsIndex was empty, we just removed files from the oldIndex
|
||||
if (file1 == null && file2 == null)
|
||||
break;
|
||||
|
||||
//test if we reached the end of one the 2 index
|
||||
if (file1 == null)
|
||||
compare= 1;
|
||||
else if (file2 == null)
|
||||
compare= -1;
|
||||
else
|
||||
compare= file1.getPath().compareTo(file2.getPath());
|
||||
|
||||
//records the changes to Make
|
||||
if (compare == 0) {
|
||||
//the file has been modified:
|
||||
//we remove it from the oldIndex and add it to the addsIndex
|
||||
removeFile(file1, OLD_INDEX);
|
||||
mappingAdds[file2.getFileNumber()]= positionInMerge;
|
||||
file1.setFileNumber(positionInMerge);
|
||||
mergeOutput.addFile(file1);
|
||||
oldInput.moveToNextFile();
|
||||
addsInput.moveToNextFile();
|
||||
} else if (compare < 0) {
|
||||
mappingOld[file1.getFileNumber()]= positionInMerge;
|
||||
file1.setFileNumber(positionInMerge);
|
||||
mergeOutput.addFile(file1);
|
||||
oldInput.moveToNextFile();
|
||||
} else {
|
||||
mappingAdds[file2.getFileNumber()]= positionInMerge;
|
||||
file2.setFileNumber(positionInMerge);
|
||||
mergeOutput.addFile(file2);
|
||||
addsInput.moveToNextFile();
|
||||
}
|
||||
positionInMerge++;
|
||||
}
|
||||
mergeOutput.flushFiles();
|
||||
}
|
||||
/**
|
||||
* Merges the files of the 2 indexes in the new index, according to the changes
|
||||
* recorded during mergeFiles().
|
||||
*/
|
||||
protected void mergeReferences() throws IOException {
|
||||
int compare;
|
||||
while (oldInput.hasMoreWords() || addsInput.hasMoreWords()) {
|
||||
WordEntry word1= oldInput.getCurrentWordEntry();
|
||||
WordEntry word2= addsInput.getCurrentWordEntry();
|
||||
|
||||
if (word1 == null && word2 == null)
|
||||
break;
|
||||
|
||||
if (word1 == null)
|
||||
compare= 1;
|
||||
else if (word2 == null)
|
||||
compare= -1;
|
||||
else
|
||||
compare= Util.compare(word1.getWord(), word2.getWord());
|
||||
if (compare < 0) {
|
||||
word1.mapRefs(mappingOld);
|
||||
mergeOutput.addWord(word1);
|
||||
oldInput.moveToNextWordEntry();
|
||||
} else if (compare > 0) {
|
||||
word2.mapRefs(mappingAdds);
|
||||
mergeOutput.addWord(word2);
|
||||
addsInput.moveToNextWordEntry();
|
||||
} else {
|
||||
word1.mapRefs(mappingOld);
|
||||
word2.mapRefs(mappingAdds);
|
||||
word1.addRefs(word2.getRefs());
|
||||
mergeOutput.addWord(word1);
|
||||
addsInput.moveToNextWordEntry();
|
||||
oldInput.moveToNextWordEntry();
|
||||
}
|
||||
}
|
||||
mergeOutput.flushWords();
|
||||
}
|
||||
/**
|
||||
* Records the deletion of one file.
|
||||
*/
|
||||
protected void removeFile(IndexedFile file, int index) {
|
||||
if (index == OLD_INDEX)
|
||||
mappingOld[file.getFileNumber()]= -1;
|
||||
else
|
||||
mappingAdds[file.getFileNumber()]= -1;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given file has to be removed from the given index
|
||||
* (ADDS_INDEX or OLD_INDEX). If it has to be removed, the mergeFactory
|
||||
* deletes it and records the changes.
|
||||
*/
|
||||
|
||||
protected boolean wasRemoved(IndexedFile indexedFile, int index) {
|
||||
String path= indexedFile.getPath();
|
||||
if (index == OLD_INDEX) {
|
||||
if (removedInOld.remove(path) != null) {
|
||||
mappingOld[indexedFile.getFileNumber()]= -1;
|
||||
return true;
|
||||
}
|
||||
} else if (index == ADDS_INDEX) {
|
||||
Int lastRemoved= (Int) removedInAdds.get(path);
|
||||
if (lastRemoved != null) {
|
||||
int fileNum= indexedFile.getFileNumber();
|
||||
if (lastRemoved.value >= fileNum) {
|
||||
mappingAdds[fileNum]= -1;
|
||||
//if (lastRemoved.value == fileNum) // ONLY if files in sorted order for names AND fileNums
|
||||
//removedInAdds.remove(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
/**
|
||||
* The properties of a document are stored into a hashtable.
|
||||
* @see IDocument
|
||||
*/
|
||||
|
||||
public abstract class PropertyDocument implements IDocument {
|
||||
protected Hashtable properties;
|
||||
public PropertyDocument() {
|
||||
properties= new Hashtable(5);
|
||||
}
|
||||
/**
|
||||
* @see IDocument#getProperty
|
||||
*/
|
||||
public String getProperty(String property) {
|
||||
return (String) properties.get(property);
|
||||
}
|
||||
/**
|
||||
* @see IDocument#getPropertyNames
|
||||
*/
|
||||
|
||||
public Enumeration getPropertyNames() {
|
||||
return properties.keys();
|
||||
}
|
||||
/**
|
||||
* @see IDocument#setProperty
|
||||
*/
|
||||
|
||||
public void setProperty(String property, String value) {
|
||||
properties.put(property, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* A safe subclass of RandomAccessFile, which ensure that it's closed
|
||||
* on finalize.
|
||||
*/
|
||||
public class SafeRandomAccessFile extends RandomAccessFile {
|
||||
public SafeRandomAccessFile(java.io.File file, String mode) throws java.io.IOException {
|
||||
super(file, mode);
|
||||
}
|
||||
public SafeRandomAccessFile(String name, String mode) throws java.io.IOException {
|
||||
super(name, mode);
|
||||
}
|
||||
protected void finalize() throws IOException {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
|
||||
/**
|
||||
* A simpleIndexInput is an input on an in memory Index.
|
||||
*/
|
||||
|
||||
public class SimpleIndexInput extends IndexInput {
|
||||
protected WordEntry[] sortedWordEntries;
|
||||
protected IndexedFile currentFile;
|
||||
protected IndexedFile[] sortedFiles;
|
||||
protected InMemoryIndex index;
|
||||
|
||||
public SimpleIndexInput(InMemoryIndex index) {
|
||||
super();
|
||||
this.index= index;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#clearCache()
|
||||
*/
|
||||
public void clearCache() {
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
sortedFiles= null;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getCurrentFile()
|
||||
*/
|
||||
public IndexedFile getCurrentFile() throws IOException {
|
||||
if (!hasMoreFiles())
|
||||
return null;
|
||||
return currentFile;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getIndexedFile(int)
|
||||
*/
|
||||
public IndexedFile getIndexedFile(int fileNum) throws IOException {
|
||||
for (int i= 0; i < sortedFiles.length; i++)
|
||||
if (sortedFiles[i].getFileNumber() == fileNum)
|
||||
return sortedFiles[i];
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getIndexedFile(IDocument)
|
||||
*/
|
||||
public IndexedFile getIndexedFile(IDocument document) throws IOException {
|
||||
String name= document.getName();
|
||||
for (int i= index.getNumFiles(); i >= 1; i--) {
|
||||
IndexedFile file= getIndexedFile(i);
|
||||
if (name.equals(file.getPath()))
|
||||
return file;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getNumFiles()
|
||||
*/
|
||||
public int getNumFiles() {
|
||||
return index.getNumFiles();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getNumWords()
|
||||
*/
|
||||
public int getNumWords() {
|
||||
return sortedWordEntries.length;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#getSource()
|
||||
*/
|
||||
public Object getSource() {
|
||||
return index;
|
||||
}
|
||||
public void init() {
|
||||
index.init();
|
||||
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#moveToNextFile()
|
||||
*/
|
||||
public void moveToNextFile() throws IOException {
|
||||
filePosition++;
|
||||
if (!hasMoreFiles()) {
|
||||
return;
|
||||
}
|
||||
currentFile= sortedFiles[filePosition - 1];
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#moveToNextWordEntry()
|
||||
*/
|
||||
public void moveToNextWordEntry() throws IOException {
|
||||
wordPosition++;
|
||||
if (hasMoreWords())
|
||||
currentWordEntry= sortedWordEntries[wordPosition - 1];
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#open()
|
||||
*/
|
||||
public void open() throws IOException {
|
||||
sortedWordEntries= index.getSortedWordEntries();
|
||||
sortedFiles= index.getSortedFiles();
|
||||
filePosition= 1;
|
||||
wordPosition= 1;
|
||||
setFirstFile();
|
||||
setFirstWord();
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#query(String)
|
||||
*/
|
||||
public IQueryResult[] query(String word) throws IOException {
|
||||
char[] wordChar= word.toCharArray();
|
||||
WordEntry wordEntry= index.getWordEntry(wordChar);
|
||||
int[] fileNums= wordEntry.getRefs();
|
||||
IQueryResult[] files= new IQueryResult[fileNums.length];
|
||||
for (int i= 0; i < files.length; i++)
|
||||
files[i]= getIndexedFile(fileNums[i]);
|
||||
return files;
|
||||
}
|
||||
public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
|
||||
return null;
|
||||
}
|
||||
public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#queryInDocumentNames(String)
|
||||
*/
|
||||
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||
setFirstFile();
|
||||
ArrayList matches= new ArrayList();
|
||||
while (hasMoreFiles()) {
|
||||
IndexedFile file= getCurrentFile();
|
||||
if (file.getPath().indexOf(word) != -1)
|
||||
matches.add(file.getPath());
|
||||
moveToNextFile();
|
||||
}
|
||||
IQueryResult[] match= new IQueryResult[matches.size()];
|
||||
matches.toArray(match);
|
||||
return match;
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#setFirstFile()
|
||||
*/
|
||||
protected void setFirstFile() throws IOException {
|
||||
filePosition= 1;
|
||||
if (sortedFiles.length > 0) {
|
||||
currentFile= sortedFiles[0];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see IndexInput#setFirstWord()
|
||||
*/
|
||||
protected void setFirstWord() throws IOException {
|
||||
wordPosition= 1;
|
||||
if (sortedWordEntries.length > 0)
|
||||
currentWordEntry= sortedWordEntries[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UTFDataFormatException;
|
||||
|
||||
public class Util {
|
||||
|
||||
private Util() {
|
||||
}
|
||||
/**
|
||||
* Compares two strings lexicographically.
|
||||
* The comparison is based on the Unicode value of each character in
|
||||
* the strings.
|
||||
*
|
||||
* @return the value <code>0</code> if the str1 is equal to str2;
|
||||
* a value less than <code>0</code> if str1
|
||||
* is lexicographically less than str2;
|
||||
* and a value greater than <code>0</code> if str1 is
|
||||
* lexicographically greater than str2.
|
||||
*/
|
||||
public static int compare(char[] str1, char[] str2) {
|
||||
int len1= str1.length;
|
||||
int len2= str2.length;
|
||||
int n= Math.min(len1, len2);
|
||||
int i= 0;
|
||||
while (n-- != 0) {
|
||||
char c1= str1[i];
|
||||
char c2= str2[i++];
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the common prefix between s1 and s2.
|
||||
*/
|
||||
public static int prefixLength(char[] s1, char[] s2) {
|
||||
int len= 0;
|
||||
int max= Math.min(s1.length, s2.length);
|
||||
for (int i= 0; i < max && s1[i] == s2[i]; ++i)
|
||||
++len;
|
||||
return len;
|
||||
}
|
||||
/**
|
||||
* Returns the length of the common prefix between s1 and s2.
|
||||
*/
|
||||
public static int prefixLength(String s1, String s2) {
|
||||
int len= 0;
|
||||
int max= Math.min(s1.length(), s2.length());
|
||||
for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
|
||||
++len;
|
||||
return len;
|
||||
}
|
||||
private static void quickSort(char[][] list, int left, int right) {
|
||||
int original_left= left;
|
||||
int original_right= right;
|
||||
char[] mid= list[(left + right) / 2];
|
||||
do {
|
||||
while (compare(list[left], mid) < 0) {
|
||||
left++;
|
||||
}
|
||||
while (compare(mid, list[right]) < 0) {
|
||||
right--;
|
||||
}
|
||||
if (left <= right) {
|
||||
char[] tmp= list[left];
|
||||
list[left]= list[right];
|
||||
list[right]= tmp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
} while (left <= right);
|
||||
if (original_left < right) {
|
||||
quickSort(list, original_left, right);
|
||||
}
|
||||
if (left < original_right) {
|
||||
quickSort(list, left, original_right);
|
||||
}
|
||||
}
|
||||
private static void quickSort(int[] list, int left, int right) {
|
||||
int original_left= left;
|
||||
int original_right= right;
|
||||
int mid= list[(left + right) / 2];
|
||||
do {
|
||||
while (list[left] < mid) {
|
||||
left++;
|
||||
}
|
||||
while (mid < list[right]) {
|
||||
right--;
|
||||
}
|
||||
if (left <= right) {
|
||||
int tmp= list[left];
|
||||
list[left]= list[right];
|
||||
list[right]= tmp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
} while (left <= right);
|
||||
if (original_left < right) {
|
||||
quickSort(list, original_left, right);
|
||||
}
|
||||
if (left < original_right) {
|
||||
quickSort(list, left, original_right);
|
||||
}
|
||||
}
|
||||
private static void quickSort(String[] list, int left, int right) {
|
||||
int original_left= left;
|
||||
int original_right= right;
|
||||
String mid= list[(left + right) / 2];
|
||||
do {
|
||||
while (list[left].compareTo(mid) < 0) {
|
||||
left++;
|
||||
}
|
||||
while (mid.compareTo(list[right]) < 0) {
|
||||
right--;
|
||||
}
|
||||
if (left <= right) {
|
||||
String tmp= list[left];
|
||||
list[left]= list[right];
|
||||
list[right]= tmp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
} while (left <= right);
|
||||
if (original_left < right) {
|
||||
quickSort(list, original_left, right);
|
||||
}
|
||||
if (left < original_right) {
|
||||
quickSort(list, left, original_right);
|
||||
}
|
||||
}
|
||||
private static void quickSort(IndexedFile[] list, int left, int right) {
|
||||
int original_left= left;
|
||||
int original_right= right;
|
||||
String mid= list[(left + right) / 2].path;
|
||||
do {
|
||||
while (list[left].path.compareTo(mid) < 0) {
|
||||
left++;
|
||||
}
|
||||
while (mid.compareTo(list[right].path) < 0) {
|
||||
right--;
|
||||
}
|
||||
if (left <= right) {
|
||||
IndexedFile tmp= list[left];
|
||||
list[left]= list[right];
|
||||
list[right]= tmp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
} while (left <= right);
|
||||
if (original_left < right) {
|
||||
quickSort(list, original_left, right);
|
||||
}
|
||||
if (left < original_right) {
|
||||
quickSort(list, left, original_right);
|
||||
}
|
||||
}
|
||||
private static void quickSort(WordEntry[] list, int left, int right) {
|
||||
int original_left= left;
|
||||
int original_right= right;
|
||||
char[] mid= list[(left + right) / 2].fWord;
|
||||
do {
|
||||
while (compare(list[left].fWord, mid) < 0) {
|
||||
left++;
|
||||
}
|
||||
while (compare(mid, list[right].fWord) < 0) {
|
||||
right--;
|
||||
}
|
||||
if (left <= right) {
|
||||
WordEntry tmp= list[left];
|
||||
list[left]= list[right];
|
||||
list[right]= tmp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
} while (left <= right);
|
||||
if (original_left < right) {
|
||||
quickSort(list, original_left, right);
|
||||
}
|
||||
if (left < original_right) {
|
||||
quickSort(list, left, original_right);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reads in a string from the specified data input stream. The
|
||||
* string has been encoded using a modified UTF-8 format.
|
||||
* <p>
|
||||
* The first two bytes are read as if by
|
||||
* <code>readUnsignedShort</code>. This value gives the number of
|
||||
* following bytes that are in the encoded string, not
|
||||
* the length of the resulting string. The following bytes are then
|
||||
* interpreted as bytes encoding characters in the UTF-8 format
|
||||
* and are converted into characters.
|
||||
* <p>
|
||||
* This method blocks until all the bytes are read, the end of the
|
||||
* stream is detected, or an exception is thrown.
|
||||
*
|
||||
* @param in a data input stream.
|
||||
* @return a Unicode string.
|
||||
* @exception EOFException if the input stream reaches the end
|
||||
* before all the bytes.
|
||||
* @exception IOException if an I/O error occurs.
|
||||
* @exception UTFDataFormatException if the bytes do not represent a
|
||||
* valid UTF-8 encoding of a Unicode string.
|
||||
* @see java.io.DataInputStream#readUnsignedShort()
|
||||
*/
|
||||
public final static char[] readUTF(DataInput in) throws IOException {
|
||||
int utflen= in.readUnsignedShort();
|
||||
char str[]= new char[utflen];
|
||||
int count= 0;
|
||||
int strlen= 0;
|
||||
while (count < utflen) {
|
||||
int c= in.readUnsignedByte();
|
||||
int char2, char3;
|
||||
switch (c >> 4) {
|
||||
case 0 :
|
||||
case 1 :
|
||||
case 2 :
|
||||
case 3 :
|
||||
case 4 :
|
||||
case 5 :
|
||||
case 6 :
|
||||
case 7 :
|
||||
// 0xxxxxxx
|
||||
count++;
|
||||
str[strlen++]= (char) c;
|
||||
break;
|
||||
case 12 :
|
||||
case 13 :
|
||||
// 110x xxxx 10xx xxxx
|
||||
count += 2;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= in.readUnsignedByte();
|
||||
if ((char2 & 0xC0) != 0x80)
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14 :
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
count += 3;
|
||||
if (count > utflen)
|
||||
throw new UTFDataFormatException();
|
||||
char2= in.readUnsignedByte();
|
||||
char3= in.readUnsignedByte();
|
||||
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||
throw new UTFDataFormatException();
|
||||
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||
break;
|
||||
default :
|
||||
// 10xx xxxx, 1111 xxxx
|
||||
throw new UTFDataFormatException();
|
||||
}
|
||||
}
|
||||
if (strlen < utflen) {
|
||||
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
public static void sort(char[][] list) {
|
||||
if (list.length > 1)
|
||||
quickSort(list, 0, list.length - 1);
|
||||
}
|
||||
public static void sort(int[] list) {
|
||||
if (list.length > 1)
|
||||
quickSort(list, 0, list.length - 1);
|
||||
}
|
||||
public static void sort(String[] list) {
|
||||
if (list.length > 1)
|
||||
quickSort(list, 0, list.length - 1);
|
||||
}
|
||||
public static void sort(IndexedFile[] list) {
|
||||
if (list.length > 1)
|
||||
quickSort(list, 0, list.length - 1);
|
||||
}
|
||||
public static void sort(WordEntry[] list) {
|
||||
if (list.length > 1)
|
||||
quickSort(list, 0, list.length - 1);
|
||||
}
|
||||
/**
|
||||
* Writes a string to the given output stream using UTF-8
|
||||
* encoding in a machine-independent manner.
|
||||
* <p>
|
||||
* First, two bytes are written to the output stream as if by the
|
||||
* <code>writeShort</code> method giving the number of bytes to
|
||||
* follow. This value is the number of bytes actually written out,
|
||||
* not the length of the string. Following the length, each character
|
||||
* of the string is output, in sequence, using the UTF-8 encoding
|
||||
* for the character.
|
||||
*
|
||||
* @param str a string to be written.
|
||||
* @exception IOException if an I/O error occurs.
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public static void writeUTF(OutputStream out, char[] str) throws IOException {
|
||||
int strlen= str.length;
|
||||
int utflen= 0;
|
||||
for (int i= 0; i < strlen; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
if (utflen > 65535)
|
||||
throw new UTFDataFormatException();
|
||||
out.write((utflen >>> 8) & 0xFF);
|
||||
out.write((utflen >>> 0) & 0xFF);
|
||||
for (int i= 0; i < strlen; i++) {
|
||||
int c= str[i];
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
out.write(c);
|
||||
} else if (c > 0x07FF) {
|
||||
out.write(0xE0 | ((c >> 12) & 0x0F));
|
||||
out.write(0x80 | ((c >> 6) & 0x3F));
|
||||
out.write(0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
out.write(0xC0 | ((c >> 6) & 0x1F));
|
||||
out.write(0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
public class WordEntry {
|
||||
protected char[] fWord;
|
||||
protected int fNumRefs;
|
||||
protected int[] fRefs;
|
||||
public WordEntry() {
|
||||
this(CharOperation.NO_CHAR);
|
||||
}
|
||||
public WordEntry(char[] word) {
|
||||
fWord= word;
|
||||
fNumRefs= 0;
|
||||
fRefs= new int[1];
|
||||
}
|
||||
/**
|
||||
* Adds a reference and records the change in footprint.
|
||||
*/
|
||||
public int addRef(int fileNum) {
|
||||
if (fNumRefs > 0 && fRefs[fNumRefs - 1] == fileNum) {
|
||||
return 0;
|
||||
}
|
||||
if (fNumRefs < fRefs.length) {
|
||||
fRefs[fNumRefs++]= fileNum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For rt.jar, 73265 word entries are created. 51997 have 1 ref, then 9438, 3738, 1980, 1214, 779, 547, 429, 371 etc.
|
||||
int newSize= fNumRefs < 4 ? 4 : fNumRefs * 2; // so will start @ 1, grow to 4, 8, 16, 32, 64 etc.
|
||||
System.arraycopy(fRefs, 0, fRefs= new int[newSize], 0, fNumRefs);
|
||||
fRefs[fNumRefs++]= fileNum;
|
||||
return (newSize - fNumRefs + 1) * 4;
|
||||
}
|
||||
/**
|
||||
* Adds a set of references and records the change in footprint.
|
||||
*/
|
||||
public void addRefs(int[] refs) {
|
||||
int[] newRefs= new int[fNumRefs + refs.length];
|
||||
int pos1= 0;
|
||||
int pos2= 0;
|
||||
int posNew= 0;
|
||||
int compare;
|
||||
int r1= 0;
|
||||
int r2= 0;
|
||||
while (pos1 < fNumRefs || pos2 < refs.length) {
|
||||
if (pos1 >= fNumRefs) {
|
||||
r2= refs[pos2];
|
||||
compare= -1;
|
||||
} else if (pos2 >= refs.length) {
|
||||
compare= 1;
|
||||
r1= fRefs[pos1];
|
||||
} else {
|
||||
r1= fRefs[pos1];
|
||||
r2= refs[pos2];
|
||||
compare= r2 - r1;
|
||||
}
|
||||
if (compare > 0) {
|
||||
newRefs[posNew]= r1;
|
||||
posNew++;
|
||||
pos1++;
|
||||
} else {
|
||||
if (r2 != 0) {
|
||||
newRefs[posNew]= r2;
|
||||
posNew++;
|
||||
}
|
||||
pos2++;
|
||||
}
|
||||
}
|
||||
fRefs= newRefs;
|
||||
fNumRefs= posNew;
|
||||
/*for (int i = 0; i < refs.length; i++)
|
||||
addRef(refs[i]);
|
||||
int[] newRefs = new int[fNumRefs];
|
||||
System.arraycopy(fRefs, 0, newRefs, 0, fNumRefs);
|
||||
fRefs = newRefs;
|
||||
Util.sort(fRefs);*/
|
||||
}
|
||||
/**
|
||||
* Returns the size of the wordEntry
|
||||
*/
|
||||
public int footprint() {
|
||||
return 8 + (3 * 4) + (8 + fWord.length * 2) + (8 + fRefs.length * 4);
|
||||
}
|
||||
/**
|
||||
* Returns the number of references, e.g. the number of files this word appears in.
|
||||
*/
|
||||
public int getNumRefs() {
|
||||
return fNumRefs;
|
||||
}
|
||||
/**
|
||||
* returns the file number in the i position in the list of references.
|
||||
*/
|
||||
public int getRef(int i) {
|
||||
if (i < fNumRefs) return fRefs[i];
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
/**
|
||||
* Returns the references of the wordEntry (the number of the files it appears in).
|
||||
*/
|
||||
public int[] getRefs() {
|
||||
int[] result= new int[fNumRefs];
|
||||
System.arraycopy(fRefs, 0, result, 0, fNumRefs);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* returns the word of the wordEntry.
|
||||
*/
|
||||
public char[] getWord() {
|
||||
return fWord;
|
||||
}
|
||||
/**
|
||||
* Changes the references of the wordEntry to match the mapping. For example,<br>
|
||||
* if the current references are [1 3 4]<br>
|
||||
* and mapping is [1 2 3 4 5]<br>
|
||||
* in references 1 becomes mapping[1] = 2, 3->4, and 4->5<br>
|
||||
* => references = [2 4 5].<br>
|
||||
*/
|
||||
public void mapRefs(int[] mappings) {
|
||||
int position= 0;
|
||||
for (int i= 0; i < fNumRefs; i++) {
|
||||
int map= mappings[fRefs[i]];
|
||||
if (map != -1 && map != 0)
|
||||
fRefs[position++]= map;
|
||||
}
|
||||
fNumRefs= position;
|
||||
|
||||
//to be changed!
|
||||
System.arraycopy(fRefs, 0, (fRefs= new int[fNumRefs]), 0, fNumRefs);
|
||||
Util.sort(fRefs);
|
||||
}
|
||||
/**
|
||||
* Clears the wordEntry.
|
||||
*/
|
||||
public void reset(char[] word) {
|
||||
for (int i= fNumRefs; i-- > 0;) {
|
||||
fRefs[i]= 0;
|
||||
}
|
||||
fNumRefs= 0;
|
||||
fWord= word;
|
||||
}
|
||||
public String toString() {
|
||||
return new String(fWord);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.index.impl;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
public final class WordEntryHashedArray {
|
||||
|
||||
// to avoid using Enumerations, walk the objects skipping nulls
|
||||
public WordEntry elements[];
|
||||
public int elementSize; // number of elements in the table
|
||||
public int threshold;
|
||||
|
||||
public WordEntryHashedArray(int size) {
|
||||
if (size < 7) size = 7;
|
||||
this.elements = new WordEntry[2 * size + 1];
|
||||
this.elementSize = 0;
|
||||
this.threshold = size + 1; // size is the expected number of elements
|
||||
}
|
||||
|
||||
public WordEntry add(WordEntry entry) {
|
||||
int length = elements.length;
|
||||
char[] word = entry.getWord();
|
||||
int index = CharOperation.hashCode(word) % length;
|
||||
WordEntry current;
|
||||
while ((current = elements[index]) != null) {
|
||||
if (CharOperation.equals(current.getWord(), word)) return elements[index] = entry;
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
elements[index] = entry;
|
||||
|
||||
// assumes the threshold is never equal to the size of the table
|
||||
if (++elementSize > threshold) grow();
|
||||
return entry;
|
||||
}
|
||||
|
||||
public WordEntry[] asArray() {
|
||||
WordEntry[] array = new WordEntry[elementSize];
|
||||
for (int i = 0, j = 0, length = elements.length; i < length; i++) {
|
||||
WordEntry current = elements[i];
|
||||
if (current != null) array[j++] = current;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public WordEntry get(char[] word) {
|
||||
int length = elements.length;
|
||||
int index = CharOperation.hashCode(word) % length;
|
||||
WordEntry current;
|
||||
while ((current = elements[index]) != null) {
|
||||
if (CharOperation.equals(current.getWord(), word)) return current;
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
WordEntryHashedArray newArray = new WordEntryHashedArray(elementSize * 2); // double the number of expected elements
|
||||
for (int i = 0, length = elements.length; i < length; i++)
|
||||
if (elements[i] != null)
|
||||
newArray.add(elements[i]);
|
||||
|
||||
this.elements = newArray.elements;
|
||||
this.elementSize = newArray.elementSize;
|
||||
this.threshold = newArray.threshold;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = ""; //$NON-NLS-1$
|
||||
WordEntry[] entries = asArray();
|
||||
for (int i = 0, length = entries.length; i < length; i++)
|
||||
s += entries[i].toString() + "\n"; //$NON-NLS-1$
|
||||
return s;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,93 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search;
|
||||
|
||||
/**
|
||||
* Hashtable for non-zero int keys.
|
||||
*/
|
||||
|
||||
public final class HashtableOfInt {
|
||||
// to avoid using Enumerations, walk the individual tables skipping nulls
|
||||
public int[] keyTable;
|
||||
public Object[] valueTable;
|
||||
|
||||
int elementSize; // number of elements in the table
|
||||
int threshold;
|
||||
public HashtableOfInt() {
|
||||
this(13);
|
||||
}
|
||||
public HashtableOfInt(int size) {
|
||||
this.elementSize = 0;
|
||||
this.threshold = size; // size represents the expected number of elements
|
||||
int extraRoom = (int) (size * 1.75f);
|
||||
if (this.threshold == extraRoom)
|
||||
extraRoom++;
|
||||
this.keyTable = new int[extraRoom];
|
||||
this.valueTable = new Object[extraRoom];
|
||||
}
|
||||
public boolean containsKey(int key) {
|
||||
int index = key % valueTable.length;
|
||||
int currentKey;
|
||||
while ((currentKey = keyTable[index]) != 0) {
|
||||
if (currentKey == key)
|
||||
return true;
|
||||
index = (index + 1) % keyTable.length;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public Object get(int key) {
|
||||
int index = key % valueTable.length;
|
||||
int currentKey;
|
||||
while ((currentKey = keyTable[index]) != 0) {
|
||||
if (currentKey == key) return valueTable[index];
|
||||
index = (index + 1) % keyTable.length;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Object put(int key, Object value) {
|
||||
int index = key % valueTable.length;
|
||||
int currentKey;
|
||||
while ((currentKey = keyTable[index]) != 0) {
|
||||
if (currentKey == key) return valueTable[index] = value;
|
||||
index = (index + 1) % keyTable.length;
|
||||
}
|
||||
keyTable[index] = key;
|
||||
valueTable[index] = value;
|
||||
|
||||
// assumes the threshold is never equal to the size of the table
|
||||
if (++elementSize > threshold)
|
||||
rehash();
|
||||
return value;
|
||||
}
|
||||
private void rehash() {
|
||||
HashtableOfInt newHashtable = new HashtableOfInt(elementSize * 2); // double the number of expected elements
|
||||
int currentKey;
|
||||
for (int i = keyTable.length; --i >= 0;)
|
||||
if ((currentKey = keyTable[i]) != 0)
|
||||
newHashtable.put(currentKey, valueTable[i]);
|
||||
|
||||
this.keyTable = newHashtable.keyTable;
|
||||
this.valueTable = newHashtable.valueTable;
|
||||
this.threshold = newHashtable.threshold;
|
||||
}
|
||||
public int size() {
|
||||
return elementSize;
|
||||
}
|
||||
public String toString() {
|
||||
String s = ""; //$NON-NLS-1$
|
||||
Object object;
|
||||
for (int i = 0, length = valueTable.length; i < length; i++)
|
||||
if ((object = valueTable[i]) != null)
|
||||
s += keyTable[i] + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search;
|
||||
|
||||
/**
|
||||
* A simple lookup table is a non-synchronized Hashtable, whose keys
|
||||
* and values are Objects. It also uses linear probing to resolve collisions
|
||||
* rather than a linked list of hash table entries.
|
||||
*/
|
||||
public final class SimpleLookupTable implements Cloneable {
|
||||
|
||||
// to avoid using Enumerations, walk the individual tables skipping nulls
|
||||
public Object[] keyTable;
|
||||
public Object[] valueTable;
|
||||
public int elementSize; // number of elements in the table
|
||||
public int threshold;
|
||||
|
||||
public SimpleLookupTable() {
|
||||
this(13);
|
||||
}
|
||||
|
||||
public SimpleLookupTable(int size) {
|
||||
if (size < 3) size = 3;
|
||||
this.elementSize = 0;
|
||||
this.threshold = size + 1; // size is the expected number of elements
|
||||
int tableLength = 2 * size + 1;
|
||||
this.keyTable = new Object[tableLength];
|
||||
this.valueTable = new Object[tableLength];
|
||||
}
|
||||
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
SimpleLookupTable result = (SimpleLookupTable) super.clone();
|
||||
result.elementSize = this.elementSize;
|
||||
result.threshold = this.threshold;
|
||||
|
||||
int length = this.keyTable.length;
|
||||
result.keyTable = new Object[length];
|
||||
System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
|
||||
|
||||
length = this.valueTable.length;
|
||||
result.valueTable = new Object[length];
|
||||
System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
int length = keyTable.length;
|
||||
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||
Object currentKey;
|
||||
while ((currentKey = keyTable[index]) != null) {
|
||||
if (currentKey.equals(key)) return true;
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
int length = keyTable.length;
|
||||
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||
Object currentKey;
|
||||
while ((currentKey = keyTable[index]) != null) {
|
||||
if (currentKey.equals(key)) return valueTable[index];
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object keyForValue(Object valueToMatch) {
|
||||
if (valueToMatch != null)
|
||||
for (int i = 0, l = valueTable.length; i < l; i++)
|
||||
if (valueToMatch.equals(valueTable[i]))
|
||||
return keyTable[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
int length = keyTable.length;
|
||||
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||
Object currentKey;
|
||||
while ((currentKey = keyTable[index]) != null) {
|
||||
if (currentKey.equals(key)) return valueTable[index] = value;
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
keyTable[index] = key;
|
||||
valueTable[index] = value;
|
||||
|
||||
// assumes the threshold is never equal to the size of the table
|
||||
if (++elementSize > threshold) rehash();
|
||||
return value;
|
||||
}
|
||||
|
||||
public void removeKey(Object key) {
|
||||
int length = keyTable.length;
|
||||
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||
Object currentKey;
|
||||
while ((currentKey = keyTable[index]) != null) {
|
||||
if (currentKey.equals(key)) {
|
||||
elementSize--;
|
||||
keyTable[index] = null;
|
||||
valueTable[index] = null;
|
||||
if (keyTable[index + 1 == length ? 0 : index + 1] != null)
|
||||
rehash(); // only needed if a possible collision existed
|
||||
return;
|
||||
}
|
||||
if (++index == length) index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeValue(Object valueToRemove) {
|
||||
boolean rehash = false;
|
||||
for (int i = 0, l = valueTable.length; i < l; i++) {
|
||||
Object value = valueTable[i];
|
||||
if (value != null && value.equals(valueToRemove)) {
|
||||
elementSize--;
|
||||
keyTable[i] = null;
|
||||
valueTable[i] = null;
|
||||
if (!rehash && keyTable[i + 1 == l ? 0 : i + 1] != null)
|
||||
rehash = true; // only needed if a possible collision existed
|
||||
}
|
||||
}
|
||||
if (rehash) rehash();
|
||||
}
|
||||
|
||||
private void rehash() {
|
||||
SimpleLookupTable newLookupTable = new SimpleLookupTable(elementSize * 2); // double the number of expected elements
|
||||
Object currentKey;
|
||||
for (int i = keyTable.length; --i >= 0;)
|
||||
if ((currentKey = keyTable[i]) != null)
|
||||
newLookupTable.put(currentKey, valueTable[i]);
|
||||
|
||||
this.keyTable = newLookupTable.keyTable;
|
||||
this.valueTable = newLookupTable.valueTable;
|
||||
this.elementSize = newLookupTable.elementSize;
|
||||
this.threshold = newLookupTable.threshold;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = ""; //$NON-NLS-1$
|
||||
Object object;
|
||||
for (int i = 0, l = valueTable.length; i < l; i++)
|
||||
if ((object = valueTable[i]) != null)
|
||||
s += keyTable[i].toString() + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
|
||||
return s;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.search;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.eclipse.core.resources.IContainer;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
public class Util {
|
||||
|
||||
private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
|
||||
private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
|
||||
private static final int DEFAULT_READING_SIZE = 8192;
|
||||
|
||||
/* Bundle containing messages */
|
||||
protected static ResourceBundle bundle;
|
||||
private final static String bundleName = "org.eclipse.cdt.internal.core.search.messages"; //$NON-NLS-1$
|
||||
static {
|
||||
relocalize();
|
||||
}
|
||||
/**
|
||||
* Lookup the message with the given ID in this catalog and bind its
|
||||
* substitution locations with the given strings.
|
||||
*/
|
||||
public static String bind(String id, String binding1, String binding2) {
|
||||
return bind(id, new String[] {binding1, binding2});
|
||||
}
|
||||
/**
|
||||
* Lookup the message with the given ID in this catalog and bind its
|
||||
* substitution locations with the given string.
|
||||
*/
|
||||
public static String bind(String id, String binding) {
|
||||
return bind(id, new String[] {binding});
|
||||
}
|
||||
/**
|
||||
* Lookup the message with the given ID in this catalog and bind its
|
||||
* substitution locations with the given string values.
|
||||
*/
|
||||
public static String bind(String id, String[] bindings) {
|
||||
if (id == null)
|
||||
return "No message available"; //$NON-NLS-1$
|
||||
String message = null;
|
||||
try {
|
||||
message = bundle.getString(id);
|
||||
} catch (MissingResourceException e) {
|
||||
// If we got an exception looking for the message, fail gracefully by just returning
|
||||
// the id we were looking for. In most cases this is semi-informative so is not too bad.
|
||||
return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
|
||||
}
|
||||
// for compatibility with MessageFormat which eliminates double quotes in original message
|
||||
char[] messageWithNoDoubleQuotes =
|
||||
CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
|
||||
message = new String(messageWithNoDoubleQuotes);
|
||||
|
||||
if (bindings == null)
|
||||
return message;
|
||||
int length = message.length();
|
||||
int start = -1;
|
||||
int end = length;
|
||||
StringBuffer output = new StringBuffer(80);
|
||||
while (true) {
|
||||
if ((end = message.indexOf('{', start)) > -1) {
|
||||
output.append(message.substring(start + 1, end));
|
||||
if ((start = message.indexOf('}', end)) > -1) {
|
||||
int index = -1;
|
||||
try {
|
||||
index = Integer.parseInt(message.substring(end + 1, start));
|
||||
output.append(bindings[index]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
output.append(message.substring(end + 1, start + 1));
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
output.append(message.substring(end, length));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
output.append(message.substring(start + 1, length));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
/**
|
||||
* Lookup the message with the given ID in this catalog
|
||||
*/
|
||||
public static String bind(String id) {
|
||||
return bind(id, (String[])null);
|
||||
}
|
||||
/**
|
||||
* Creates a NLS catalog for the given locale.
|
||||
*/
|
||||
public static void relocalize() {
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
|
||||
} catch(MissingResourceException e) {
|
||||
System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the given file as a byte array.
|
||||
* @throws IOException if a problem occured reading the file.
|
||||
*/
|
||||
public static byte[] getFileByteContent(File file) throws IOException {
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = new BufferedInputStream(new FileInputStream(file));
|
||||
return getInputStreamAsByteArray(stream, (int) file.length());
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the contents of the given file as a char array.
|
||||
* When encoding is null, then the platform default one is used
|
||||
* @throws IOException if a problem occured reading the file.
|
||||
*/
|
||||
public static char[] getFileCharContent(File file, String encoding) throws IOException {
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = new BufferedInputStream(new FileInputStream(file));
|
||||
return Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given input stream's contents as a byte array.
|
||||
* If a length is specified (ie. if length != -1), only length bytes
|
||||
* are returned. Otherwise all bytes in the stream are returned.
|
||||
* Note this doesn't close the stream.
|
||||
* @throws IOException if a problem occured reading the stream.
|
||||
*/
|
||||
public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
|
||||
throws IOException {
|
||||
byte[] contents;
|
||||
if (length == -1) {
|
||||
contents = new byte[0];
|
||||
int contentsLength = 0;
|
||||
int amountRead = -1;
|
||||
do {
|
||||
int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K
|
||||
|
||||
// resize contents if needed
|
||||
if (contentsLength + amountRequested > contents.length) {
|
||||
System.arraycopy(
|
||||
contents,
|
||||
0,
|
||||
contents = new byte[contentsLength + amountRequested],
|
||||
0,
|
||||
contentsLength);
|
||||
}
|
||||
|
||||
// read as many bytes as possible
|
||||
amountRead = stream.read(contents, contentsLength, amountRequested);
|
||||
|
||||
if (amountRead > 0) {
|
||||
// remember length of contents
|
||||
contentsLength += amountRead;
|
||||
}
|
||||
} while (amountRead != -1);
|
||||
|
||||
// resize contents if necessary
|
||||
if (contentsLength < contents.length) {
|
||||
System.arraycopy(
|
||||
contents,
|
||||
0,
|
||||
contents = new byte[contentsLength],
|
||||
0,
|
||||
contentsLength);
|
||||
}
|
||||
} else {
|
||||
contents = new byte[length];
|
||||
int len = 0;
|
||||
int readSize = 0;
|
||||
while ((readSize != -1) && (len != length)) {
|
||||
// See PR 1FMS89U
|
||||
// We record first the read size. In this case len is the actual read size.
|
||||
len += readSize;
|
||||
readSize = stream.read(contents, len, length - len);
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given input stream's contents as a character array.
|
||||
* If a length is specified (ie. if length != -1), only length chars
|
||||
* are returned. Otherwise all chars in the stream are returned.
|
||||
* Note this doesn't close the stream.
|
||||
* @throws IOException if a problem occured reading the stream.
|
||||
*/
|
||||
public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
|
||||
throws IOException {
|
||||
InputStreamReader reader = null;
|
||||
reader = encoding == null
|
||||
? new InputStreamReader(stream)
|
||||
: new InputStreamReader(stream, encoding);
|
||||
char[] contents;
|
||||
if (length == -1) {
|
||||
contents = CharOperation.NO_CHAR;
|
||||
int contentsLength = 0;
|
||||
int amountRead = -1;
|
||||
do {
|
||||
int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K
|
||||
|
||||
// resize contents if needed
|
||||
if (contentsLength + amountRequested > contents.length) {
|
||||
System.arraycopy(
|
||||
contents,
|
||||
0,
|
||||
contents = new char[contentsLength + amountRequested],
|
||||
0,
|
||||
contentsLength);
|
||||
}
|
||||
|
||||
// read as many chars as possible
|
||||
amountRead = reader.read(contents, contentsLength, amountRequested);
|
||||
|
||||
if (amountRead > 0) {
|
||||
// remember length of contents
|
||||
contentsLength += amountRead;
|
||||
}
|
||||
} while (amountRead != -1);
|
||||
|
||||
// resize contents if necessary
|
||||
if (contentsLength < contents.length) {
|
||||
System.arraycopy(
|
||||
contents,
|
||||
0,
|
||||
contents = new char[contentsLength],
|
||||
0,
|
||||
contentsLength);
|
||||
}
|
||||
} else {
|
||||
contents = new char[length];
|
||||
int len = 0;
|
||||
int readSize = 0;
|
||||
while ((readSize != -1) && (len != length)) {
|
||||
// See PR 1FMS89U
|
||||
// We record first the read size. In this case len is the actual read size.
|
||||
len += readSize;
|
||||
readSize = reader.read(contents, len, length - len);
|
||||
}
|
||||
// See PR 1FMS89U
|
||||
// Now we need to resize in case the default encoding used more than one byte for each
|
||||
// character
|
||||
if (len != length)
|
||||
System.arraycopy(contents, 0, (contents = new char[len]), 0, len);
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method - returns the targeted item (IResource if internal or java.io.File if external),
|
||||
* or null if unbound
|
||||
* Internal items must be referred to using container relative paths.
|
||||
*/
|
||||
public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
|
||||
|
||||
if (path == null) return null;
|
||||
|
||||
// lookup - inside the container
|
||||
if (path.getDevice() == null) { // container relative paths should not contain a device
|
||||
// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
|
||||
// (case of a workspace rooted at d:\ )
|
||||
IResource resource = container.findMember(path);
|
||||
if (resource != null){
|
||||
if (!checkResourceExistence ||resource.exists()) return resource;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// if path is relative, it cannot be an external path
|
||||
// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
|
||||
if (!path.isAbsolute()) return null;
|
||||
|
||||
// lookup - outside the container
|
||||
File externalFile = new File(path.toOSString());
|
||||
if (!checkResourceExistence) {
|
||||
return externalFile;
|
||||
} else if (existingExternalFiles.contains(externalFile)) {
|
||||
return externalFile;
|
||||
} else {
|
||||
//TODO: BOG do we need to add something here?
|
||||
/*
|
||||
if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
|
||||
System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
*/
|
||||
if (externalFile.exists()) {
|
||||
// cache external file
|
||||
existingExternalFiles.add(externalFile);
|
||||
return externalFile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* A set of java.io.Files used as a cache of external jars that
|
||||
* are known to be existing.
|
||||
* Note this cache is kept for the whole session.
|
||||
*/
|
||||
public static HashSet existingExternalFiles = new HashSet();
|
||||
|
||||
/*
|
||||
* Returns whether the given resource matches one of the exclusion patterns.
|
||||
*
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
|
||||
IPath path = resource.getFullPath();
|
||||
// ensure that folders are only excluded if all of their children are excluded
|
||||
if (resource.getType() == IResource.FOLDER)
|
||||
path = path.append("*"); //$NON-NLS-1$
|
||||
return isExcluded(path, exclusionPatterns);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the given resource path matches one of the exclusion
|
||||
* patterns.
|
||||
*
|
||||
* @see IClasspathEntry#getExclusionPatterns
|
||||
*/
|
||||
public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
|
||||
if (exclusionPatterns == null) return false;
|
||||
char[] path = resourcePath.toString().toCharArray();
|
||||
for (int i = 0, length = exclusionPatterns.length; i < length; i++)
|
||||
if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 31, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.cdt.core.parser.ast.ClassKind;
|
||||
import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier;
|
||||
import org.eclipse.cdt.core.search.ICSearchConstants;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexer;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexerOutput;
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
|
||||
/**
|
||||
* @author bgheorgh
|
||||
*/
|
||||
|
||||
public abstract class AbstractIndexer implements IIndexer, IIndexConstants, ICSearchConstants {
|
||||
|
||||
IIndexerOutput output;
|
||||
final static int CLASS = 1;
|
||||
final static int STRUCT = 2;
|
||||
final static int UNION = 3;
|
||||
|
||||
public AbstractIndexer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void addClassSpecifier(IASTClassSpecifier classSpecification){
|
||||
if (classSpecification.getClassKind().equals(ClassKind.CLASS))
|
||||
{
|
||||
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),CLASS));
|
||||
}
|
||||
else if (classSpecification.getClassKind().equals(ClassKind.STRUCT))
|
||||
{
|
||||
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),STRUCT));
|
||||
}
|
||||
else if (classSpecification.getClassKind().equals(ClassKind.UNION))
|
||||
{
|
||||
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),UNION));
|
||||
}
|
||||
}
|
||||
|
||||
public void addConstructorDeclaration(){
|
||||
|
||||
}
|
||||
public void addConstructorReference(){
|
||||
|
||||
}
|
||||
|
||||
public void addMemberDeclaration(){
|
||||
|
||||
}
|
||||
public void addMemberReference(){
|
||||
|
||||
}
|
||||
|
||||
public void addFunctionDeclaration(){
|
||||
|
||||
}
|
||||
|
||||
public void addFunctionReference(){
|
||||
|
||||
}
|
||||
|
||||
public void addNameReference(){
|
||||
|
||||
}
|
||||
|
||||
private void addSuperTypeReference(int modifiers, char[] packageName, char[] typeName, char[][] enclosingTypeNames, char classOrInterface, char[] superTypeName, char superClassOrInterface){
|
||||
|
||||
}
|
||||
|
||||
public void addTypeReference(char[] typeName){
|
||||
this.output.addRef(CharOperation.concat(TYPE_REF, CharOperation.lastSegment(typeName, '.')));
|
||||
}
|
||||
/**
|
||||
* Type entries are encoded as follow: 'typeDecl/' ('C' | 'S' | 'U' ) '/' TypeName '/'
|
||||
*/
|
||||
protected static final char[] encodeTypeEntry( char[] typeName, int classType) {
|
||||
|
||||
int pos;
|
||||
//3 - 1 for SUFFIX letter, 2 Separators
|
||||
char[] result = new char[TYPE_DECL_LENGTH + typeName.length + 3];
|
||||
System.arraycopy(TYPE_DECL, 0, result, 0, pos = TYPE_DECL_LENGTH);
|
||||
switch (classType)
|
||||
{
|
||||
case(CLASS):
|
||||
result[pos++] = CLASS_SUFFIX;
|
||||
break;
|
||||
|
||||
case(STRUCT):
|
||||
result[pos++] = STRUCT_SUFFIX;
|
||||
break;
|
||||
|
||||
case(UNION):
|
||||
result[pos++] = UNION_SUFFIX;
|
||||
break;
|
||||
}
|
||||
|
||||
result[pos++] = SEPARATOR;
|
||||
System.arraycopy(typeName, 0, result, pos, typeName.length);
|
||||
pos += typeName.length;
|
||||
result[pos++] = SEPARATOR;
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Returns the file types the <code>IIndexer</code> handles.
|
||||
*/
|
||||
public abstract String[] getFileTypes();
|
||||
/**
|
||||
* @see IIndexer#index(IDocument document, IIndexerOutput output)
|
||||
*/
|
||||
public void index(IDocument document, IIndexerOutput output) throws IOException {
|
||||
this.output = output;
|
||||
if (shouldIndex(document)) indexFile(document);
|
||||
}
|
||||
|
||||
protected abstract void indexFile(IDocument document) throws IOException;
|
||||
/**
|
||||
* @see IIndexer#shouldIndex(IDocument document)
|
||||
*/
|
||||
public boolean shouldIndex(IDocument document) {
|
||||
String type = document.getType();
|
||||
String[] supportedTypes = this.getFileTypes();
|
||||
for (int i = 0; i < supportedTypes.length; ++i) {
|
||||
if (supportedTypes[i].equals(type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||
|
||||
public class AddCompilationUnitToIndex extends AddFileToIndex {
|
||||
char[] contents;
|
||||
|
||||
public AddCompilationUnitToIndex(IFile resource, IPath indexedContainer, IndexManager manager) {
|
||||
super(resource, indexedContainer, manager);
|
||||
}
|
||||
protected boolean indexDocument(IIndex index) throws IOException {
|
||||
if (!initializeContents()) return false;
|
||||
index.add(new IFileDocument(resource, this.contents), new SourceIndexer(resource));
|
||||
return true;
|
||||
}
|
||||
public boolean initializeContents() {
|
||||
if (this.contents == null) {
|
||||
try {
|
||||
IPath location = resource.getLocation();
|
||||
if (location != null)
|
||||
this.contents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(location.toFile(), null);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return this.contents != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
|
||||
public abstract class AddFileToIndex extends IndexRequest {
|
||||
IFile resource;
|
||||
|
||||
public AddFileToIndex(IFile resource, IPath indexPath, IndexManager manager) {
|
||||
super(indexPath, manager);
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
/* ensure no concurrent write access to index */
|
||||
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
try {
|
||||
monitor.enterWrite(); // ask permission to write
|
||||
if (!indexDocument(index)) return false;
|
||||
} catch (IOException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to index " + this.resource + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitWrite(); // free write lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean indexDocument(IIndex index) throws IOException;
|
||||
|
||||
public String toString() {
|
||||
return "indexing " + this.resource.getFullPath(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IResourceProxy;
|
||||
import org.eclipse.core.resources.IResourceProxyVisitor;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.search.Util;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
|
||||
class AddFolderToIndex extends IndexRequest {
|
||||
IPath folderPath;
|
||||
IProject project;
|
||||
char[][] exclusionPattern;
|
||||
|
||||
public AddFolderToIndex(IPath folderPath, IProject project, char[][] exclusionPattern, IndexManager manager) {
|
||||
super(project.getFullPath(), manager);
|
||||
this.folderPath = folderPath;
|
||||
this.project = project;
|
||||
this.exclusionPattern = exclusionPattern;
|
||||
}
|
||||
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
if (!project.isAccessible()) return true; // nothing to do
|
||||
IResource folder = this.project.getParent().findMember(this.folderPath);
|
||||
if (folder == null || folder.getType() == IResource.FILE) return true; // nothing to do, source folder was removed
|
||||
|
||||
/* ensure no concurrent write access to index */
|
||||
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
|
||||
try {
|
||||
monitor.enterRead(); // ask permission to read
|
||||
|
||||
final IPath container = this.indexPath;
|
||||
final IndexManager indexManager = this.manager;
|
||||
final char[][] pattern = exclusionPattern;
|
||||
folder.accept(
|
||||
new IResourceProxyVisitor() {
|
||||
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||
switch(proxy.getType()) {
|
||||
case IResource.FILE :
|
||||
// TODO: BOG Put the file name checking back
|
||||
//if (Util.isJavaFileName(proxy.getName())) {
|
||||
IResource resource = proxy.requestResource();
|
||||
if (pattern == null || !Util.isExcluded(resource, pattern))
|
||||
indexManager.addSource((IFile)resource, container);
|
||||
//}
|
||||
//return false;
|
||||
case IResource.FOLDER :
|
||||
if (pattern != null && Util.isExcluded(proxy.requestResource(), pattern))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
IResource.NONE
|
||||
);
|
||||
} catch (CoreException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to add " + this.folderPath + " to index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitRead(); // free read lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "adding " + this.folderPath + " to index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
/**
|
||||
* @author bgheorgh
|
||||
*/
|
||||
public interface IIndexConstants {
|
||||
|
||||
/* index encoding */
|
||||
char[] REF= "ref/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] TYPE_REF= "typeRef/".toCharArray(); //$NON-NLS-1$
|
||||
char[] TYPE_DECL = "typeDecl/".toCharArray(); //$NON-NLS-1$
|
||||
int TYPE_DECL_LENGTH = 9;
|
||||
|
||||
char[] FUNCTION_REF= "functionRef/".toCharArray(); //$NON-NLS-1$
|
||||
char[] FUNCTION_DECL= "functionDecl/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] CONSTRUCTOR_REF= "constructorRef/".toCharArray(); //$NON-NLS-1$
|
||||
char[] CONSTRUCTOR_DECL= "constructorDecl/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] NAMESPACE_REF= "namespaceRef/".toCharArray(); //$NON-NLS-1$
|
||||
char[] NAMESPACE_DECL= "namespaceDecl/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] MEMBER_REF= "memberRef/".toCharArray(); //$NON-NLS-1$
|
||||
char[] MEMBER_DECL= "memberDecl/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
//a Var REF will be treated as a typeREF
|
||||
//char[] VAR_REF= "varRef/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
//a Struct REF will be treated as a typeREF
|
||||
//char[] STRUCT_REF= "structRef/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
//a Enum REF will be treated as a typeREF
|
||||
//char[] ENUM_REF= "enumRef/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
//a UNION REF will be treated as a typeREF
|
||||
//char[] UNION_REF= "unionRef/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
|
||||
char[] SUPER_REF = "superRef/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] CLASS_DECL= "typeDecl/C/".toCharArray(); //$NON-NLS-1$
|
||||
char[] VAR_DECL= "typeDecl/V/".toCharArray(); //$NON-NLS-1$
|
||||
char[] STRUCT_DECL= "typeDecl/S/".toCharArray(); //$NON-NLS-1$
|
||||
char[] ENUM_DECL= "typeDecl/E/".toCharArray(); //$NON-NLS-1$
|
||||
char[] UNION_DECL= "typeDecl/U/".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
|
||||
char[][] COUNTS=
|
||||
new char[][] { new char[] {'0'}, new char[] {'1'}, new char[] {'2'}, new char[] {'3'}, new char[] {'4'}, new char[] {'5'}, new char[] {'6'}, new char[] {'7'}, new char[] {'8'}, new char[] {'9'}
|
||||
};
|
||||
char CLASS_SUFFIX = 'C';
|
||||
char VAR_SUFFIX = 'V';
|
||||
char STRUCT_SUFFIX = 'S';
|
||||
char ENUM_SUFFIX = 'E';
|
||||
char UNION_SUFFIX = 'U';
|
||||
|
||||
char TYPE_SUFFIX = 0;
|
||||
char SEPARATOR= '/';
|
||||
|
||||
char[] ONE_STAR = new char[] {'*'};
|
||||
char[][] ONE_STAR_CHAR = new char[][] {ONE_STAR};
|
||||
|
||||
// used as special marker for enclosing type name of local and anonymous classes
|
||||
char[] ONE_ZERO = new char[] {'0'};
|
||||
char[][] ONE_ZERO_CHAR = new char[][] {ONE_ZERO};
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IResourceProxy;
|
||||
import org.eclipse.core.resources.IResourceProxyVisitor;
|
||||
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.internal.core.search.Util;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
|
||||
import org.eclipse.cdt.internal.core.model.CModel;
|
||||
import org.eclipse.cdt.internal.core.model.CModelManager;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
||||
|
||||
public class IndexAllProject extends IndexRequest {
|
||||
IProject project;
|
||||
|
||||
public IndexAllProject(IProject project, IndexManager manager) {
|
||||
super(project.getFullPath(), manager);
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof IndexAllProject)
|
||||
return this.project.equals(((IndexAllProject) o).project);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Ensure consistency of a project index. Need to walk all nested resources,
|
||||
* and discover resources which have either been changed, added or deleted
|
||||
* since the index was produced.
|
||||
*/
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
if (!project.isAccessible()) return true; // nothing to do
|
||||
|
||||
IIndex index = this.manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
|
||||
try {
|
||||
monitor.enterRead(); // ask permission to read
|
||||
saveIfNecessary(index, monitor);
|
||||
|
||||
IQueryResult[] results = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
|
||||
int max = results == null ? 0 : results.length;
|
||||
final SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
|
||||
final String OK = "OK"; //$NON-NLS-1$
|
||||
final String DELETED = "DELETED"; //$NON-NLS-1$
|
||||
for (int i = 0; i < max; i++)
|
||||
indexedFileNames.put(results[i].getPath(), DELETED);
|
||||
final long indexLastModified = max == 0 ? 0L : index.getIndexFile().lastModified();
|
||||
|
||||
CModel model = (CModel) CModelManager.getDefault().getCModel();
|
||||
ICProject cProject = model.getCProject(project.getName());
|
||||
ICElement[] kids = cProject.getChildren();
|
||||
IPath cProjectPath = cProject.getPath();
|
||||
|
||||
IWorkspaceRoot root = this.project.getWorkspace().getRoot();
|
||||
IResource sourceFolder = root.findMember(cProjectPath);
|
||||
|
||||
if (this.isCancelled) return false;
|
||||
|
||||
if (sourceFolder != null) {
|
||||
|
||||
// collect output locations if source is project (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32041)
|
||||
final HashSet outputs = new HashSet();
|
||||
|
||||
final boolean hasOutputs = !outputs.isEmpty();
|
||||
|
||||
final char[][] patterns = null;
|
||||
if (max == 0) {
|
||||
sourceFolder.accept(
|
||||
new IResourceProxyVisitor() {
|
||||
public boolean visit(IResourceProxy proxy) {
|
||||
if (isCancelled) return false;
|
||||
switch(proxy.getType()) {
|
||||
case IResource.FILE :
|
||||
//TODO: BOG Put the file name checking back
|
||||
//if (Util.isCCFileName(proxy.getName())) {
|
||||
IResource resource = proxy.requestResource();
|
||||
if (resource.getLocation() != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
|
||||
String name = new IFileDocument((IFile) resource).getName();
|
||||
indexedFileNames.put(name, resource);
|
||||
}
|
||||
//}
|
||||
// return false;
|
||||
|
||||
case IResource.FOLDER :
|
||||
if (patterns != null && Util.isExcluded(proxy.requestResource(), patterns))
|
||||
return false;
|
||||
if (hasOutputs && outputs.contains(proxy.requestFullPath())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
IResource.NONE
|
||||
);
|
||||
} else {
|
||||
sourceFolder.accept(
|
||||
new IResourceProxyVisitor() {
|
||||
public boolean visit(IResourceProxy proxy) {
|
||||
if (isCancelled) return false;
|
||||
switch(proxy.getType()) {
|
||||
case IResource.FILE :
|
||||
// TODO: BOG Put the file name checking back
|
||||
//if (Util.isCCFileName(proxy.getName())) {
|
||||
IResource resource = proxy.requestResource();
|
||||
IPath path = resource.getLocation();
|
||||
if (path != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
|
||||
String name = new IFileDocument((IFile) resource).getName();
|
||||
indexedFileNames.put(name,
|
||||
indexedFileNames.get(name) == null || indexLastModified < path.toFile().lastModified()
|
||||
? (Object) resource
|
||||
: (Object) OK);
|
||||
}
|
||||
//}
|
||||
//return false;
|
||||
case IResource.FOLDER :
|
||||
if (patterns != null && Util.isExcluded(proxy.requestResource(), patterns))
|
||||
return false;
|
||||
if (hasOutputs && outputs.contains(proxy.requestFullPath())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
IResource.NONE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Object[] names = indexedFileNames.keyTable;
|
||||
Object[] values = indexedFileNames.valueTable;
|
||||
boolean shouldSave = false;
|
||||
for (int i = 0, length = names.length; i < length; i++) {
|
||||
String name = (String) names[i];
|
||||
if (name != null) {
|
||||
if (this.isCancelled) return false;
|
||||
|
||||
Object value = values[i];
|
||||
if (value != OK) {
|
||||
shouldSave = true;
|
||||
if (value == DELETED)
|
||||
this.manager.remove(name, this.indexPath);
|
||||
else
|
||||
this.manager.addSource((IFile) value, this.indexPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// request to save index when all cus have been indexed
|
||||
if (shouldSave)
|
||||
this.manager.request(new SaveIndex(this.indexPath, this.manager));
|
||||
|
||||
} catch (CoreException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.manager.removeIndex(this.indexPath);
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.manager.removeIndex(this.indexPath);
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitRead(); // free read lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.project.hashCode();
|
||||
}
|
||||
|
||||
protected Integer updatedIndexState() {
|
||||
return IndexManager.REBUILDING_STATE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "indexing project " + this.project.getFullPath(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,611 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IWorkspace;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.QualifiedName;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
import org.eclipse.cdt.internal.core.search.processing.IJob;
|
||||
import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
|
||||
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.impl.Index;
|
||||
import org.eclipse.cdt.internal.core.model.CProject;
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
|
||||
public class IndexManager extends JobManager implements IIndexConstants {
|
||||
/* number of file contents in memory */
|
||||
public static int MAX_FILES_IN_MEMORY = 0;
|
||||
|
||||
public IWorkspace workspace;
|
||||
public SimpleLookupTable indexNames = new SimpleLookupTable();
|
||||
private Map indexes = new HashMap(5);
|
||||
|
||||
/* read write monitors */
|
||||
private Map monitors = new HashMap(5);
|
||||
|
||||
/* need to save ? */
|
||||
private boolean needToSave = false;
|
||||
private static final CRC32 checksumCalculator = new CRC32();
|
||||
private IPath javaPluginLocation = null;
|
||||
|
||||
/* can only replace a current state if its less than the new one */
|
||||
private SimpleLookupTable indexStates = null;
|
||||
private File savedIndexNamesFile =
|
||||
new File(getJavaPluginWorkingLocation().append("savedIndexNames.txt").toOSString()); //$NON-NLS-1$
|
||||
public static Integer SAVED_STATE = new Integer(0);
|
||||
public static Integer UPDATING_STATE = new Integer(1);
|
||||
public static Integer UNKNOWN_STATE = new Integer(2);
|
||||
public static Integer REBUILDING_STATE = new Integer(3);
|
||||
|
||||
public synchronized void aboutToUpdateIndex(IPath path, Integer newIndexState) {
|
||||
// newIndexState is either UPDATING_STATE or REBUILDING_STATE
|
||||
// must tag the index as inconsistent, in case we exit before the update job is started
|
||||
String indexName = computeIndexName(path);
|
||||
Object state = getIndexStates().get(indexName);
|
||||
Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
|
||||
if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index
|
||||
|
||||
int compare = newIndexState.compareTo(currentIndexState);
|
||||
if (compare > 0) {
|
||||
// so UPDATING_STATE replaces SAVED_STATE and REBUILDING_STATE replaces everything
|
||||
updateIndexState(indexName, newIndexState);
|
||||
} else if (compare < 0 && this.indexes.get(path) == null) {
|
||||
// if already cached index then there is nothing more to do
|
||||
rebuildIndex(indexName, path);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Not at the moment...
|
||||
* @param resource
|
||||
* @param indexedContainer
|
||||
*/
|
||||
/*
|
||||
public void addBinary(IFile resource, IPath indexedContainer){
|
||||
if (JavaCore.getPlugin() == null) return;
|
||||
AddClassFileToIndex job = new AddClassFileToIndex(resource, indexedContainer, this);
|
||||
if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
|
||||
// reduces the chance that the file is open later on, preventing it from being deleted
|
||||
if (!job.initializeContents()) return;
|
||||
}
|
||||
request(job);
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Trigger addition of a resource to an index
|
||||
* Note: the actual operation is performed in background
|
||||
*/
|
||||
public void addSource(IFile resource, IPath indexedContainer){
|
||||
if (CCorePlugin.getDefault() == null) return;
|
||||
AddCompilationUnitToIndex job = new AddCompilationUnitToIndex(resource, indexedContainer, this);
|
||||
if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
|
||||
// reduces the chance that the file is open later on, preventing it from being deleted
|
||||
if (!job.initializeContents()) return;
|
||||
}
|
||||
request(job);
|
||||
}
|
||||
|
||||
String computeIndexName(IPath path) {
|
||||
String name = (String) indexNames.get(path);
|
||||
if (name == null) {
|
||||
String pathString = path.toOSString();
|
||||
checksumCalculator.reset();
|
||||
checksumCalculator.update(pathString.getBytes());
|
||||
String fileName = Long.toString(checksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
name = getJavaPluginWorkingLocation().append(fileName).toOSString();
|
||||
indexNames.put(path, name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
/**
|
||||
* Returns the index for a given project, according to the following algorithm:
|
||||
* - if index is already in memory: answers this one back
|
||||
* - if (reuseExistingFile) then read it and return this index and record it in memory
|
||||
* - if (createIfMissing) then create a new empty index and record it in memory
|
||||
*
|
||||
* Warning: Does not check whether index is consistent (not being used)
|
||||
*/
|
||||
public synchronized IIndex getIndex(IPath path, boolean reuseExistingFile, boolean createIfMissing) {
|
||||
// Path is already canonical per construction
|
||||
IIndex index = (IIndex) indexes.get(path);
|
||||
if (index == null) {
|
||||
String indexName = computeIndexName(path);
|
||||
Object state = getIndexStates().get(indexName);
|
||||
Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
|
||||
if (currentIndexState == UNKNOWN_STATE) {
|
||||
// should only be reachable for query jobs
|
||||
// IF you put an index in the cache, then AddJarFileToIndex fails because it thinks there is nothing to do
|
||||
rebuildIndex(indexName, path);
|
||||
return null;
|
||||
}
|
||||
|
||||
// index isn't cached, consider reusing an existing index file
|
||||
if (reuseExistingFile) {
|
||||
File indexFile = new File(indexName);
|
||||
if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
|
||||
try {
|
||||
index = new Index(indexName, "Index for " + path.toOSString(), true /*reuse index file*/); //$NON-NLS-1$
|
||||
indexes.put(path, index);
|
||||
monitors.put(index, new ReadWriteMonitor());
|
||||
return index;
|
||||
} catch (IOException e) {
|
||||
// failed to read the existing file or its no longer compatible
|
||||
if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> cannot reuse existing index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
rebuildIndex(indexName, path);
|
||||
return null;
|
||||
} else {
|
||||
index = null; // will fall thru to createIfMissing & create a empty index for the rebuild all job to populate
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentIndexState == SAVED_STATE) { // rebuild index if existing file is missing
|
||||
rebuildIndex(indexName, path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// index wasn't found on disk, consider creating an empty new one
|
||||
if (createIfMissing) {
|
||||
try {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> create empty index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
index = new Index(indexName, "Index for " + path.toOSString(), false /*do not reuse index file*/); //$NON-NLS-1$
|
||||
indexes.put(path, index);
|
||||
monitors.put(index, new ReadWriteMonitor());
|
||||
return index;
|
||||
} catch (IOException e) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> unable to create empty index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
// The file could not be created. Possible reason: the project has been deleted.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());
|
||||
return index;
|
||||
}
|
||||
|
||||
private SimpleLookupTable getIndexStates() {
|
||||
if (indexStates != null) return indexStates;
|
||||
|
||||
this.indexStates = new SimpleLookupTable();
|
||||
char[] savedIndexNames = readIndexState();
|
||||
if (savedIndexNames.length > 0) {
|
||||
char[][] names = CharOperation.splitOn('\n', savedIndexNames);
|
||||
for (int i = 0, l = names.length; i < l; i++) {
|
||||
char[] name = names[i];
|
||||
if (name.length > 0)
|
||||
this.indexStates.put(new String(name), SAVED_STATE);
|
||||
}
|
||||
}
|
||||
return this.indexStates;
|
||||
}
|
||||
|
||||
private IPath getJavaPluginWorkingLocation() {
|
||||
if (this.javaPluginLocation != null) return this.javaPluginLocation;
|
||||
|
||||
return this.javaPluginLocation = CCorePlugin.getDefault().getStateLocation();
|
||||
}
|
||||
/**
|
||||
* Index access is controlled through a read-write monitor so as
|
||||
* to ensure there is no concurrent read and write operations
|
||||
* (only concurrent reading is allowed).
|
||||
*/
|
||||
public ReadWriteMonitor getMonitorFor(IIndex index){
|
||||
return (ReadWriteMonitor) monitors.get(index);
|
||||
}
|
||||
/**
|
||||
* Trigger addition of the entire content of a project
|
||||
* Note: the actual operation is performed in background
|
||||
*/
|
||||
public void indexAll(IProject project) {
|
||||
if (CCorePlugin.getDefault() == null) return;
|
||||
|
||||
/******
|
||||
*TODO: Remove these methods once the new indexer is
|
||||
*fully integrated
|
||||
*/
|
||||
if (!isEnabled(project)) return;
|
||||
|
||||
// check if the same request is not already in the queue
|
||||
IndexRequest request = new IndexAllProject(project, this);
|
||||
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||
if (request.equals(this.awaitingJobs[i])) return;
|
||||
this.request(request);
|
||||
}
|
||||
/**
|
||||
* Index the content of the given source folder.
|
||||
*/
|
||||
public void indexSourceFolder(CProject javaProject, IPath sourceFolder, final char[][] exclusionPattern) {
|
||||
IProject project = javaProject.getProject();
|
||||
if (this.jobEnd > this.jobStart) {
|
||||
// check if a job to index the project is not already in the queue
|
||||
IndexRequest request = new IndexAllProject(project, this);
|
||||
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||
if (request.equals(this.awaitingJobs[i])) return;
|
||||
}
|
||||
this.request(new AddFolderToIndex(sourceFolder, project, exclusionPattern, this));
|
||||
}
|
||||
|
||||
public void jobWasCancelled(IPath path) {
|
||||
Object o = this.indexes.get(path);
|
||||
if (o instanceof IIndex) {
|
||||
this.monitors.remove(o);
|
||||
this.indexes.remove(path);
|
||||
}
|
||||
updateIndexState(computeIndexName(path), UNKNOWN_STATE);
|
||||
}
|
||||
/**
|
||||
* Advance to the next available job, once the current one has been completed.
|
||||
* Note: clients awaiting until the job count is zero are still waiting at this point.
|
||||
*/
|
||||
protected synchronized void moveToNextJob() {
|
||||
// remember that one job was executed, and we will need to save indexes at some point
|
||||
needToSave = true;
|
||||
super.moveToNextJob();
|
||||
}
|
||||
/**
|
||||
* No more job awaiting.
|
||||
*/
|
||||
protected void notifyIdle(long idlingTime){
|
||||
if (idlingTime > 1000 && needToSave) saveIndexes();
|
||||
}
|
||||
/*
|
||||
* For debug purpose
|
||||
*/
|
||||
public IIndex peekAtIndex(IPath path) {
|
||||
return (IIndex) indexes.get(path);
|
||||
}
|
||||
/**
|
||||
* Name of the background process
|
||||
*/
|
||||
public String processName(){
|
||||
return org.eclipse.cdt.internal.core.search.Util.bind("process.name"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private void rebuildIndex(String indexName, IPath path) {
|
||||
Object target = org.eclipse.cdt.internal.core.search.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
|
||||
if (target == null) return;
|
||||
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> request to rebuild index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
updateIndexState(indexName, REBUILDING_STATE);
|
||||
IndexRequest request = null;
|
||||
if (target instanceof IProject) {
|
||||
IProject p = (IProject) target;
|
||||
//if (JavaProject.hasJavaNature(p))
|
||||
request = new IndexAllProject(p, this);
|
||||
}
|
||||
|
||||
if (request != null)
|
||||
request(request);
|
||||
}
|
||||
/**
|
||||
* Recreates the index for a given path, keeping the same read-write monitor.
|
||||
* Returns the new empty index or null if it didn't exist before.
|
||||
* Warning: Does not check whether index is consistent (not being used)
|
||||
*/
|
||||
public synchronized IIndex recreateIndex(IPath path) {
|
||||
// only called to over write an existing cached index...
|
||||
try {
|
||||
IIndex index = (IIndex) this.indexes.get(path);
|
||||
ReadWriteMonitor monitor = (ReadWriteMonitor) this.monitors.remove(index);
|
||||
|
||||
// Path is already canonical
|
||||
String indexPath = computeIndexName(path);
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> recreating index: "+indexPath+" for path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
index = new Index(indexPath, "Index for " + path.toOSString(), false /*reuse index file*/); //$NON-NLS-1$
|
||||
indexes.put(path, index);
|
||||
monitors.put(index, monitor);
|
||||
return index;
|
||||
} catch (IOException e) {
|
||||
// The file could not be created. Possible reason: the project has been deleted.
|
||||
if (VERBOSE) {
|
||||
JobManager.verbose("-> failed to recreate index for path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Trigger removal of a resource to an index
|
||||
* Note: the actual operation is performed in background
|
||||
*/
|
||||
public void remove(String resourceName, IPath indexedContainer){
|
||||
request(new RemoveFromIndex(resourceName, indexedContainer, this));
|
||||
}
|
||||
/**
|
||||
* Removes the index for a given path.
|
||||
* This is a no-op if the index did not exist.
|
||||
*/
|
||||
public synchronized void removeIndex(IPath path) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("removing index " + path); //$NON-NLS-1$
|
||||
String indexName = computeIndexName(path);
|
||||
File indexFile = new File(indexName);
|
||||
if (indexFile.exists())
|
||||
indexFile.delete();
|
||||
Object o = this.indexes.get(path);
|
||||
if (o instanceof IIndex)
|
||||
this.monitors.remove(o);
|
||||
this.indexes.remove(path);
|
||||
updateIndexState(indexName, null);
|
||||
}
|
||||
/**
|
||||
* Removes all indexes whose paths start with (or are equal to) the given path.
|
||||
*/
|
||||
public synchronized void removeIndexFamily(IPath path) {
|
||||
// only finds cached index files... shutdown removes all non-cached index files
|
||||
ArrayList toRemove = null;
|
||||
Iterator iterator = this.indexes.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
IPath indexPath = (IPath) iterator.next();
|
||||
if (path.isPrefixOf(indexPath)) {
|
||||
if (toRemove == null)
|
||||
toRemove = new ArrayList();
|
||||
toRemove.add(indexPath);
|
||||
}
|
||||
}
|
||||
if (toRemove != null)
|
||||
for (int i = 0, length = toRemove.size(); i < length; i++)
|
||||
this.removeIndex((IPath) toRemove.get(i));
|
||||
}
|
||||
/**
|
||||
* Remove the content of the given source folder from the index.
|
||||
*/
|
||||
public void removeSourceFolderFromIndex(CProject javaProject, IPath sourceFolder, char[][] exclusionPatterns) {
|
||||
IProject project = javaProject.getProject();
|
||||
if (this.jobEnd > this.jobStart) {
|
||||
// check if a job to index the project is not already in the queue
|
||||
IndexRequest request = new IndexAllProject(project, this);
|
||||
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||
if (request.equals(this.awaitingJobs[i])) return;
|
||||
}
|
||||
|
||||
this.request(new RemoveFolderFromIndex(sourceFolder, exclusionPatterns, project, this));
|
||||
}
|
||||
/**
|
||||
* Flush current state
|
||||
*/
|
||||
public void reset() {
|
||||
super.reset();
|
||||
if (this.indexes != null) {
|
||||
this.indexes = new HashMap(5);
|
||||
this.monitors = new HashMap(5);
|
||||
this.indexStates = null;
|
||||
}
|
||||
this.indexNames = new SimpleLookupTable();
|
||||
this.javaPluginLocation = null;
|
||||
}
|
||||
|
||||
public void saveIndex(IIndex index) throws IOException {
|
||||
// must have permission to write from the write monitor
|
||||
if (index.hasChanged()) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
|
||||
index.save();
|
||||
}
|
||||
String indexName = index.getIndexFile().getPath();
|
||||
if (this.jobEnd > this.jobStart) {
|
||||
Object indexPath = indexNames.keyForValue(indexName);
|
||||
if (indexPath != null) {
|
||||
for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
|
||||
IJob job = this.awaitingJobs[i];
|
||||
if (job instanceof IndexRequest)
|
||||
if (((IndexRequest) job).indexPath.equals(indexPath)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateIndexState(indexName, SAVED_STATE);
|
||||
}
|
||||
/**
|
||||
* Commit all index memory changes to disk
|
||||
*/
|
||||
public void saveIndexes() {
|
||||
// only save cached indexes... the rest were not modified
|
||||
ArrayList toSave = new ArrayList();
|
||||
synchronized(this) {
|
||||
for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
|
||||
Object o = iter.next();
|
||||
if (o instanceof IIndex)
|
||||
toSave.add(o);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, length = toSave.size(); i < length; i++) {
|
||||
IIndex index = (IIndex) toSave.get(i);
|
||||
ReadWriteMonitor monitor = getMonitorFor(index);
|
||||
if (monitor == null) continue; // index got deleted since acquired
|
||||
try {
|
||||
monitor.enterWrite();
|
||||
try {
|
||||
saveIndex(index);
|
||||
} catch(IOException e){
|
||||
if (VERBOSE) {
|
||||
JobManager.verbose("-> got the following exception while saving:"); //$NON-NLS-1$
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Util.log(e);
|
||||
}
|
||||
} finally {
|
||||
monitor.exitWrite();
|
||||
}
|
||||
}
|
||||
needToSave = false;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("Shutdown"); //$NON-NLS-1$
|
||||
//TODO: BOG Put in Shutdown
|
||||
/*
|
||||
IndexSelector indexSelector = new IndexSelector(new JavaWorkspaceScope(), null, false, this);
|
||||
IIndex[] selectedIndexes = indexSelector.getIndexes();
|
||||
SimpleLookupTable knownPaths = new SimpleLookupTable();
|
||||
for (int i = 0, max = selectedIndexes.length; i < max; i++) {
|
||||
String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
|
||||
knownPaths.put(path, path);
|
||||
}
|
||||
|
||||
if (indexStates != null) {
|
||||
Object[] indexNames = indexStates.keyTable;
|
||||
for (int i = 0, l = indexNames.length; i < l; i++) {
|
||||
String key = (String) indexNames[i];
|
||||
if (key != null && !knownPaths.containsKey(key))
|
||||
updateIndexState(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
File indexesDirectory = new File(getJavaPluginWorkingLocation().toOSString());
|
||||
if (indexesDirectory.isDirectory()) {
|
||||
File[] indexesFiles = indexesDirectory.listFiles();
|
||||
if (indexesFiles != null) {
|
||||
for (int i = 0, indexesFilesLength = indexesFiles.length; i < indexesFilesLength; i++) {
|
||||
String fileName = indexesFiles[i].getAbsolutePath();
|
||||
if (!knownPaths.containsKey(fileName) && fileName.toLowerCase().endsWith(".index")) { //$NON-NLS-1$
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("Deleting index file " + indexesFiles[i]); //$NON-NLS-1$
|
||||
indexesFiles[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
super.shutdown();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(10);
|
||||
buffer.append(super.toString());
|
||||
buffer.append("In-memory indexes:\n"); //$NON-NLS-1$
|
||||
int count = 0;
|
||||
for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
|
||||
buffer.append(++count).append(" - ").append(iter.next().toString()).append('\n'); //$NON-NLS-1$
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private char[] readIndexState() {
|
||||
try {
|
||||
return org.eclipse.cdt.internal.core.search.Util.getFileCharContent(savedIndexNamesFile, null);
|
||||
} catch (IOException ignored) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("Failed to read saved index file names"); //$NON-NLS-1$
|
||||
return new char[0];
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIndexState(String indexName, Integer indexState) {
|
||||
getIndexStates(); // ensure the states are initialized
|
||||
if (indexState != null) {
|
||||
if (indexState.equals(indexStates.get(indexName))) return; // not changed
|
||||
indexStates.put(indexName, indexState);
|
||||
} else {
|
||||
if (!indexStates.containsKey(indexName)) return; // did not exist anyway
|
||||
indexStates.removeKey(indexName);
|
||||
}
|
||||
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
|
||||
Object[] indexNames = indexStates.keyTable;
|
||||
Object[] states = indexStates.valueTable;
|
||||
for (int i = 0, l = states.length; i < l; i++) {
|
||||
if (states[i] == SAVED_STATE) {
|
||||
writer.write((String) indexNames[i]);
|
||||
writer.write('\n');
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("Failed to write saved index file names"); //$NON-NLS-1$
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
if (VERBOSE) {
|
||||
String state = "?"; //$NON-NLS-1$
|
||||
if (indexState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$
|
||||
else if (indexState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$
|
||||
else if (indexState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$
|
||||
else if (indexState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$
|
||||
JobManager.verbose("-> index state updated to: " + state + " for: "+indexName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
||||
/*************
|
||||
*TODO: Remove these methods once the new indexer is
|
||||
*fully integrated
|
||||
* START OF TEMP INDEXER ENABLE SECTION
|
||||
*/
|
||||
final static String INDEX_MODEL_ID = CCorePlugin.PLUGIN_ID + ".newindexmodel";
|
||||
final static String ACTIVATION = "enable";
|
||||
|
||||
static QualifiedName activationKey = new QualifiedName(INDEX_MODEL_ID, ACTIVATION);
|
||||
|
||||
public boolean isEnabled(IProject project) {
|
||||
String prop = null;
|
||||
try {
|
||||
if (project != null) {
|
||||
prop = project.getPersistentProperty(activationKey);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
return ((prop != null) && prop.equalsIgnoreCase("true"));
|
||||
}
|
||||
|
||||
public void setEnabled(IProject project, boolean on) {
|
||||
try {
|
||||
if (project != null) {
|
||||
Boolean newValue = new Boolean(on);
|
||||
Boolean oldValue = new Boolean(isEnabled(project));
|
||||
if (!oldValue.equals(newValue)) {
|
||||
project.setPersistentProperty(activationKey, newValue.toString());
|
||||
if (on) {
|
||||
indexAll(project);
|
||||
} else {
|
||||
//remove(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/************
|
||||
* END OF TEMP INDEXER ENABLE SECTION
|
||||
*/
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.processing.IJob;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
|
||||
public abstract class IndexRequest implements IJob {
|
||||
protected boolean isCancelled = false;
|
||||
protected IPath indexPath;
|
||||
protected IndexManager manager;
|
||||
|
||||
public IndexRequest(IPath indexPath, IndexManager manager) {
|
||||
this.indexPath = indexPath;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public boolean belongsTo(String projectName) {
|
||||
return projectName.equals(this.indexPath.segment(0));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.manager.jobWasCancelled(this.indexPath);
|
||||
this.isCancelled = true;
|
||||
}
|
||||
|
||||
public boolean isReadyToRun() {
|
||||
// tag the index as inconsistent
|
||||
this.manager.aboutToUpdateIndex(indexPath, updatedIndexState());
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* This code is assumed to be invoked while monitor has read lock
|
||||
*/
|
||||
protected void saveIfNecessary(IIndex index, ReadWriteMonitor monitor) throws IOException {
|
||||
/* if index has changed, commit these before querying */
|
||||
if (index.hasChanged()) {
|
||||
try {
|
||||
monitor.exitRead(); // free read lock
|
||||
monitor.enterWrite(); // ask permission to write
|
||||
this.manager.saveIndex(index);
|
||||
} finally {
|
||||
monitor.exitWriteEnterRead(); // finished writing and reacquire read permission
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Integer updatedIndexState() {
|
||||
return IndexManager.UPDATING_STATE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
/**
|
||||
* Monitor ensuring no more than one writer working concurrently.
|
||||
* Multiple readers are allowed to perform simultaneously.
|
||||
*/
|
||||
public class ReadWriteMonitor {
|
||||
|
||||
/**
|
||||
* <0 : writing (cannot go beyond -1, i.e one concurrent writer)
|
||||
* =0 : idle
|
||||
* >0 : reading (number of concurrent readers)
|
||||
*/
|
||||
private int status = 0;
|
||||
/**
|
||||
* Concurrent reading is allowed
|
||||
* Blocking only when already writing.
|
||||
*/
|
||||
public synchronized void enterRead() {
|
||||
|
||||
while (status < 0){
|
||||
try {
|
||||
wait();
|
||||
} catch(InterruptedException e){
|
||||
}
|
||||
}
|
||||
status++;
|
||||
}
|
||||
/**
|
||||
* Only one writer at a time is allowed to perform
|
||||
* Blocking only when already writing or reading.
|
||||
*/
|
||||
public synchronized void enterWrite() {
|
||||
|
||||
while (status != 0){
|
||||
try {
|
||||
wait();
|
||||
} catch(InterruptedException e){
|
||||
}
|
||||
}
|
||||
status--;
|
||||
}
|
||||
/**
|
||||
* Only notify waiting writer(s) if last reader
|
||||
*/
|
||||
public synchronized void exitRead() {
|
||||
if (--status == 0) notifyAll();
|
||||
}
|
||||
/**
|
||||
* When writing is over, all readers and possible
|
||||
* writers are granted permission to restart concurrently
|
||||
*/
|
||||
public synchronized void exitWrite() {
|
||||
if (++status == 0) notifyAll();
|
||||
}
|
||||
/**
|
||||
* Atomic exitWrite/enterRead: Allows to keep monitor in between
|
||||
* exit write and next enter read.
|
||||
* When writing is over, all readers are granted permissing to restart
|
||||
* concurrently.
|
||||
* This is the same as:
|
||||
* <pre>
|
||||
* synchronized(monitor) {
|
||||
* monitor.exitWrite();
|
||||
* monitor.enterRead();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public synchronized void exitWriteEnterRead() {
|
||||
this.exitWrite();
|
||||
this.enterRead();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.cdt.internal.core.search.Util;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
|
||||
class RemoveFolderFromIndex extends IndexRequest {
|
||||
IPath folderPath;
|
||||
char[][] exclusionPatterns;
|
||||
IProject project;
|
||||
|
||||
public RemoveFolderFromIndex(IPath folderPath, char[][] exclusionPatterns, IProject project, IndexManager manager) {
|
||||
super(project.getFullPath(), manager);
|
||||
this.folderPath = folderPath;
|
||||
this.exclusionPatterns = exclusionPatterns;
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
|
||||
/* ensure no concurrent write access to index */
|
||||
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
|
||||
try {
|
||||
monitor.enterRead(); // ask permission to read
|
||||
IQueryResult[] results = index.queryInDocumentNames(this.folderPath.toString());
|
||||
// all file names belonging to the folder or its subfolders and that are not excluded (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32607)
|
||||
for (int i = 0, max = results == null ? 0 : results.length; i < max; i++) {
|
||||
String documentPath = results[i].getPath();
|
||||
if (this.exclusionPatterns == null || !Util.isExcluded(new Path(documentPath), this.exclusionPatterns)) {
|
||||
manager.remove(documentPath, this.indexPath); // write lock will be acquired by the remove operation
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to remove " + this.folderPath + " from index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitRead(); // free read lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "removing " + this.folderPath + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
|
||||
class RemoveFromIndex extends IndexRequest {
|
||||
String resourceName;
|
||||
|
||||
public RemoveFromIndex(String resourceName, IPath indexPath, IndexManager manager) {
|
||||
super(indexPath, manager);
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
|
||||
/* ensure no concurrent write access to index */
|
||||
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
|
||||
try {
|
||||
monitor.enterWrite(); // ask permission to write
|
||||
index.remove(resourceName);
|
||||
} catch (IOException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to remove " + this.resourceName + " from index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitWrite(); // free write lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "removing " + this.resourceName + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||
|
||||
/*
|
||||
* Save the index of a project.
|
||||
*/
|
||||
public class SaveIndex extends IndexRequest {
|
||||
public SaveIndex(IPath indexPath, IndexManager manager) {
|
||||
super(indexPath, manager);
|
||||
}
|
||||
|
||||
public boolean execute(IProgressMonitor progressMonitor) {
|
||||
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||
|
||||
/* ensure no concurrent write access to index */
|
||||
IIndex index = this.manager.getIndex(this.indexPath, true /*reuse index file*/, false /*don't create if none*/);
|
||||
if (index == null) return true;
|
||||
ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
|
||||
if (monitor == null) return true; // index got deleted since acquired
|
||||
|
||||
try {
|
||||
monitor.enterWrite(); // ask permission to write
|
||||
this.manager.saveIndex(index);
|
||||
} catch (IOException e) {
|
||||
if (JobManager.VERBOSE) {
|
||||
JobManager.verbose("-> failed to save index " + this.indexPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
monitor.exitWrite(); // free write lock
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "saving index for " + this.indexPath; //$NON-NLS-1$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 1, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.indexing;
|
||||
|
||||
/**
|
||||
* @author bgheorgh
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.cdt.core.parser.IParser;
|
||||
import org.eclipse.cdt.core.parser.ParserFactory;
|
||||
import org.eclipse.cdt.core.parser.ParserMode;
|
||||
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||
|
||||
/**
|
||||
* A SourceIndexer indexes source files using the parser. The following items are indexed:
|
||||
* Declarations:
|
||||
* - Classes
|
||||
* - Structs
|
||||
* - Unions
|
||||
* References:
|
||||
* - Classes
|
||||
* - Structs
|
||||
* - Unions
|
||||
*/
|
||||
public class SourceIndexer extends AbstractIndexer {
|
||||
|
||||
//TODO: Indexer, add additional file types
|
||||
public static final String[] FILE_TYPES= new String[] {"cpp","h"}; //$NON-NLS-1$
|
||||
//protected DefaultProblemFactory problemFactory= new DefaultProblemFactory(Locale.getDefault());
|
||||
IFile resourceFile;
|
||||
|
||||
SourceIndexer(IFile resourceFile) {
|
||||
this.resourceFile = resourceFile;
|
||||
}
|
||||
/**
|
||||
* Returns the file types the <code>IIndexer</code> handles.
|
||||
*/
|
||||
public String[] getFileTypes(){
|
||||
return FILE_TYPES;
|
||||
}
|
||||
|
||||
protected void indexFile(IDocument document) throws IOException {
|
||||
// Add the name of the file to the index
|
||||
output.addDocument(document);
|
||||
// Create a new Parser
|
||||
SourceIndexerRequestor requestor = new SourceIndexerRequestor(this, document);
|
||||
IParser parser = ParserFactory.createParser(
|
||||
ParserFactory.createScanner( new StringReader( document.getStringContent() ), document.getName(), null, null, ParserMode.QUICK_PARSE ),
|
||||
requestor, ParserMode.QUICK_PARSE);
|
||||
try{
|
||||
parser.parse();
|
||||
}
|
||||
catch( Exception e ){
|
||||
System.out.println( "Parse Exception in SourceIndexer" );
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the document types the <code>IIndexer</code> handles.
|
||||
*/
|
||||
|
||||
public void setFileTypes(String[] fileTypes){}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,16 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2000, 2003 IBM Corporation and others.
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Common Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/cpl-v10.html
|
||||
#
|
||||
# Contributors:
|
||||
# IBM Corporation - initial API and implementation
|
||||
###############################################################################
|
||||
### Eclipse CDT Core Search messages.
|
||||
|
||||
engine.searching = Searching...
|
||||
exception.wrongFormat = Wrong format
|
||||
process.name = CDT Indexer
|
||||
manager.filesToIndex = {0} files to index
|
|
@ -8,6 +8,7 @@ package org.eclipse.cdt.core.model;
|
|||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.internal.core.model.BatchOperation;
|
||||
import org.eclipse.cdt.internal.core.model.CModelManager;
|
||||
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IFolder;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
|
@ -215,4 +216,14 @@ public class CoreModel {
|
|||
workspace.run(new BatchOperation(action), monitor);
|
||||
}
|
||||
}
|
||||
|
||||
public void startIndexing()
|
||||
{
|
||||
manager.getIndexManager().reset();
|
||||
}
|
||||
|
||||
public IndexManager getIndexManager(){
|
||||
return manager.getIndexManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.core.resources.ResourcesPlugin;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||
|
||||
public class CModelManager implements IResourceChangeListener {
|
||||
|
||||
|
@ -755,4 +756,8 @@ public class CModelManager implements IResourceChangeListener {
|
|||
}
|
||||
}
|
||||
|
||||
public IndexManager getIndexManager() {
|
||||
return this.fDeltaProcessor.indexManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.eclipse.core.resources.IResource;
|
|||
import org.eclipse.core.resources.IResourceDelta;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||
|
||||
/**
|
||||
* This class is used by <code>CModelManager</code> to convert
|
||||
* <code>IResourceDelta</code>s into <code>ICElementDelta</code>s.
|
||||
|
@ -31,6 +33,8 @@ public class DeltaProcessor {
|
|||
* The <code>CElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
|
||||
*/
|
||||
protected CElementDelta fCurrentDelta;
|
||||
|
||||
protected IndexManager indexManager = new IndexManager();
|
||||
|
||||
/* The C element that was last created (see createElement(IResource).
|
||||
* This is used as a stack of C elements (using getParent() to pop it, and
|
||||
|
@ -333,6 +337,7 @@ public class DeltaProcessor {
|
|||
// get the workspace delta, and start processing there.
|
||||
IResourceDelta[] deltas = changes.getAffectedChildren();
|
||||
ICElementDelta[] translatedDeltas = new CElementDelta[deltas.length];
|
||||
System.out.println("delta.length: " + deltas.length);
|
||||
for (int i = 0; i < deltas.length; i++) {
|
||||
IResourceDelta delta = deltas[i];
|
||||
fCurrentDelta = new CElementDelta(root);
|
||||
|
@ -446,9 +451,37 @@ public class DeltaProcessor {
|
|||
|
||||
protected void updateIndexAddResource(ICElement element, IResourceDelta delta) {
|
||||
//CModelManager.getDefault().getIndexManager().addResource(delta.getResource());
|
||||
|
||||
if (indexManager == null)
|
||||
return;
|
||||
|
||||
switch (element.getElementType()) {
|
||||
case ICElement.C_PROJECT :
|
||||
this.indexManager.indexAll(element.getCProject().getProject());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void updateIndexRemoveResource(ICElement element, IResourceDelta delta) {
|
||||
//CModelManager.getDefault().getIndexManager().removeResource(delta.getResource());
|
||||
|
||||
/*
|
||||
if (indexManager == null)
|
||||
return;
|
||||
|
||||
switch (element.getElementType()) {
|
||||
case ICElement.C_PROJECT :
|
||||
this.indexManager.removeIndexFamily(element.getCProject().getProject().getFullPath());
|
||||
// NB: Discarding index jobs belonging to this project was done during PRE_DELETE
|
||||
break;
|
||||
// NB: Update of index if project is opened, closed, or its java nature is added or removed
|
||||
// is done in updateCurrentDeltaAndIndex
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
10
core/org.eclipse.cdt.core/search/ChangeLog
Normal file
10
core/org.eclipse.cdt.core/search/ChangeLog
Normal file
|
@ -0,0 +1,10 @@
|
|||
2003-06-25 Bogdan Gheorghe
|
||||
|
||||
Modified:
|
||||
|
||||
* search/org/eclipse/cdt/core/search/ICSearchConstants.java
|
||||
* search/org/eclipse/cdt/internal/core/search/Utils.java
|
||||
- moved to index/org/eclipse/cdt/internal/core/search/Utils.java
|
||||
* search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java
|
||||
* search/org/eclipse/cdt/internal/core/search/processing/IJob.java
|
||||
* search/org/eclipse/cdt/internal/core/search/processing/JobManager.java
|
|
@ -9,15 +9,24 @@
|
|||
* IBM Corp. - Rational Software - initial implementation
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 11, 2003
|
||||
* Created on May 31, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.core.search;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
*
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
* @author bgheorgh
|
||||
*/
|
||||
import org.eclipse.cdt.internal.core.search.processing.*;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines the constants used by the search engine.
|
||||
* </p>
|
||||
* <p>
|
||||
* This interface declares constants only; it is not intended to be implemented.
|
||||
* </p>
|
||||
* @see org.eclipse.cdt.core.search.SearchEngine
|
||||
*/
|
||||
public interface ICSearchConstants {
|
||||
/**
|
||||
|
@ -34,37 +43,56 @@ public interface ICSearchConstants {
|
|||
int TYPE= 0;
|
||||
|
||||
/**
|
||||
* The searched element is a method.
|
||||
* The searched element is a function.
|
||||
*/
|
||||
int METHOD= 1;
|
||||
int FUNCTION= 1;
|
||||
|
||||
/**
|
||||
* The searched element is a package.
|
||||
*/
|
||||
//int PACKAGE= 2;
|
||||
|
||||
* The searched element is a namespace.
|
||||
*/
|
||||
int NAMESPACE= 2;
|
||||
|
||||
/**
|
||||
* The searched element is a constructor.
|
||||
*/
|
||||
int CONSTRUCTOR= 2;
|
||||
int CONSTRUCTOR= 3;
|
||||
|
||||
/**
|
||||
* The searched element is a field.
|
||||
* The searched element is a member.
|
||||
*/
|
||||
int MEMBER= 4;
|
||||
|
||||
/**
|
||||
* The searched element is a variable.
|
||||
* More selective than using TYPE
|
||||
*/
|
||||
int FIELD= 3;
|
||||
int VAR= 5;
|
||||
|
||||
/**
|
||||
* The searched element is a class.
|
||||
* More selective than using TYPE
|
||||
*/
|
||||
int CLASS= 4;
|
||||
int CLASS= 6;
|
||||
|
||||
/**
|
||||
* The searched element is an interface.
|
||||
* The searched element is a struct.
|
||||
* More selective than using TYPE
|
||||
*/
|
||||
int INTERFACE= 5;
|
||||
int STRUCT= 7;
|
||||
|
||||
/**
|
||||
* The searched element is a enum.
|
||||
* More selective than using TYPE
|
||||
*/
|
||||
int ENUM= 8;
|
||||
|
||||
/**
|
||||
* The searched element is a union.
|
||||
* More selective than using TYPE
|
||||
*/
|
||||
int UNION= 9;
|
||||
|
||||
|
||||
/* Nature of match */
|
||||
|
||||
/**
|
||||
|
@ -81,7 +109,7 @@ public interface ICSearchConstants {
|
|||
* rather exclusively search for classes implementing an interface, or interfaces
|
||||
* extending an interface.
|
||||
*/
|
||||
int IMPLEMENTORS= 1;
|
||||
int DEFINITIONS= 1;
|
||||
|
||||
/**
|
||||
* The search result is a reference.
|
||||
|
@ -100,23 +128,6 @@ public interface ICSearchConstants {
|
|||
*/
|
||||
int ALL_OCCURRENCES= 3;
|
||||
|
||||
/**
|
||||
* When searching for field matches, it will exclusively find read accesses, as
|
||||
* opposed to write accesses. Note that some expressions are considered both
|
||||
* as field read/write accesses: for example, x++; x+= 1;
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
int READ_ACCESSES = 4;
|
||||
|
||||
/**
|
||||
* When searching for field matches, it will exclusively find write accesses, as
|
||||
* opposed to read accesses. Note that some expressions are considered both
|
||||
* as field read/write accesses: for example, x++; x+= 1;
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
int WRITE_ACCESSES = 5;
|
||||
|
||||
/* Syntactic match modes */
|
||||
|
||||
|
@ -156,17 +167,17 @@ public interface ICSearchConstants {
|
|||
* has not finished indexing the workspace. Results will more likely
|
||||
* not contain all the matches.
|
||||
*/
|
||||
//int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
|
||||
int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
|
||||
/**
|
||||
* The search operation throws an <code>org.eclipse.core.runtime.OperationCanceledException</code>
|
||||
* if the underlying indexer has not finished indexing the workspace.
|
||||
*/
|
||||
//int CANCEL_IF_NOT_READY_TO_SEARCH = IJob.CancelIfNotReady;
|
||||
int CANCEL_IF_NOT_READY_TO_SEARCH = IJob.CancelIfNotReady;
|
||||
/**
|
||||
* The search operation waits for the underlying indexer to finish indexing
|
||||
* the workspace before starting the search.
|
||||
*/
|
||||
//int WAIT_UNTIL_READY_TO_SEARCH = IJob.WaitUntilReady;
|
||||
|
||||
int WAIT_UNTIL_READY_TO_SEARCH = IJob.WaitUntilReady;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2003 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corp. - Rational Software - initial implementation
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 13, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
*
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Util() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public static String bind(String string) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -52,15 +52,15 @@ public abstract class CSearchPattern
|
|||
case ICSearchConstants.TYPE:
|
||||
pattern = createTypePattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
break;
|
||||
case ICSearchConstants.METHOD:
|
||||
pattern = createMethodPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
break;
|
||||
//case ICSearchConstants.METHOD:
|
||||
// pattern = createMethodPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
// break;
|
||||
case ICSearchConstants.CONSTRUCTOR:
|
||||
pattern = createConstructorPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
break;
|
||||
case ICSearchConstants.FIELD:
|
||||
pattern = createFieldPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
break;
|
||||
//case ICSearchConstants.FIELD:
|
||||
// pattern = createFieldPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||
// break;
|
||||
}
|
||||
|
||||
return pattern;
|
||||
|
|
|
@ -9,19 +9,17 @@
|
|||
* IBM Corp. - Rational Software - initial implementation
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 13, 2003
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.processing;
|
||||
|
||||
/**
|
||||
* @author bgheorgh
|
||||
*/
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
*
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public interface IJob {
|
||||
|
||||
/* Waiting policies */
|
||||
int ForceImmediate = 1;
|
||||
int CancelIfNotReady = 2;
|
||||
|
@ -32,7 +30,7 @@ public interface IJob {
|
|||
boolean COMPLETE = true;
|
||||
|
||||
/**
|
||||
* Answer true if the job belongs to a given family (tag)
|
||||
* True if job belongs to the passed in jobFamily
|
||||
*/
|
||||
public boolean belongsTo(String jobFamily);
|
||||
/**
|
||||
|
@ -48,4 +46,5 @@ public interface IJob {
|
|||
* Answer whether the job is ready to run.
|
||||
*/
|
||||
public boolean isReadyToRun();
|
||||
|
||||
}
|
||||
|
|
|
@ -9,32 +9,426 @@
|
|||
* IBM Corp. - Rational Software - initial implementation
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 13, 2003
|
||||
* Created on May 30, 2003
|
||||
*/
|
||||
package org.eclipse.cdt.internal.core.search.processing;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
*
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class JobManager implements Runnable {
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.OperationCanceledException;
|
||||
import org.eclipse.core.runtime.SubProgressMonitor;
|
||||
import org.eclipse.cdt.internal.core.search.Util;
|
||||
|
||||
public abstract class JobManager implements Runnable {
|
||||
|
||||
/* queue of jobs to execute */
|
||||
protected IJob[] awaitingJobs = new IJob[10];
|
||||
protected int jobStart = 0;
|
||||
protected int jobEnd = -1;
|
||||
protected boolean executing = false;
|
||||
|
||||
/* background processing */
|
||||
protected Thread thread;
|
||||
|
||||
/* flag indicating whether job execution is enabled or not */
|
||||
private boolean enabled = true;
|
||||
|
||||
public static boolean VERBOSE = false;
|
||||
/* flag indicating that the activation has completed */
|
||||
public boolean activated = false;
|
||||
|
||||
private int awaitingClients = 0;
|
||||
|
||||
public static void verbose(String log) {
|
||||
System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Invoked exactly once, in background, before starting processing any job
|
||||
*/
|
||||
public JobManager() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
public void activateProcessing() {
|
||||
this.activated = true;
|
||||
}
|
||||
/**
|
||||
* Answer the amount of awaiting jobs.
|
||||
*/
|
||||
public synchronized int awaitingJobsCount() {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
// pretend busy in case concurrent job attempts performing before activated
|
||||
if (!activated)
|
||||
return 1;
|
||||
|
||||
return jobEnd - jobStart + 1;
|
||||
|
||||
}
|
||||
/**
|
||||
* Answers the first job in the queue, or null if there is no job available
|
||||
* Until the job has completed, the job manager will keep answering the same job.
|
||||
*/
|
||||
public synchronized IJob currentJob() {
|
||||
|
||||
if (!enabled)
|
||||
return null;
|
||||
|
||||
if (jobStart <= jobEnd) {
|
||||
return awaitingJobs[jobStart];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void disable() {
|
||||
enabled = false;
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("DISABLING background indexing"); //$NON-NLS-1$
|
||||
}
|
||||
/**
|
||||
* Remove the index from cache for a given project.
|
||||
* Passing null as a job family discards them all.
|
||||
*/
|
||||
public void discardJobs(String jobFamily) {
|
||||
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("DISCARD background job family - " + jobFamily); //$NON-NLS-1$
|
||||
|
||||
boolean wasEnabled = isEnabled();
|
||||
try {
|
||||
IJob currentJob;
|
||||
// cancel current job if it belongs to the given family
|
||||
synchronized(this){
|
||||
currentJob = this.currentJob();
|
||||
disable();
|
||||
}
|
||||
if (currentJob != null
|
||||
&& (jobFamily == null || currentJob.belongsTo(jobFamily))) {
|
||||
|
||||
currentJob.cancel();
|
||||
|
||||
// wait until current active job has finished
|
||||
while (thread != null && executing){
|
||||
try {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
Thread.sleep(50);
|
||||
} catch(InterruptedException e){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flush and compact awaiting jobs
|
||||
int loc = -1;
|
||||
synchronized(this) {
|
||||
for (int i = jobStart; i <= jobEnd; i++) {
|
||||
currentJob = awaitingJobs[i];
|
||||
awaitingJobs[i] = null;
|
||||
if (!(jobFamily == null
|
||||
|| currentJob.belongsTo(jobFamily))) { // copy down, compacting
|
||||
awaitingJobs[++loc] = currentJob;
|
||||
} else {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$
|
||||
currentJob.cancel();
|
||||
}
|
||||
}
|
||||
jobStart = 0;
|
||||
jobEnd = loc;
|
||||
}
|
||||
} finally {
|
||||
if (wasEnabled)
|
||||
enable();
|
||||
}
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("DISCARD DONE with background job family - " + jobFamily); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public synchronized void enable() {
|
||||
enabled = true;
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("ENABLING background indexing"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public synchronized boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
/**
|
||||
* Advance to the next available job, once the current one has been completed.
|
||||
* Note: clients awaiting until the job count is zero are still waiting at this point.
|
||||
*/
|
||||
protected synchronized void moveToNextJob() {
|
||||
|
||||
//if (!enabled) return;
|
||||
|
||||
if (jobStart <= jobEnd) {
|
||||
awaitingJobs[jobStart++] = null;
|
||||
if (jobStart > jobEnd) {
|
||||
jobStart = 0;
|
||||
jobEnd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* When idle, give chance to do something
|
||||
*/
|
||||
protected void notifyIdle(long idlingTime) {
|
||||
}
|
||||
/**
|
||||
* This API is allowing to run one job in concurrence with background processing.
|
||||
* Indeed since other jobs are performed in background, resource sharing might be
|
||||
* an issue.Therefore, this functionality allows a given job to be run without
|
||||
* colliding with background ones.
|
||||
* Note: multiple thread might attempt to perform concurrent jobs at the same time,
|
||||
* and should synchronize (it is deliberately left to clients to decide whether
|
||||
* concurrent jobs might interfere or not. In general, multiple read jobs are ok).
|
||||
*
|
||||
* Waiting policy can be:
|
||||
* IJobConstants.ForceImmediateSearch
|
||||
* IJobConstants.CancelIfNotReadyToSearch
|
||||
* IJobConstants.WaitUntilReadyToSearch
|
||||
*
|
||||
*/
|
||||
public boolean performConcurrentJob(
|
||||
IJob searchJob,
|
||||
int waitingPolicy,
|
||||
IProgressMonitor progress) {
|
||||
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("STARTING concurrent job - " + searchJob); //$NON-NLS-1$
|
||||
if (!searchJob.isReadyToRun()) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("ABORTED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||
return IJob.FAILED;
|
||||
}
|
||||
|
||||
int concurrentJobWork = 100;
|
||||
if (progress != null)
|
||||
progress.beginTask("", concurrentJobWork); //$NON-NLS-1$
|
||||
boolean status = IJob.FAILED;
|
||||
if (awaitingJobsCount() > 0) {
|
||||
switch (waitingPolicy) {
|
||||
|
||||
case IJob.ForceImmediate :
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$
|
||||
boolean wasEnabled = isEnabled();
|
||||
try {
|
||||
disable(); // pause indexing
|
||||
status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
|
||||
} finally {
|
||||
if (wasEnabled)
|
||||
enable();
|
||||
}
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||
return status;
|
||||
|
||||
case IJob.CancelIfNotReady :
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$
|
||||
if (progress != null) progress.setCanceled(true);
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||
throw new OperationCanceledException();
|
||||
|
||||
case IJob.WaitUntilReady :
|
||||
int awaitingWork;
|
||||
IJob previousJob = null;
|
||||
IJob currentJob;
|
||||
IProgressMonitor subProgress = null;
|
||||
int totalWork = this.awaitingJobsCount();
|
||||
if (progress != null && totalWork > 0) {
|
||||
subProgress = new SubProgressMonitor(progress, concurrentJobWork / 2);
|
||||
subProgress.beginTask("", totalWork); //$NON-NLS-1$
|
||||
concurrentJobWork = concurrentJobWork / 2;
|
||||
}
|
||||
int originalPriority = this.thread.getPriority();
|
||||
try {
|
||||
synchronized(this) {
|
||||
|
||||
// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
|
||||
Thread t = this.thread;
|
||||
if (t != null) {
|
||||
t.setPriority(Thread.currentThread().getPriority());
|
||||
}
|
||||
this.awaitingClients++;
|
||||
}
|
||||
while ((awaitingWork = awaitingJobsCount()) > 0) {
|
||||
if (subProgress != null && subProgress.isCanceled())
|
||||
throw new OperationCanceledException();
|
||||
currentJob = currentJob();
|
||||
// currentJob can be null when jobs have been added to the queue but job manager is not enabled
|
||||
if (currentJob != null && currentJob != previousJob) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$
|
||||
if (subProgress != null) {
|
||||
subProgress.subTask(
|
||||
Util.bind("manager.filesToIndex", Integer.toString(awaitingWork))); //$NON-NLS-1$
|
||||
subProgress.worked(1);
|
||||
}
|
||||
previousJob = currentJob;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
synchronized(this) {
|
||||
this.awaitingClients--;
|
||||
|
||||
// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
|
||||
Thread t = this.thread;
|
||||
if (t != null) {
|
||||
t.setPriority(originalPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subProgress != null) {
|
||||
subProgress.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
|
||||
if (progress != null) {
|
||||
progress.done();
|
||||
}
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||
return status;
|
||||
}
|
||||
|
||||
public abstract String processName();
|
||||
|
||||
public synchronized void request(IJob job) {
|
||||
if (!job.isReadyToRun()) {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("ABORTED request of background job - " + job); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
|
||||
// append the job to the list of ones to process later on
|
||||
int size = awaitingJobs.length;
|
||||
if (++jobEnd == size) { // when growing, relocate jobs starting at position 0
|
||||
jobEnd -= jobStart;
|
||||
System.arraycopy(
|
||||
awaitingJobs,
|
||||
jobStart,
|
||||
(awaitingJobs = new IJob[size * 2]),
|
||||
0,
|
||||
jobEnd);
|
||||
jobStart = 0;
|
||||
}
|
||||
awaitingJobs[jobEnd] = job;
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("REQUEST background job - " + job); //$NON-NLS-1$
|
||||
|
||||
}
|
||||
/**
|
||||
* Flush current state
|
||||
*/
|
||||
public void reset() {
|
||||
if (VERBOSE)
|
||||
JobManager.verbose("Reset"); //$NON-NLS-1$
|
||||
|
||||
if (thread != null) {
|
||||
discardJobs(null); // discard all jobs
|
||||
} else {
|
||||
/* initiate background processing */
|
||||
thread = new Thread(this, this.processName());
|
||||
thread.setDaemon(true);
|
||||
// less prioritary by default, priority is raised if clients are actively waiting on it
|
||||
thread.setPriority(Thread.NORM_PRIORITY-1);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Infinite loop performing resource indexing
|
||||
*/
|
||||
public void run() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
long idlingStart = -1;
|
||||
activateProcessing();
|
||||
try {
|
||||
while (this.thread != null) {
|
||||
try {
|
||||
IJob job;
|
||||
if ((job = currentJob()) == null) {
|
||||
if (idlingStart < 0)
|
||||
idlingStart = System.currentTimeMillis();
|
||||
notifyIdle(System.currentTimeMillis() - idlingStart);
|
||||
Thread.sleep(500);
|
||||
continue;
|
||||
} else {
|
||||
idlingStart = -1;
|
||||
}
|
||||
if (VERBOSE) {
|
||||
JobManager.verbose(awaitingJobsCount() + " awaiting jobs"); //$NON-NLS-1$
|
||||
JobManager.verbose("STARTING background job - " + job); //$NON-NLS-1$
|
||||
}
|
||||
try {
|
||||
executing = true;
|
||||
/*boolean status = */job.execute(null);
|
||||
//if (status == FAILED) request(job);
|
||||
} finally {
|
||||
executing = false;
|
||||
if (VERBOSE) {
|
||||
JobManager.verbose("FINISHED background job - " + job); //$NON-NLS-1$
|
||||
}
|
||||
moveToNextJob();
|
||||
if (this.awaitingClients == 0) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) { // background indexing was interrupted
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
if (this.thread != null) { // if not shutting down
|
||||
// log exception
|
||||
org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
|
||||
|
||||
// keep job manager alive
|
||||
this.discardJobs(null);
|
||||
this.thread = null;
|
||||
this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
|
||||
}
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
if (this.thread != null && !(e instanceof ThreadDeath)) {
|
||||
// log exception
|
||||
org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
|
||||
|
||||
// keep job manager alive
|
||||
this.discardJobs(null);
|
||||
this.thread = null;
|
||||
this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Stop background processing, and wait until the current job is completed before returning
|
||||
*/
|
||||
public void shutdown() {
|
||||
|
||||
disable();
|
||||
discardJobs(null); // will wait until current executing job has completed
|
||||
Thread thread = this.thread;
|
||||
this.thread = null; // mark the job manager as shutting down so that the thread will stop by itself
|
||||
try {
|
||||
if (thread != null) { // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=31858
|
||||
thread.join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(10);
|
||||
buffer.append("Enabled:").append(this.enabled).append('\n'); //$NON-NLS-1$
|
||||
int numJobs = jobEnd - jobStart + 1;
|
||||
buffer.append("Jobs in queue:").append(numJobs).append('\n'); //$NON-NLS-1$
|
||||
for (int i = 0; i < numJobs && i < 15; i++) {
|
||||
buffer.append(i).append(" - job["+i+"]: ").append(awaitingJobs[jobStart+i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -139,7 +139,10 @@ public class CCorePlugin extends Plugin {
|
|||
// Fired up the indexer. It should delay itself for 10 seconds
|
||||
fIndexModel = IndexModel.getDefault();
|
||||
fIndexModel.startup();
|
||||
|
||||
|
||||
//Fired up the new indexer
|
||||
fCoreModel.startIndexing();
|
||||
|
||||
fDescriptorManager = new CDescriptorManager();
|
||||
fDescriptorManager.startup();
|
||||
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
Began structuring expressions and declarators in Parser for ISourceElementRequestor.
|
||||
Updated other packages to use new interfaces.
|
||||
|
||||
2003-06-25 Bogdan Gheorghe
|
||||
Added a new checkbox to the Indexer tab of the C/C++ Project Settings
|
||||
to allow the new indexer to be turned on or off.
|
||||
* src/org/eclipse/cdt/ui/wizards/IndexerBlock.java
|
||||
|
||||
Modified the CSearchPage to work with the new CSearchConstants
|
||||
* src/org/eclipse/cdt/internal/ui/search/CSearchPage.java
|
||||
|
||||
2003-06-24 Thomas Fletcher
|
||||
|
||||
- Proposals will now include additional help information with them
|
||||
|
|
|
@ -161,8 +161,8 @@ public class CSearchPage extends DialogPage implements ISearchPage, ICSearchCons
|
|||
};
|
||||
|
||||
fSearchFor[ TYPE ].addSelectionListener(cElementInitializer);
|
||||
fSearchFor[ METHOD ].addSelectionListener(cElementInitializer);
|
||||
fSearchFor[ FIELD ].addSelectionListener(cElementInitializer);
|
||||
fSearchFor[ FUNCTION ].addSelectionListener(cElementInitializer);
|
||||
fSearchFor[ MEMBER ].addSelectionListener(cElementInitializer);
|
||||
fSearchFor[CONSTRUCTOR].addSelectionListener(cElementInitializer);
|
||||
//fSearchFor[ PACKAGE ].addSelectionListener(cElementInitializer);
|
||||
|
||||
|
@ -283,34 +283,34 @@ public class CSearchPage extends DialogPage implements ISearchPage, ICSearchCons
|
|||
}
|
||||
private void setLimitTo(int searchFor) {
|
||||
fLimitTo[ DECLARATIONS ].setEnabled( true );
|
||||
fLimitTo[ IMPLEMENTORS ].setEnabled( false);
|
||||
//fLimitTo[ IMPLEMENTORS ].setEnabled( false);
|
||||
fLimitTo[ REFERENCES ].setEnabled( true );
|
||||
fLimitTo[ ALL_OCCURRENCES ].setEnabled( true );
|
||||
fLimitTo[ READ_ACCESSES ].setEnabled( false);
|
||||
fLimitTo[ WRITE_ACCESSES ].setEnabled( false);
|
||||
//fLimitTo[ READ_ACCESSES ].setEnabled( false);
|
||||
//fLimitTo[ WRITE_ACCESSES ].setEnabled( false);
|
||||
|
||||
if (!(searchFor == TYPE || searchFor == INTERFACE) && fLimitTo[IMPLEMENTORS].getSelection()) {
|
||||
fLimitTo[ IMPLEMENTORS ].setSelection(false);
|
||||
fLimitTo[ REFERENCES ].setSelection(true);
|
||||
}
|
||||
|
||||
if (!(searchFor == FIELD) && (getLimitTo() == READ_ACCESSES || getLimitTo() == WRITE_ACCESSES)) {
|
||||
fLimitTo[ getLimitTo()].setSelection(false);
|
||||
fLimitTo[ REFERENCES ].setSelection(true);
|
||||
}
|
||||
|
||||
switch (searchFor) {
|
||||
case TYPE:
|
||||
case INTERFACE:
|
||||
fLimitTo[ IMPLEMENTORS ].setEnabled(true);
|
||||
break;
|
||||
case FIELD:
|
||||
fLimitTo[ READ_ACCESSES ].setEnabled(true);
|
||||
fLimitTo[ WRITE_ACCESSES ].setEnabled(true);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
// if (!(searchFor == TYPE || searchFor == INTERFACE) && fLimitTo[IMPLEMENTORS].getSelection()) {
|
||||
// fLimitTo[ IMPLEMENTORS ].setSelection(false);
|
||||
// fLimitTo[ REFERENCES ].setSelection(true);
|
||||
// }
|
||||
//
|
||||
// if (!(searchFor == FIELD) && (getLimitTo() == READ_ACCESSES || getLimitTo() == WRITE_ACCESSES)) {
|
||||
// fLimitTo[ getLimitTo()].setSelection(false);
|
||||
// fLimitTo[ REFERENCES ].setSelection(true);
|
||||
// }
|
||||
//
|
||||
// switch (searchFor) {
|
||||
// case TYPE:
|
||||
// case INTERFACE:
|
||||
// fLimitTo[ IMPLEMENTORS ].setEnabled(true);
|
||||
// break;
|
||||
// case FIELD:
|
||||
// fLimitTo[ READ_ACCESSES ].setEnabled(true);
|
||||
// fLimitTo[ WRITE_ACCESSES ].setEnabled(true);
|
||||
// break;
|
||||
// default :
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
private Control createSearchFor(Composite parent) {
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.eclipse.cdt.ui.wizards;
|
|||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.index.IndexModel;
|
||||
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||
import org.eclipse.cdt.utils.ui.swt.IValidation;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
@ -18,6 +19,7 @@ import org.eclipse.swt.widgets.Composite;
|
|||
|
||||
public class IndexerBlock implements IWizardTab {
|
||||
private Button indexerSwitch;
|
||||
private Button indexerSwitch2;
|
||||
IProject project;
|
||||
IValidation page;
|
||||
|
||||
|
@ -39,8 +41,13 @@ public class IndexerBlock implements IWizardTab {
|
|||
|
||||
indexerSwitch = new Button(composite, SWT.CHECK | SWT.RIGHT);
|
||||
indexerSwitch.setAlignment(SWT.LEFT);
|
||||
indexerSwitch.setText("Enable indexing service for this project");
|
||||
indexerSwitch.setText("Enable CTAGS indexing service for this project");
|
||||
indexerSwitch.setSelection(indexer.isEnabled(project));
|
||||
|
||||
indexerSwitch2 = new Button(composite, SWT.CHECK | SWT.RIGHT);
|
||||
indexerSwitch2.setAlignment(SWT.LEFT);
|
||||
indexerSwitch2.setText("Enable NEW indexing service for this project");
|
||||
indexerSwitch2.setSelection(false);
|
||||
return composite;
|
||||
}
|
||||
|
||||
|
@ -50,6 +57,9 @@ public class IndexerBlock implements IWizardTab {
|
|||
public void doRun(IProject project, IProgressMonitor monitor) {
|
||||
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
||||
indexer.setEnabled(project, indexerSwitch.getSelection());
|
||||
|
||||
IndexManager newIndexer = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||
newIndexer.setEnabled(project, indexerSwitch2.getSelection());
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,12 +89,21 @@ public class IndexerBlock implements IWizardTab {
|
|||
*/
|
||||
public void setVisible(boolean visible) {
|
||||
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
||||
|
||||
IndexManager newIndexer = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||
|
||||
if (indexerSwitch != null) {
|
||||
//indexerSwitch.setAlignment(SWT.LEFT);
|
||||
//indexerSwitch.setText("Enable indexing service for this project");
|
||||
indexerSwitch.setSelection(indexer.isEnabled(project));
|
||||
}
|
||||
|
||||
if (indexerSwitch2 != null) {
|
||||
//indexerSwitch.setAlignment(SWT.LEFT);
|
||||
//indexerSwitch.setText("Enable indexing service for this project");
|
||||
indexerSwitch2.setSelection(newIndexer.isEnabled(project));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue