![JAR search and dependency download from the Maven repository](/logo.png)
com.sematext.ag.player.RealTimePlayer Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2010 Sematext International
*
* Licensed 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 com.sematext.ag.player;
import com.sematext.ag.Player;
import com.sematext.ag.PlayerConfig;
import com.sematext.ag.event.Event;
import com.sematext.ag.exception.InitializationFailedException;
import com.sematext.ag.sink.Sink;
import com.sematext.ag.source.Source;
import com.sematext.ag.source.SourceFactory;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* Simulates constant real-time user load: users using service with reasonable delays between actions.
*
* @author sematext, http://www.sematext.com/
*/
public class RealTimePlayer extends Player {
private static final Logger LOG = Logger.getLogger(RealTimePlayer.class);
public static final String TIME_TO_WORK_KEY = "player.realtime.timeToWorkInSec";
public static final String MIN_ACTION_DELAY_KEY = "player.realtime.minActionDelayInMs";
public static final String MAX_ACTION_DELAY_KEY = "player.realtime.maxActionDelayInMs";
public static final String SOURCES_THREADS_COUNT_KEY = "player.realtime.sources.threadsCount";
public static final String SOURCES_PER_THREAD_COUNT_KEY = "player.realtime.sources.perThreadCount";
private long timeToWork; // in ms
private int threadsNum;
private int sourcesPerThread;
private long minActionDelay;
private long maxActionDelay;
/**
* (non-Javadoc)
*
* @see com.sematext.ag.Player#init(com.sematext.ag.PlayerConfig)
*/
@Override
public void init(PlayerConfig config) throws InitializationFailedException {
super.init(config);
validate(config);
timeToWork = Long.valueOf(config.get(TIME_TO_WORK_KEY)) * 1000;
minActionDelay = Long.valueOf(config.get(MIN_ACTION_DELAY_KEY));
maxActionDelay = Long.valueOf(config.get(MAX_ACTION_DELAY_KEY));
threadsNum = Integer.valueOf(config.get(SOURCES_THREADS_COUNT_KEY));
sourcesPerThread = Integer.valueOf(config.get(SOURCES_PER_THREAD_COUNT_KEY));
}
private void validate(PlayerConfig config) throws InitializationFailedException {
config.checkRequired(TIME_TO_WORK_KEY);
config.checkRequired(MIN_ACTION_DELAY_KEY);
config.checkRequired(MAX_ACTION_DELAY_KEY);
config.checkRequired(SOURCES_THREADS_COUNT_KEY);
config.checkRequired(SOURCES_PER_THREAD_COUNT_KEY);
}
/**
* (non-Javadoc)
*
* @see com.sematext.ag.Player#play(com.sematext.ag.source.SourceFactory, com.sematext.ag.sink.Sink)
*/
@Override
public void play(SourceFactory sourceFactory, Sink sink) {
List> sourceGroups = initSources(sourceFactory);
Thread[] threads = new Thread[threadsNum];
int i = 0;
for (List sourceGroup : sourceGroups) {
threads[i] = new UserGroupThread(sourceGroup, sink, timeToWork, minActionDelay, maxActionDelay);
threads[i].start();
i++;
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
LOG.error(e); // TODO: handle properly
}
}
}
private static class UserGroupThread extends Thread {
private List sourceGroup;
private Sink sink;
private long timeToWork;
private long minActionDelay;
private long maxActionDelay;
public UserGroupThread(List sourceGroup, Sink sink, long timeToWork, long minActionDelay,
long maxActionDelay) {
this.sourceGroup = sourceGroup;
this.sink = sink;
this.timeToWork = timeToWork;
this.minActionDelay = minActionDelay;
this.maxActionDelay = maxActionDelay;
}
@Override
public void run() {
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() < startTime + timeToWork && sourceGroup.size() > 0) {
int sourceIndex = (int) (Math.random() * sourceGroup.size());
Source source = sourceGroup.get(sourceIndex);
Event event = source.nextEvent();
if (null == event) {
LOG.info("Source finished producing events, left sources in group: " + sourceGroup.size()
+ ", completed source: " + source);
close(source);
sourceGroup.remove(source);
} else {
try {
sink.startCounters();
sink.write(event);
sink.endCounters();
} catch (Exception ex) {
LOG.error("Error writing to sink, skipping event. Cause: " + ex.getCause());
}
}
try {
if (sourceGroup.size() > 0) {
long sleepTime = (long) ((minActionDelay + Math.random() * (maxActionDelay - minActionDelay)) / sourceGroup
.size());
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
LOG.error(e); // TODO: handle properly
}
}
for (Source source : sourceGroup) {
close(source);
}
}
private void close(Source source) {
LOG.info("Closing source: " + source + "...");
source.close();
LOG.info("Closing source: " + source + "... DONE.");
}
}
private List> initSources(SourceFactory sourceFactory) {
List> result = new ArrayList>();
int sourceCount = 0;
for (int i = 0; i < threadsNum; i++) {
List sourceList = new ArrayList();
for (int k = 0; k < sourcesPerThread; k++) {
Source source = null;
try {
source = sourceFactory.create();
} catch (InitializationFailedException e) {
LOG.error("Creating source failed.", e);
continue;
}
sourceList.add(source);
}
LOG.info("Initialized source group, sources count: " + sourceList.size());
if (sourceList.size() == 0) {
LOG.warn("Source group contains no sources, group will be ignored");
continue;
}
result.add(sourceList);
sourceCount += sourceList.size();
}
LOG.info("Created " + result.size() + " source groups with total " + sourceCount + " sources.");
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy