SGF-173. Added NoResult methods to FunctionTemplate and checked for FunctionExecution exception related to Function.hasResult() = false

This commit is contained in:
David Turanski
2013-04-17 09:58:40 -04:00
parent 3258b0826d
commit 3a4f727334
7 changed files with 145 additions and 95 deletions

View File

@@ -35,30 +35,33 @@ import com.gemstone.gemfire.cache.execute.ResultCollector;
*/
abstract class AbstractFunctionExecution {
private final static String NO_RESULT_MESSAGE = "Cannot return any result as the Function#hasResult() is false";
protected final Log logger = LogFactory.getLog(this.getClass());
private volatile ResultCollector<?, ?> resultCollector;
private Object[] args;
private Function function;
private String functionId;
private Function function;
private String functionId;
private long timeout;
public AbstractFunctionExecution(Function function, Object... args) {
Assert.notNull(function,"function cannot be null");
this.function = function;
Assert.notNull(function, "function cannot be null");
this.function = function;
this.functionId = function.getId();
this.args = args;
}
public AbstractFunctionExecution(String functionId, Object... args) {
Assert.isTrue(StringUtils.hasLength(functionId),"functionId cannot be null or empty");
this.functionId = functionId;
Assert.isTrue(StringUtils.hasLength(functionId), "functionId cannot be null or empty");
this.functionId = functionId;
this.args = args;
}
AbstractFunctionExecution() {
}
ResultCollector<?, ?> getCollector() {
return resultCollector;
}
@@ -70,17 +73,21 @@ abstract class AbstractFunctionExecution {
String getFunctionId() {
return functionId;
}
Function getFunction() {
return function;
}
long getTimeout() {
return timeout;
}
@SuppressWarnings("unchecked")
}
<T> Iterable<T> execute() {
return execute(true);
}
@SuppressWarnings("unchecked")
<T> Iterable<T> execute(Boolean returnResult) {
Execution execution = this.getExecution();
if (getKeys() != null) {
execution = execution.withFilter(getKeys());
@@ -88,107 +95,119 @@ abstract class AbstractFunctionExecution {
if (getCollector() != null) {
execution = execution.withCollector(getCollector());
}
ResultCollector<?,?> resultCollector = null;
ResultCollector<?, ?> resultCollector = null;
execution = execution.withArgs(getArgs());
if (isRegisteredFunction()){
resultCollector = (ResultCollector<?,?>) execution.execute(functionId);
if (isRegisteredFunction()) {
resultCollector = (ResultCollector<?, ?>) execution.execute(functionId);
} else {
resultCollector = (ResultCollector<?,?>) execution.execute(function);
resultCollector = (ResultCollector<?, ?>) execution.execute(function);
if (!function.hasResult()) {
return (Iterable<T>) null;
}
}
if (!returnResult) {
return (Iterable<T>) null;
}
if (logger.isDebugEnabled()) {
logger.debug("using ResultsCollector:" + resultCollector.getClass().getName());
}
Iterable<T> results = null;
if (this.timeout > 0 ){
try {
results= (Iterable<T>)resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
try {
if (this.timeout > 0) {
try {
results = (Iterable<T>) resultCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
} catch (FunctionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
results = (Iterable<T>) resultCollector.getResult();
}
catch (FunctionException e) {
throw new RuntimeException(e);
return replaceSingletonNullCollectionWithEmptyList(results);
} catch (FunctionException e) {
//TODO: Come up with a better way to determine that the function should not return a result;
if (!e.getMessage().equals(NO_RESULT_MESSAGE)) {
throw e;
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
results = (Iterable<T>) resultCollector.getResult();
}
return replaceSingletonNullCollectionWithEmptyList(results);
return results;
}
<T> T executeAndExtract() {
Iterable<T> results = this.execute();
if (results == null || !results.iterator().hasNext()) {
return null;
}
return results.iterator().next();
}
protected abstract Execution getExecution();
protected AbstractFunctionExecution setFunctionId(String functionId) {
this.functionId = functionId;
return this;
}
protected AbstractFunctionExecution setFunction(Function function) {
this.function = function;
return this;
}
protected AbstractFunctionExecution setArgs(Object... args) {
this.args = args;
return this;
}
protected Set<?> getKeys() {
return null;
}
protected AbstractFunctionExecution setTimeout(long timeout) {
this.timeout = timeout;
return this;
}
protected AbstractFunctionExecution setResultCollector(ResultCollector<?,?> resultCollector) {
protected AbstractFunctionExecution setResultCollector(ResultCollector<?, ?> resultCollector) {
this.resultCollector = resultCollector;
return this;
}
/**
* @return
*/
private boolean isRegisteredFunction() {
return function == null;
return function == null;
}
private <T> Iterable<T> replaceSingletonNullCollectionWithEmptyList(Iterable<T> results) {
if (results == null) {
return results;
}
Iterator<T> it = results.iterator();
if (!it.hasNext()) {
return results;
}
if (it.next()==null && !it.hasNext()) {
if (it.next() == null && !it.hasNext()) {
return new ArrayList<T>();
}
return results;
}
}

View File

@@ -56,6 +56,14 @@ abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
.setFunctionId(functionId);
return execute(functionExecution);
}
@Override
public void executeWithNoResult(String functionId, Object... args) {
AbstractFunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId);
execute(functionExecution,false);
}
@Override
public <T> T executeAndExtract(String functionId, Object... args) {
@@ -78,6 +86,12 @@ abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
return execution.execute();
}
protected <T> Iterable<T> execute(AbstractFunctionExecution execution, boolean returnResult) {
execution.setTimeout(timeout)
.setResultCollector(resultCollector);
return execution.execute(returnResult);
}
protected <T> T executeAndExtract(AbstractFunctionExecution execution) {
execution.setTimeout(timeout)
.setResultCollector(resultCollector);

View File

@@ -49,6 +49,13 @@ public interface GemfireFunctionOperations {
*/
public abstract <T> Iterable<T> execute(String functionId, Object... args);
/**
* Execute a function registered with an ID with no return value
* @param functionId the function ID
* @param args the calling arguments
*/
public void executeWithNoResult(String functionId, Object... args);
/**
* Execute a function registered with an ID and with an expected singleton result
* @param functionId the function ID

View File

@@ -50,5 +50,4 @@ public class GemfireOnMemberFunctionTemplate extends AbstractFunctionTemplate {
}
return new DistributedMemberFunctionExecution(this.distributedMember);
}
}

View File

@@ -23,51 +23,46 @@ import com.gemstone.gemfire.cache.execute.Function;
* @author David Turanski
*
*/
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
private Region<?, ?> region;
/**
*
* @param region
*/
public GemfireOnRegionFunctionTemplate(Region<?,?> region) {
Assert.notNull(region, "Region cannot be null");
this.region = region;
}
@Override
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunction(function)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return this.<T> executeAndExtract(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
public GemfireOnRegionFunctionTemplate(Region<?, ?> region) {
Assert.notNull(region, "Region cannot be null");
this.region = region;
}
@Override
protected AbstractFunctionExecution getFunctionExecution() {
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunction(function).setTimeout(timeout)
.setArgs(args));
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
.setArgs(args));
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return this.<T> executeAndExtract(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId)
.setTimeout(timeout).setArgs(args));
}
@Override
protected AbstractFunctionExecution getFunctionExecution() {
return new RegionFunctionExecution(this.region);
}
@Override
public void executeWithNoResult(String functionId, Set<?> keys, Object... args) {
execute(new RegionFunctionExecution(region).setKeys(keys).setFunctionId(functionId).setTimeout(timeout)
.setArgs(args), false);
}
}

View File

@@ -25,6 +25,7 @@ public interface GemfireOnRegionOperations extends GemfireFunctionOperations {
public abstract <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args);
public abstract <T> Iterable<T> execute(Function function, Set<?> keys, Object... args);
public abstract void executeWithNoResult(String functionId, Set<?> keys, Object... args);
public abstract <T> T executeAndextract(String functionId, Set<?> keys, Object... args);
}