Apache Geode Native .NET Framework
CHANGELOG
Function Execution
A client can invoke a server-resident function, with parameters, and can collect and operate on the returned results.
Server-side Requirements
To be callable from your client, a function must be
- resident on the server, and
- registered as available for client access.
See Executing a Function in Apache Geode in the Geode User Guide for details on how to write and register server-resident functions.
Client-side Requirements
The client must connect to the server through a connection pool in order to invoke a server-side function.
How Functions Execute
- The calling client application runs the
Executemethod on theExecutionobject. The function must already be registered on the servers. - The function is invoked on the servers where it needs to run. The servers are determined by the
FunctionService On*method calls, region configuration, and any filters. - If the function has results, the result is returned in a
ResultCollectorobject. - The client collects results using the
ResultCollector.GetResult()method.
In every client where you want to execute the function and process the results:
- Use one of the
FunctionService On*methods to create anExecutionobject. TheOn*methods,OnRegion,OnServerandOnServers, define the highest level where the function is run. - If you use
OnRegionyou can further narrow your run scope by setting key filters. - A function run using
OnRegionis a data dependent function – others are data-independent functions. You can run a data dependent function against partitioned and colocated partitioned regions. From the client, provide the appropriate key sets to the function call.
The
Executionobject allows you to customize the invocation by:- Providing a set of data keys to
WithFilterto narrow the execution scope. This works only forOnRegionExecution objects (data-dependent functions). - Providing function arguments to
WithArgs. - Defining a custom
ResultCollectorforWithCollector.
- Providing a set of data keys to
Call the
Execution.Execute()method to run the function.
Processing Function Results
To get the results from the function in the client app, use the result collector returned from the function execution.
The GetResult methods of the default result collector block until all results are received, then return the full result set.
The client can use the default result collector. If the client needs special results handling, code a custom ResultsCollector implementation to replace the default.
Use the Execution::withCollector method to specify the custom collector.
To handle the results in a custom manner:
- Write a class that implements the
ResultCollectorinterface to handle the results in a custom manner. The methods are of two types: one handles data and information from Geode and populates the results set, while the other returns the compiled results to the calling application:-
AddResultis called when results arrive from theFunctionmethods. UseAddResultto add a single result to the ResultCollector. -
EndResultsis called to signal the end of all results from the function execution. -
GetResultis available to your executing application (the one that callsExecution.Execute) to retrieve the results. This may block until all results are available. -
ClearResultsis called to clear partial results from the results collector. This is used only for highly availableOnRegionfunctions where the calling application waits for the results. If the call fails, before Geode retries the execution, it callsClearResultsto ready the instance for a clean set of results.
-
- Use the
Executionobject in your executing member to callWithCollector, passing your custom collector.
Function Execution Example
The native client release contains an example of function execution in ../examples/dotnet/functionexecution.
- The example begins with a server-side script that runs
gfshcommands to create a region, simply called “partition_region”. - The function is preloaded with a JAR file containing the server-side Java function code.
- The function, called “ExampleMultiGetFunction”, is defined in the
examples/utilitiesdirectory of your distribution. As its input parameter, the function takes an array of keys, then performs aGeton each key and returns an array containing the results. - The function does not load values into the data store. That is a separate operation, performed in these examples by the client, and does not involve the server-side function.
As prerequisites, the client code must be aware of the connection to the server, the name of the function, and the expected type/format of the input parameter and return value.
The client:
- creates an execution object
- provides the execution object with a populated input parameter array
- invokes the object’s execute method to invoke the server-side function
If the client expects results, it must create a result object.
The .NET Framework example uses a built-in result collector (IResultCollector.GetResults()) to retrieve the function results.
.NET Framework Example
This section contains code snippets showing highlights of the .NET Framework function execution example. They are not intended for cut-and-paste execution. For the complete source, see the example source directory.
The .NET Framework example creates a cache, then uses it to create a connection pool.
var cacheFactory = new CacheFactory()
.Set("log-level", "none");
var cache = cacheFactory.Create();
var poolFactory = cache.GetPoolFactory()
.AddLocator("localhost", 10334);
var pool = poolFactory.Create("pool");
The example uses the connection pool to create a region, with the same characteristics and name as the server-side region (partition_region).
var regionFactory = cache.CreateRegionFactory(RegionShortcut.PROXY)
.SetPoolName("pool");
var region = regionFactory.Create<object, object>("partition_region");
The sample client populates the server’s datastore with values, using the API and some sample key-value pairs.
string rtimmonsKey = "rtimmons";
string rtimmonsValue = "Robert Timmons";
string scharlesKey = "scharles";
string scharlesValue = "Sylvia Charles";
region.Put(rtimmonsKey, rtimmonsValue, null);
region.Put(scharlesKey, scharlesValue, null);
To confirm that the data has been stored, the client uses the API to retrieve the values and write them to the console. This is done without reference to the server-side example function.
var user1 = region.Get(rtimmonsKey, null);
var user2 = region.Get(scharlesKey, null);
Console.WriteLine(rtimmonsKey + " = " + user1);
Console.WriteLine(scharlesKey + " = " + user2);
Next, the client retrieves those same values using the server-side example function. The client code creates the input parameter, an array of keys whose values are to be retrieved.
ArrayList keyArgs = new ArrayList();
keyArgs.Add(rtimmonsKey);
keyArgs.Add(scharlesKey);
The client creates an execution object using Client.FunctionService.OnRegion and specifying the region.
var exc = Client.FunctionService<object>.OnRegion<object, object>(region);
The client then calls the server side function with its input arguments and stores the results in a Client.IResultCollector.
Client.IResultCollector<object> rc = exc.WithArgs<object>(keyArgs).Execute("ExampleMultiGetFunction");
It then loops through the results and prints the retrieved values.
ICollection<object> res = rc.GetResult();
Console.WriteLine("Function Execution Results:");
Console.WriteLine(" Count = {0}", res.Count);
foreach (List<object> item in res)
{
foreach (object item2 in item)
{
Console.WriteLine(" value = {0}", item2.ToString());
}
}
Apache Geode Native .NET Framework Documentation