/******************************************************************************* * gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/ * Copyright (C) 2014 SVS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package staticContent.evaluation.loadGenerator.fixedSchedule; import staticContent.evaluation.loadGenerator.ClientTrafficScheduleWriter; import staticContent.evaluation.loadGenerator.LoadGenerator; import staticContent.evaluation.loadGenerator.LoadGenerator.AL_Mode; import staticContent.evaluation.loadGenerator.applicationLevelTraffic.requestReply.ApplicationLevelMessage; import staticContent.evaluation.loadGenerator.scheduler.InOrderYieldWaitScheduler; import staticContent.evaluation.loadGenerator.scheduler.ScheduleTarget; import staticContent.evaluation.loadGenerator.scheduler.Scheduler; import staticContent.evaluation.loadGenerator.scheduler.ThreadPoolScheduler; import staticContent.framework.config.Settings; public class AL_FixedScheduleLoadGenerator extends FixedScheduleLoadGenerator { private boolean readAheadRequired = true; private boolean stopExecution = false; private Scheduler<ApplicationLevelMessage> scheduler; private ClientTrafficScheduleWriter<ApplicationLevelMessage> scheduleWriter; private ScheduleWriterThread scheduleWriterThread; private volatile boolean scheduleWriterActive = false; // used for weak overload detection private boolean hasMore = true; // TODO: use more than one scheduler (distribute events round robin-like to schedulers unless two or more events belong to the same client-socket; in that case, schedule all for the same scheduler as sending through a single socket cant be parallelized) public AL_FixedScheduleLoadGenerator(LoadGenerator owner) { super(owner); boolean useYieldWaitScheduler = !settings.isPropertyPresent("USE_SLOW_BUT_ACCURATE_SCHEDULER") ? false : settings.getPropertyAsBoolean("USE_SLOW_BUT_ACCURATE_SCHEDULER"); if (useYieldWaitScheduler) this.scheduler = new InOrderYieldWaitScheduler<ApplicationLevelMessage>(settings); else this.scheduler = new ThreadPoolScheduler<ApplicationLevelMessage>(settings); this.scheduleWriterThread = new ScheduleWriterThread(); // create suiting ClientTrafficScheduleWriter: if (owner.AL_MODE == AL_Mode.TRACE_FILE) this.scheduleWriter = new ALM_FS_Tracefile(this); else if (owner.AL_MODE == AL_Mode.POISSON) this.scheduleWriter = new ALM_FS_Poisson(this); else if (owner.AL_MODE == AL_Mode.CONSTANT_RATE) this.scheduleWriter = new ALM_FS_ConstantRate(this); else throw new RuntimeException("unsupportd mode: " +owner.AL_MODE); // start simulation: schedule(); if (hasMore) this.scheduleWriterThread.start(); } public Scheduler<ApplicationLevelMessage> getScheduler() { return this.scheduler; } public Settings getSettings() { return this.settings; } public LoadGenerator getLoadGenerator() { return this.owner; } private class ScheduleWriterThread extends Thread implements ScheduleTarget<ApplicationLevelMessage> { @Override public void run() { while (hasMore) { synchronized (scheduleWriterThread) { while (!readAheadRequired) { try { scheduleWriterThread.wait(); } catch (InterruptedException e) { continue; } } readAheadRequired = false; } if (!stopExecution) schedule(); } } @Override public void execute(ApplicationLevelMessage attachment) { if (scheduleWriterActive) System.err.println("TRACE_READER: warning: it seems the " +"trace file can't be read fast enough. simulation may " +"be inaccurate!"); synchronized (scheduleWriterThread) { readAheadRequired = true; scheduleWriterThread.notifyAll(); } } } private void schedule() { scheduleWriterActive = true; long start = System.currentTimeMillis(); System.out.println("start scheduling"); hasMore = scheduleWriter.scheduleRecords(owner.SCHEDULE_AHEAD/2, scheduler); System.out.println("finished scheduling (duration: " +(System.currentTimeMillis()-start) +"ms)"); scheduler.notifyOnOutputOfLast(scheduleWriterThread); scheduleWriterActive = false; } }