Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,8 @@ limitations under the License.
<li class="has_submenu">
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/configuring/configuration.html">Configuring a Client Application</a>
<ul>
<li class="has_submenu">
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/configuring/system-level-configuration.html">System Level Configuration</a>
<ul>
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/configuring/sysprops.html">System Properties</a>
</li>
</ul>
</li>
</ul>
</li>
Expand All @@ -55,6 +50,9 @@ limitations under the License.
<li class="has_submenu">
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/regions/regions.html">Configuring Regions</a>
<ul>
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/regions/registering-interest-for-entries.html">Registering Interest for Entries</a>
</li>
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/regions/region-attributes.html">Region Attributes</a>
</li>
Expand Down Expand Up @@ -92,6 +90,9 @@ limitations under the License.
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/transactions/transactions.html">Transactions</a>
</li>
<li>
<a href="/docs/geode-native/<%=vars.product_version_nodot%>/configuring/sysprops.html">System Properties</a>
</li>
</ul>
</div>
</div>
51 changes: 34 additions & 17 deletions docs/geode-native-docs/continuous-queries.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ in the *<%=vars.product_name%> User Guide*.

Continuous querying provides the following features:

- **Standard <%=vars.product_name%> native client query syntax and semantics**. Continuous queries are expressed in the same language used for other native client queries. See [Remote Queries](remote-queries.html).
- **Standard <%=vars.product_name%> native client query syntax and semantics**. Continuous queries are expressed in the same language used for other native client queries. See [Remote Queries](remote-queries.html).

- **Standard <%=vars.product_name%> events-based management of CQ events**. The event handling used
to process CQ events is based on the standard <%=vars.product_name%> event handling framework.
Expand All @@ -41,32 +41,35 @@ server failure (see [High Availability for Client-to-Server Communication](prese
If your clients are durable, you can also define any of your CQs as durable (see [Durable Client Messaging](preserving-data/durable-client-messaging.html)).

- **Interest criteria based on data values**. Continuous queries are run against the region's entry values.
Compare this to register interest by reviewing [Registering Interest for Entries](client-cache/registering-interest-for-entries.html).
Compare this to register interest by reviewing [Registering Interest for Entries](regions/registering-interest-for-entries.html).

- **Active query execution**. Once initialized, the queries operate only on new events, rather than on the entire region data set.
Events that change the query result are sent to the client immediately.
- **Active query execution**. Once initialized, the queries operate on new events. Events that change the query result are sent to the client immediately.

## <a id="cq_api"></a>Typical Continuous Query Lifecycle

1. The client creates the CQ. This sets up everything for running the query and provides the client with a `CqQuery` object, but does not execute the CQ. At this point, the query is in a `STOPPED `state, ready to be closed or run.
2. The client initiates the CQ with an API call to one of the `CqQuery execute*` methods. This puts the query into a `RUNNING` state on the client and on the server. The server remotely evaluates the query string, and optionally returns the results to the client.
1. The CqListener waits for events. When it receives events, it takes action accordingly. Events are not result sets. If the action requires doing something with the data, the data must first be retrieved.
2. The client initiates the CQ with an API call to one of the `CqQuery execute*` methods. This puts the query into a `RUNNING` state on the client and on the server. The server remotely evaluates the query string, and optionally returns the results to the client. `CqQuery execute*` methods include:
- .NET: `CqQuery.Execute()` and `CqQuery.ExecuteWithInitialResults()`
- C++: `CqQuery.execute()` and `CqQuery.executeWithInitialResults()`

1. A CQ Listener waits for events. When it receives events, it takes action accordingly with the data in the CqEvent.
3. The CQ is closed by a client call to `CqQuery.close`. This de-allocates all resources in use for the CQ on the client and server. At this point, the cycle could begin again with the creation of a new `CqQuery` instance.

## <a id="ExecutingACQ"></a>Executing a Continuous Query from the Client

The essential steps to create and execute a continuous query are:

1. Create an instance of the `QueryService` class. If you are using the pool API (recommended), you should obtain the `QueryService` from the pool.
1. Create a `CqListener` to field events sent from the server.
1. Use the `Query.execute()` method to submit the query string to the cache server. The server
remotely evaluates the query string, then monitors those results and notifies the client if they change.
1. Define a CQ Listener (in .NET, an `ICqListener`, in C++, a `CqListener`) to field events sent from the server.
1. Use one of the `CqQuery execute*` methods to submit the query string to the cache server.
1. The server remotely evaluates the query string, then monitors those results and notifies the client if they change.
1. The client listens for changes that match the query predicate.
1. Iterate through the returned objects.
1. When finished, close down the continuous query.

### <a id="DotNetCQExample"></a>.NET Continuous Query Example

These C# code excerpts are from the `examples\dotnet\ContinuousQueryCs` example included in your client
These C# code excerpts are from the `examples\dotnet\continuousquery` example included in your client
distribution. See the example for full context.

Following the steps listed above,
Expand All @@ -77,15 +80,17 @@ Following the steps listed above,
var queryService = pool.GetQueryService();
```

1. Create a CQ Listener:
1. Define an ICqListener:

```
var cqListener = new MyCqListener<string, Order>();
public class MyCqListener<TKey, TResult> : ICqListener<TKey, TResult>
{
```

1. Insert the CQ Listener into a CQ attributes object:
1. Create an instance of your ICqListener and insert it into a CQ attributes object:

```
var cqListener = new MyCqListener<string, Order>();
var cqAttributesFactory = new CqAttributesFactory<string, Order>();
cqAttributesFactory.AddCqListener(cqListener);
var cqAttributes = cqAttributesFactory.Create();
Expand All @@ -97,12 +102,18 @@ Following the steps listed above,
var query = queryService.NewCq("MyCq", "SELECT * FROM /example_orderobject WHERE quantity > 30", cqAttributes, false);
```

1. Execute the query:

```
query.Execute();
```

1. Wait for events and do something with them.

```
/* Excerpt from the CqListener */

/* Determine OP Type */
/* Determine Operation Type */
switch (ev.getQueryOperation())
{
case CqOperation.OP_TYPE_CREATE:
Expand Down Expand Up @@ -149,13 +160,13 @@ Following the steps listed above,
auto queryService = pool->getQueryService();
```

1. Create a CQ Listener:
1. Define a CqListener:

```
class MyCqListener : public CqListener {
```

1. Insert the CQ Listener into a CQ attributes object:
1. Create an instance of your CqListener and insert it into a CQ attributes object:

```
CqAttributesFactory cqFactory;
Expand All @@ -174,12 +185,18 @@ Following the steps listed above,
cqAttributes);
```

1. Execute the query:

```
query->execute();
```

1. Wait for events and do something with them.

```
/* Excerpt from the CqListener */

/* Determine OP Type */
/* Determine Operation Type */
switch (cqEvent.getQueryOperation()) {
case CqOperation::OP_TYPE_CREATE:
opStr = "CREATE";
Expand Down
74 changes: 34 additions & 40 deletions docs/geode-native-docs/function-execution.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ See the License for the specific language governing permissions and
limitations under the License.
-->

A client can invoke a server-resident function, with paramaters, and can collect and operate on the returned results.
A client can invoke a server-resident function, with parameters, and can collect and operate on the returned results.

## <a id="server_side_requirements"></a>Server-side Requirements

To be callable from your client, a function must be resident on the server and registered as available for client access.
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 <%=vars.product_name_long%>](/serverman/developing/function_exec/function_execution.html)
in the <%=vars.product_name%> User Guide for details on how to write and register server-resident functions.

Expand All @@ -34,67 +38,57 @@ The client must connect to the server through a connection pool in order to invo
## <a id="how_functions_execute"></a>How Functions Execute

1. The calling client application runs the `execute` method on the `Execution` object. The function must already be registered on the servers.
2. The function is invoked on all servers where it needs to run. The locations are determined by the `FunctionService on*`
2. 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.
3. If the function has results, the result is returned in a `ResultCollector` object.
4. The client collects results using the result collector `getResult`.
4. 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 an `Execution` object. The `on*` methods,
`onRegion`, `onServer` and `onServers`, define the highest level where the function is run. If
you use `onRegion` you can further narrow your run scope by setting key filters. The function run
using `onRegion` is a data dependent function – the 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
`onRegion`, `onServer` and `onServers`, define the highest level where the function is run.
- If you use `onRegion` you can further narrow your run scope by setting key filters.
- A function run using `onRegion` is 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.

- Use the `Execution` object as needed for additional function configuration. You can:
- Provide a set of data keys to `withFilter` to narrow the execution scope. This works only for `onRegion` Execution objects.
- Provide function arguments to `withArgs`.
- Provide a custom `ResultCollector` to `withCollector`.
- The `Execution` object allows you to customize the invocation by:
- Providing a set of data keys to `withFilter` to narrow the execution scope. This works only for `onRegion` Execution objects (data-dependent functions).
- Providing function arguments to `withArgs`.
- Defining a custom `ResultCollector` for `withCollector`.

- Call the `Execution` object execute method to run the function.
- Call the `Execution.execute()` method to run the function.

## <a id="processing_function_results"></a>Processing Function Results

The client may 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 define the custom collector.

For example, to program your client to get the results from a function, use the result collector returned from the function execution, like this:

```cpp
ResultCollectorPtr rc = FunctionService::onRegion(region)
->withArgs(args)
->withFilter(keySet)
->withCollector(new MyCustomResultCollector())
.execute(Function);
CacheableVectorPtr functionResult = rc.getResult();
```

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:

1. Write a class that implements the `ResultCollector` interface to handle the results in a custom manner. The methods are of two types: one handles data and information from <%=vars.product_name%> and populates the results set, while the other returns the compiled results to the calling application:
- `addResult` is called when results arrive from the `Function` methods. Use `addResult` to add a single result to the ResultCollector.
- `endResults` is called to signal the end of all results from the function execution.
- `getResult` is available to your executing application (the one that calls `Execution.execute`) to retrieve the results. This may block until all results are available.
- `clearResults` is called to clear partial results from the results collector. This is used only for highly available `onRegion` functions where the calling application waits for the results. If the call fails, before <%=vars.product_name%> retries the execution, it calls `clearResults` to ready the instance for a clean set of results.
2. Use the `Execution` object in your executing member to call `withCollector`, passing your custom collector, as shown in the example above.
2. Use the `Execution` object in your executing member to call `withCollector`, passing your custom collector.

# <a id="examples"></a>Examples

The native client source release contains examples of function execution written for .NET and
C++. The examples are located in `../examples/dotnet/FunctionExecutionCs` and
The native client release contains examples of function execution written for .NET and
C++. The examples are located in `../examples/dotnet/functionexecution` and
`../examples/cpp/function-execution`, respectively.

Both examples begin with a server-side script that runs `gfsh` commands to create
a region, simply called "partition_region", which is preloaded with a JAR file containing the
server-side Java function code. The function, called "ExampleMultiGetFunction", is defined in the
The two examples share some common elements:

- They begin with a server-side script that runs `gfsh` commands 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/utilities` directory of your distribution. As its input parameter, the function takes an array of keys,
then performs a `get` on 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 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
Expand All @@ -103,12 +97,12 @@ of the input parameter and return value.
The client:

- creates an execution object
- populates the execution object with input parameters
- invokes the object's execute method to invoke the server-side function.
- 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. Optionally, the client can use a provided ResultCollector which offers some predefined
methods for iterating over and processing return values.
If the client expects results, it must create a result object. The C++ example uses a result object to hold the function results.
Alternatively, the client can use a provided Result Collector which offers some predefined methods for iterating over and processing return values.
The .NET example uses a built-in result collector (`IResultCollector.getRestults()`) to retrieve the function results.

## <a id="dotnet_example"></a>.NET Example
This section contains code snippets showing highlights of the .NET function execution example. They are not intended for cut-and-paste execution.
Expand Down
Loading