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}