Line data Source code
1 : // Copyright (C) 2011 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.git; 16 : 17 : import static java.util.stream.Collectors.toList; 18 : 19 : import com.google.gerrit.common.Nullable; 20 : import com.google.gerrit.entities.Project; 21 : import com.google.gerrit.proto.Protos; 22 : import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto; 23 : import com.google.gerrit.server.cache.serialize.CacheSerializer; 24 : import java.util.Collection; 25 : import org.eclipse.jgit.lib.Ref; 26 : import org.eclipse.jgit.lib.Repository; 27 : 28 : public class TagSetHolder { 29 10 : private final Object buildLock = new Object(); 30 : private final Project.NameKey projectName; 31 : 32 : @Nullable private volatile TagSet tags; 33 : 34 10 : TagSetHolder(Project.NameKey projectName) { 35 10 : this.projectName = projectName; 36 10 : } 37 : 38 : Project.NameKey getProjectName() { 39 1 : return projectName; 40 : } 41 : 42 : TagSet getTagSet() { 43 6 : return tags; 44 : } 45 : 46 : void setTagSet(TagSet tags) { 47 1 : this.tags = tags; 48 1 : } 49 : 50 : public TagMatcher matcher(TagCache cache, Repository db, Collection<Ref> include) { 51 9 : include = include.stream().filter(r -> !TagSet.skip(r)).collect(toList()); 52 : 53 9 : TagSet tags = this.tags; 54 9 : if (tags == null) { 55 9 : tags = build(cache, db); 56 : } 57 : 58 9 : TagMatcher m = new TagMatcher(this, cache, db, include, tags, false); 59 9 : tags.prepare(m); 60 9 : if (!m.newRefs.isEmpty() || !m.lostRefs.isEmpty()) { 61 1 : tags = rebuild(cache, db, tags, m); 62 : 63 1 : m = new TagMatcher(this, cache, db, include, tags, true); 64 1 : tags.prepare(m); 65 : } 66 9 : return m; 67 : } 68 : 69 : void rebuildForNewTags(TagCache cache, TagMatcher m) { 70 5 : m.tags = rebuild(cache, m.db, m.tags, null); 71 5 : m.mask.clear(); 72 5 : m.newRefs.clear(); 73 5 : m.lostRefs.clear(); 74 5 : m.tags.prepare(m); 75 5 : } 76 : 77 : private TagSet build(TagCache cache, Repository db) { 78 9 : synchronized (buildLock) { 79 9 : TagSet tags = this.tags; 80 9 : if (tags == null) { 81 9 : tags = new TagSet(projectName); 82 9 : tags.build(db, null, null); 83 9 : this.tags = tags; 84 9 : cache.put(projectName, this); 85 : } 86 9 : return tags; 87 : } 88 : } 89 : 90 : private TagSet rebuild(TagCache cache, Repository db, TagSet old, TagMatcher m) { 91 5 : synchronized (buildLock) { 92 5 : TagSet cur = this.tags; 93 5 : if (cur == old) { 94 5 : cur = new TagSet(projectName); 95 5 : cur.build(db, old, m); 96 5 : this.tags = cur; 97 5 : cache.put(projectName, this); 98 : } 99 5 : return cur; 100 : } 101 : } 102 : 103 152 : enum Serializer implements CacheSerializer<TagSetHolder> { 104 152 : INSTANCE; 105 : 106 : @Override 107 : public byte[] serialize(TagSetHolder object) { 108 : TagSetHolderProto.Builder b = 109 1 : TagSetHolderProto.newBuilder().setProjectName(object.projectName.get()); 110 1 : TagSet tags = object.tags; 111 1 : if (tags != null) { 112 1 : b.setTags(tags.toProto()); 113 : } 114 1 : return Protos.toByteArray(b.build()); 115 : } 116 : 117 : @Override 118 : public TagSetHolder deserialize(byte[] in) { 119 1 : TagSetHolderProto proto = Protos.parseUnchecked(TagSetHolderProto.parser(), in); 120 1 : TagSetHolder holder = new TagSetHolder(Project.nameKey(proto.getProjectName())); 121 1 : if (proto.hasTags()) { 122 1 : holder.tags = TagSet.fromProto(proto.getTags()); 123 : } 124 1 : return holder; 125 : } 126 : } 127 : }