/*
* Copyright (C) 2008 Universidade Federal de Campina Grande
*
* This file is part of OurGrid.
*
* OurGrid is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.ourgrid.acceptance.util.peer;
import static org.easymock.EasyMock.eq;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.easymock.classextension.EasyMock;
import org.ourgrid.acceptance.util.PeerAcceptanceUtil;
import org.ourgrid.acceptance.util.WorkerAllocation;
import org.ourgrid.common.interfaces.LocalWorkerProvider;
import org.ourgrid.common.interfaces.RemoteWorkerProvider;
import org.ourgrid.common.interfaces.Worker;
import org.ourgrid.common.interfaces.management.RemoteWorkerManagement;
import org.ourgrid.common.interfaces.management.RemoteWorkerManagementClient;
import org.ourgrid.common.interfaces.management.WorkerManagement;
import org.ourgrid.matchers.RequestRepetitionRunnableMatcher;
import org.ourgrid.peer.PeerComponent;
import org.ourgrid.peer.PeerConfiguration;
import br.edu.ufcg.lsd.commune.container.ObjectDeployment;
import br.edu.ufcg.lsd.commune.container.logging.CommuneLogger;
import br.edu.ufcg.lsd.commune.container.servicemanager.actions.RepetitionRunnable;
import br.edu.ufcg.lsd.commune.context.ModuleContext;
import br.edu.ufcg.lsd.commune.identification.DeploymentID;
import br.edu.ufcg.lsd.commune.testinfra.AcceptanceTestUtil;
import br.edu.ufcg.lsd.commune.testinfra.util.TestStub;
public class Req_015_Util extends PeerAcceptanceUtil {
public Req_015_Util(ModuleContext context) {
super(context);
}
/**
* A local consumer disposes a local worker
*
* @param component The peer component
* @param worker The worker to be disposed
* @param allocation This allocation must contain information about
* the consumer that disposed the worker (loserID), the consumer that
* will receive the worker (winnerID) and the request.
* If the winnerID is null, the worker is commanded to stop working
*/
public void localConsumerDisposesLocalWorker(PeerComponent component, Worker worker,
WorkerAllocation allocation) {
localConsumerDisposesLocalWorker(component, worker, allocation, null);
}
/**
* A local consumer disposes a local worker
*
* @param component The peer component
* @param worker The worker to be disposed
* @param allocation This allocation must contain information about
* the consumer that disposed the worker (loserID), the consumer that
* will receive the worker (winnerID) and the request.
* If the winnerID is null, the worker is commanded to stop working
* @param future The future of the request to be canceled
*/
public void localConsumerDisposesLocalWorker(PeerComponent component, Worker worker,
WorkerAllocation allocation, ScheduledFuture<?> future) {
//Changes temporarily the logger mock
CommuneLogger oldLogger = component.getLogger();
CommuneLogger newLogger = EasyMock.createMock(CommuneLogger.class);
component.setLogger(newLogger);
WorkerManagement workerManag = (WorkerManagement) AcceptanceTestUtil.getBoundObject(allocation.workerID);
EasyMock.reset(workerManag);
newLogger.debug("Request " + allocation.loserRequestSpecification.getRequestId() + ": ["+allocation.loserID.getServiceID()+"] " +
"disposed the worker ["+allocation.workerID.getServiceID()+"].");
if (allocation.winnerID != null) {
workerManag.workForBroker(allocation.winnerID);
} else {
//newLogger.debug("Worker <" + allocation.workerID + "> is now IDLE");
workerManag.stopWorking();
}
if (future != null) {
EasyMock.reset(future);
EasyMock.expect(future.cancel(true)).andReturn(true);
EasyMock.replay(future);
}
EasyMock.replay(workerManag);
EasyMock.replay(newLogger);
ObjectDeployment lwpOD = getLocalWorkerProviderDeployment();
LocalWorkerProvider lwp = getLocalWorkerProvider();
AcceptanceTestUtil.setExecutionContext(component, lwpOD, allocation.loserID.getPublicKey());
lwp.disposeWorker(allocation.workerID.getServiceID());
if (future != null) {
EasyMock.verify(future);
}
EasyMock.verify(workerManag);
EasyMock.verify(newLogger);
component.setLogger(oldLogger);
}
/**
* A local consumer disposes a remote worker and another consumer receives it
*
* @param component The peer component
* @param worker The worker to bo disposed
* @param allocation This allocation must contain information about
* the consumer that disposed the worker (loserID), the consumer that
* will receive the worker (winnerID) and the request. The winnerID
* must not be null, even if the consumer that disposed the worker receives it back
* @param rescheduleRequest Determines whether the request must be rescheduled
*/
public void localDisposeRemoteWorker(PeerComponent component, TestStub workerStub, WorkerAllocation allocation, boolean rescheduleRequest) {
localDisposeRemoteWorker(component, workerStub, allocation, null, null, rescheduleRequest);
}
/**
* A local consumer disposes a remote worker
*
* @param component The peer component
* @param worker The worker to be disposed
* @param allocation This allocation must contain information about
* the consumer that disposed the worker (loserID), the consumer that
* will receive the worker (winnerID) and the request.
* If the winnerID is not provided, it is assumed that the worker is
* going to be disposed to its remote provider.
* In this case the RemoteWorkerProvider must not be null.
* @param rwp The RemoteWorkerProvider that provided the worker to be disposed
* @param rescheduleRequest Determines whether the request must be rescheduled
*/
@SuppressWarnings("unchecked")
public void localDisposeRemoteWorker(PeerComponent component,
TestStub workerStub, WorkerAllocation allocation, RemoteWorkerProvider rwp, DeploymentID rwpOID, boolean rescheduleRequest) {
//Changes temporarily the logger and timer mock
CommuneLogger oldLogger = component.getLogger();
CommuneLogger newLogger = EasyMock.createMock(CommuneLogger.class);
ScheduledExecutorService oldTimer = component.getTimer();
ScheduledExecutorService newTimer = EasyMock.createMock(ScheduledExecutorService.class);
component.setLogger(newLogger);
component.setTimer(newTimer);
RemoteWorkerManagement remoteWorkerManag = (RemoteWorkerManagement) AcceptanceTestUtil.getBoundObject(allocation.workerID);
EasyMock.reset(remoteWorkerManag);
newLogger.debug("Request " + allocation.loserRequestSpecification.getRequestId() + ": ["+allocation.loserID.getServiceID() +"] " +
"disposed the worker ["+workerStub.getDeploymentID().getServiceID()+"].");
if (allocation.winnerID == null) {
//No request fits with the disposed worker, dispose it back to its provider
EasyMock.reset(rwp);
rwp.disposeWorker(allocation.workerID.getServiceID());
EasyMock.replay(rwp);
newLogger.debug("The remote worker " + allocation.workerID.getServiceID() +" does not match any request. " +
"Disposing it back to its provider: " + rwpOID.getServiceID() + ".");
} else {
//A request fits with the disposed worker
RemoteWorkerManagementClient rwmc = getRemoteWorkerManagementClient();
remoteWorkerManag.workForBroker(rwmc, allocation.winnerID.getPublicKey());
}
if (rescheduleRequest) {
//No local worker fits the request. Reschedule request for repetition.
long delay = context.parseIntegerProperty(PeerConfiguration.PROP_REPEAT_REQUEST_DELAY);
newLogger.debug("Request " + allocation.loserRequestSpecification.getRequestId() + ": request scheduled for " +
"repetition in " + delay + " seconds.");
RepetitionRunnable runnable =
createRequestWorkersRunnable(component, allocation.loserRequestSpecification.getRequestId());
EasyMock.expect((ScheduledFuture)newTimer.scheduleWithFixedDelay(RequestRepetitionRunnableMatcher.eqMatcher(runnable),
eq(delay), eq(delay), eq(TimeUnit.SECONDS))).andReturn(null).once();
EasyMock.replay(newTimer);
}
EasyMock.replay(remoteWorkerManag);
EasyMock.replay(newLogger);
LocalWorkerProvider lwp = getLocalWorkerProviderProxy();
if (rwp != null) {
AcceptanceTestUtil.publishTestObject(component, rwpOID, rwp, RemoteWorkerProvider.class);
}
AcceptanceTestUtil.publishTestObject(component, workerStub.getDeploymentID(), workerStub.getObject(),
Worker.class);
AcceptanceTestUtil.publishTestObject(component, allocation.workerID, remoteWorkerManag,
RemoteWorkerManagement.class);
AcceptanceTestUtil.setExecutionContext(component, getLocalWorkerProviderDeployment(), allocation.loserID);
lwp.disposeWorker(workerStub.getDeploymentID().getServiceID());
if (allocation.winnerID == null) {
EasyMock.verify(rwp);
}
if (rescheduleRequest) {
EasyMock.verify(newTimer);
}
EasyMock.verify(remoteWorkerManag);
EasyMock.verify(newLogger);
//Set old timer and logger back
component.setLogger(oldLogger);
component.setTimer(oldTimer);
}
/**
* A remote consumer disposes a local worker
*
* @param component Peer component
* @param remoteClientOID ID of the Peer which is disposing the worker
* @param rwm The worker that is being disposed
* @param wmOID ID of the Worker Management object
*/
public void remoteDisposeLocalWorker(PeerComponent component, DeploymentID remoteClientOID,
RemoteWorkerManagement rwm, DeploymentID wmOID) {
//Changes temporarily the logger mock
CommuneLogger oldLogger = component.getLogger();
CommuneLogger newLogger = EasyMock.createMock(CommuneLogger.class);
component.setLogger(newLogger);
WorkerManagement workerManag = (WorkerManagement) AcceptanceTestUtil.getBoundObject(wmOID);
EasyMock.reset(workerManag);
newLogger.debug("The remote client [" + remoteClientOID.getServiceID() + "] " +
"disposed the worker [" + wmOID.getServiceID() + "].");
workerManag.stopWorking();
EasyMock.replay(workerManag);
EasyMock.replay(newLogger);
RemoteWorkerProvider rwp = getRemoteWorkerProviderProxy();
AcceptanceTestUtil.publishTestObject(component, wmOID, workerManag, WorkerManagement.class);
AcceptanceTestUtil.setExecutionContext(component, getRemoteWorkerProviderDeployment(), remoteClientOID);
rwp.disposeWorker(wmOID.getServiceID());
EasyMock.verify(workerManag);
EasyMock.verify(newLogger);
component.setLogger(oldLogger);
}
}