package com.epickrram.workshop.perf.config; ////////////////////////////////////////////////////////////////////////////////// // Copyright 2015 Mark Price mark at epickrram.com // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.Properties; import static java.lang.String.format; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; public final class Overrides { private static final String PROPERTY_PREFIX = "perf.workshop."; private static final String JOURNALLER_ENABLED_KEY = PROPERTY_PREFIX + "journaller.enabled"; private static final String THREAD_AFFINITY_PREFIX = PROPERTY_PREFIX + "affinity."; private static final String PRODUCER = "producer"; private static final String JOURNALLER = "journaller"; private static final String ACCUMULATOR = "accumulator"; private static final boolean DEFAULT_JOURNALLER_ENABLED_VALUE = false; private final String overrideFile; private final Properties properties = new Properties(); public Overrides(final CommandLineArgs commandLineArgs) { this.overrideFile = commandLineArgs.getOverrideFile(); } public void init() throws IOException { final File file = new File(overrideFile); if(!file.exists()) { System.out.println(format("Cannot find overrides file, creating one for you at %s", overrideFile)); properties.setProperty(threadAffinityKeyFor(PRODUCER), ""); properties.setProperty(threadAffinityKeyFor(JOURNALLER), ""); properties.setProperty(threadAffinityKeyFor(ACCUMULATOR), ""); properties.setProperty(JOURNALLER_ENABLED_KEY, Boolean.toString(DEFAULT_JOURNALLER_ENABLED_VALUE)); try(final FileWriter writer = new FileWriter(file, false)) { properties.store(writer, "override properties for perf workshop"); } } else { System.out.println(format("Loading overrides file from %s", overrideFile)); try (final FileReader reader = new FileReader(file)) { properties.load(reader); } ensurePropertiesArePresent(JOURNALLER_ENABLED_KEY, threadAffinityKeyFor(PRODUCER), threadAffinityKeyFor(JOURNALLER), threadAffinityKeyFor(ACCUMULATOR)); } } public int[] getProducerThreadAffinity() { return getThreadAffinity(PRODUCER); } public int[] getJournallerThreadAffinity() { return getThreadAffinity(JOURNALLER); } public int[] getAccumulatorThreadAffinity() { return getThreadAffinity(ACCUMULATOR); } public boolean enableJournaller() { return Boolean.valueOf(properties.getProperty(JOURNALLER_ENABLED_KEY)); } private void ensurePropertiesArePresent(final String... requiredKeys) { stream(requiredKeys).forEach((key) -> { if(!properties.stringPropertyNames().contains(key)) { throw new IllegalStateException( format("Required property %s not found! Try deleting the override file, and it will be regenerated", key)); } }); } private int[] getThreadAffinity(final String threadName) { final String threadAffinity = properties.getProperty(threadAffinityKeyFor(threadName)); if(threadAffinity != null && !"".equals(threadAffinity)) { final List<Integer> cpuSet = stream(threadAffinity.split(",")). map(Integer::parseInt).collect(toList()); final int[] cpus = new int[cpuSet.size()]; for(int i = 0; i < cpuSet.size(); i++) { cpus[i] = cpuSet.get(i); } return cpus; } return new int[0]; } private static String threadAffinityKeyFor(final String threadName) { return THREAD_AFFINITY_PREFIX + threadName; } }