/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.flink.runtime.operators.testutils; import java.io.IOException; import java.util.Random; import org.apache.flink.core.memory.DataInputView; import org.apache.flink.core.memory.DataOutputView; import org.apache.flink.types.StringValue; import org.apache.flink.types.Value; public final class PairGenerator { public static class Pair implements Value { private static final long serialVersionUID = 1L; private int key; private StringValue value = new StringValue(); public Pair() {} public int getKey() { return key; } public StringValue getValue() { return value; } @Override public void write(DataOutputView out) throws IOException { out.writeInt(key); value.write(out); } @Override public void read(DataInputView in) throws IOException { key = in.readInt(); value.read(in); } @Override public int hashCode() { return 31 * key + value.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof Pair) { Pair other = (Pair) obj; return other.key == this.key && other.value.equals(this.value); } else { return false; } } @Override public String toString() { return String.format("(%d, %s)", key, value); } } public enum KeyMode { SORTED, RANDOM }; public enum ValueMode { FIX_LENGTH, RANDOM_LENGTH, CONSTANT }; private static char[] alpha = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' }; private final long seed; private final int keyMax; private final int valueLength; private final KeyMode keyMode; private final ValueMode valueMode; private Random random; private int counter; private final StringValue valueConstant; public PairGenerator(long seed, int keyMax, int valueLength) { this(seed, keyMax, valueLength, KeyMode.RANDOM, ValueMode.FIX_LENGTH); } public PairGenerator(long seed, int keyMax, int valueLength, KeyMode keyMode, ValueMode valueMode) { this(seed, keyMax, valueLength, keyMode, valueMode, null); } public PairGenerator(long seed, int keyMax, int valueLength, KeyMode keyMode, ValueMode valueMode, String constant) { this.seed = seed; this.keyMax = keyMax; this.valueLength = valueLength; this.keyMode = keyMode; this.valueMode = valueMode; this.random = new Random(seed); this.counter = 0; this.valueConstant = new StringValue(); if (constant != null) { this.valueConstant.setValue(constant); } } public void next(Pair target) { target.key = (keyMode == KeyMode.SORTED ? ++counter : Math.abs(random.nextInt() % keyMax) + 1); if (valueMode == ValueMode.CONSTANT) { target.value = valueConstant; } else { randomString(target.value); } } public void reset() { this.random = new Random(seed); this.counter = 0; } private void randomString(StringValue target) { int length = valueMode == ValueMode.FIX_LENGTH ? valueLength : valueLength - random.nextInt(valueLength / 3); target.setLength(0); for (int i = 0; i < length; i++) { target.append(alpha[random.nextInt(alpha.length)]); } } }