mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
less garbage and synchronization during building indexed
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
package org.intellij.images.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -65,7 +66,7 @@ public class ImageInfoReader {
|
||||
|
||||
@Nullable
|
||||
private static Info read(@NotNull final byte[] data) {
|
||||
final DataInputStream is = new DataInputStream(new ByteArrayInputStream(data));
|
||||
final DataInputStream is = new DataInputStream(new UnsyncByteArrayInputStream(data));
|
||||
try {
|
||||
return readFileData(is);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
package com.intellij.psi.stubs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
@@ -45,7 +46,7 @@ public class SerializedStubTree {
|
||||
}
|
||||
|
||||
public StubElement getStub() {
|
||||
return SerializationManager.getInstance().deserialize(new ByteArrayInputStream(myBytes));
|
||||
return SerializationManager.getInstance().deserialize(new UnsyncByteArrayInputStream(myBytes));
|
||||
}
|
||||
|
||||
public boolean equals(final Object that) {
|
||||
|
||||
+3
-4
@@ -15,17 +15,16 @@
|
||||
*/
|
||||
package com.intellij.openapi.util.io;
|
||||
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
public class BufferExposingByteArrayInputStream extends ByteArrayInputStream {
|
||||
public class BufferExposingByteArrayInputStream extends UnsyncByteArrayInputStream {
|
||||
public BufferExposingByteArrayInputStream(@NotNull byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public byte[] getInternalBuffer() {
|
||||
return buf;
|
||||
return myBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-9
@@ -15,13 +15,11 @@
|
||||
*/
|
||||
package com.intellij.openapi.util.io;
|
||||
|
||||
import com.intellij.util.io.UnsyncByteArrayOutputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class BufferExposingByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
public BufferExposingByteArrayOutputStream() {
|
||||
}
|
||||
public class BufferExposingByteArrayOutputStream extends UnsyncByteArrayOutputStream {
|
||||
public BufferExposingByteArrayOutputStream() {}
|
||||
|
||||
public BufferExposingByteArrayOutputStream(int size) {
|
||||
super(size);
|
||||
@@ -29,14 +27,14 @@ public class BufferExposingByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
|
||||
@NotNull
|
||||
public byte[] getInternalBuffer() {
|
||||
return buf;
|
||||
return myBuffer;
|
||||
}
|
||||
|
||||
// moves back the written bytes pointer by {@link #size}, to "unwrite" last {@link #size} bytes
|
||||
public int backOff(int size) {
|
||||
assert size >= 0 : size;
|
||||
count -= size;
|
||||
assert count >= 0 : count;
|
||||
return count;
|
||||
myCount -= size;
|
||||
assert myCount >= 0 : myCount;
|
||||
return myCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -130,10 +129,11 @@ class IntToIntBtree {
|
||||
return pageStart;
|
||||
}
|
||||
|
||||
public @Nullable Integer get(int key) {
|
||||
public boolean get(int key, int[] result) {
|
||||
if (hasCachedMappings) {
|
||||
if (myCachedMappings.containsKey(key)) {
|
||||
return myCachedMappings.get(key);
|
||||
result[0] = myCachedMappings.get(key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +141,9 @@ class IntToIntBtree {
|
||||
currentIndexNode.setAddress(root.address);
|
||||
int index = currentIndexNode.locate(key, false);
|
||||
|
||||
if (index < 0) return null;
|
||||
return currentIndexNode.addressAt(index);
|
||||
if (index < 0) return false;
|
||||
result[0] = currentIndexNode.addressAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void put(int key, int value) {
|
||||
|
||||
@@ -186,9 +186,11 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
|
||||
out:
|
||||
for(IntToIntBtree.BtreeIndexNodeView page:leafPages) {
|
||||
for(int key:page.exportKeys()) {
|
||||
Integer record = btree.get(key);
|
||||
boolean hasMapping = btree.get(key, myResultBuf);
|
||||
p.setCurrentKey(key);
|
||||
assert record != null;
|
||||
assert hasMapping;
|
||||
int record = myResultBuf[0];
|
||||
|
||||
if (record > 0) {
|
||||
if (!p.process(record)) return false;
|
||||
} else {
|
||||
@@ -259,22 +261,23 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
|
||||
return super.getValue(keyId, processingKey);
|
||||
}
|
||||
|
||||
private final int[] myResultBuf = new int[1];
|
||||
|
||||
protected synchronized int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue) throws IOException {
|
||||
synchronized (ourLock) {
|
||||
if (IntToIntBtree.doDump) System.out.println(value);
|
||||
final int valueHC = myDataDescriptor.getHashCode(value);
|
||||
|
||||
final Integer keyValue = btree.get(valueHC);
|
||||
if (keyValue == null && onlyCheckForExisting) {
|
||||
final boolean hasMapping = btree.get(valueHC, myResultBuf);
|
||||
if (!hasMapping && onlyCheckForExisting) {
|
||||
return NULL_ID;
|
||||
}
|
||||
|
||||
int indexNodeValueAddress = keyValue != null ? keyValue:0;
|
||||
int indexNodeValueAddress = hasMapping ? myResultBuf[0]:0;
|
||||
int collisionAddress = NULL_ID;
|
||||
Data existingData = null;
|
||||
|
||||
if (!myInlineKeysNoMapping) {
|
||||
indexNodeValueAddress = keyValue != null ? keyValue:0;
|
||||
collisionAddress = NULL_ID;
|
||||
|
||||
if (indexNodeValueAddress > 0) {
|
||||
@@ -309,7 +312,7 @@ public class PersistentBTreeEnumerator<Data> extends PersistentEnumeratorBase<Da
|
||||
|
||||
if (onlyCheckForExisting) return NULL_ID;
|
||||
} else {
|
||||
if (keyValue != null) {
|
||||
if (hasMapping) {
|
||||
if(!saveNewValue) return indexNodeValueAddress;
|
||||
existingData = value;
|
||||
}
|
||||
|
||||
@@ -69,25 +69,12 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
super(new BufferExposingByteArrayOutputStream());
|
||||
}
|
||||
|
||||
public int getBufferSize() {
|
||||
return ((ByteArrayOutputStream)out).size();
|
||||
private void reset() {
|
||||
((UnsyncByteArrayOutputStream)out).reset();
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream stream) throws IOException {
|
||||
((ByteArrayOutputStream)out).writeTo(stream);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
((ByteArrayOutputStream)out).reset();
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return ((ByteArrayOutputStream)out).toByteArray();
|
||||
}
|
||||
|
||||
public ByteSequence getInternalBuffer() {
|
||||
final BufferExposingByteArrayOutputStream _out = (BufferExposingByteArrayOutputStream)out;
|
||||
return new ByteSequence(_out.getInternalBuffer(), 0, _out.size());
|
||||
private BufferExposingByteArrayOutputStream getInternalBuffer() {
|
||||
return (BufferExposingByteArrayOutputStream)out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,16 +97,14 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
protected void onDropFromCache(final Key key, final AppendStream value) {
|
||||
synchronized (PersistentEnumerator.ourLock) {
|
||||
try {
|
||||
final ByteSequence bytes = value.getInternalBuffer();
|
||||
final BufferExposingByteArrayOutputStream bytes = value.getInternalBuffer();
|
||||
final int id = enumerate(key);
|
||||
HeaderRecord oldHeaderRecord = readValueId(id);
|
||||
long oldHeaderRecord = readValueId(id);
|
||||
|
||||
HeaderRecord headerRecord = new HeaderRecord(
|
||||
myValueStorage.appendBytes(bytes, oldHeaderRecord.address)
|
||||
);
|
||||
long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), oldHeaderRecord);
|
||||
|
||||
updateValueId(id, headerRecord, oldHeaderRecord, key, 0);
|
||||
if (oldHeaderRecord == HeaderRecord.EMPTY) {
|
||||
if (oldHeaderRecord == NULL_ADDR) {
|
||||
myLiveAndGarbageKeysCounter += LIVE_KEY_MASK;
|
||||
}
|
||||
|
||||
@@ -266,18 +251,18 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
|
||||
final AppendStream record = new AppendStream();
|
||||
myValueExternalizer.save(record, value);
|
||||
final ByteSequence bytes = record.getInternalBuffer();
|
||||
final BufferExposingByteArrayOutputStream bytes = record.getInternalBuffer();
|
||||
final int id = enumerate(key);
|
||||
|
||||
HeaderRecord oldheader = readValueId(id);
|
||||
if (oldheader != HeaderRecord.EMPTY) {
|
||||
long oldheader = readValueId(id);
|
||||
if (oldheader != NULL_ADDR) {
|
||||
myLiveAndGarbageKeysCounter++;
|
||||
}
|
||||
else {
|
||||
myLiveAndGarbageKeysCounter += LIVE_KEY_MASK;
|
||||
}
|
||||
|
||||
HeaderRecord header = new HeaderRecord(myValueStorage.appendBytes(bytes, 0));
|
||||
long header = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), 0);
|
||||
|
||||
updateValueId(id, header, oldheader, key, 0);
|
||||
}
|
||||
@@ -330,41 +315,39 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
myAppendCache.clear();
|
||||
return myEnumerator.processAllDataObject(processor, new PersistentEnumerator.DataFilter() {
|
||||
public boolean accept(final int id) {
|
||||
return readValueId(id).address != NULL_ADDR;
|
||||
return readValueId(id) != NULL_ADDR;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public final Value get(Key key) throws IOException {
|
||||
public final @Nullable Value get(Key key) throws IOException {
|
||||
synchronized (myEnumerator) {
|
||||
return doGet(key);
|
||||
}
|
||||
}
|
||||
|
||||
protected Value doGet(Key key) throws IOException {
|
||||
protected @Nullable Value doGet(Key key) throws IOException {
|
||||
synchronized (PersistentEnumerator.ourLock) {
|
||||
myAppendCache.remove(key);
|
||||
final int id = tryEnumerate(key);
|
||||
if (id == PersistentEnumerator.NULL_ID) {
|
||||
return null;
|
||||
}
|
||||
final HeaderRecord oldHeader = readValueId(id);
|
||||
if (oldHeader.address == PersistentEnumerator.NULL_ID) {
|
||||
final long oldHeader = readValueId(id);
|
||||
if (oldHeader == PersistentEnumerator.NULL_ID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Pair<Long, byte[]> readResult = myValueStorage.readBytes(oldHeader.address);
|
||||
if (readResult.first != null && readResult.first != oldHeader.address) {
|
||||
Pair<Long, byte[]> readResult = myValueStorage.readBytes(oldHeader);
|
||||
if (readResult.first != null && readResult.first != oldHeader) {
|
||||
myEnumerator.markDirty(true);
|
||||
|
||||
updateValueId(id, new HeaderRecord(readResult.first), oldHeader, key, 0);
|
||||
if (oldHeader != HeaderRecord.EMPTY) {
|
||||
myLiveAndGarbageKeysCounter++;
|
||||
}
|
||||
updateValueId(id, readResult.first, oldHeader, key, 0);
|
||||
myLiveAndGarbageKeysCounter++;
|
||||
}
|
||||
|
||||
final DataInputStream input = new DataInputStream(new ByteArrayInputStream(readResult.second));
|
||||
final DataInputStream input = new DataInputStream(new UnsyncByteArrayInputStream(readResult.second));
|
||||
try {
|
||||
return myValueExternalizer.read(input);
|
||||
}
|
||||
@@ -387,7 +370,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
if (id == PersistentEnumerator.NULL_ID) {
|
||||
return false;
|
||||
}
|
||||
return readValueId(id).address != NULL_ADDR;
|
||||
return readValueId(id) != NULL_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,12 +389,12 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
}
|
||||
myEnumerator.markDirty(true);
|
||||
|
||||
final HeaderRecord record = readValueId(id);
|
||||
if (record != HeaderRecord.EMPTY) {
|
||||
final long record = readValueId(id);
|
||||
if (record != NULL_ADDR) {
|
||||
myLiveAndGarbageKeysCounter++;
|
||||
}
|
||||
|
||||
updateValueId(id, HeaderRecord.EMPTY, record, key, 0);
|
||||
updateValueId(id, NULL_ADDR, record, key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,10 +456,10 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
|
||||
traverseAllRecords(new PersistentEnumerator.RecordsProcessor() {
|
||||
public boolean process(final int keyId) throws IOException {
|
||||
final HeaderRecord record = readValueId(keyId);
|
||||
if (record.address != NULL_ADDR) {
|
||||
Pair<Long, byte[]> readResult = myValueStorage.readBytes(record.address);
|
||||
HeaderRecord value = new HeaderRecord(newStorage.appendBytes(new ByteSequence(readResult.second), 0));
|
||||
final long record = readValueId(keyId);
|
||||
if (record != NULL_ADDR) {
|
||||
Pair<Long, byte[]> readResult = myValueStorage.readBytes(record);
|
||||
long value = newStorage.appendBytes(new ByteSequence(readResult.second), 0);
|
||||
updateValueId(keyId, value, record, null, getCurrentKey());
|
||||
myLiveAndGarbageKeysCounter += LIVE_KEY_MASK;
|
||||
}
|
||||
@@ -496,10 +479,10 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
}
|
||||
}
|
||||
|
||||
private HeaderRecord readValueId(final int keyId) {
|
||||
private long readValueId(final int keyId) {
|
||||
long address = myEnumerator.myStorage.getInt(keyId + myParentValueRefOffset);
|
||||
if (address == 0 || address == -POSITIVE_VALUE_SHIFT) {
|
||||
return HeaderRecord.EMPTY;
|
||||
return NULL_ADDR;
|
||||
}
|
||||
|
||||
if (address < 0) {
|
||||
@@ -509,7 +492,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
address = ((address << 32) + value) & ~USED_LONG_VALUE_MASK;
|
||||
}
|
||||
|
||||
return new HeaderRecord(address);
|
||||
return address;
|
||||
}
|
||||
|
||||
private int smallKeys;
|
||||
@@ -517,19 +500,19 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
private int transformedKeys;
|
||||
private int requests;
|
||||
|
||||
private int updateValueId(int keyId, HeaderRecord value, HeaderRecord oldValue, @Nullable Key key, int processingKey) throws IOException {
|
||||
final boolean newKey = oldValue == null || oldValue.address == NULL_ADDR;
|
||||
private int updateValueId(int keyId, long value, long oldValue, @Nullable Key key, int processingKey) throws IOException {
|
||||
final boolean newKey = oldValue == NULL_ADDR;
|
||||
if (newKey) ++requests;
|
||||
boolean defaultSizeInfo = true;
|
||||
|
||||
if (myCanReEnumerate) {
|
||||
if (canUseIntAddressForNewRecord(value.address)) {
|
||||
if (canUseIntAddressForNewRecord(value)) {
|
||||
defaultSizeInfo = false;
|
||||
myEnumerator.myStorage.putInt(keyId + myParentValueRefOffset, -(int)(value.address + POSITIVE_VALUE_SHIFT));
|
||||
myEnumerator.myStorage.putInt(keyId + myParentValueRefOffset, -(int)(value + POSITIVE_VALUE_SHIFT));
|
||||
if (newKey) ++smallKeys;
|
||||
} else {
|
||||
if (newKey && myWatermarkId == 0) myWatermarkId = keyId;
|
||||
if (keyId < myWatermarkId && (oldValue == null || canUseIntAddressForNewRecord(oldValue.address))) {
|
||||
if (keyId < myWatermarkId && (oldValue == NULL_ADDR || canUseIntAddressForNewRecord(oldValue))) {
|
||||
// keyId is result of enumerate, if we do reenumerate then it is no longer accessible unless somebody cached it
|
||||
myIntAddressForNewRecord = false;
|
||||
keyId = myEnumerator.reenumerate(key == null ? myEnumerator.getValue(keyId, processingKey) : key);
|
||||
@@ -539,7 +522,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
}
|
||||
|
||||
if (defaultSizeInfo) {
|
||||
myEnumerator.myStorage.putLong(keyId + myParentValueRefOffset, value.address | USED_LONG_VALUE_MASK);
|
||||
myEnumerator.myStorage.putLong(keyId + myParentValueRefOffset, value | USED_LONG_VALUE_MASK);
|
||||
if (newKey) ++largeKeys;
|
||||
}
|
||||
|
||||
@@ -548,21 +531,11 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
",@"+getBaseFile().getPath());
|
||||
}
|
||||
if (doHardConsistencyChecks) {
|
||||
HeaderRecord checkRecord = readValueId(keyId);
|
||||
if (checkRecord.address != value.address) {
|
||||
assert false:value.address;
|
||||
long checkRecord = readValueId(keyId);
|
||||
if (checkRecord != value) {
|
||||
assert false:value;
|
||||
}
|
||||
}
|
||||
return keyId;
|
||||
}
|
||||
|
||||
private static class HeaderRecord {
|
||||
final long address;
|
||||
|
||||
HeaderRecord(long address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
static final HeaderRecord EMPTY = new HeaderRecord(NULL_ADDR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,13 @@ public class PersistentHashMapValueStorage {
|
||||
private static final int INT_LENGTH_LONG_ADDRESS = 4 + 8;
|
||||
|
||||
public long appendBytes(ByteSequence data, long prevChunkAddress) throws IOException {
|
||||
return appendBytes(data.getBytes(), data.getOffset(), data.getLength(), prevChunkAddress);
|
||||
}
|
||||
|
||||
public long appendBytes(byte[] data, int offset, int dataLength, long prevChunkAddress) throws IOException {
|
||||
assert !myCompactionMode;
|
||||
long result = mySize;
|
||||
final CacheValue<DataOutputStream> appender = ourAppendersCache.get(myPath);
|
||||
int dataLength = data.getLength();
|
||||
int serviceFieldsSizeIncrease;
|
||||
|
||||
try {
|
||||
@@ -102,7 +105,7 @@ public class PersistentHashMapValueStorage {
|
||||
dataOutputStream.writeLong(prevChunkAddress);
|
||||
serviceFieldsSizeIncrease = INT_LENGTH_LONG_ADDRESS;
|
||||
}
|
||||
dataOutputStream.write(data.getBytes(), data.getOffset(), dataLength);
|
||||
dataOutputStream.write(data, offset, dataLength);
|
||||
if (requests % IOStatistics.KEYS_FACTOR == 0 && IOStatistics.DEBUG) {
|
||||
IOStatistics.dump("Small writes:"+smallWritesCount +", bytes:"+smallWrites + ", largeWrites:"+largeWritesCount
|
||||
+ ", bytes:"+largeWrites+", total:"+requests + "@"+myFile.getPath());
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.intellij.util.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class UnsyncByteArrayInputStream extends InputStream {
|
||||
protected byte[] myBuffer;
|
||||
private int myPosition;
|
||||
private int myCount;
|
||||
private int myMarkedPosition;
|
||||
|
||||
public UnsyncByteArrayInputStream(byte buf[]) {
|
||||
this.myBuffer = buf;
|
||||
this.myPosition = 0;
|
||||
this.myCount = buf.length;
|
||||
}
|
||||
|
||||
public int read() {
|
||||
return (myPosition < myCount) ? (myBuffer[myPosition++] & 0xff) : -1;
|
||||
}
|
||||
|
||||
public int read(byte b[], int off, int len) {
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if (off < 0 || len < 0 || len > b.length - off) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (myPosition >= myCount) {
|
||||
return -1;
|
||||
}
|
||||
if (myPosition + len > myCount) {
|
||||
len = myCount - myPosition;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
System.arraycopy(myBuffer, myPosition, b, off, len);
|
||||
myPosition += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
public long skip(long n) {
|
||||
if (myPosition + n > myCount) {
|
||||
n = myCount - myPosition;
|
||||
}
|
||||
if (n < 0) {
|
||||
return 0;
|
||||
}
|
||||
myPosition += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
public int available() {
|
||||
return myCount - myPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
myMarkedPosition = myPosition;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myPosition = myMarkedPosition;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class UnsyncByteArrayOutputStream extends OutputStream {
|
||||
protected byte[] myBuffer;
|
||||
protected int myCount;
|
||||
|
||||
public UnsyncByteArrayOutputStream() {
|
||||
this(32);
|
||||
}
|
||||
|
||||
public UnsyncByteArrayOutputStream(int size) {
|
||||
myBuffer = new byte[size];
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
int newcount = myCount + 1;
|
||||
if (newcount > myBuffer.length) {
|
||||
myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount));
|
||||
}
|
||||
myBuffer[myCount] = (byte)b;
|
||||
myCount = newcount;
|
||||
}
|
||||
|
||||
public void write(byte b[], int off, int len) {
|
||||
if ((off < 0) || (off > b.length) || (len < 0) ||
|
||||
((off + len) > b.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
int newcount = myCount + len;
|
||||
if (newcount > myBuffer.length) {
|
||||
myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount));
|
||||
}
|
||||
System.arraycopy(b, off, myBuffer, myCount, len);
|
||||
myCount = newcount;
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
out.write(myBuffer, 0, myCount);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myCount = 0;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return Arrays.copyOf(myBuffer, myCount);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return myCount;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String(myBuffer, 0, myCount);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.io.PagePool;
|
||||
import com.intellij.util.io.RecordDataOutput;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.*;
|
||||
@@ -228,7 +229,7 @@ public abstract class AbstractStorage implements Disposable, Forceable {
|
||||
|
||||
public DataInputStream readStream(int record) throws IOException {
|
||||
final byte[] bytes = readBytes(record);
|
||||
return new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
return new DataInputStream(new UnsyncByteArrayInputStream(bytes));
|
||||
}
|
||||
|
||||
protected byte[] readBytes(int record) throws IOException {
|
||||
|
||||
@@ -5,10 +5,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.StreamUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.xml.NanoXmlUtil;
|
||||
import net.n3.nanoxml.StdXMLReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -91,7 +88,7 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesInd
|
||||
private static MyIXMLBuilderAdapter parse(byte[] bytes, boolean stopIfAccepted) {
|
||||
StdXMLReader reader;
|
||||
try {
|
||||
reader = new StdXMLReader(new ByteArrayInputStream(bytes)) {
|
||||
reader = new StdXMLReader(new UnsyncByteArrayInputStream(bytes)) {
|
||||
@Override
|
||||
public Reader openStream(String publicID, String systemID) throws IOException {
|
||||
if (!"http://java.sun.com/dtd/properties.dtd".equals(systemID)) throw new IOException();
|
||||
|
||||
@@ -22,12 +22,12 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import com.intellij.util.xml.impl.DomApplicationComponent;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -50,7 +50,7 @@ public class DomFileIndex extends ScalarIndexExtension<String>{
|
||||
@NotNull
|
||||
public Map<String, Void> map(final FileContent inputData) {
|
||||
final Set<String> namespaces = new THashSet<String>();
|
||||
final XmlFileHeader header = NanoXmlUtil.parseHeader(new ByteArrayInputStream(inputData.getContent()));
|
||||
final XmlFileHeader header = NanoXmlUtil.parseHeader(new UnsyncByteArrayInputStream(inputData.getContent()));
|
||||
ContainerUtil.addIfNotNull(header.getPublicId(), namespaces);
|
||||
ContainerUtil.addIfNotNull(header.getSystemId(), namespaces);
|
||||
ContainerUtil.addIfNotNull(header.getRootTagNamespace(), namespaces);
|
||||
|
||||
@@ -24,10 +24,10 @@ import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.FileContent;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -67,7 +67,7 @@ public class XmlNamespaceIndex extends XmlIndex<String> {
|
||||
return new DataIndexer<String, String, FileContent>() {
|
||||
@NotNull
|
||||
public Map<String, String> map(final FileContent inputData) {
|
||||
final String ns = XsdNamespaceBuilder.computeNamespace(new ByteArrayInputStream(inputData.getContent()));
|
||||
final String ns = XsdNamespaceBuilder.computeNamespace(new UnsyncByteArrayInputStream(inputData.getContent()));
|
||||
final HashMap<String, String> map = new HashMap<String, String>(2);
|
||||
if (ns != null) {
|
||||
map.put(ns, "");
|
||||
|
||||
@@ -20,9 +20,9 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -50,7 +50,7 @@ public class XmlTagNamesIndex extends XmlIndex<Void> {
|
||||
return new DataIndexer<String, Void, FileContent>() {
|
||||
@NotNull
|
||||
public Map<String, Void> map(final FileContent inputData) {
|
||||
final Collection<String> tags = XsdTagNameBuilder.computeTagNames(new ByteArrayInputStream(inputData.getContent()));
|
||||
final Collection<String> tags = XsdTagNameBuilder.computeTagNames(new UnsyncByteArrayInputStream(inputData.getContent()));
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
final HashMap<String, Void> map = new HashMap<String, Void>(tags.size());
|
||||
for (String tag : tags) {
|
||||
|
||||
Reference in New Issue
Block a user