001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.spi;
015
016import ch.qos.logback.core.helpers.CyclicBuffer;
017
018import java.util.*;
019
020/**
021 * @author Ceki Gülcü
022 */
023public class CyclicBufferTrackerSimulator {
024
025    static class Parameters {
026        public int keySpaceLen;
027        public int maxTimestampInc;
028        public int simulationLength;
029    }
030
031    CyclicBufferTracker<Object> realCBTracker = new CyclicBufferTracker<Object>();
032    CyclicBufferTrackerT<Object> t_CBTracker = new CyclicBufferTrackerT<Object>();
033
034    List<SimulationEvent> scenario = new ArrayList<SimulationEvent>();
035    List<String> keySpace = new ArrayList<String>();
036    Random randomKeyGen = new Random(100);
037    Random simulatorRandom = new Random(11234);
038    Parameters params;
039
040    int getToEndOfLifeRatio = 10;
041
042    CyclicBufferTrackerSimulator(Parameters params) {
043        this.params = params;
044        Map<String, String> checkMap = new HashMap<String, String>();
045        for (int i = 0; i < params.keySpaceLen; i++) {
046            String k = getRandomKeyStr();
047            if (checkMap.containsKey(k)) {
048                System.out.println("random key collision occurred");
049                k += "" + i;
050            }
051            keySpace.add(k);
052            checkMap.put(k, k);
053        }
054
055    }
056
057    private String getRandomKeyStr() {
058        int ri = randomKeyGen.nextInt();
059        return String.format("%X", ri);
060    }
061
062    void buildScenario() {
063        long timestamp = 30000;
064        int keySpaceLen = keySpace.size();
065        for (int i = 0; i < params.simulationLength; i++) {
066            int keyIndex = simulatorRandom.nextInt(keySpaceLen);
067            timestamp += simulatorRandom.nextInt(params.maxTimestampInc);
068            String key = keySpace.get(keyIndex);
069            scenario.add(new SimulationEvent(EventType.INSERT, key, timestamp));
070            if (simulatorRandom.nextInt(getToEndOfLifeRatio) == 0) {
071                scenario.add(new SimulationEvent(EventType.END_OF_LIFE, key, timestamp));
072            }
073            scenario.add(new SimulationEvent(EventType.REMOVE_STALE, key, timestamp));
074        }
075    }
076
077    public void dump() {
078        for (SimulationEvent simeEvent : scenario) {
079            System.out.println(simeEvent);
080        }
081    }
082
083    void play(SimulationEvent simulationEvent, ComponentTracker<CyclicBuffer<Object>> tracker) {
084        String key = simulationEvent.key;
085        long timestamp = simulationEvent.timestamp;
086        EventType eventType = simulationEvent.eventType;
087        switch (eventType) {
088        case INSERT:
089            tracker.getOrCreate(key, timestamp);
090            break;
091        case END_OF_LIFE:
092            tracker.endOfLife(key);
093            break;
094        case REMOVE_STALE:
095            tracker.removeStaleComponents(timestamp);
096            break;
097        }
098    }
099
100    public void simulate() {
101        for (SimulationEvent simeEvent : scenario) {
102            play(simeEvent, realCBTracker);
103            play(simeEvent, t_CBTracker);
104        }
105    }
106
107    // =========================================================================
108    enum EventType {
109        INSERT, END_OF_LIFE, REMOVE_STALE;
110    }
111
112    class SimulationEvent {
113        final public String key;
114        final public long timestamp;
115        final EventType eventType;
116
117        public SimulationEvent(EventType eventType, String key, long timestamp) {
118            this.eventType = eventType;
119            this.key = key;
120            this.timestamp = timestamp;
121        }
122
123        @Override
124        public String toString() {
125            return "SimulationEvent{" + "eventType=" + eventType + ", key='" + key + '\'' + ", timestamp=" + timestamp + '}';
126        }
127    }
128}