diff options
Diffstat (limited to 'java/com/google/gerrit/server/git/TagSetHolder.java')
-rw-r--r-- | java/com/google/gerrit/server/git/TagSetHolder.java | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/java/com/google/gerrit/server/git/TagSetHolder.java b/java/com/google/gerrit/server/git/TagSetHolder.java new file mode 100644 index 0000000000..4c0c035e02 --- /dev/null +++ b/java/com/google/gerrit/server/git/TagSetHolder.java @@ -0,0 +1,128 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// 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.gerrit.server.git; + +import static java.util.stream.Collectors.toList; + +import com.google.gerrit.common.Nullable; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto; +import com.google.gerrit.server.cache.serialize.CacheSerializer; +import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers; +import java.util.Collection; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; + +public class TagSetHolder { + private final Object buildLock = new Object(); + private final Project.NameKey projectName; + + @Nullable private volatile TagSet tags; + + TagSetHolder(Project.NameKey projectName) { + this.projectName = projectName; + } + + Project.NameKey getProjectName() { + return projectName; + } + + TagSet getTagSet() { + return tags; + } + + void setTagSet(TagSet tags) { + this.tags = tags; + } + + public TagMatcher matcher(TagCache cache, Repository db, Collection<Ref> include) { + include = include.stream().filter(r -> !TagSet.skip(r)).collect(toList()); + + TagSet tags = this.tags; + if (tags == null) { + tags = build(cache, db); + } + + TagMatcher m = new TagMatcher(this, cache, db, include, tags, false); + tags.prepare(m); + if (!m.newRefs.isEmpty() || !m.lostRefs.isEmpty()) { + tags = rebuild(cache, db, tags, m); + + m = new TagMatcher(this, cache, db, include, tags, true); + tags.prepare(m); + } + return m; + } + + void rebuildForNewTags(TagCache cache, TagMatcher m) { + m.tags = rebuild(cache, m.db, m.tags, null); + m.mask.clear(); + m.newRefs.clear(); + m.lostRefs.clear(); + m.tags.prepare(m); + } + + private TagSet build(TagCache cache, Repository db) { + synchronized (buildLock) { + TagSet tags = this.tags; + if (tags == null) { + tags = new TagSet(projectName); + tags.build(db, null, null); + this.tags = tags; + cache.put(projectName, this); + } + return tags; + } + } + + private TagSet rebuild(TagCache cache, Repository db, TagSet old, TagMatcher m) { + synchronized (buildLock) { + TagSet cur = this.tags; + if (cur == old) { + cur = new TagSet(projectName); + cur.build(db, old, m); + this.tags = cur; + cache.put(projectName, this); + } + return cur; + } + } + + enum Serializer implements CacheSerializer<TagSetHolder> { + INSTANCE; + + @Override + public byte[] serialize(TagSetHolder object) { + TagSetHolderProto.Builder b = + TagSetHolderProto.newBuilder().setProjectName(object.projectName.get()); + TagSet tags = object.tags; + if (tags != null) { + b.setTags(tags.toProto()); + } + return ProtoCacheSerializers.toByteArray(b.build()); + } + + @Override + public TagSetHolder deserialize(byte[] in) { + TagSetHolderProto proto = + ProtoCacheSerializers.parseUnchecked(TagSetHolderProto.parser(), in); + TagSetHolder holder = new TagSetHolder(new Project.NameKey(proto.getProjectName())); + if (proto.hasTags()) { + holder.tags = TagSet.fromProto(proto.getTags()); + } + return holder; + } + } +} |