1   /*
2    * Copyright 2017 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package com.linecorp.centraldogma.server.internal.storage.repository.cache;
18  
19  import static com.linecorp.centraldogma.server.internal.storage.repository.RepositoryCache.logger;
20  import static java.util.Objects.requireNonNull;
21  
22  import java.util.Map;
23  import java.util.Objects;
24  import java.util.concurrent.CompletableFuture;
25  
26  import com.google.common.base.MoreObjects.ToStringHelper;
27  
28  import com.linecorp.centraldogma.common.Change;
29  import com.linecorp.centraldogma.common.Revision;
30  import com.linecorp.centraldogma.server.storage.repository.AbstractCacheableCall;
31  import com.linecorp.centraldogma.server.storage.repository.DiffResultType;
32  import com.linecorp.centraldogma.server.storage.repository.Repository;
33  
34  final class CacheableMultiDiffCall extends AbstractCacheableCall<Map<String, Change<?>>> {
35  
36      private final Revision from;
37      private final Revision to;
38      private final String pathPattern;
39      private final DiffResultType diffResultType;
40      private final int hashCode;
41  
42      CacheableMultiDiffCall(Repository repo, Revision from, Revision to, String pathPattern,
43                             DiffResultType diffResultType) {
44          super(repo);
45  
46          this.from = requireNonNull(from, "from");
47          this.to = requireNonNull(to, "to");
48          this.pathPattern = requireNonNull(pathPattern, "pathPattern");
49          this.diffResultType = requireNonNull(diffResultType, "diffResultType");
50  
51          hashCode = Objects.hash(from, to, pathPattern, diffResultType) * 31 + System.identityHashCode(repo);
52  
53          assert !from.isRelative();
54          assert !to.isRelative();
55      }
56  
57      @Override
58      public int weigh(Map<String, Change<?>> value) {
59          int weight = 0;
60          weight += pathPattern.length();
61          for (Change<?> e : value.values()) {
62              weight += e.path().length();
63              final String content = e.contentAsText();
64              if (content != null) {
65                  weight += content.length();
66              }
67          }
68          return weight;
69      }
70  
71      @Override
72      public CompletableFuture<Map<String, Change<?>>> execute() {
73          logger.debug("Cache miss: {}", this);
74          return repo().diff(from, to, pathPattern, diffResultType);
75      }
76  
77      @Override
78      public int hashCode() {
79          return hashCode;
80      }
81  
82      @Override
83      public boolean equals(Object o) {
84          if (!super.equals(o)) {
85              return false;
86          }
87  
88          final CacheableMultiDiffCall that = (CacheableMultiDiffCall) o;
89          return from.equals(that.from) &&
90                 to.equals(that.to) &&
91                 pathPattern.equals(that.pathPattern) &&
92                 diffResultType == that.diffResultType;
93      }
94  
95      @Override
96      protected void toString(ToStringHelper helper) {
97          helper.add("from", from)
98                .add("to", to)
99                .add("pathPattern", pathPattern)
100               .add("diffResultType", diffResultType);
101     }
102 }