/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.blur.lucene.codec; import java.io.IOException; import org.apache.blur.utils.ThreadValue; import org.apache.lucene.codecs.compressing.Decompressor; import org.apache.lucene.store.DataInput; import org.apache.lucene.store.IndexInput; import org.apache.lucene.util.ArrayUtil; import org.apache.lucene.util.BytesRef; public class CachedDecompressor extends Decompressor { private final Decompressor _decompressor; private final ThreadValue<Entry> _entry = new ThreadValue<Entry>() { @Override protected Entry initialValue() { return new Entry(); } }; public CachedDecompressor(Decompressor decompressor) { _decompressor = decompressor; } @Override public void decompress(final DataInput in, final int originalLength, final int offset, final int length, final BytesRef bytes) throws IOException { if (in instanceof IndexInput) { IndexInput indexInput = (IndexInput) in; String name = indexInput.toString(); long filePointer = indexInput.getFilePointer(); Entry entry = _entry.get(); if (!entry.isValid(indexInput, name, filePointer)) { entry.setup(indexInput, name, filePointer); entry._cache.grow(originalLength + 7); _decompressor.decompress(indexInput, originalLength, 0, originalLength, entry._cache); entry._cache.length = originalLength; entry._cache.offset = 0; _entry.set(entry); } if (bytes.bytes.length < originalLength + 7) { bytes.bytes = new byte[ArrayUtil.oversize(originalLength + 7, 1)]; } System.arraycopy(entry._cache.bytes, entry._cache.offset, bytes.bytes, 0, length + offset); bytes.offset = offset; bytes.length = length; } else { _decompressor.decompress(in, originalLength, offset, length, bytes); } } @Override public Decompressor clone() { return new CachedDecompressor(_decompressor.clone()); } static class Entry { String _name; long _filePointer = -1; BytesRef _cache = new BytesRef(); int _indexInputHashCode; void setup(IndexInput indexInput, String name, long filePointer) { _indexInputHashCode = System.identityHashCode(indexInput); _name = name; _filePointer = filePointer; } boolean isValid(IndexInput indexInput, String name, long filePointer) { if (_indexInputHashCode != System.identityHashCode(indexInput)) { return false; } if (!_name.equals(name)) { return false; } if (_filePointer != filePointer) { return false; } return true; } } }