when enumerating nontrivial key, instead of valueOf / equals on existing previous key do compare serialized bytes of current key with previous one

This commit is contained in:
Maxim.Mossienko
2012-06-07 17:23:07 +04:00
parent dcf8774575
commit db8aadc5e3
3 changed files with 71 additions and 14 deletions
@@ -2,6 +2,7 @@ package com.intellij.psi.search;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.indexing.*;
@@ -79,7 +80,18 @@ public class FileTypeIndex extends ScalarIndexExtension<FileType>
@Override
public FileType read(DataInput in) throws IOException {
return myFileTypeManager.getStdFileType(myEnumeratorStringDescriptor.read(in));
String read = myEnumeratorStringDescriptor.read(in);
FileType type = myFileTypeManager.getStdFileType(read);
// TODO: Abstract file types are not std one, so need to be restored specially,
// currently there are 6 of them and restoration does not happen very often so just iteration is enough
if (type == PlainTextFileType.INSTANCE && !read.equals(type.getName())) {
for(FileType fileType:myFileTypeManager.getRegisteredFileTypes()) {
if (read.equals(fileType.getName())) {
return fileType;
}
}
}
return type;
}
@Override
@@ -281,24 +281,21 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
return NULL_ID;
}
int indexNodeValueAddress = hasMapping ? myResultBuf[0]:0;
final int indexNodeValueAddress = hasMapping ? myResultBuf[0]:0;
int collisionAddress = NULL_ID;
Data existingData = null;
boolean hasExistingData = false;
if (!myInlineKeysNoMapping) {
collisionAddress = NULL_ID;
if (indexNodeValueAddress > 0) {
// we found reference to no dupe key
Data candidate = valueOf(indexNodeValueAddress);
if (IntToIntBtree.doSanityCheck) IntToIntBtree.myAssert(myDataDescriptor.getHashCode(candidate) == valueHC);
if (myDataDescriptor.isEqual(value, candidate)) {
if (isKeyAtIndex(value, indexNodeValueAddress)) {
if (!saveNewValue) {
++myExistingKeysEnumerated;
return indexNodeValueAddress;
}
existingData = candidate;
hasExistingData = true;
}
collisionAddress = indexNodeValueAddress;
@@ -307,13 +304,11 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
while (true) {
final int address = myStorage.getInt(collisionAddress);
Data candidate = valueOf(address);
if (myDataDescriptor.isEqual(value, candidate)) {
if (isKeyAtIndex(value, address)) {
if (!saveNewValue) return address;
existingData = candidate;
hasExistingData = true;
break;
}
if (IntToIntBtree.doSanityCheck) IntToIntBtree.myAssert(myDataDescriptor.getHashCode(candidate) == valueHC);
int newCollisionAddress = myStorage.getInt(collisionAddress + COLLISION_OFFSET);
if (newCollisionAddress == 0) break;
@@ -325,7 +320,7 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
} else {
if (hasMapping) {
if(!saveNewValue) return indexNodeValueAddress;
existingData = value;
hasExistingData = true;
}
}
@@ -344,7 +339,7 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
}
if (collisionAddress != NULL_ID) {
if (existingData != null) {
if (hasExistingData) {
if (indexNodeValueAddress > 0) {
btree.put(valueHC, newValueId);
} else {
@@ -369,6 +369,56 @@ abstract class PersistentEnumeratorBase<Data> implements Forceable, Closeable {
protected abstract int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue) throws IOException;
protected boolean isKeyAtIndex(Data value, int idx) throws IOException {
if (myKeyStorage == null) return false;
// check if previous serialized state is the same as for value
// this is much faster than myDataDescriptor.isEqualTo(valueOf(idx), value)
final boolean sameValue[] = new boolean[1]; // TODO: key storage lock
final int addr = indexToAddr(idx);
OutputStream comparer;
if (myKeyStoreFileLength <= addr) {
comparer = new OutputStream() {
int address = addr - myKeyStoreFileLength;
boolean same = true;
@Override
public void write(int b) throws IOException {
if (same) {
same = address < myKeyStoreBufferPosition && myKeyStoreFileBuffer[address++] == (byte)b;
}
}
@Override
public void close() throws IOException {
sameValue[0] = same;
}
};
} else {
comparer = new OutputStream() {
int address = addr;
boolean same = true;
@Override
public void write(int b) throws IOException {
if (same) {
same = address < myKeyStoreFileLength && myKeyStorage.get(address++) == (byte)b;
}
}
@Override
public void close() throws IOException {
sameValue[0] = same;
}
};
}
DataOutput out = new DataOutputStream(comparer);
myDataDescriptor.save(out, value);
comparer.close();
return sameValue[0];
}
protected int writeData(final Data value, int hashCode) {
try {
markDirty(true);