| /* |
| * 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.cassandra.simulator.debug; |
| |
| import java.util.function.Supplier; |
| |
| import org.apache.cassandra.simulator.RandomSource; |
| import org.hsqldb.lib.IntKeyLongValueHashMap; |
| |
| import static org.apache.cassandra.simulator.SimulatorUtils.failWithOOM; |
| |
| public class SelfReconcilingRandom implements Supplier<RandomSource> |
| { |
| static class Map extends IntKeyLongValueHashMap |
| { |
| public boolean put(int i, long v) |
| { |
| int size = this.size(); |
| super.addOrRemove((long)i, (long)v, (Object)null, (Object)null, false); |
| return size != this.size(); |
| } |
| } |
| final Map map = new Map(); |
| long[] tmp = new long[1]; |
| boolean isNextPrimary = true; |
| |
| static abstract class AbstractVerifying extends RandomSource.Abstract |
| { |
| final RandomSource wrapped; |
| int cur = 0; |
| |
| protected AbstractVerifying(RandomSource wrapped) |
| { |
| this.wrapped = wrapped; |
| } |
| |
| abstract void next(long verify); |
| |
| public int uniform(int min, int max) |
| { |
| int v = wrapped.uniform(min, max); |
| next(v); |
| return v; |
| } |
| |
| public long uniform(long min, long max) |
| { |
| long v = wrapped.uniform(min, max); |
| next(v); |
| return v; |
| } |
| |
| public float uniformFloat() |
| { |
| float v = wrapped.uniformFloat(); |
| next(Float.floatToIntBits(v)); |
| return v; |
| } |
| |
| public double uniformDouble() |
| { |
| double v = wrapped.uniformDouble(); |
| next(Double.doubleToLongBits(v)); |
| return v; |
| } |
| } |
| |
| public RandomSource get() |
| { |
| if (isNextPrimary) |
| { |
| isNextPrimary = false; |
| return new AbstractVerifying(new RandomSource.Default()) |
| { |
| void next(long verify) |
| { |
| map.put(++cur, verify); |
| } |
| |
| public void reset(long seed) |
| { |
| map.clear(); |
| cur = 0; |
| wrapped.reset(seed); |
| } |
| |
| public long reset() |
| { |
| map.clear(); |
| cur = 0; |
| return wrapped.reset(); |
| } |
| }; |
| } |
| |
| return new AbstractVerifying(new RandomSource.Default()) |
| { |
| void next(long v) |
| { |
| if (!map.get(++cur, tmp)) |
| throw failWithOOM(); |
| map.remove(cur); |
| if (tmp[0] != v) |
| throw failWithOOM(); |
| } |
| |
| public void reset(long seed) |
| { |
| cur = 0; |
| wrapped.reset(seed); |
| } |
| |
| public long reset() |
| { |
| cur = 0; |
| return wrapped.reset(); |
| } |
| }; |
| } |
| } |