/* * Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved * http://www.griddynamics.com * * This library is free software; you can redistribute it and/or modify it under the terms of * the Apache License; either * version 2.0 of the License, or any later version. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.griddynamics.jagger.engine.e1.scenario; import com.griddynamics.jagger.coordinator.NodeId; import com.griddynamics.jagger.user.ProcessingConfig; import com.griddynamics.jagger.util.Parser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** * User: dkotlyarov */ public class UserGroup { private static final Logger log = LoggerFactory.getLogger(UserGroup.class); private final int id; private final long life; private final int count; private final long startBy; private final UserClock clock; final ArrayList<User> users; int activeUserCount = 0; private int startCount; private final long startInTime; private long startByTime = -1; int startedUserCount = 0; private double extraUser; private double extraUserStep; public UserGroup(UserClock clock, int id, ProcessingConfig.Test.Task.User config, long time) { this(clock, id, Parser.parseInt(config.getCount(), clock.getRandom()), (int) config.getStartCount(), time + Parser.parseTime(config.getStartIn(), clock.getRandom()), Parser.parseTime(config.getStartBy(), clock.getRandom()), Parser.parseTime(config.getLife(), clock.getRandom()) ); double floor = (Double.compare(config.getStartCount(), 1.0) < 0) ? +0.0 : +Math.floor(config.getStartCount()); double extraUserStep = config.getStartCount() - floor; this.extraUserStep = extraUserStep; this.extraUser = extraUserStep; } public UserGroup(UserClock clock, int id, int count, int startCount, long startInTime, long startBy, long life) { this.clock = clock; this.id = id; this.count = count; this.users = new ArrayList<User>(count); this.startCount = startCount; this.life = life; this.startInTime = startInTime; this.startBy = startBy; log.info(String.format("User group %d is created", id)); } public int getId() { return id; } public int getCount() { return count; } public long getLife() { return life; } public int getActiveUserCount() { return activeUserCount; } public int getStartCount() { return startCount; } public long getStartInTime() { return startInTime; } public long getStartByTime() { return startByTime; } public void tick(long time, LinkedHashMap<NodeId, WorkloadConfiguration> workloadConfigurations) { // to allow user set floating value of users extraUser += extraUserStep; for (User user : users) { user.tick(time, workloadConfigurations); } if (users.size() < count) { if (users.isEmpty()) { if (time >= startInTime) { spawnUsers(time, workloadConfigurations); startByTime = time + startBy; } } else { while (time >= startByTime) { spawnUsers(time, workloadConfigurations); } } } } public void spawnUsers(long time, LinkedHashMap<NodeId, WorkloadConfiguration> workloadConfigurations) { // if true at this tick should appear one additional user if (extraUser >= 1.0) { startCount++; } for (int i = 0; i < startCount; ++i) { if (users.size() < count) { new User(clock, this, time, findNodeWithMinThreadCount(workloadConfigurations), workloadConfigurations); } } // decrement the number of additional users if (extraUser >= 1.0) { startCount--; extraUser -= 1.0; } startByTime += startBy; } public static NodeId findNodeWithMinThreadCount(LinkedHashMap<NodeId, WorkloadConfiguration> workloadConfigurations) { Iterator<Map.Entry<NodeId, WorkloadConfiguration>> it = workloadConfigurations.entrySet().iterator(); Map.Entry<NodeId, WorkloadConfiguration> minNode = it.next(); while (it.hasNext()) { Map.Entry<NodeId, WorkloadConfiguration> node = it.next(); if (node.getValue().getThreads() < minNode.getValue().getThreads()) { minNode = node; } } return minNode.getKey(); } public int getStartedUserCount() { return startedUserCount; } }