cacheRunner

GemFire Enterprise Native Client

C++ Programming Example

The cacheRunner C++ example is an interactive program for modifying and viewing GemFire cache contents as a C++ native client interacts with a GemFire cache server. The cacheRunner program joins the distributed system, creates a cache, and then accepts command-line input for inspecting, modifying, and remotely querying the cache while working with a cache server. XML files are provided to configure cacheRunner for different functional operations or behavior.

You can review the C++ source code for this example by opening the files in the cacheRunner directory that have .cpp and .hpp file extensions.

This example is divided into four parts, with each part requiring different sets of configuration files for both cacheRunner and the cache server. The cacheRunner example can also be configured using a local gfcpp.properties file.

The cacheRunner C++ example is located in the native client installation under NativeClient_xxxx/examples/cacheRunner, where xxxx represents the four-digit product version number.

The instructions in this example apply to the Windows operating system, so alter them as needed for your system.


Part 1: Modifying the Cache


Running cacheRunner

The cacheRunner example uses a GemFire cache server configuration file, cacherunner.xml. When the cache server starts, cacherunner.xml creates two regions root and listenerWriterLoader. This is a description of each cache server region and how each region is configured:

The cacheRunner application comes with a set of XML configuration files that configure its local cache and demonstrate various operations with the cache server. The following XML files are used with this example. The application is run separately for each of these XML files:

The procedures in this example introduce a few of the cacheRunner commands. For information on the others, enter help or ? at the session prompt. In the procedures, the lines you type are shown in a boldface fixed font. System output is shown in a regular fixed font.


Configuring the Environment

Examples that interact with a cache server require specific environment configurations so the cache server runs properly. Follow the configuration steps listed below that apply to your operating system. Throughout this example, when the native client directory is referenced replace the xxxx in NativeClient_xxxx with the actual four-digit product version number.

  1. Start a terminal session from the GemFire Enterprise product installation directory, then configure your environment settings by following the steps in examples/EnvSetup.html. Refer to the system configuration information in the GemFire Enterprise Developer's Guide if you need help with this step.

  2. Set the JAVA_HOME and GF_JAVA_HOME environment variables to point to your installed Java JRE or JDK. See the installation information in the GemFire Enterprise System Administrator's Guide for the versions of Java that are compatible with GemFire Enterprise. The JAVA_HOME setting is for your applications, and GF_JAVA_HOME is for the GemFire scripts. You must have a compatible Java JRE or JDK installed, and you must set JAVA_HOME and GF_JAVA_HOME to point to it.

  3. Add $JAVA_HOME/bin to the start of your PATH.

  4. For Solaris and Linux only: Set the LD_LIBRARY_PATH environment variable to point to the NativeClient_xxxx/lib directory.

The following is a list of the environment configuration commands for the cacheRunner example. Choose the set of commands that are appropriate for your operating system. The text that you type is shown in bold.

Bourne and Korn shells (sh, ksh, bash)

% cd GemFireInstallDirectory
% GEMFIRE=GemFireInstallDirectory; export GEMFIRE
% CLASSPATH=$GEMFIRE/lib/gemfire.jar:$GEMFIRE/lib/antlr.jar:$CLASSPATH; export CLASSPATH
% JAVA_HOME=<installed JRE PATH>; export JAVA_HOME
% GF_JAVA_HOME=$JAVA_HOME; export GF_JAVA_HOME
% PATH=$JAVA_HOME/bin:$GEMFIRE/bin:$PATH; export PATH
% LD_LIBRARY_PATH=<full path to NativeClient_xxxx/lib>:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH

Windows

> cd GemFireInstallDirectory
> set GEMFIRE=GemFireInstallDirectory
> set CLASSPATH=%GEMFIRE%\lib\gemfire.jar;%GEMFIRE%\lib\antlr.jar;%CLASSPATH%
> set JAVA_HOME=<installed JRE PATH>
> set GF_JAVA_HOME=%JAVA_HOME%
> set PATH=%JAVA_HOME%\bin;%GEMFIRE%\bin;%PATH%


Starting the Cache Server

Start the cache server by completing the following steps:

  1. Configure the session environment according to the steps listed in Configuring the Environment.

  2. Go to the native client's cacheRunner directory (replace the xxxx in NativeClient_xxxx with the actual four-digit product version):

    cd \NativeClient_xxxx\examples\cacheRunner

  3. Start the cache server:

    cacheserver start cache-xml-file=cacherunner.xml

    The cache server is initialized using the region settings in the cacherunner.xml file. A message similar to the following appears, indicating that the cache server is running:

  4. Cacheserver pid: 2120 status: running


Starting the CacheRunner Example

Follow these steps to start the cacheRunner example using the tcr_cache.xml initialization file:

  1. Create two sessions from the GemFire installation directory.

  2. For Solaris and Linux only:
    Configure both session environments according to the steps listed in Configuring the Environment.

  3. Go to the cacheRunner directory in both sessions

  4. cd \NativeClient_xxxx\examples\cacheRunner

  5. Start the cacheRunner application in both sessions, specifying tcr_cache.xml:

    cacheRunner tcr_cache.xml

    The cacheRunner client is initialized using the region settings in the tcr_cache.xml file. The application creates root and listenerWriterLoader regions, then the /root region prompt appears. As you move from region to region, the prompt includes a path to tell you where you are, such as /listenerWriterLoader>.

  6. Set one of the two cacheRunner sessions aside. You only need one client session for the next two Producing Data exercises.

  7. In the cacheRunner client, check the contents of the root region:

    ls
    Region Entries:

    /root>

  8. To check regions in client cache.

    lsrgn
    Number of regions in Cache: 2

    Region Name 1: listenerWriterLoader


    Region Name 2: root


    root>

Producing Data in the root Region

In this exercise you add an entry in the root region of the cacheRunner local client cache, then attempt to retrieve the entry from the cache server.

In the cacherunner client:

  1. Add an entry to the root region:

    put entry1 ball str

    This line creates an entry whose key is entry1 and whose value is the string ball.

  2. Check the contents to see the new entry:

    ls
    Region Entries:
    entry1 -> String: ball

  3. Invalidate the new entry in the local cache, then check the contents:

    inv -l entry1
    ls
    Region Entries:
    entry1 -> No value in cache.

    The value for the entry has been removed from the local cache.

  4. Now try to get the entry from the cache server:

    get entry1
    entry1 -> No value in cache.

    The entry cannot be retrieved from the cache server because the client root cache does not have an endpoint established with the cache server, so it did not propagate the entry to the server.


Producing Data in a Distributed Region

In this exercise you produce data that is distributed to the cache server.

In the cacherunner client:

  1. Go to the listenerWriterLoader region, then check the contents:
  2. chrgn listenerWriterLoader
    ls
    Region Entries:

    There are no entries in the client cache for the listenerWriterLoader region. However, the listenerWriterLoader region on the cache server was initialized with an entry named entry1 that has a value of 1.0.

  3. Retrieve entry1 from the cache server:

    get entry1
    entry1 -> String: 1.0

  4. Create a new entry in the client cache, then check the cache contents:

    put entry2 bat str
    ls
    Region Entries:
    entry2 -> String: bat
    entry1 -> String: 1.0

  5. Invalidate entry2, then check the contents:

    inv -l entry2
    ls
    Region Entries:
    entry2 -> No value in cache.
    entry1 -> String: 1.0

  6. Now get entry2 from the cache server and check the contents:

    get entry2
    ls
    Region Entries:
    entry2 -> String: bat
    entry1 -> String: 1.0

    The entry in the client cache is updated with the value stored in the cache server.

  7. Keep the cacheRunner application and the cache server running for the next exercise.


Registering Interest Using Regular Expressions

In this exercise you learn how client regions can register interest for cache server entry keys through the use of regular expressions. By registering interest, a client receives event notifications from the cache server for changes affecting the keys whose strings match the expression.

Note that regular expressions only work with string keys.

In the first cacherunner client:

  1. Make sure that the cacheRunner client session you used in the previous exercises is still set to the listenerWriterLoader region. If it isn't, then set it to that region:
  2. chrgn listenerWriterLoader

  3. Put some entries in the client region:

    put key-1 val1
    put key-2 val2
    put key-3 val3
    put key-4 val4

In the second cacherunner client:

  1. Display the second cacheRunner client session that you created at the start of this example, then go to its listenerWriterLoader region:

    chrgn listenerWriterLoader

  2. Get the four entries that were put in the first client:

    get key-1
    key-1 -> Bytes: val1
    get key-2
    key-2 -> Bytes: val2
    get key-3
    key-3 -> Bytes: val3
    get key-4
    key-4 -> Bytes: val4

  3. Register interest using a regular expression:

    regex key-[2-3]

    This registers interest in key-2 and key-3.

In the first client:

Change the values for key-2 and key-3:

    put key-2 newVal2
    put key-3 newVal3

In the second client:

  1. Check the contents of the region:
  2. ls
    Region Entries:
    key-3 -> Bytes: newVal3
    key-1 -> Bytes: val1
    key-4 -> Bytes: val4
    key-2 -> Bytes: newVal2

    The updated values for key-2 and key-3 are listed.

  3. Unregister interest for key-2 and key-3:

    unregex key-[2-3]

In the first client:

Change the values for key-2 and key-3:

    put key-2 123
    put key-3 456

In the second client:

Check the contents of the region:

ls
Region Entries:
key-3 -> Bytes: newVal3
key-1 -> Bytes: val1
key-4 -> Bytes: val4
key-2 -> Bytes: newVal2

The old values for key-2 and key-3 are listed because no interest is registered for them, so no update event notifications were received from the cache server.

Keep both cacheRunner applications and the cache server running for the next exercise.


Adding a Cache Listener to an Existing Region

In this exercise you add a cache listener to an existing region, then observe how the cache listener reports events that occur in the cache. A cache listener reports entry and region events both before and after they occur. Entry events are create, update, invalidate, and destroy. Region events are clear, create, invalidate, and destroy. A cache listener only receives callbacks for events occurring in the local cache. The local cache listener is not invoked when an entry is destroyed in a remote cache. However, if that destroy is distributed then the subsequent destroy in the local cache causes the cache listener's afterDestroy method to be called.

Some region attributes are immutable after they are established. Others, such as a cache listener, can be modified after the region is created. To see how a cache listener works, complete these steps:

In both cacherunner clients:

Make sure that the two cacheRunner client sessions you used in the previous exercise are still set to the listenerWriterLoader region. If they aren't, then set both of them to that region:

    chrgn listenerWriterLoader

In the first cacherunner client

Put some entries in the cache:

    put key-1 val1
    put key-2 val2
    put key-3 val3
    put key-4 val4

In the second cacherunner client:

  1. Retrieve the four entries that were put in the first client:

    get key-1
    key-1 -> Bytes: val1
    get key-2
    key-2 -> Bytes: newVal2
    get key-3
    key-3 -> Bytes: newVal3
    get key-4
    key-4 -> Bytes: val4

  2. Register interest for two of the keys:

    reg key-1 key-2

  3. Add a cache listener to the existing client region:

    set listener

  4. Create a new entry in the local cache:

    put key-5 val-5

    The cache listener reports the events that occur:

  5. TestCacheListener.afterCreate :
    Print Event:
    Cache Event Origin Local
    Region is : /listenerWriterLoader
    Key is : key-5
    Old value is : NULL
    New value is : val-5

In the first client:

Change the values for key-1 and key-2:

    put key-1 newVal1
    put key-2 newVal2

Look at the second client. The cache listener reports the events that occur:

TestCacheListener.afterUpdate :
Print Event:
Cache Event Origin Local
Region is : /listenerWriterLoader
Key is : key-1
Old value is : NULL
New value is : newVal1
TestCacheListener.afterUpdate :
Print Event:
Cache Event Origin Local
Region is : /listenerWriterLoader
Key is : key-2
Old value is : NULL
New value is : newVal2

In the second client:

  1. Remove the cache listener from the client region by setting the listener value to null:
  2. set listener null

  3. Create a new entry in the client cache:

    put key-6 val-6

    No event reporting occurs because the cache listener was removed from the region.

In the first client:

Change the values for key-2 and key-3:

    put key-2 123
    put key-3 456

No event reporting occurs because the cache listener was removed.

Ending the client sessions:

You need to keep one of the cacheRunner sessions open for the next exercise, but the second session can be closed. Follow these steps:

  1. End the first cacheRunner application, but leave the session open:
  2. exit

  3. End the second cacheRunner application:
  4. exit

  5. Close the second cacheRunner session:
  6. exit

  7. Keep the cache server running for the next exercise.

Using a Cacheless Region

In this exercise you learn about applications that do not perform local caching. An application can receive all events on a region without storing the data that comes with the events. Consequently, the application can pass data through to other receivers without the overhead of caching. This configuration lets you separate event processing from data management.

To see how a cacheless region works, complete these steps:

  1. In the open cacheRunner session, start cacheRunner with tcr_cacheless.xml as its initialization file:

    cacheRunner tcr_cacheless.xml

  2. Go to the listenerWriterLoader region, then check its contents:
  3. chrgn listenerWriterLoader
    ls
    Region Entries:

  4. There are no entries in the client cache for the listenerWriterLoader region. However, remember that the listenerWriterLoader region on the cache server contains an entry named entry1 that has a value of 1.0.

  5. Retrieve entry1 from the cache server:

    get entry1
    entry1 -> String: 1.0

    The local cache acknowledges that the entry was received.

  6. Check the contents again:

    ls
    Region Entries:

    The entry is not retained in the client cache.

  7. Close the cacheRunner application:

    exit

  8. Close the cacheRunner session:

    exit

  9. Stop the cache server:

    cacheserver stop

  10. Close the cache server session:

    exit



Part 2: Modifying the Cache with Security Configured


Running cacheRunner to Authenticate Credentials and Authorize Operations

In this example, cacheRunner and the cache server are configured so the cacheRunner client must submit credentials to the server for authentication before the client can connect. The cacheRunner example is also configured so that cache operations are either accepted or denied based on defined roles. The authentication and authorization configurations are made using gemfire.properties for the server and gfcpp.properties for the client.

For more information about GemFire security, see Sample Security Implementations in GemFire.

The lines you type are shown in a boldface fixed font. System output is shown in a regular fixed font.


Configuring the Environment

To demonstrate security, this example requires the configuration of specific security plugin modules. To enable the PKCS third-party security plugin implementation, OpenSSL also needs to be configured. See related sections in this document for details.

  1. For Linux and Solaris: Start a terminal session from the GemFire Enterprise product installation directory, then configure your environment settings by following the steps in examples/EnvSetup.html.

    For Windows: Run the Visual Studio 2005 Command Prompt to create a terminal session with the necessary preset compiler environment configurations. Change to the GemFire Enterprise product installation directory, then configure your environment settings by following the steps in examples/EnvSetup.html.

    See the environment configuration list below for system-specific instructions for the following steps.

  2. Install OpenSSL (optional):

    To enable authentication in GemFire, the security plugin needs to be compiled (named securityImpl.dll for Windows and libsecurityImpl.so for Solaris or Linux). The security plugin optionally depends on OpenSSL for its PKCS sample template, so OpenSSL needs to be compiled or installed first.

    For Linux and Solaris, you can download the latest tarball archive for OpenSSL. For Windows users, you can get the OpenSSL installer at www.openssl.org/related/binaries.html.

    To compile OpenSSL (Linux and Solaris):

    Copy the downloaded OpenSSL tarball to your appropriate Linux or SunOS folder at NativeClient_xxxx/templates/security/openssl, then execute buildit.sh from the shell.

    To install OpenSSL (Windows):

    Run the downloaded OpenSSL installer and accept the default installation path (C:\OpenSSL).

  3. Set the JAVA_HOME and GF_JAVA_HOME environment variables to your installed JRE or JDK. See the installation information in the GemFire Enterprise System Administrator's Guide for the versions of Java that are compatible with GemFire Enterprise. The JAVA_HOME setting is for your applications, and GF_JAVA_HOME is for the GemFire scripts. You must have a compatible JRE or JDK installed and you must set JAVA_HOME and GF_JAVA_HOME to point to it. See the Sun Java web site at http://java.sun.com for the latest Java version for your operating system.

  4. Add $JAVA_HOME/bin to the start of your PATH.

  5. Set the GFCPP environment variable to the full path to NativeClient_xxxx.

  6. Set the OPENSSL environment variable. For Linux and Solaris, point it to the parent folder for the OpenSSL binaries created from the tarball. For Windows, if you accept the default installation path in step 2, the command is set OPENSSL=C:\OpenSSL.

  7. For Solaris and Linux only:
    Set the LD_LIBRARY_PATH environment variable to point to the NativeClient_xxxx/lib directory and $OPENSSL/lib directory.

    For Windows only:
    Set the PATH environment variable to point to the NativeClient_xxxx\bin directory and %OPENSSL%\bin directory.

  8. Compile the security plugin by executing the buildit script in the NativeClient_xxxx/templates/security directory. This produces securityImpl.dll on Windows and libsecurityImpl.so on Solaris and Linux.

  9. Set the CLASSPATH environment variable to include the path to gfSecurityImpl.jar in the GemFire Enterprise lib directory.

The following environment configuration list is a summary of the commands described in steps 1 through 9. Optionally, you need to configure the OpenSSL dependency first if PKCS is enabled for the GemFire security plugin. Refer to the Sample Security Implementations in GemFire - PKCS Authentication topic for additional details and a command list.

Bourne and Korn shells (sh, ksh, bash)

% cd GemFireInstallDirectory
% GEMFIRE=<full path to the GemFire Enterprise directory>
% JAVA_HOME=<installed JRE PATH>; export JAVA_HOME
% GF_JAVA_HOME=$JAVA_HOME; export GF_JAVA_HOME
% PATH=$JAVA_HOME/bin:$PATH; export PATH
% GFCPP=<full path to NativeClient_xxxx>; export GFCPP
% OPENSSL=<parent folder for OpenSSL binaries>; export OPENSSL
% LD_LIBRARY_PATH=$GFCPP/lib
% LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$OPENSSL/lib
% export LD_LIBRARY_PATH
% CLASSPATH=$GEMFIRE/lib/gfSecurityImpl.jar:$CLASSPATH

Windows Command shell (Using the Visual Studio 2005 Command Prompt)

> cd GemFireInstallDirectory
> set GEMFIRE=<full path to the GemFire Enterprise directory>
> set JAVA_HOME=<installed JRE PATH>
> set GF_JAVA_HOME=%JAVA_HOME%
> set GFCPP=<full path to NativeClient_xxxx>
> set OPENSSL=C:\OpenSSL
> set PATH=%JAVA_HOME%\bin;%GFCPP%\bin;%OPENSSL%\bin;%PATH%
> set CLASSPATH=%GEMFIRE%\lib\gfSecurityImpl.jar;%CLASSPATH%


Starting the Cache Server

To start the cache server with authentication enabled, complete the following steps:

  1. Configure the session environment according to the steps listed in Configuring the Environment.

  2. Place a copy of server configuration file gemfire.properties in the NativeClient_xxxx\examples\cacheRunner directory. You can copy gemfire.properties from the %GEMFIRE%\defaultConfigs directory.

  3. Go to the cacheRunner directory:

    cd \NativeClient_xxxx\examples\cacheRunner
  4. Modify gemfire.properties with the following security property entries. You can use any text editor that saves the file as plain text.
    security-authz-xml-uri=authz-dummy.xml (modify security-= to produce this property name and setting)
    security-client-authenticator=templates.security.DummyAuthenticator.create
    security-client-accessor=templates.security.XmlAuthorization.create
  5. Start the cache server, using the cacherunner.xml file to configure its cache:

    cacheserver start cache-xml-file=cacherunner.xml

    The cache server is initialized using the region settings in the cacherunner.xml file and the security settings in the gemfire.properties file. A message similar to the following appears, indicating that the cache server is running:

  6. Cacheserver pid: 2120 status: running

See the Sample Security Implementations in GemFire section for additional server configuration options for cacheRunner.


Starting CacheRunner

With No Credentials:

Follow these steps to start cacheRunner so no client credentials are submitted to the cache server. The credentials are in the form of a username and password, and are specified in a local gfcpp.properties file that configures cacheRunner.

  1. Create a cacheRunner session from the GemFire installation directory.

  2. For Solaris and Linux only:
    Configure the session environment according to the steps listed in Configuring the Environment for Enabling Security.

  3. Go to the cacheRunner directory:

  4. cd \NativeClient_xxxx\examples\cacheRunner

  5. Copy the gfcpp.properties file from the native client defaultSystem directory to the \cacheRunner directory. Open the file in a text editor and note that all property entries, including security-related ones, are commented out. Close the file without making any changes.

  6. Start the cacheRunner application in the session, specifying tcr_cache.xml.

    cacheRunner tcr_cache.xml

    The following authentication error occurs and the client is prevented from connecting to the cache server. Commented-out entries in gfcpp.properties are ignored, so no credentials are supplied by the client.

  7. [warning 2008/03/27 23:30:55.324204 IST trout:25825 3076407424] Authentication required in handshake with endpoint[localhost:50505]: No security-* properties are provided Exception in CacheRunner::connectDistributedSystem [ThinClientDistributionManager::init:no authentication provided]

With Invalid Credentials:

Start cacheRunner again, but this time specify invalid credentials.

  1. Uncomment the security-username=root property in gfcpp.properties and change its value so cacheRunner submits an invalid user name:

    security-username=invalidUsr

  2. Start cacheRunner. The invalid user name generates an authentication error and the client is prevented from connecting to the cache server.

    cacheRunner tcr_cache.xml

    [warning 2008/03/27 23:29:20.425783 IST trout:25245 3076407424] Authentication failed in handshake with endpoint[localhost:50505]: DummyAuthenticator: Invalid user name [invalidUsr], password supplied. Exception in CacheRunner::connectDistributedSystem [ThinClientDistributionManager::init:authentication failed]

With Valid Credentials:

In this exercise you edit gfcpp.properties again to include valid client credentials:

  1. Open the gfcpp.properties file and uncomment all security-* properties. Change the following commands as shown below, noting any platform-specific differences.

  2. <Windows only>security-client-auth-library=securityImpl
    <Solaris and Linux only>security-client-auth-library=libsecurityImpl
    security-client-auth-factory=createUserPasswordAuthInitInstance
    security-username=writer1
    security-password=writer1

    Values of the library and factory methods are built into the security plugin, and are set according to the cache server properties set in gemfire.properties.
    Refer to the Sample Security Implementations in GemFire section for other possible property values.

  3. Start cacheRunner, specifying tcr_cache.xml:

    cacheRunner tcr_cache.xml

    The client credentials are valid, so cacheRunner successfully connects to the cache server. The application creates root and listenerWriterLoader regions, then the /root region prompt appears.

  4. Leave the client running for the next Authorizing Operations exercise.

Authorizing Operations

In this exercise you do several cache operations, then observe which operations are denied or allowed based on the submitted credentials.

In the running cacherunner client:

  1. Go to the listenerWriterLoader region, then check the contents:
  2. chrgn listenerWriterLoader
    ls
    Region Entries:

    There are no entries in the local client cache for the listenerWriterLoader region. However, the listenerWriterLoader region on the cache server was initialized with an entry named entry1 that has a value of 1.0.

  3. Get entry1 from the cache server. An authorization error occurs.

    get entry1

    [error 2008/03/27 23:27:03.639666 IST trout:24282 3076411520] ThinClientRegion::getNoThrow_internal: An exception ( com.gemstone.gemfire.security.NotAuthorizedException: Not authorized to perform GET operation on region [/listenerWriterLoader] ) happened at remote site Entry not found

    The entry from the cache server could not be obtained because the get operation is not authorized (the writer1 user name supplied by the client has limited operation capabilities). See authz-dummy.xml for a description of the operation permissions granted to the writer1 role. Refer to Sample Security Implementations in GemFire for further details.

  4. Create a new entry in the client cache that gets updated to the cache server. Check the cache contents:

    put entry2 bat str
    ls
    Region Entries:
    entry2 -> String: bat

  5. Destroy entry2 in the client cache and check the contents:

    des -l entry2
    ls
    Region Entries:

  6. Get entry2 from the cache server, then check the contents:

    get entry2

    [error 2008/03/27 23:27:03.639666 IST trout:24282 3076411520] ThinClientRegion::getNoThrow_internal: An exception ( com.gemstone.gemfire.security.NotAuthorizedException: Not authorized to perform GET operation on region [/listenerWriterLoader] ) happened at remote site Entry not found

    ls
    Region Entries:

    The entry from the cache server could not be obtained because the client get operation was not authorized. However, the put and destroy operations were allowed based on the supplied credentials.

  7. Close the cacheRunner application:

    exit

  8. Close the cacheRunner session:

    exit

  9. Stop the cache server:

    cacheserver stop

  10. Close the cache server session:

    exit

  11. Delete the modified copies of gemfire.properties and gfcpp.properties from the \cacheRunner directory. This ensures that GemFire authentication and authorization is not enabled when you run the other parts of this example.


Part 3: Remote Querying


Running cacheRunner for Querying

In this example, cacheRunner accepts query strings in input and runs them against the cached data stored on a cache server. The cacheRunner example uses a GemFire cache server configuration file, csQueryPortfolios.xml. When the cache server starts, csQueryPortfolios.xml creates a root region on the server. It also creates a region named Portfolios, which is a region of stock portfolios whose keys are the portfolio ID.

These procedures introduce a few of the querying commands. For information on others, enter help or ? at the cacheRunner client session prompt.

In the procedures, the lines you type are shown in a boldface fixed font. System output is shown in a regular fixed font.


Starting the Cache Server

To start the cache server, create a session from the GemFire installation directory and complete the following steps:

  1. Configure the session environment according to the steps listed in Configuring the Environment.

  2. Add the classes for javaobject.jar to your CLASSPATH by entering the following in a single line:

    Windows:

  3. set CLASSPATH=<full path to NativeClient_xxxx>\examples\cacheRunner\javaobject.jar;%CLASSPATH%

    Bourne and Korn shells (sh, ksh, bash):

    CLASSPATH=<path to NativeClient_xxxx>/examples/cacheRunner/javaobject.jar:$CLASSPATH; export CLASSPATH

    The file javaobject.jar is required for registering the portfolio and position object on the cache server.

  4. Go to the cacheRunner directory, then start the cache server:

    cd \NativeClient_xxxx\examples\cacheRunner

    cacheserver start cache-xml-file=csQueryPortfolios.xml

    The csQueryPortfolios.xml file configures the server with a root and Portfolios regions with five portfolio objects. A message similar to the following appears, indicating that the cache server is running:

  5. Cacheserver pid: 2120 status: running


Starting the cacheRunner Client

Follow these steps to start the cacheRunner client, using the tcr_cacheless.xml initialization file:

  1. Create a session from the GemFire installation directory.

  2. For Solaris and Linux only:
    Configure the session environment according to the steps listed in Configuring the Environment.

  3. Go to the cacheRunner directory in the session

  4. cd \NativeClient_xxxx\examples\cacheRunner

  5. Start the cacheRunner application, specifying tcr_cacheless.xml:

    cacheRunner tcr_cacheless.xml

    The cacheRunner client is initialized using the region settings in the tcr_cacheless.xml file in the cacheRunner directory. The application creates root,listenerWriterLoader and Portfolios regions, then the /root region prompt appears. As you move from region to region, the prompt includes a path to tell you where you are, such as /Portfolios>.

  6. In the cacheRunner client, go to the Portfolios region:

    chrgn Portfolios



Executing Remote Queries

In these exercises you invoke the execute method to submit several queries that are run on the cache server, then the results are returned to the local client cache.

In the cacherunner client:

  1. This query returns the status of the cache entries for the /Portfolios region on the cache server. Enter the following command:
  2. exec select distinct ID, status from /Portfolios

    This is the query output:

    Query results : Found 5 row
    Struct with 2 fields
    ID : 4
    status : inactive
    Struct with 2 fields
    ID : 5
    status : active
    Struct with 2 fields
    ID : 2
    status : inactive
    Struct with 2 fields
    ID : 3
    status : active
    Struct with 2 fields
    ID : 1
    status : active

  3. Run a second query. This query returns the row IDs on the cache server:

    exec select distinct ID from /Portfolios

    Query results : Found 5 row
    1
    2
    3
    4
    5

  4. Run a third query. This query returns the object types for the /Portfolios region on the cache server:

    exec select distinct ID, pkid, getType from /Portfolios where 1=1

    Query results : Found 5 row
    Struct with 3 fields
    ID : 2

    pkid : 2
    getType : type2
    Struct with 3 fields
    ID : 1
    pkid : 1
    getType : type1
    Struct with 3 fields
    ID : 3
    pkid : 3
    getType : type3
    Struct with 3 fields
    ID : 5
    pkid : 5
    getType : type2
    Struct with 3 fields
    ID : 4
    pkid : 4
    getType : type1


Executing Region Query Shortcuts

In these exercises you use region query shortcut methods to submit queries to the cache server, then the results are returned to the local client cache. Query shortcuts take the query "predicate" as a parameter (the part after the WHERE clause), or they can take a normal full query. The three query shortcut methods are described below:

  • query — Executes a query and returns the results.
  • existsValue —Executes a query and returns TRUE or FALSE based on whether any results (rows) are obtained.
  • selectValue —Executes a query and returns only a single result (row). If no results are obtained then it returns NULL. If more than one result (row) is obtained then a QueryException occurs.

In the cacherunner client:

  1. Run this query shortcut, which returns the Portfolios objects with an ID of 1:
  2. query ID=1

    Query result:

    query predicate is ID=1
    Query results : Found 1 row
    PortfolioObject: [ ID=1 status=active type=type1 pkid=1

                              P1: NULL P2: NULL ]

    The query shortcut takes the predicate string ID=1, constructs the full query statement, then executes the query.

  3. Run this existsValue shortcut. The query returns either TRUE or FALSE, depending on whether the result is obtained.

    existsvalue ID=1

    Query result:

    query predicate is ID=1
    Query result is TRUE

  4. Run this selectValue shortcut. The query returns the object types for the /Portfolios region on the cache server:

    selectValue ID=2

    Query result:

    query predicate is ID=2
    PortfolioObject: [ ID=2 status=inactive type=type2 pkid=2
                              P1: NULL P2: NULL ]

  5. Close the cacheRunner application:

    exit

  6. Close the cacheRunner session:

    exit

  7. Stop the cache server:

    cacheserver stop

  8. Close the cache server session:

    exit



Part 4: High Availability


Running cacheRunner for High Availability

In this example, cacheRunner demonstrates server failover to highly available client queue backups by failing over to a secondary cache server when the primary server becomes unavailable. The secondary server continues to provide the latest entry updates to the client when the primary server fails.

In the procedures, the lines you type are shown in a boldface fixed font. System output is shown in a regular fixed font.


Starting the Primary and Secondary Cache Servers

To start the primary and secondary cache servers, create a session and complete the following steps:

  1. Configure the session environment according to the steps listed in Configuring the Environment.

  2. Go to the cacheRunner directory:

    cd \NativeClient_xxxx\examples\cacheRunner

  3. Start the first (primary) cache server by running this command:

    cacheserver start cache-xml-file=cacherunner.xml -dir=gfecs1

    The gfecs1 directory contains a copy of cacherunner.xml, which specifies 50505 for the BridgeServer port for the primary cache server.

  4. Start the second (secondary) cache server by running this command:

    cacheserver start cache-xml-file=cacherunner2.xml -dir=gfecs2

    The gfecs2 directory contains a copy of cacherunner2.xml, which specifies 50506 for the BridgeServer port for the secondary cache server.

Starting the cacheRunner Client

To start the cacheRunner client, complete the following steps:

  1. Create a session from the GemFire installation directory.

  2. For Solaris and Linux only:
    Configure the session environment according to the steps listed in Configuring the Environment.

  3. Go to the cacheRunner directory in the session

  4. cd \NativeClient_xxxx\examples\cacheRunner

  5. Start the cacheRunner client, specifying tcr_hacache.xml:

    cacheRunner tcr_hacache.xml

    The cacheRunner client is initialized using the settings in tcr_hacache.xml in the cacheRunner directory. The XML specifies two cache-level server endpoints that the client connects to (50505 for the primary, and 50506 for the secondary). The redundancy-level=1 attribute specifies the number of redundant, or secondary, servers to maintain in addition to the primary server.

Performing Cache Operations

In these steps you produce data in the cacheRunner local client cache. The primary and secondary cache servers receive the updated values.

  1. In the cacheRunner client, go to the listenerWriterLoader region:

    chrgn listenerWriterLoader

  2. Add an entry to the region:

    put entry1 ball str

    This line creates an entry whose key is entry1 and whose value is the string ball.

  3. Check the contents to see the new entry:

    ls
    Region Entries:
    entry1 -> String: ball

  4. Invalidate the new entry in the local cache and then check the contents:

    inv -l entry1
    ls
    Region Entries:
    entry1 -> No value in cache.

    The value for the entry has been removed from the local cache.

  5. Get the entry from the primary cache server:

    get entry1
    entry1 -> String: ball


Initiating Server Failover

In this procedure you stop and start the primary and secondary servers to initiate a server failover condition.

  1. Stop the primary cache server by running this command in the cache server session:

    cacheserver stop -dir=gfecs1

    The following message displays in the server session:

  2. CacheServer stopped.

    A redundancy level warning continuously displays in the client session as a result of the stopped server:

    Requested redundancy level 1 is not satisfiable with 1 servers available

  3. The secondary server is now the primary. In the client session, get an entry from the new primary server:

    get entry1
    entry1 -> String: ball

    The updated entry is retrieved from the server.

  4. Put a new entry in the client session, then get the entry from the server:

    put entry2 bat str
    get entry2
    entry2 -> String: bat

  5. Start the first cache server again by running this command in the cache server session:

    cacheserver start cache-xml-file=cacherunner.xml -dir=gfecs1

  6. In the cache server session, stop the second (primary) cache server:

    cacheserver stop -dir=gfecs2

  7. In the client session, get the new entry from the new primary server:

    get entry2
    entry2 -> String: bat

    Both the primary and secondary servers maintain client cache updates in case a server failover occurs.


Closing the Cache Server and Client

  1. Close the cacheRunner application:

    exit

  2. Close the cacheRunner session:

    exit

  3. Stop the remaining cache server:

    cacheserver stop -dir=gfecs1

  4. Close the cache server session:

    exit


Changing System Parameters

This product ships configured to run with default system properties. If you need to run in a non-default configuration, GemFire also takes a system-level configuration file. Copy the gfcpp.properties file into your cacheRunner directory from the native client defaultSystem directory and edit it as needed. For example, to change the name of the cache.xml file, uncomment this line and change the file name:

#cache-xml-file=cache.xml

When you are finished with the example, delete the copied gfcpp.properties file from the cacheRunner directory so it can run with the default configuration.

Sample Security Implementations in GemFire

There are two aspects to GemFire security:

  1. Authentication, which verifies the validity of the client(s).
  2. Authorization, which evaluates the permission for GemFire operation(s) by the client(s).

Authentication can be either dummy or LDAP server-based or PKCS-based, whereas authorization is xml-based only. For different authentication schemes, the corresponding authorization xml configigurations should be provided to the sample authorization module.

Source code for the client side sample implementations is available in NativeClient_xxxx/templates/security. Corresponding server side samples can be found in GemfireInstallDirectory/templates/security.

Dummy Authentication

The authentication scheme is based on a simple username and password. The server side authenticator is in package templates.security.DummyAuthenticator.create. The client side initializer for it is in the compiled securityImpl.dll library with a factory method name createUserPasswordAuthInitInstance.

Mapping between Authentication credentials and Authorization roles & privileges
Authentication User Name Authorization Roles Permission to the Roles
root, admin, administrator reader, writer, cacheOps
reader     : get, register_interest, unregister_interest, key_set, contains_key
writer      : put, destroy, region_clear
cacheOps: query, execute_cq, stop_cq, close_cq, region_create, region_destroy
reader0, reader1, reader2 reader
reader     : get, register_interest, unregister_interest, key_set, contains_key
writer0, writer1, writer2 writer
writer      : put, destroy, region_clear
reader3, reader4 queryRegions
queryRegions: query, execute_cq, stop_cq, close_cq

LDAP Authentication

This scheme of authentication is based on the Usernames and Password configured in a LDAP server. Refer to the Security chapter in the Gemfire Enterprise Native Client Guide for more details. The server side authenticator is in package templates.security.LdapUserAuthenticator.create. The client side initializer for it is in the securityImpl.dll library (Windows) or the libsecurityImpl.so library (Solaris or Linux) with a factory method name createUserPasswordAuthInitInstance.

Mapping between Authentication credentials and Authorization roles & privileges
Authentication User Name Authorization Roles Permission to the Roles
gemfire1, gemfire2 reader, writer, cacheOps
reader     : get, register_interest, unregister_interest, key_set, contains_key
writer      : put, destroy, region_clear
cacheOps: query, execute_cq, stop_cq, close_cq, region_create, region_destroy
gemfire3, gemfire4, gemfire5 reader
reader     : get, register_interest, unregister_interest, key_set, contains_key
gemfire6, gemfire7, gemfire6 writer
writer      : put, destroy, region_clear
gemfire9, gemfire10 queryRegions
queryRegions: query, execute_cq, stop_cq, close_cq

PKCS Authentication

This scheme of authentication is based on public/private key-based encryption/decryption. Refer to the Security chapter in the Gemfire Enterprise Native Client Guide for keystore configurations. The server side authenticator is in package templates.security.PKCSAuthenticator.create. The client side initializer for it is in the securityImpl.dll library (Windows) or the libsecurityImpl.so library (Solaris or Linux) with a factory method name createPKCSAuthInitInstance.

PKCS configuration details

  1. See Configuring the Environment in Part 2: Modifying the Cache with Security Configured for details on downloading, compiling and configuring OpenSSL to work with the PKCS implementation.

  2. Create the keystore with aliases from gemfire1 to gemfire10, as described in the Security chapter for the GemFire Enterprise Native Client Guide.

  3. Provide the following properties in gfcpp.properties for client side configuration:
    Note: All of these properties are user-provided information to keytool-like utilities during public/private key generation and self-signing.

    % security-keystorepath=<absolute filepath to keystore where keys are generated>
    % security-alias=<alias name given while generating public & private key pair for the client>
    % security-keystorepass=<password entered while generating private key while self-signing>

  4. Provide the following properties in gemfire.properties for server side configuration:
    Note: All of these properties are user-provided information to keytool-like utilities during truststore creation.

    % security-publickey-filepath=<absolute filepath to keystore where public keys are generated>
    % security-publickey-pass=<password entered while generating key to truststore>

Mapping between Authentication credentials and Authorization roles & privileges.
Authentication KeyStore Aliases Authorization Roles Permission to the Roles
gemfire1, gemfire2 reader, writer, cacheOps
reader     : get, register_interest, unregister_interest, key_set, contains_key
writer      : put, destroy, region_clear
cacheOps: query, execute_cq, stop_cq, close_cq, region_create, region_destroy
gemfire3, gemfire4, gemfire5 reader
reader     : get, register_interest, unregister_interest, key_set, contains_key
gemfire6, gemfire7, gemfire6 writer
writer      : put, destroy, region_clear
gemfire9, gemfire10 queryRegions
queryRegions: query, execute_cq, stop_cq, close_cq

Xml-Based Authorization

This authorization scheme is based on the prior mapping of authentication credentials to roles and privileges. Permissions configured in xml files are supplied corresponding to the authentication scheme. Refer to the Security chapter in the GemFire Enterprise Native Client Guide for further information. The server side security-accessor is in package templates.security.XmlAuthorization.create, and security-authz-xml-uri should point to either authz-dummy.xml, authz-ldap.xml, or authz-pkcs.xml, depending on the security-authenticator provided.

Top

 

Copyright © 2005-2010 by GemStone Systems, Inc. All rights reserved. GemStone®, GemFire®, and the GemStone logo are trademarks or registered trademarks of GemStone Systems, Inc. All other trade names or trademarks are the property of their respective owners. Information in this document is subject to change without notice.