/*
* 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.google.common.collect.Maps;
import com.griddynamics.jagger.coordinator.NodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class VirtualUsersClockConfiguration implements WorkloadClockConfiguration {
private Logger log = LoggerFactory.getLogger(VirtualUsersClockConfiguration.class);
private int users;
private int tickInterval;
private InvocationDelayConfiguration delay = FixedDelay.noDelay();
public void setUsers(int users) {
this.users = users;
}
public void setCount(int users) {
this.users = users;
}
public void setTickInterval(int tickInterval) {
this.tickInterval = tickInterval;
}
@Override
public WorkloadClock getClock() {
return new VirtualUsersClock();
}
public void setDelay(InvocationDelayConfiguration delay) {
this.delay = delay;
}
public InvocationDelayConfiguration getDelay() {
return delay;
}
private class VirtualUsersClock implements WorkloadClock {
@Override
public Map<NodeId, Integer> getPoolSizes(Set<NodeId> nodes) {
float a = ((float) users) / nodes.size();
int max = (int) Math.ceil(a);
Map<NodeId, Integer> result = Maps.newHashMap();
for (NodeId node : nodes) {
result.put(node, max);
}
return result;
}
@Override
public void tick(WorkloadExecutionStatus status, WorkloadAdjuster adjuster) {
log.debug("Going to perform tick with status {}", status);
int totalThreads = status.getTotalThreads();
int diff = users - totalThreads;
if (diff < 0) {
throw new IllegalStateException("Required to execute " + users + " users but " + totalThreads + " is executed at this moment.");
}
Map<NodeId, Integer> threadNumbers = partition(diff, status.getNodes());
for (Map.Entry<NodeId, Integer> entry : threadNumbers.entrySet()) {
Integer adjustment = entry.getValue();
NodeId node = entry.getKey();
if (adjustment > 0) {
log.debug("Controller should adjust task number on node {} to {}", node, adjustment);
int delayInterval = delay.getInvocationDelay().getValue();
log.debug("Controller should adjust invocation delay on node {} to {}", node, adjustment);
adjuster.adjustConfiguration(node, WorkloadConfiguration.with(adjustment, delayInterval));
}
}
}
private Map<NodeId, Integer> partition(int threads, Set<NodeId> availableNodes) {
Iterator<NodeId> nodes = availableNodes.iterator();
Map<NodeId, Integer> threadNumbers = Maps.newHashMap();
while (threads > 0) {
if (!nodes.hasNext()) {
nodes = availableNodes.iterator();
}
NodeId node = nodes.next();
Integer currentAdjustment = threadNumbers.get(node);
if (currentAdjustment == null) {
currentAdjustment = 0;
}
int newAdjustment = currentAdjustment + 1;
threadNumbers.put(node, newAdjustment);
threads--;
}
return threadNumbers;
}
@Override
public int getTickInterval() {
return tickInterval;
}
@Override
public int getValue() {
return users;
}
@Override
public String toString() {
return users + " virtual users with " + delay + " delay";
}
}
@Override
public String toString() {
return users + " virtual users with " + delay + " delay";
}
}