All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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