Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 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 | package com.google.devtools.build.skyframe; |
| 15 | |
Googler | 2c19a57 | 2015-07-16 08:38:49 +0000 | [diff] [blame] | 16 | import com.google.common.base.MoreObjects; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 17 | import com.google.common.base.Preconditions; |
| 18 | import com.google.common.collect.ImmutableList; |
| 19 | import com.google.common.collect.ImmutableSet; |
| 20 | import com.google.common.collect.Iterables; |
| 21 | import com.google.common.collect.Lists; |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 22 | import com.google.devtools.build.lib.collect.CompactHashSet; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 23 | |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 24 | import java.util.ArrayList; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 25 | import java.util.Collection; |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 26 | import java.util.HashSet; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 27 | import java.util.List; |
| 28 | import java.util.Set; |
| 29 | |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 30 | import javax.annotation.Nullable; |
| 31 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 32 | /** |
| 33 | * A utility class that allows us to keep the reverse dependencies as an array list instead of a |
| 34 | * set. This is more memory-efficient. At the same time it allows us to group the removals and |
| 35 | * uniqueness checks so that it also performs well. |
| 36 | * |
| 37 | * <p>The reason of this class it to share non-trivial code between BuildingState and NodeEntry. We |
| 38 | * could simply make those two classes extend this class instead, but we would be less |
Janak Ramakrishnan | 2f55dd8 | 2015-08-03 19:08:11 +0000 | [diff] [blame] | 39 | * memory-efficient since object memory alignment does not cross classes (you would have two memory |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 40 | * alignments, one for the base class and one for the extended one). |
Janak Ramakrishnan | 2f55dd8 | 2015-08-03 19:08:11 +0000 | [diff] [blame] | 41 | * |
| 42 | * <p>This class is public only for the benefit of alternative graph implementations outside of the |
| 43 | * package. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 44 | */ |
Janak Ramakrishnan | 2f55dd8 | 2015-08-03 19:08:11 +0000 | [diff] [blame] | 45 | public abstract class ReverseDepsUtil<T> { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 46 | |
| 47 | static final int MAYBE_CHECK_THRESHOLD = 10; |
| 48 | |
| 49 | abstract void setReverseDepsObject(T container, Object object); |
| 50 | |
| 51 | abstract void setSingleReverseDep(T container, boolean singleObject); |
| 52 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 53 | abstract void setDataToConsolidate(T container, @Nullable List<Object> dataToConsolidate); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 54 | |
| 55 | abstract Object getReverseDepsObject(T container); |
| 56 | |
| 57 | abstract boolean isSingleReverseDep(T container); |
| 58 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 59 | abstract List<Object> getDataToConsolidate(T container); |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 60 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 61 | private enum ConsolidateOp { |
| 62 | CHECK, |
| 63 | ADD, |
| 64 | REMOVE |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 65 | } |
| 66 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 67 | /** |
| 68 | * Opaque container for a pending operation on the reverse deps set. We use subclasses to save |
| 69 | * 8 bytes of memory instead of keeping a field in this class, and we store |
| 70 | * {@link ConsolidateOp#CHECK} operations as the bare {@link SkyKey} in order to save the wrapper |
| 71 | * object in that case. |
| 72 | */ |
| 73 | private abstract static class KeyToConsolidate { |
| 74 | // Do not access directly -- use the {@link #key} static accessor instead. |
| 75 | private final SkyKey key; |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 76 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 77 | /** Do not call directly -- use the {@link #create} static method instead. */ |
| 78 | private KeyToConsolidate(SkyKey key) { |
| 79 | this.key = key; |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 80 | } |
| 81 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 82 | @Override |
| 83 | public String toString() { |
| 84 | return MoreObjects.toStringHelper(this).add("key", key).toString(); |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 85 | } |
| 86 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 87 | /** Gets which operation was delayed for the given object. */ |
| 88 | static ConsolidateOp op(Object obj) { |
| 89 | if (obj instanceof SkyKey) { |
| 90 | return ConsolidateOp.CHECK; |
| 91 | } |
| 92 | if (obj instanceof KeyToRemove) { |
| 93 | return ConsolidateOp.REMOVE; |
| 94 | } |
| 95 | Preconditions.checkState(obj instanceof KeyToAdd, obj); |
| 96 | return ConsolidateOp.ADD; |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 99 | /** Gets the key whose operation was delayed for the given object. */ |
| 100 | static SkyKey key(Object obj) { |
| 101 | if (obj instanceof SkyKey) { |
| 102 | return (SkyKey) obj; |
| 103 | } |
| 104 | Preconditions.checkState(obj instanceof KeyToConsolidate, obj); |
| 105 | return ((KeyToConsolidate) obj).key; |
| 106 | } |
| 107 | |
| 108 | static Object create(SkyKey key, ConsolidateOp op) { |
| 109 | switch (op) { |
| 110 | case CHECK: |
| 111 | return key; |
| 112 | case REMOVE: |
| 113 | return new KeyToRemove(key); |
| 114 | case ADD: |
| 115 | return new KeyToAdd(key); |
| 116 | default: |
| 117 | throw new IllegalStateException(op + ", " + key); |
| 118 | } |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 122 | private static final class KeyToAdd extends KeyToConsolidate { |
| 123 | KeyToAdd(SkyKey key) { |
| 124 | super(key); |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 128 | private static final class KeyToRemove extends KeyToConsolidate { |
| 129 | KeyToRemove(SkyKey key) { |
| 130 | super(key); |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 134 | private void maybeDelayReverseDepOp(T container, Iterable<SkyKey> reverseDeps, ConsolidateOp op) { |
| 135 | List<Object> consolidations = getDataToConsolidate(container); |
| 136 | int currentReverseDepSize = getCurrentReverseDepSize(container); |
| 137 | if (consolidations == null) { |
| 138 | consolidations = new ArrayList<>(currentReverseDepSize); |
| 139 | setDataToConsolidate(container, consolidations); |
| 140 | } |
| 141 | for (SkyKey reverseDep : reverseDeps) { |
| 142 | consolidations.add(KeyToConsolidate.create(reverseDep, op)); |
| 143 | } |
| 144 | // TODO(janakr): Should we consolidate more aggressively? This threshold can be customized. |
| 145 | if (consolidations.size() == currentReverseDepSize) { |
| 146 | consolidateData(container); |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 147 | } |
| 148 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 149 | |
| 150 | /** |
| 151 | * We check that the reverse dependency is not already present. We only do that if reverseDeps is |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 152 | * small, so that it does not impact performance. We do not check if there are delayed data to |
| 153 | * consolidate, since then presence or absence is not known. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 154 | */ |
| 155 | void maybeCheckReverseDepNotPresent(T container, SkyKey reverseDep) { |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 156 | if (getDataToConsolidate(container) != null) { |
| 157 | return; |
| 158 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 159 | if (isSingleReverseDep(container)) { |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 160 | Preconditions.checkState( |
| 161 | !getReverseDepsObject(container).equals(reverseDep), |
| 162 | "Reverse dep %s already present in %s", |
| 163 | reverseDep, |
| 164 | container); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 165 | return; |
| 166 | } |
| 167 | @SuppressWarnings("unchecked") |
| 168 | List<SkyKey> asList = (List<SkyKey>) getReverseDepsObject(container); |
| 169 | if (asList.size() < MAYBE_CHECK_THRESHOLD) { |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 170 | Preconditions.checkState( |
| 171 | !asList.contains(reverseDep), |
| 172 | "Reverse dep %s already present in %s for %s", |
| 173 | reverseDep, |
| 174 | asList, |
| 175 | container); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 176 | } |
| 177 | } |
| 178 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 179 | private int getCurrentReverseDepSize(T container) { |
| 180 | return isSingleReverseDep(container) |
| 181 | ? 1 |
| 182 | : ((List<SkyKey>) getReverseDepsObject(container)).size(); |
| 183 | } |
| 184 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 185 | /** |
| 186 | * We use a memory-efficient trick to keep reverseDeps memory usage low. Edges in Bazel are |
| 187 | * dominant over the number of nodes. |
| 188 | * |
| 189 | * <p>Most of the nodes have zero or one reverse dep. That is why we use immutable versions of the |
| 190 | * lists for those cases. In case of the size being > 1 we switch to an ArrayList. That is because |
| 191 | * we also have a decent number of nodes for which the reverseDeps are huge (for example almost |
| 192 | * everything depends on BuildInfo node). |
| 193 | * |
| 194 | * <p>We also optimize for the case where we have only one dependency. In that case we keep the |
| 195 | * object directly instead of a wrapper list. |
| 196 | */ |
| 197 | @SuppressWarnings("unchecked") |
Janak Ramakrishnan | 2f55dd8 | 2015-08-03 19:08:11 +0000 | [diff] [blame] | 198 | public void addReverseDeps(T container, Collection<SkyKey> newReverseDeps) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 199 | if (newReverseDeps.isEmpty()) { |
| 200 | return; |
| 201 | } |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 202 | List<Object> dataToConsolidate = getDataToConsolidate(container); |
| 203 | if (dataToConsolidate != null) { |
| 204 | maybeDelayReverseDepOp(container, newReverseDeps, ConsolidateOp.ADD); |
| 205 | return; |
| 206 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 207 | Object reverseDeps = getReverseDepsObject(container); |
| 208 | int reverseDepsSize = isSingleReverseDep(container) ? 1 : ((List<SkyKey>) reverseDeps).size(); |
| 209 | int newSize = reverseDepsSize + newReverseDeps.size(); |
| 210 | if (newSize == 1) { |
| 211 | overwriteReverseDepsWithObject(container, Iterables.getOnlyElement(newReverseDeps)); |
| 212 | } else if (reverseDepsSize == 0) { |
| 213 | overwriteReverseDepsList(container, Lists.newArrayList(newReverseDeps)); |
| 214 | } else if (reverseDepsSize == 1) { |
| 215 | List<SkyKey> newList = Lists.newArrayListWithExpectedSize(newSize); |
| 216 | newList.add((SkyKey) reverseDeps); |
| 217 | newList.addAll(newReverseDeps); |
| 218 | overwriteReverseDepsList(container, newList); |
| 219 | } else { |
| 220 | ((List<SkyKey>) reverseDeps).addAll(newReverseDeps); |
| 221 | } |
| 222 | } |
| 223 | |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 224 | void checkReverseDep(T container, SkyKey reverseDep) { |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 225 | maybeDelayReverseDepOp(container, ImmutableList.of(reverseDep), ConsolidateOp.CHECK); |
Janak Ramakrishnan | 7ad99cb | 2015-09-10 20:35:21 +0000 | [diff] [blame] | 226 | } |
| 227 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 228 | /** |
| 229 | * See {@code addReverseDeps} method. |
| 230 | */ |
| 231 | void removeReverseDep(T container, SkyKey reverseDep) { |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 232 | maybeDelayReverseDepOp(container, ImmutableList.of(reverseDep), ConsolidateOp.REMOVE); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | ImmutableSet<SkyKey> getReverseDeps(T container) { |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 236 | consolidateData(container); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 237 | |
| 238 | // TODO(bazel-team): Unfortunately, we need to make a copy here right now to be on the safe side |
| 239 | // wrt. thread-safety. The parents of a node get modified when any of the parents is deleted, |
| 240 | // and we can't handle that right now. |
| 241 | if (isSingleReverseDep(container)) { |
| 242 | return ImmutableSet.of((SkyKey) getReverseDepsObject(container)); |
| 243 | } else { |
| 244 | @SuppressWarnings("unchecked") |
| 245 | List<SkyKey> reverseDeps = (List<SkyKey>) getReverseDepsObject(container); |
| 246 | ImmutableSet<SkyKey> set = ImmutableSet.copyOf(reverseDeps); |
| 247 | Preconditions.checkState(set.size() == reverseDeps.size(), |
| 248 | "Duplicate reverse deps present in %s: %s. %s", this, reverseDeps, container); |
| 249 | return set; |
| 250 | } |
| 251 | } |
| 252 | |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 253 | private void consolidateData(T container) { |
| 254 | List<Object> dataToConsolidate = getDataToConsolidate(container); |
| 255 | if (dataToConsolidate == null) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 256 | return; |
| 257 | } |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 258 | setDataToConsolidate(container, null); |
Janak Ramakrishnan | 441dcb1 | 2015-10-09 22:44:31 +0000 | [diff] [blame^] | 259 | Object reverseDeps = getReverseDepsObject(container); |
| 260 | if (isSingleReverseDep(container)) { |
| 261 | Preconditions.checkState( |
| 262 | dataToConsolidate.size() == 1, |
| 263 | "dataToConsolidate not size 1 even though only one rdep: %s %s %s", |
| 264 | dataToConsolidate, |
| 265 | reverseDeps, |
| 266 | container); |
| 267 | Object keyToConsolidate = Iterables.getOnlyElement(dataToConsolidate); |
| 268 | SkyKey key = KeyToConsolidate.key(keyToConsolidate); |
| 269 | switch (KeyToConsolidate.op(keyToConsolidate)) { |
| 270 | case REMOVE: |
| 271 | overwriteReverseDepsList(container, ImmutableList.<SkyKey>of()); |
| 272 | // Fall through to check. |
| 273 | case CHECK: |
| 274 | Preconditions.checkState( |
| 275 | key.equals(reverseDeps), "%s %s %s", keyToConsolidate, reverseDeps, container); |
| 276 | break; |
| 277 | case ADD: |
| 278 | throw new IllegalStateException( |
| 279 | "Shouldn't delay add if only one element: " |
| 280 | + keyToConsolidate |
| 281 | + ", " |
| 282 | + reverseDeps |
| 283 | + ", " |
| 284 | + container); |
| 285 | default: |
| 286 | throw new IllegalStateException(keyToConsolidate + ", " + reverseDeps + ", " + container); |
| 287 | } |
| 288 | return; |
| 289 | } |
| 290 | List<SkyKey> reverseDepsAsList = (List<SkyKey>) reverseDeps; |
| 291 | Set<SkyKey> reverseDepsAsSet = CompactHashSet.create(reverseDepsAsList); |
| 292 | |
| 293 | if (reverseDepsAsSet.size() != reverseDepsAsList.size()) { |
| 294 | // We're about to crash. Try to print an informative error message. |
| 295 | Set<SkyKey> seen = new HashSet<>(); |
| 296 | List<SkyKey> duplicates = new ArrayList<>(); |
| 297 | for (SkyKey key : reverseDepsAsList) { |
| 298 | if (!seen.add(key)) { |
| 299 | duplicates.add(key); |
| 300 | } |
| 301 | } |
| 302 | throw new IllegalStateException( |
| 303 | (reverseDepsAsList.size() - reverseDepsAsSet.size()) |
| 304 | + " duplicates: " |
| 305 | + duplicates |
| 306 | + " for " |
| 307 | + container); |
| 308 | } |
| 309 | for (Object keyToConsolidate : dataToConsolidate) { |
| 310 | SkyKey key = KeyToConsolidate.key(keyToConsolidate); |
| 311 | switch (KeyToConsolidate.op(keyToConsolidate)) { |
| 312 | case CHECK: |
| 313 | Preconditions.checkState( |
| 314 | reverseDepsAsSet.contains(key), |
| 315 | "%s %s %s", |
| 316 | keyToConsolidate, |
| 317 | reverseDepsAsSet, |
| 318 | container); |
| 319 | break; |
| 320 | case REMOVE: |
| 321 | Preconditions.checkState( |
| 322 | reverseDepsAsSet.remove(key), "%s %s %s", keyToConsolidate, reverseDeps, container); |
| 323 | break; |
| 324 | case ADD: |
| 325 | Preconditions.checkState( |
| 326 | reverseDepsAsSet.add(key), "%s %s %s", keyToConsolidate, reverseDeps, container); |
| 327 | break; |
| 328 | default: |
| 329 | throw new IllegalStateException( |
| 330 | keyToConsolidate + ", " + reverseDepsAsSet + ", " + container); |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | if (reverseDepsAsSet.isEmpty()) { |
| 335 | overwriteReverseDepsList(container, ImmutableList.<SkyKey>of()); |
| 336 | } else if (reverseDepsAsSet.size() == 1) { |
| 337 | overwriteReverseDepsWithObject(container, Iterables.getOnlyElement(reverseDepsAsSet)); |
| 338 | } else { |
| 339 | overwriteReverseDepsList(container, new ArrayList<>(reverseDepsAsSet)); |
| 340 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 341 | } |
| 342 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 343 | String toString(T container) { |
Googler | 2c19a57 | 2015-07-16 08:38:49 +0000 | [diff] [blame] | 344 | return MoreObjects.toStringHelper("ReverseDeps") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 345 | .add("reverseDeps", getReverseDepsObject(container)) |
| 346 | .add("singleReverseDep", isSingleReverseDep(container)) |
Janak Ramakrishnan | 5877b8b | 2015-09-22 17:37:10 +0000 | [diff] [blame] | 347 | .add("dataToConsolidate", getDataToConsolidate(container)) |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 348 | .toString(); |
| 349 | } |
| 350 | |
| 351 | private void overwriteReverseDepsWithObject(T container, SkyKey newObject) { |
| 352 | setReverseDepsObject(container, newObject); |
| 353 | setSingleReverseDep(container, true); |
| 354 | } |
| 355 | |
| 356 | private void overwriteReverseDepsList(T container, List<SkyKey> list) { |
| 357 | setReverseDepsObject(container, list); |
| 358 | setSingleReverseDep(container, false); |
| 359 | } |
| 360 | } |