| /* |
| * 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 com.google.common.collect.Lists.newArrayList; |
| import static com.google.common.collect.Maps.newHashMap; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.jetbrains.annotations.NotNull; |
| |
| /** |
| * A mutable, thread-safe implementation of {@link SegmentReferences}. |
| */ |
| class MutableSegmentReferences implements SegmentReferences { |
| |
| private final Object lock = new Object(); |
| |
| private final List<SegmentId> ids = newArrayList(); |
| |
| private final Map<SegmentId, Integer> numbers = newHashMap(); |
| |
| @Override |
| public SegmentId getSegmentId(int reference) { |
| SegmentId id = ids.get(reference - 1); |
| |
| if (id != null) { |
| return id; |
| } |
| |
| synchronized (lock) { |
| return ids.get(reference - 1); |
| } |
| } |
| |
| /** |
| * Generate a reference or return the existing reference for the provided |
| * segment ID. |
| * |
| * @param id an instance of {@link SegmentId}. It should not be {@code |
| * null}. |
| * @return a reference to the provided segment ID. The reference number is |
| * strictly greater than zero. |
| */ |
| int addOrReference(SegmentId id) { |
| Integer number = numbers.get(id); |
| |
| if (number != null) { |
| return number; |
| } |
| |
| synchronized (lock) { |
| number = numbers.get(id); |
| |
| if (number != null) { |
| return number; |
| } |
| |
| ids.add(id); |
| number = ids.size(); |
| numbers.put(id, number); |
| return number; |
| } |
| } |
| |
| /** |
| * Return the number of references (segment IDs) accessible from this |
| * instance. |
| * |
| * @return the number of references (segment IDs) accessible from this |
| * instance. |
| */ |
| int size() { |
| synchronized (lock) { |
| return numbers.size(); |
| } |
| } |
| |
| /** |
| * Check if a reference exists for a provided segment ID. |
| * |
| * @param id The segment ID to check for a reference. |
| * @return {@code true} if a reference exists for the provided segment ID, |
| * {@code false} otherwise. |
| */ |
| boolean contains(SegmentId id) { |
| boolean contains = numbers.containsKey(id); |
| |
| if (contains) { |
| return true; |
| } |
| |
| synchronized (lock) { |
| return numbers.containsKey(id); |
| } |
| } |
| |
| @NotNull |
| @Override |
| public Iterator<SegmentId> iterator() { |
| synchronized (lock) { |
| return ids.iterator(); |
| } |
| } |
| |
| } |