1 /* 2 * Copyright (C) 2012 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.caliper.model; 18 19 import static com.google.caliper.model.PersistentHashing.getPersistentHashFunction; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 22 import com.google.common.annotations.VisibleForTesting; 23 import com.google.common.base.MoreObjects; 24 import com.google.common.collect.ImmutableSortedMap; 25 import com.google.common.collect.Maps; 26 import com.google.common.hash.Funnel; 27 import com.google.common.hash.HashFunction; 28 import com.google.common.hash.PrimitiveSink; 29 30 import java.util.Map; 31 import java.util.SortedMap; 32 import java.util.logging.Logger; 33 34 /** 35 * The performance-informing properties of the host on which a benchmark is run. 36 * 37 * @author gak@google.com (Gregory Kick) 38 */ 39 public final class Host { 40 static final Host DEFAULT = new Host(); 41 private static final Logger logger = Logger.getLogger(Host.class.getName()); 42 43 @ExcludeFromJson private int id; 44 private SortedMap<String, String> properties; 45 @ExcludeFromJson private int hash; 46 Host()47 private Host() { 48 this.properties = Maps.newTreeMap(); 49 } 50 Host(Builder builder)51 private Host(Builder builder) { 52 this.properties = Maps.newTreeMap(builder.properties); 53 // eagerly initialize hash to allow for the test-only hash function 54 initHash(builder.hashFunction); 55 } 56 properties()57 public ImmutableSortedMap<String, String> properties() { 58 return ImmutableSortedMap.copyOf(properties); 59 } 60 equals(Object obj)61 @Override public boolean equals(Object obj) { 62 if (obj == this) { 63 return true; 64 } else if (obj instanceof Host) { 65 Host that = (Host) obj; 66 return this.properties.equals(that.properties); 67 } else { 68 return false; 69 } 70 } 71 initHash(HashFunction hashFunction)72 private void initHash(HashFunction hashFunction) { 73 if (hash == 0) { 74 this.hash = hashFunction.hashObject(this, HostFunnel.INSTANCE).asInt(); 75 } 76 } 77 initHash()78 private void initHash() { 79 initHash(getPersistentHashFunction()); 80 } 81 hashCode()82 @Override public int hashCode() { 83 initHash(); 84 return hash; 85 } 86 toString()87 @Override public String toString() { 88 return MoreObjects.toStringHelper(this) 89 .add("properties", properties) 90 .toString(); 91 } 92 93 enum HostFunnel implements Funnel<Host> { 94 INSTANCE; 95 funnel(Host from, PrimitiveSink into)96 @Override public void funnel(Host from, PrimitiveSink into) { 97 StringMapFunnel.INSTANCE.funnel(from.properties, into); 98 } 99 } 100 101 public static final class Builder { 102 private final SortedMap<String, String> properties = Maps.newTreeMap(); 103 private HashFunction hashFunction = getPersistentHashFunction(); 104 addProperty(String key, String value)105 public Builder addProperty(String key, String value) { 106 properties.put(key, value); 107 return this; 108 } 109 addAllProperies(Map<String, String> properties)110 public Builder addAllProperies(Map<String, String> properties) { 111 this.properties.putAll(properties); 112 return this; 113 } 114 115 /** 116 * This only exists for tests to induce hash collisions. Only use this in test code as changing 117 * the hash function will break persisted objects. 118 */ hashFunctionForTesting(HashFunction hashFunction)119 @VisibleForTesting public Builder hashFunctionForTesting(HashFunction hashFunction) { 120 logger.warning("somebody is setting the hash function. this should only be used in tests"); 121 this.hashFunction = checkNotNull(hashFunction); 122 return this; 123 } 124 build()125 public Host build() { 126 return new Host(this); 127 } 128 } 129 } 130