// Copyright 2016 Twitter. All rights reserved. // // 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. package com.twitter.heron.api.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import com.google.protobuf.ByteString; import com.twitter.heron.api.Config; import com.twitter.heron.api.generated.TopologyAPI; public final class Utils { private static final Logger LOG = Logger.getLogger(Utils.class.getName()); public static final String DEFAULT_STREAM_ID = "default"; private Utils() { } public static List<Object> tuple(Object... values) { List<Object> ret = new ArrayList<>(); Collections.addAll(ret, values); return ret; } public static void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { throw new RuntimeException(e); } } public static Map<String, String> readCommandLineOpts() { Map<String, String> ret = new HashMap<>(); String commandOptions = System.getenv("HERON_OPTIONS"); if (commandOptions != null) { commandOptions = commandOptions.replaceAll("%%%%", " "); String[] configs = commandOptions.split(","); for (String config : configs) { String[] options = config.split("="); if (options.length == 2) { ret.put(options[0], options[1]); } } } return ret; } public static byte[] serialize(Object obj) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.close(); return bos.toByteArray(); } catch (IOException ioe) { throw new RuntimeException(ioe); } } public static Object deserialize(byte[] serialized) { try { ByteArrayInputStream bis = new ByteArrayInputStream(serialized); ObjectInputStream ois = new ObjectInputStream(bis); Object ret = ois.readObject(); ois.close(); return ret; } catch (IOException ioe) { throw new RuntimeException(ioe); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static byte[] toByteArray(ByteBuffer buffer) { byte[] ret = new byte[buffer.remaining()]; buffer.get(ret, 0, ret.length); return ret; } public static <S, T> T get(Map<S, T> m, S key, T defaultValue) { T ret = m.get(key); if (ret == null) { ret = defaultValue; } return ret; } /** * Converts a Heron Config object into a TopologyAPI.Config.Builder. Config entries with null * keys or values are ignored. * * @param config heron Config object * @return TopologyAPI.Config.Builder with values loaded from config */ public static TopologyAPI.Config.Builder getConfigBuilder(Config config) { TopologyAPI.Config.Builder cBldr = TopologyAPI.Config.newBuilder(); Set<String> apiVars = config.getApiVars(); for (String key : config.keySet()) { if (key == null) { LOG.warning("ignore: null config key found"); continue; } Object value = config.get(key); if (value == null) { LOG.warning("ignore: config key " + key + " has null value"); continue; } TopologyAPI.Config.KeyValue.Builder b = TopologyAPI.Config.KeyValue.newBuilder(); b.setKey(key); if (apiVars.contains(key)) { b.setType(TopologyAPI.ConfigValueType.STRING_VALUE); b.setValue(value.toString()); } else { b.setType(TopologyAPI.ConfigValueType.JAVA_SERIALIZED_VALUE); b.setSerializedValue(ByteString.copyFrom(serialize(value))); } cBldr.addKvs(b); } return cBldr; } }