blob: d5f52b5e73ecf1658e1e294a868a9e48671ef724 [file] [log] [blame]
/*
* 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.jackrabbit.oak.segment;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
import org.jetbrains.annotations.NotNull;
/**
* A thread-safe, mutable record table.
*/
class MutableRecordNumbers implements RecordNumbers {
private int[] recordEntries;
private int size;
public MutableRecordNumbers() {
recordEntries = new int[16384];
fill(recordEntries, -1);
}
@Override
public int getOffset(int recordNumber) {
int recordEntry = getRecordEntry(recordEntries, recordNumber);
if (recordEntry == -1) {
synchronized (this) {
recordEntry = getRecordEntry(recordEntries, recordNumber);
}
}
return recordEntry;
}
private static int getRecordEntry(int[] entries, int index) {
return index * 2 >= entries.length
? -1
: entries[index * 2];
}
@NotNull
@Override
public synchronized Iterator<Entry> iterator() {
return new AbstractIterator<Entry>() {
final int[] entries = copyOf(recordEntries, size * 2);
int index = 0;
@Override
protected Entry computeNext() {
if (index < entries.length) {
return new Entry() {
final int recordNumber = index/2;
final int offset = entries[index++];
final RecordType type = RecordType.values()[entries[index++]];
@Override
public int getRecordNumber() {
return recordNumber;
}
@Override
public int getOffset() {
return offset;
}
@Override
public RecordType getType() {
return type;
}
};
} else {
return endOfData();
}
}
};
}
/**
* Return the size of this table.
*
* @return the size of this table.
*/
public synchronized int size() {
return size;
}
/**
* Add a new offset to this table and generate a record number for it.
*
* @param type the type of the record.
* @param offset an offset to be added to this table.
* @return the record number associated to the offset.
*/
synchronized int addRecord(RecordType type, int offset) {
if (recordEntries.length <= size * 2) {
recordEntries = copyOf(recordEntries, recordEntries.length * 2);
fill(recordEntries, recordEntries.length/2, recordEntries.length, -1);
}
recordEntries[2 * size] = offset;
recordEntries[2 * size + 1] = type.ordinal();
return size++;
}
}