/*******************************************************************************
* Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved
*
* 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.cloudifysource.utilitydomain.context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.cloudifysource.domain.context.Service;
import org.cloudifysource.domain.context.ServiceInstance;
import org.openspaces.admin.pu.ProcessingUnit;
import org.openspaces.admin.pu.ProcessingUnitInstance;
//TODO - RENAME THIS CLASS! IT IS CONSTANTLY COLLIDING WITH THE SERVICE DSL CLASS
/**
*
* @author barakme
* @since 1.0
*/
public class ServiceImpl implements Service {
private static final int DEFAULT_INVOKE_TIMEOUT = 60 * 1000; // one minute
private final ProcessingUnit pu;
private final String name;
// only used for debugging in IntegratedContainer
private final int planned;
/**
* Constructor.
*
* @param pu
* underline processing unit that represents this service
*/
ServiceImpl(final ProcessingUnit pu) {
this.pu = pu;
this.name = pu.getName();
planned = 0;
}
/**
* Constructor.
*
* @param name
* service name
* @param planned
* number of planned instances
*/
ServiceImpl(final String name, final int planned) {
this.name = name;
this.pu = null;
this.planned = planned;
}
/**
* Invokes a given life cycle command on the service
*
* @param commandName
* command name
*/
// public void invoke(final String commandName) {
// throw new UnsupportedOperationException("Invoke not implemented yet!");
// }
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#getName()
*/
@Override
public String getName() {
return name;
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#getNumberOfPlannedInstances()
*/
@Override
public int getNumberOfPlannedInstances() {
if (this.pu != null) {
return pu.getNumberOfInstances();
} else {
return planned;
}
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#getNumberOfActualInstances()
*/
@Override
public int getNumberOfActualInstances() {
return getInstances().length;
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#waitForInstances(int, long, java.util.concurrent.TimeUnit)
*/
@Override
public ServiceInstance[] waitForInstances(final int howmany, final long timeout, final TimeUnit timeUnit) {
if (this.pu == null) {
return new ServiceInstance[] { new ServiceInstanceImpl(null) };
}
final boolean result = pu.waitFor(howmany, timeout, timeUnit);
if (result) {
return getInstances();
}
return null;
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#getInstances()
*/
@Override
public ServiceInstanceImpl[] getInstances() {
if (this.pu != null) {
final ProcessingUnitInstance[] puis = pu.getInstances();
final ServiceInstanceImpl[] sis = new ServiceInstanceImpl[puis.length];
for (int i = 0; i < sis.length; i++) {
final ProcessingUnitInstance pui = puis[i];
final ServiceInstanceImpl serviceInstance = new ServiceInstanceImpl(pui);
sis[i] = serviceInstance;
}
return sis;
} else {
return new ServiceInstanceImpl[] { new ServiceInstanceImpl(null) };
}
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#invoke(java.lang.String, java.lang.Object[],
* long, java.util.concurrent.TimeUnit)
*/
@Override
public Object[] invoke(final String commandName, final Object[] params, final long timeout, final TimeUnit unit)
throws Exception {
final ServiceInstanceImpl[] instances = this.getInstances();
final List<Future<Object>> futures = new ArrayList<Future<Object>>();
for (final ServiceInstanceImpl instance : instances) {
final Future<Object> future = instance.invokeAsync(commandName,
params);
futures.add(future);
}
final long start = System.currentTimeMillis();
final long end = start + unit.toMillis(timeout);
Exception firstException = null;
final Object[] results = new Object[instances.length];
for (int i = 0; i < results.length; i++) {
final Future<Object> future = futures.get(i);
try {
results[i] = future.get(end - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
} catch (final Exception e) {
results[i] = e;
if (firstException == null) {
firstException = e;
}
}
}
if (firstException != null) {
throw firstException;
}
return results;
}
/* (non-Javadoc)
* @see org.cloudifysource.dsl.context.IService#invoke(java.lang.String, java.lang.Object[])
*/
@Override
public Object[] invoke(final String commandName, final Object[] params)
throws Exception {
return invoke(commandName, params, DEFAULT_INVOKE_TIMEOUT, TimeUnit.MILLISECONDS);
}
@Override
public String toString() {
return "Service [getName()=" + getName() + ", getNumberOfPlannedInstances()=" + getNumberOfPlannedInstances()
+ ", getNumberOfActualInstances()=" + getNumberOfActualInstances() + ", getInstances()="
+ Arrays.toString(getInstances()) + "]";
}
}