/* * Copyright 2009 the original author or authors. * * 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 org.rioproject.test.scaling; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceTemplate; import net.jini.lookup.LookupCache; import net.jini.lookup.ServiceDiscoveryEvent; import net.jini.lookup.ServiceDiscoveryListener; import net.jini.lookup.ServiceDiscoveryManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.rmi.RemoteException; import java.util.Random; /** * The class represents an object that distributes total load among * {@link SettableLoadService}s. */ public class LoadDistributor { /** * The logger used by this class. */ static Logger logger = LoggerFactory.getLogger("org.rioproject.test.scaling"); /** * The lookup cache used to monitor services. */ private LookupCache lookupCache; /** * The flag indicates if service load update is needed. */ private boolean serviceLoadUpdateNeeded = true; /** * The current total load. */ private double totalLoad = 0; /** * The number of times to invoke the setServiceLoad * method on the service */ private int iterations = 1; /** * Constructs a <code>LoadDistributor</code>. * * @param sdm the service discovery manager to use to discover * {@link SettableLoadService}s. * @throws java.rmi.RemoteException If connectivity fails */ public LoadDistributor(ServiceDiscoveryManager sdm) throws RemoteException { // Create LookupCache Class[] types = new Class[] {SettableLoadService.class}; ServiceTemplate template = new ServiceTemplate(null, types, null); ServiceDiscoveryListener listener = new ServiceDiscoveryListener() { public void serviceAdded(ServiceDiscoveryEvent event) { logger.info("serviceAdded() event received: " + event); triggerServiceLoadUpdate(); } public void serviceChanged(ServiceDiscoveryEvent event) { logger.info("serviceChanged() event received: " + event); triggerServiceLoadUpdate(); } public void serviceRemoved(ServiceDiscoveryEvent event) { logger.info("serviceRemoved() event received: " + event); triggerServiceLoadUpdate(); } }; lookupCache = sdm.createLookupCache(template, null, listener); // Run the monitoring method in a separate thread Runnable starter = new Runnable() { public void run() { LoadDistributor.this.run(); } }; new Thread(starter).start(); } /** * Sets the total load to distribute among the services. * * @param totalLoad the new total load. */ void setTotalLoad(double totalLoad) { setTotalLoad(totalLoad, 1); } /** * Sets the total load to distribute among the services. * * @param totalLoad the new total load. * @param iterations The number of times to invoke the setServiceLoad * method on the service */ void setTotalLoad(double totalLoad, int iterations) { this.totalLoad = totalLoad; this.iterations = iterations; triggerServiceLoadUpdate(); } /** * Triggers the service load update. */ private synchronized void triggerServiceLoadUpdate() { serviceLoadUpdateNeeded = true; notifyAll(); } /** * Monitors the {@link #serviceLoadUpdateNeeded} flag and, when * necessary, distributes the total load among available services. */ private void run() { while(true) { synchronized (this) { while(!serviceLoadUpdateNeeded) { try { wait(10000); } catch (InterruptedException e) { } } serviceLoadUpdateNeeded = false; } updateServiceLoad(); } } /** * Distributes the total load among available services. */ private void updateServiceLoad() { double totalLoad = this.totalLoad; ServiceItem[] items = lookupCache.lookup(null, Integer.MAX_VALUE); String msg = "===> Changing service load."; msg += " Total load: " + totalLoad + ","; msg += " number of services: " + items.length + ", iterations: "+iterations+"."; logger.info(""); logger.info(msg); if (items.length > 0) { double load = totalLoad / items.length; boolean retry = true; while(retry) { Random random = new Random(); int index = items.length-1; if(index>1) index = random.nextInt(index); //for (int i = 0; i < items.length; i++) { SettableLoadService service = (SettableLoadService) items[index].service; String str = "service [" + index + "].setLoad(" + load + ") - "; try { for(int i=0; i<iterations; i++) service.setLoad(load); logger.info(str + "OK"); retry = false; } catch (RemoteException e) { logger.info(str + "FAILURE"); logger.info(e.toString()); } } } } }