Monday, 8 April 2013

vFabric GemFire and the Native Client World using c#

Recently I had to step out of my comfort zone and learn how to create a c# client to access a GemFire 7 distributed system for a demo to a customer. OIf course there was more to it then just that but this outlines what you need to do to connect as a c# client to GemFire. I was using the following here.

  • Visual Studio 2012
  • GemFire 32 bit Naive Client
1. Install GemFire Native client 32 bit or 64 bit depending on your OS. It can be downloaded from the following location.

https://my.vmware.com/web/vmware/info/slug/application_platform/vmware_vfabric_gemfire/7_0

2. Once installed setup an ENV variable as shown below pointing to the location of the native client install.

C:\Windows\system32>echo %GFCPP%
C:\vFabric_NativeClient_32bit_7010


3. In your Visual Studio 2012 Project / Solution add a reference to GemFire DLL as shown below.




4. In Visual Studio 2012 create a cache.xml as shown below. This client cache is going to use a locator to connect to a cache server instance for the client itself.

xml/cache.xml
  
<?xml version="1.0"?>
<!DOCTYPE client-cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<client-cache>
  <pool name="client" subscription-enabled="true">
    <locator host="172.16.62.1" port="10334" />
  </pool>

  <region name="CommandRegion">
    <region-attributes refid="PROXY" pool-name="client">
    </region-attributes>
  </region>
  
  <region name="changeTrackingRegion">
    <region-attributes data-policy="normal" pool-name="client">
    </region-attributes>
  </region>
</client-cache>

5. Create 2 c# classes as shown below.

GemFireClient.cs
  
using GemStone.GemFire.Cache.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace pivotal.au.company.poc
{
    class GemFireClient
    {
        private static bool isStarted = false;
        private static GemFireClient instance = new GemFireClient();
        private string configFileLocation = "xml/cache.xml";
        private Properties<string, string> properties = Properties<string, string>.Create<string, string>();
        private CacheFactory cacheFactory;
        private Cache cache;
        IRegion<string, string> ctrRegion;

        private GemFireClient()
        {
            Console.WriteLine("Reading properties file xml/cache.xml...");
            string clientCacheXml = getCacheConfigLocation(configFileLocation);
            properties.Insert("cache-xml-file", clientCacheXml);
            Serializable.RegisterPdxSerializer(new ReflectionBasedAutoSerializer());

            cacheFactory = CacheFactory.CreateCacheFactory(properties);
            cache = cacheFactory.Create();
  
            ctrRegion = cache.GetRegion<string, string>("changeTrackingRegion");
            ctrRegion.GetSubscriptionService().RegisterRegex("."); 
            
            Console.WriteLine("ctrRegion size = " + ctrRegion.Count);
        }

        public static GemFireClient getInstance()
        {
            return instance;
        }

        public void closeClientCache()
        {
            cache.Close();
            Console.WriteLine("Client Cache closed...");
        }

        public Cache getCache()
        {
            return cache;
        }

        private static string getCacheConfigLocation(string cacheXml)
        {
            var directoryName = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (File.Exists(System.Environment.GetEnvironmentVariable("COMPANY_CONFIG") + "/" + cacheXml) == true)
            {
                return System.Environment.GetEnvironmentVariable("COMPANY_CONFIG") + "/" + cacheXml;
            }
            else if (File.Exists(Path.Combine(directoryName, cacheXml)) == true)
            {
                return Path.Combine(directoryName, cacheXml);
            }
            else
            {
                throw new SystemException("Unable to find /" + cacheXml);
            }
        }
    }
}

GemFireTest.cs
  
using pivotal.au.company.poc.domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GemStone.GemFire.Cache.Generic;

namespace pivotal.au.company.poc
{
    class GemFireTest
    {
        GemFireClient gfClient;

        public void doInsert()
        {
            gfClient = GemFireClient.getInstance();

            // get command region
            IRegion<string, Command> commandRegion = gfClient.getCache().GetRegion<string, Command>("CommandRegion");

            // insert a Command Object into the region
            Command command = new Command();
            command.eventType = "INSERT";
            command.tableName = "Holiday";
            command.tableKey = "1";
            command.sequence = 31;
            command.payload = new Dictionary<object, object>()
                { 
                  {"Id", "1"},
               {"name", "apples"},
                  {"createdate", "10-10-2009"}
                };

            Console.WriteLine(command.ToString());

            commandRegion[command.tableKey] = command;

        }

        public void queryCommandRegion()
        {
            gfClient = GemFireClient.getInstance();

            Console.WriteLine("about to query commandRegion");

            QueryService<string, Command> queryService = gfClient.getCache().GetQueryService<string, Command>();
            Query<Command> qry = queryService.NewQuery("SELECT * FROM /CommandRegion");
            ISelectResults<Command> results = qry.Execute();
            SelectResultsIterator<Command> iter = results.GetIterator();
            while (iter.MoveNext())
            {
                Console.WriteLine(iter.Current.ToString());
            }

        }

        public void closeCache()
        {
            gfClient.closeClientCache();
        }

        public void run()
        {
            GemFireTest test = new GemFireTest();
            test.doInsert();
            test.queryCommandRegion();
            test.closeCache();
        }

    }
}

Output omitted but this should give you the general idea.

No comments: