package com.bigdata.service; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.log4j.Logger; /** * Implementation that may be used when service scores are not yet * available. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ abstract public class AbstractServiceLoadHelperWithoutScores extends AbstractServiceLoadHelper { protected static final Logger log = Logger .getLogger(AbstractServiceLoadHelperWithoutScores.class); protected static final boolean INFO = log.isInfoEnabled(); // protected static final boolean DEBUG = log.isDebugEnabled(); /** * * @param joinTimeout */ protected AbstractServiceLoadHelperWithoutScores(final long joinTimeout) { super(joinTimeout); } /** * Computes the under-utilized services in the case where where <i>minCount</i> * is non-zero and we do not have pre-computed {@link #serviceScores} on hand. If * there are also no active services, then this awaits the join of at least * one service. Once it has at least one service that is not the optionally * <i>exclude</i>d service, it returns the "under-utilized" services. * * @throws TimeoutException * If the result could not be obtained before the timeout was * triggered. * * @throws InterruptedException */ public UUID[] getUnderUtilizedDataServices(final int minCount, final int maxCount, final UUID exclude) throws TimeoutException, InterruptedException { final long begin = System.currentTimeMillis(); while (true) { final long elapsed = System.currentTimeMillis() - begin; if (elapsed > joinTimeout) { log.warn("Timeout waiting for service to join."); throw new TimeoutException(); } // all services that we know about right now. final UUID[] knownServiceUUIDs = getActiveServices(); if (knownServiceUUIDs.length == 0) { // await a join. awaitJoin(100, TimeUnit.MILLISECONDS); continue; } /* * Scan and see if we have anything left after verifying that * the service is still on our "live" list and after excluding * this the optional [exclude] service. */ int nok = 0; for (int i = 0; i < knownServiceUUIDs.length; i++) { if (exclude != null && exclude.equals(knownServiceUUIDs[i])) { knownServiceUUIDs[i] = null; continue; } if (!isActiveDataService(knownServiceUUIDs[i])) { knownServiceUUIDs[i] = null; continue; } nok++; } if (nok <= 0) { // await a join. awaitJoin(100, TimeUnit.MILLISECONDS); continue; } /* * Now that we have at least one UUID, populate the return array. * * Note: We return at least minCount UUIDs, even if we have to * return the same UUID in each slot. */ final UUID[] uuids = new UUID[Math.max(minCount, nok)]; int n = 0, i = 0; while (n < uuids.length) { final UUID tmp = knownServiceUUIDs[i++ % nok]; if (tmp == null) { // entry in array was cleared above. continue; } if (exclude != null && tmp.equals(exclude)) { // entry should have been cleared above. throw new RuntimeException(); } // an acceptable entry. uuids[n++] = tmp; } return uuids; } } }