org.apache.lucene.util.packed.GrowableWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.lucene.util.packed.GrowableWriter.java

Source

/*
 * 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.lucene.util.packed;

import java.io.IOException;

import org.apache.lucene.store.DataOutput;
import org.apache.lucene.util.RamUsageEstimator;

/**     
 * Implements {@link PackedInts.Mutable}, but grows the
 * bit count of the underlying packed ints on-demand.
 * <p>Beware that this class will accept to set negative values but in order
 * to do this, it will grow the number of bits per value to 64.
 *
 * <p>@lucene.internal</p>
 */
public class GrowableWriter extends PackedInts.Mutable {

    private long currentMask;
    private PackedInts.Mutable current;
    private final float acceptableOverheadRatio;

    /**
     * @param startBitsPerValue       the initial number of bits per value, may grow depending on the data
     * @param valueCount              the number of values
     * @param acceptableOverheadRatio an acceptable overhead ratio
     */
    public GrowableWriter(int startBitsPerValue, int valueCount, float acceptableOverheadRatio) {
        this.acceptableOverheadRatio = acceptableOverheadRatio;
        current = PackedInts.getMutable(valueCount, startBitsPerValue, this.acceptableOverheadRatio);
        currentMask = mask(current.getBitsPerValue());
    }

    private static long mask(int bitsPerValue) {
        return bitsPerValue == 64 ? ~0L : PackedInts.maxValue(bitsPerValue);
    }

    @Override
    public long get(int index) {
        return current.get(index);
    }

    @Override
    public int size() {
        return current.size();
    }

    @Override
    public int getBitsPerValue() {
        return current.getBitsPerValue();
    }

    public PackedInts.Mutable getMutable() {
        return current;
    }

    private void ensureCapacity(long value) {
        if ((value & currentMask) == value) {
            return;
        }
        final int bitsRequired = PackedInts.unsignedBitsRequired(value);
        assert bitsRequired > current.getBitsPerValue();
        final int valueCount = size();
        PackedInts.Mutable next = PackedInts.getMutable(valueCount, bitsRequired, acceptableOverheadRatio);
        PackedInts.copy(current, 0, next, 0, valueCount, PackedInts.DEFAULT_BUFFER_SIZE);
        current = next;
        currentMask = mask(current.getBitsPerValue());
    }

    @Override
    public void set(int index, long value) {
        ensureCapacity(value);
        current.set(index, value);
    }

    @Override
    public void clear() {
        current.clear();
    }

    public GrowableWriter resize(int newSize) {
        GrowableWriter next = new GrowableWriter(getBitsPerValue(), newSize, acceptableOverheadRatio);
        final int limit = Math.min(size(), newSize);
        PackedInts.copy(current, 0, next, 0, limit, PackedInts.DEFAULT_BUFFER_SIZE);
        return next;
    }

    @Override
    public int get(int index, long[] arr, int off, int len) {
        return current.get(index, arr, off, len);
    }

    @Override
    public int set(int index, long[] arr, int off, int len) {
        long max = 0;
        for (int i = off, end = off + len; i < end; ++i) {
            // bitwise or is nice because either all values are positive and the
            // or-ed result will require as many bits per value as the max of the
            // values, or one of them is negative and the result will be negative,
            // forcing GrowableWriter to use 64 bits per value
            max |= arr[i];
        }
        ensureCapacity(max);
        return current.set(index, arr, off, len);
    }

    @Override
    public void fill(int fromIndex, int toIndex, long val) {
        ensureCapacity(val);
        current.fill(fromIndex, toIndex, val);
    }

    @Override
    public long ramBytesUsed() {
        return RamUsageEstimator.alignObjectSize(RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
                + RamUsageEstimator.NUM_BYTES_OBJECT_REF + Long.BYTES + Float.BYTES) + current.ramBytesUsed();
    }

    @Override
    public void save(DataOutput out) throws IOException {
        current.save(out);
    }

}