| // Copyright 2014 The Bazel Authors. All rights reserved. | |
| // | |
| // 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.google.devtools.build.lib.actions; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.Iterables; | |
| import com.google.common.collect.MapMaker; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import java.util.concurrent.ConcurrentMap; | |
| import java.util.concurrent.locks.ReadWriteLock; | |
| import java.util.concurrent.locks.ReentrantReadWriteLock; | |
| /** | |
| * A registry that keeps a map of artifacts to unique integer ids. | |
| */ | |
| class ArtifactIdRegistry implements ArtifactSerializer, ArtifactDeserializer { | |
| /** | |
| * A sequence of registered artifacts. The position in the list is the artifact's id. | |
| * | |
| * <p>Synchronized using {@link #artifactIdsLock}. | |
| */ | |
| private final List<Artifact> serializedArtifactList = new ArrayList<>(); | |
| /** | |
| * A map of artifacts to unique integer ids. | |
| * | |
| * <p>Writes to this map must be synchronized using {@link #artifactIdsLock}, in order to | |
| * maintain consistency with {@link #serializedArtifactList}. | |
| */ | |
| private final ConcurrentMap<Artifact, Integer> serializedArtifactIds = | |
| new MapMaker().concurrencyLevel(1).makeMap(); | |
| /** | |
| * A lock for keeping {@code serializedArtifactList} and {@code serializedArtifactIds} in sync. | |
| */ | |
| private ReadWriteLock artifactIdsLock = new ReentrantReadWriteLock(); | |
| ArtifactIdRegistry() { | |
| } | |
| @Override | |
| public int getArtifactId(Artifact artifact) { | |
| Integer artifactId = serializedArtifactIds.get(artifact); | |
| if (artifactId == null) { | |
| artifactId = assignArtifactId(artifact); | |
| } | |
| return artifactId; | |
| } | |
| private Integer assignArtifactId(Artifact artifact) { | |
| artifactIdsLock.writeLock().lock(); | |
| try { | |
| Integer artifactId = serializedArtifactIds.get(artifact); | |
| if (artifactId == null) { | |
| artifactId = serializedArtifactList.size(); | |
| serializedArtifactList.add(artifact); | |
| serializedArtifactIds.put(artifact, artifactId); | |
| } | |
| return artifactId; | |
| } finally { | |
| artifactIdsLock.writeLock().unlock(); | |
| } | |
| } | |
| @Override | |
| public Artifact lookupArtifactById(int artifactId) { | |
| artifactIdsLock.readLock().lock(); | |
| try { | |
| return serializedArtifactList.get(artifactId); | |
| } finally { | |
| artifactIdsLock.readLock().unlock(); | |
| } | |
| } | |
| @Override | |
| public ImmutableList<Artifact> lookupArtifactsByIds(Iterable<Integer> artifactIds) { | |
| int size = Iterables.size(artifactIds); | |
| Artifact[] result = new Artifact[size]; | |
| int i = 0; | |
| artifactIdsLock.readLock().lock(); | |
| try { | |
| for (int artifactId : artifactIds) { | |
| result[i] = serializedArtifactList.get(artifactId); | |
| i++; | |
| } | |
| } finally { | |
| artifactIdsLock.readLock().unlock(); | |
| } | |
| return ImmutableList.copyOf(result); | |
| } | |
| } |