1e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin/*
2e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * Copyright (C) 2010 Google Inc.
3e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin *
4e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
5e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * you may not use this file except in compliance with the License.
6e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * You may obtain a copy of the License at
7e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin *
8e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
9e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin *
10e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * Unless required by applicable law or agreed to in writing, software
11e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
12e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * See the License for the specific language governing permissions and
14e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * limitations under the License.
15e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin */
16e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
17e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinpackage com.google.caliper.runner;
18e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
19e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.caliper.model.Host;
20e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.common.collect.ImmutableMultimap;
21e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.common.collect.ImmutableMultiset;
22e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.common.collect.Maps;
23e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.common.collect.Multimap;
24e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport com.google.common.io.Files;
25e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
26e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.io.File;
27e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.io.IOException;
28e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.nio.charset.Charset;
29e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.util.Collection;
30e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.util.List;
31e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.util.Map;
32e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinimport java.util.TreeMap;
33e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
34e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin/**
35e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * An instance of this class is responsible for returning a Map that describes the environment:
36e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin * JVM version, os details, etc.
37e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin */
38e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffinfinal class EnvironmentGetter {
39e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  Host getHost() {
40e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    return new Host.Builder()
41e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        .addAllProperies(getProperties())
42e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        .build();
43e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  }
44e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
45e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  private Map<String, String> getProperties() {
46e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    TreeMap<String, String> propertyMap = Maps.newTreeMap();
47e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
48e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    Map<String, String> sysProps = Maps.fromProperties(System.getProperties());
49e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
50e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    // Sometimes java.runtime.version is more descriptive than java.version
51e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    String version = sysProps.get("java.version");
52e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    String alternateVersion = sysProps.get("java.runtime.version");
53e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    if (alternateVersion != null && alternateVersion.length() > version.length()) {
54e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      version = alternateVersion;
55e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    }
56e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.availableProcessors",
57e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        Integer.toString(Runtime.getRuntime().availableProcessors()));
58e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
59e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    String osName = sysProps.get("os.name");
60e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("os.name", osName);
61e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("os.version", sysProps.get("os.version"));
62e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("os.arch", sysProps.get("os.arch"));
63e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
64e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    if (osName.equals("Linux")) {
65e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      getLinuxEnvironment(propertyMap);
66e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    }
67e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
68e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    return propertyMap;
69e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  }
70e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
71e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  private void getLinuxEnvironment(Map<String, String> propertyMap) {
72e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    // the following probably doesn't work on ALL linux
73e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    Multimap<String, String> cpuInfo = propertiesFromLinuxFile("/proc/cpuinfo");
74e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.cpus", Integer.toString(cpuInfo.get("processor").size()));
75e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    String s = "cpu cores";
76e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.cpu.cores", describe(cpuInfo, s));
77e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.cpu.names", describe(cpuInfo, "model name"));
78e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.cpu.cachesize", describe(cpuInfo, "cache size"));
79e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
80e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    Multimap<String, String> memInfo = propertiesFromLinuxFile("/proc/meminfo");
81e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    // TODO redo memInfo.toString() so we don't get square brackets
82e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.memory.physical", memInfo.get("MemTotal").toString());
83e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    propertyMap.put("host.memory.swap", memInfo.get("SwapTotal").toString());
84e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  }
85e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
86e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  private static String describe(Multimap<String, String> cpuInfo, String s) {
87e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    Collection<String> strings = cpuInfo.get(s);
88e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    // TODO redo the ImmutableMultiset.toString() call so we don't get square brackets
89e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    return (strings.size() == 1)
90e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        ? strings.iterator().next()
91e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        : ImmutableMultiset.copyOf(strings).toString();
92e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  }
93e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin
94e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  /**
95e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   * Returns the key/value pairs from the specified properties-file like file.
96e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   * Unlike standard Java properties files, {@code reader} is allowed to list
97e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   * the same property multiple times. Comments etc. are unsupported.
98e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   *
99e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   * <p>If there's any problem reading the file's contents, we'll return an
100e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   * empty Multimap.
101e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin   */
102e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  private static Multimap<String, String> propertiesFromLinuxFile(String file) {
103e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    try {
104e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      List<String> lines = Files.readLines(new File(file), Charset.defaultCharset());
105e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      ImmutableMultimap.Builder<String, String> result = ImmutableMultimap.builder();
106e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      for (String line : lines) {
107e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        // TODO(schmoe): replace with Splitter (in Guava release 10)
108e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        String[] parts = line.split("\\s*\\:\\s*", 2);
109e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        if (parts.length == 2) {
110e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin          result.put(parts[0], parts[1]);
111e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin        }
112e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      }
113e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      return result.build();
114e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    } catch (IOException e) {
115e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      // If there's any problem reading the file, just return an empty multimap.
116e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin      return ImmutableMultimap.of();
117e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin    }
118e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin  }
119e236301e5fc778bffe1748ed80d7936e6c807012Paul Duffin}
120