blob: 444ec443444c6cd8bfe7d3811359e5e6ecd7aca8 [file] [log] [blame]
/*
* 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();
}
};
}
}