/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.core.spi;
import ch.qos.logback.core.helpers.CyclicBuffer;
import java.util.*;
/**
* @author Ceki Gücü
*/
public class CyclicBufferTrackerSimulator {
static class Parameters {
public int keySpaceLen;
public int maxTimestampInc;
public int simulationLength;
}
CyclicBufferTracker<Object> realCBTracker = new CyclicBufferTracker<Object>();
CyclicBufferTrackerT<Object> t_CBTracker = new CyclicBufferTrackerT<Object>();
List<SimulationEvent> scenario = new ArrayList<SimulationEvent>();
List<String> keySpace = new ArrayList<String>();
Random randomKeyGen = new Random(100);
Random simulatorRandom = new Random(11234);
Parameters params;
int getToEndOfLifeRatio = 10;
CyclicBufferTrackerSimulator(Parameters params) {
this.params = params;
Map<String, String> checkMap = new HashMap<String, String>();
for (int i = 0; i < params.keySpaceLen; i++) {
String k = getRandomKeyStr();
if (checkMap.containsKey(k)) {
System.out.println("random key collision occurred");
k += "" + i;
}
keySpace.add(k);
checkMap.put(k, k);
}
}
private String getRandomKeyStr() {
int ri = randomKeyGen.nextInt();
return String.format("%X", ri);
}
void buildScenario() {
long timestamp = 30000;
int keySpaceLen = keySpace.size();
for (int i = 0; i < params.simulationLength; i++) {
int keyIndex = simulatorRandom.nextInt(keySpaceLen);
timestamp += simulatorRandom.nextInt(params.maxTimestampInc);
String key = keySpace.get(keyIndex);
scenario.add(new SimulationEvent(EventType.INSERT, key, timestamp));
if (simulatorRandom.nextInt(getToEndOfLifeRatio) == 0) {
scenario.add(new SimulationEvent(EventType.END_OF_LIFE, key, timestamp));
}
scenario.add(new SimulationEvent(EventType.REMOVE_STALE, key, timestamp));
}
}
public void dump() {
for (SimulationEvent simeEvent : scenario) {
System.out.println(simeEvent);
}
}
void play(SimulationEvent simulationEvent,
ComponentTracker<CyclicBuffer<Object>> tracker) {
String key = simulationEvent.key;
long timestamp = simulationEvent.timestamp;
EventType eventType = simulationEvent.eventType;
switch (eventType) {
case INSERT:
tracker.getOrCreate(key, timestamp);
break;
case END_OF_LIFE:
tracker.endOfLife(key);
break;
case REMOVE_STALE:
tracker.removeStaleComponents(timestamp);
break;
}
}
public void simulate() {
for (SimulationEvent simeEvent : scenario) {
play(simeEvent, realCBTracker);
play(simeEvent, t_CBTracker);
}
}
// =========================================================================
enum EventType {
INSERT, END_OF_LIFE, REMOVE_STALE;
}
class SimulationEvent {
final public String key;
final public long timestamp;
final EventType eventType;
public SimulationEvent(EventType eventType, String key, long timestamp) {
this.eventType = eventType;
this.key = key;
this.timestamp = timestamp;
}
@Override
public String toString() {
return "SimulationEvent{" +
"eventType=" + eventType +
", key='" + key + '\'' +
", timestamp=" + timestamp +
'}';
}
}
}