http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyListener.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyListener.cs 
b/clicache/integration-test/TallyListener.cs
new file mode 100644
index 0000000..62a6df0
--- /dev/null
+++ b/clicache/integration-test/TallyListener.cs
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+
+  class TallyListener : Apache.Geode.Client.CacheListenerAdapter<Object, 
Object>
+  {
+    #region Private members
+
+    private int m_creates = 0;
+    private int m_updates = 0;
+    private int m_invalidates = 0;
+    private int m_destroys = 0;
+    private int m_clears = 0;
+    private Apache.Geode.Client.ICacheableKey m_lastKey = null;
+    private Apache.Geode.Client.IGeodeSerializable m_lastValue = null;
+    private Apache.Geode.Client.IGeodeSerializable m_callbackArg = null;
+    private bool m_ignoreTimeout = false;
+    private bool m_quiet = false;
+    private bool isListenerInvoke = false;
+    private bool isCallbackCalled = false;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Creates
+    {
+      get
+      {
+        return m_creates;
+      }
+    }
+
+    public int Clears
+    {
+      get
+      {
+        return m_clears;
+      }
+    }
+
+    public int Updates
+    {
+      get
+      {
+        return m_updates;
+      }
+    }
+
+    public int Invalidates
+    {
+      get
+      {
+        return m_invalidates;
+      }
+    }
+
+    public int Destroys
+    {
+      get
+      {
+        return m_destroys;
+      }
+    }
+
+    public Apache.Geode.Client.IGeodeSerializable LastKey
+    {
+      get
+      {
+        return m_lastKey;
+      }
+    }
+
+    public bool IsListenerInvoked
+    {
+      get
+      {
+        return isListenerInvoke;
+      }
+    }
+
+    public bool IsCallBackArgCalled
+    {
+      get
+      {
+        return isCallbackCalled;
+      }
+    }
+
+    public Apache.Geode.Client.IGeodeSerializable LastValue
+    {
+      get
+      {
+        return m_lastValue;
+      }
+    }
+
+    public bool IgnoreTimeout
+    {
+      set
+      {
+        m_ignoreTimeout = value;
+      }
+    }
+
+    public bool Quiet
+    {
+      set
+      {
+        m_quiet = value;
+      }
+    }
+
+     public void SetCallBackArg(Apache.Geode.Client.IGeodeSerializable 
callbackArg)
+    {
+      m_callbackArg = callbackArg;
+    }
+
+
+    #endregion
+
+    public void CheckcallbackArg(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      if (!isListenerInvoke)
+        isListenerInvoke = true;
+      if (m_callbackArg != null)
+      {
+        Apache.Geode.Client.IGeodeSerializable callbkArg = 
(Apache.Geode.Client.IGeodeSerializable)ev.CallbackArgument;
+        if (m_callbackArg.Equals(callbkArg))
+          isCallbackCalled = true;
+      }
+    }
+
+   
+    public void ResetListenerInvokation()
+    {
+      isListenerInvoke = false;
+      isCallbackCalled = false;
+    }
+    public int ExpectCreates(int expected)
+    {
+      int tries = 0;
+      while ((m_creates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_creates;
+    }
+
+    public int ExpectUpdates(int expected)
+    {
+      int tries = 0;
+      while ((m_updates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_updates;
+    }
+
+    public int ExpectedInvalidates(int expected)
+    {
+      int tries = 0;
+      while ((m_invalidates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_invalidates;
+    }
+
+    public int ExpectedDestroys(int expected)
+    {
+      int tries = 0;
+      while ((m_destroys < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_destroys;
+    }
+         
+    public void ShowTallies()
+    {
+      Util.Log("TallyListener state: (updates = {0}, creates = {1}, 
invalidates = {2}, destroys = {3})",
+        Updates,Creates, Invalidates, Destroys);
+    }
+
+    #region Logging functions that check for m_quiet
+
+    private void WriteLog(string message)
+    {
+      if (!m_quiet)
+      {
+        Util.Log(message);
+      }
+    }
+
+    private void WriteLog(string format, params object[] args)
+    {
+      if (!m_quiet)
+      {
+        Util.Log(format, args);
+      }
+    }
+
+    public static TallyListener Create()
+    {
+      return new TallyListener();
+    }
+
+    #endregion
+
+    #region ICacheListener Members
+
+    public override void AfterCreate(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_creates++;
+      m_lastKey = (Apache.Geode.Client.ICacheableKey)ev.Key;
+      m_lastValue = (Apache.Geode.Client.IGeodeSerializable)ev.NewValue;
+      CheckcallbackArg(ev);
+
+      string keyString = m_lastKey.ToString();
+      WriteLog("TallyListener create - key = \"{0}\", value = \"{1}\"",
+        keyString, m_lastValue.ToString());
+
+      if ((!m_ignoreTimeout) && (keyString.IndexOf("timeout") >= 0))
+      {
+        WriteLog("TallyListener: Sleeping 10 seconds to force a timeout.");
+        Thread.Sleep(10000); // this should give the client cause to timeout...
+        WriteLog("TallyListener: done sleeping..");
+      }
+    }
+
+    public override void AfterUpdate(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_updates++;
+      m_lastKey = (Apache.Geode.Client.ICacheableKey)ev.Key;
+      m_lastValue = (Apache.Geode.Client.IGeodeSerializable)ev.NewValue;
+      CheckcallbackArg(ev);
+     
+      string keyString = m_lastKey.ToString();
+      WriteLog("TallyListener update - key = \"{0}\", value = \"{1}\"",
+        keyString, m_lastValue.ToString());
+
+      if ((!m_ignoreTimeout) && (keyString.IndexOf("timeout") >= 0))
+      {
+        WriteLog("TallyListener: Sleeping 10 seconds to force a timeout.");
+        Thread.Sleep(10000); // this should give the client cause to timeout...
+        WriteLog("TallyListener: done sleeping..");
+      }
+    }
+    public override void AfterDestroy(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_destroys++;
+      CheckcallbackArg(ev);
+    }
+    public override void 
AfterInvalidate(Apache.Geode.Client.EntryEvent<Object, Object> ev)
+    {
+      m_invalidates++;
+      CheckcallbackArg(ev);
+    }
+
+    public override void 
AfterRegionDestroy(Apache.Geode.Client.RegionEvent<Object, Object> ev) { }
+
+    public override void 
AfterRegionClear(Apache.Geode.Client.RegionEvent<Object, Object> ev) 
+    { 
+        m_clears++;
+    }
+
+    public override void 
AfterRegionInvalidate(Apache.Geode.Client.RegionEvent<Object, Object> ev) { }
+
+    public override void 
AfterRegionLive(Apache.Geode.Client.RegionEvent<Object, Object> ev) { }
+
+    public override void Close(Apache.Geode.Client.IRegion<Object, Object> 
region) { }
+
+    #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyListenerN.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyListenerN.cs 
b/clicache/integration-test/TallyListenerN.cs
new file mode 100644
index 0000000..3bad24e
--- /dev/null
+++ b/clicache/integration-test/TallyListenerN.cs
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+  using Apache.Geode.Client;
+  //using Region = Apache.Geode.Client.IRegion<Object, Object>;
+
+  class TallyListener<TKey, TVal> : CacheListenerAdapter<TKey, TVal>
+  {
+    #region Private members
+
+    private int m_creates = 0;
+    private int m_updates = 0;
+    private int m_invalidates = 0;
+    private int m_destroys = 0;
+    private int m_clears = 0;
+    private TKey m_lastKey = default(TKey);
+    private TVal m_lastValue = default(TVal);
+    private object m_callbackArg = null;
+    private bool m_ignoreTimeout = false;
+    private bool m_quiet = false;
+    private bool isListenerInvoke = false;
+    private bool isCallbackCalled = false;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Creates
+    {
+      get
+      {
+        return m_creates;
+      }
+    }
+
+    public int Clears
+    {
+      get
+      {
+        return m_clears;
+      }
+    }
+
+    public int Updates
+    {
+      get
+      {
+        return m_updates;
+      }
+    }
+
+    public int Invalidates
+    {
+      get
+      {
+        return m_invalidates;
+      }
+    }
+
+    public int Destroys
+    {
+      get
+      {
+        return m_destroys;
+      }
+    }
+
+    public TKey LastKey
+    {
+      get
+      {
+        return m_lastKey;
+      }
+    }
+
+    public bool IsListenerInvoked
+    {
+      get
+      {
+        return isListenerInvoke;
+      }
+    }
+
+    public bool IsCallBackArgCalled
+    {
+      get
+      {
+        return isCallbackCalled;
+      }
+    }
+
+    public TVal LastValue
+    {
+      get
+      {
+        return m_lastValue;
+      }
+    }
+
+    public bool IgnoreTimeout
+    {
+      set
+      {
+        m_ignoreTimeout = value;
+      }
+    }
+
+    public bool Quiet
+    {
+      set
+      {
+        m_quiet = value;
+      }
+    }
+
+     public void SetCallBackArg(object callbackArg)
+    {
+      m_callbackArg = callbackArg;
+    }
+
+
+    #endregion
+
+     public void CheckcallbackArg<TKey1, TVal1>(EntryEvent<TKey1, TVal1> ev)
+    {
+      Util.Log("TallyListenerN: Checking callback arg for EntryEvent " +
+          "key:{0} oldval: {1} newval:{2} cbArg:{3} for region:{4} and 
remoteOrigin:{5}",
+          ev.Key, ev.NewValue, ev.OldValue, ev.CallbackArgument, 
ev.Region.Name, ev.RemoteOrigin);
+
+      if (!isListenerInvoke)
+        isListenerInvoke = true;
+      /*
+      if (m_callbackArg != null)
+      {
+        IGeodeSerializable callbkArg1 = ev.CallbackArgument as 
IGeodeSerializable;
+        IGeodeSerializable callbkArg2 = m_callbackArg as IGeodeSerializable;
+        if (callbkArg2 != null && callbkArg2.Equals(callbkArg1))
+        {
+          isCallbackCalled = true;
+        }
+        string callbkArg3 = ev.CallbackArgument as string;
+        string callbkArg4 = m_callbackArg as string;
+        if (callbkArg3 != null && callbkArg3.Equals(callbkArg4))
+        {
+          isCallbackCalled = true;
+        }
+      }
+      */
+      if (m_callbackArg != null && m_callbackArg.Equals(ev.CallbackArgument))
+      {
+        isCallbackCalled = true;
+      }
+    }
+
+   
+    public void ResetListenerInvokation()
+    {
+      isListenerInvoke = false;
+      isCallbackCalled = false;
+    }
+    public int ExpectCreates(int expected)
+    {
+      int tries = 0;
+      while ((m_creates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_creates;
+    }
+
+    public int ExpectUpdates(int expected)
+    {
+      int tries = 0;
+      while ((m_updates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_updates;
+    }
+
+    public int ExpectedInvalidates(int expected)
+    {
+      int tries = 0;
+      while ((m_invalidates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_invalidates;
+    }
+
+    public int ExpectedDestroys(int expected)
+    {
+      int tries = 0;
+      while ((m_destroys < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_destroys;
+    }
+         
+    public void ShowTallies()
+    {
+      Util.Log("TallyListener state: (updates = {0}, creates = {1}, 
invalidates = {2}, destroys = {3})",
+        Updates,Creates, Invalidates, Destroys);
+    }
+
+    #region Logging functions that check for m_quiet
+
+    private void WriteLog(string message)
+    {
+      if (!m_quiet)
+      {
+        Util.Log(message);
+      }
+    }
+
+    private void WriteLog(string format, params object[] args)
+    {
+      if (!m_quiet)
+      {
+        Util.Log(format, args);
+      }
+    }
+
+    public static TallyListener<TKey, TVal> Create()
+    {
+      return new TallyListener<TKey, TVal>();
+    }
+
+    #endregion
+
+    #region ICacheListener Members
+
+    public override void AfterCreate(EntryEvent<TKey, TVal> ev)
+    {
+      m_creates++;
+      m_lastKey = (TKey)ev.Key;
+      m_lastValue = ev.NewValue;
+      CheckcallbackArg(ev);
+
+      string keyString = m_lastKey.ToString();
+      if (m_lastValue != null)
+        WriteLog("TallyListener create - key = \"{0}\", value = \"{1}\"",
+          keyString, m_lastValue.ToString());
+      else
+        WriteLog("TallyListener create - key = \"{0}\", value = \"null\"",
+          keyString);
+
+      if ((!m_ignoreTimeout) && (keyString.IndexOf("timeout") >= 0))
+      {
+        WriteLog("TallyListener: Sleeping 10 seconds to force a timeout.");
+        Thread.Sleep(10000); // this should give the client cause to timeout...
+        WriteLog("TallyListener: done sleeping..");
+      }
+    }
+
+    public override void AfterUpdate(EntryEvent<TKey, TVal> ev)
+    {
+      m_updates++;
+      m_lastKey = (TKey)ev.Key;
+      m_lastValue = ev.NewValue;
+      CheckcallbackArg(ev);
+     
+      string keyString = m_lastKey.ToString();
+      if (m_lastValue != null)
+        WriteLog("TallyListener update - key = \"{0}\", value = \"{1}\"",
+          keyString, m_lastValue.ToString());
+      else
+        WriteLog("TallyListener update - key = \"{0}\", value = \"null\"",
+          keyString);
+
+      if ((!m_ignoreTimeout) && (keyString.IndexOf("timeout") >= 0))
+      {
+        WriteLog("TallyListener: Sleeping 10 seconds to force a timeout.");
+        Thread.Sleep(10000); // this should give the client cause to timeout...
+        WriteLog("TallyListener: done sleeping..");
+      }
+    }
+    public override void AfterDestroy(EntryEvent<TKey, TVal> ev)
+    {
+      WriteLog("TallyListener destroy - key = \"{0}\"",
+          ((TKey)ev.Key).ToString());
+      m_destroys++;
+      CheckcallbackArg(ev);
+    }
+    public override void AfterInvalidate(EntryEvent<TKey, TVal> ev)
+    {
+      WriteLog("TallyListener invalidate - key = \"{0}\"",
+          ((TKey)ev.Key).ToString()); 
+      m_invalidates++;
+      CheckcallbackArg(ev);
+    }
+
+    public override void AfterRegionDestroy(RegionEvent<TKey, TVal> ev) { }
+
+    public override void AfterRegionClear(RegionEvent<TKey, TVal> ev) 
+    { 
+        m_clears++;
+    }
+
+    public override void AfterRegionInvalidate(RegionEvent<TKey, TVal> ev) { }
+
+    public override void AfterRegionLive(RegionEvent<TKey, TVal> ev) { }
+
+    public override void Close(IRegion<TKey, TVal> region) { }
+
+    #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyLoaderN.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyLoaderN.cs 
b/clicache/integration-test/TallyLoaderN.cs
new file mode 100644
index 0000000..64db895
--- /dev/null
+++ b/clicache/integration-test/TallyLoaderN.cs
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+
+  using Apache.Geode.Client;
+  using Apache.Geode.Client;
+
+  class TallyLoader<TKey, TVal> : ICacheLoader<TKey, TVal>
+  {
+    #region Private members
+
+    private int m_loads = 0;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Loads
+    {
+      get
+      {
+        return m_loads;
+      }
+    }
+
+    #endregion
+
+    public int ExpectLoads(int expected)
+    {
+      int tries = 0;
+      while ((m_loads < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_loads;
+    }
+
+    public void Reset()
+    {
+      m_loads = 0;
+    }
+
+    public void ShowTallies()
+    {
+      Util.Log("TallyLoader state: (loads = {0})", Loads);
+    }
+
+    public static TallyLoader<TKey, TVal> Create()
+    {
+      return new TallyLoader<TKey, TVal>();
+    }
+
+    public virtual int GetLoadCount()
+    {
+      return m_loads;
+    }
+
+    #region ICacheLoader<TKey, TVal> Members
+
+    public virtual TVal Load(IRegion<TKey, TVal> region, TKey key, object 
helper)
+    {
+      m_loads++;
+      Util.Log("TallyLoader Load: (m_loads = {0}) TYPEOF key={1} val={2} for 
region {3}",
+        m_loads, typeof(TKey), typeof(TVal), region.Name);
+      if (typeof(TVal) == typeof(string))
+      {
+        return (TVal) (object) m_loads.ToString();
+      }
+      if (typeof(TVal) == typeof(int))
+      {
+        return (TVal)(object) m_loads;
+      }
+      return default(TVal);
+    }
+
+    public virtual void Close(IRegion<TKey, TVal> region)
+    {
+      Util.Log("TallyLoader<TKey, TVal>::Close");
+    }
+
+    #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyResolverN.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyResolverN.cs 
b/clicache/integration-test/TallyResolverN.cs
new file mode 100755
index 0000000..a37c3a0
--- /dev/null
+++ b/clicache/integration-test/TallyResolverN.cs
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+
+  using Apache.Geode.Client;
+  using Apache.Geode.Client;
+
+  class TallyResolver<TKey, TVal> : IPartitionResolver<TKey, TVal>
+  {
+    #region Private members
+
+    private int m_loads = 0;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Loads
+    {
+      get
+      {
+        return m_loads;
+      }
+    }
+
+    #endregion
+
+    public int ExpectLoads(int expected)
+    {
+      int tries = 0;
+      while ((m_loads < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_loads;
+    }
+
+    public void Reset()
+    {
+      m_loads = 0;
+    }
+
+    public void ShowTallies()
+    {
+      Util.Log("TallyResolver state: (loads = {0})", Loads);
+    }
+
+    public static TallyResolver<TKey, TVal> Create()
+    {
+      return new TallyResolver<TKey, TVal>();
+    }
+
+    public virtual int GetLoadCount()
+    {
+      return m_loads;
+    }
+
+    #region IPartitionResolver<TKey, TVal> Members
+
+    public virtual Object GetRoutingObject(EntryEvent<TKey, TVal> ev)
+    {
+      m_loads++;
+      Util.Log("TallyResolver Load: (m_loads = {0}) TYPEOF key={1} val={2} for 
region {3}",
+        m_loads, typeof(TKey), typeof(TVal), ev.Region.Name);
+      return ev.Key;
+    }
+
+    public virtual string GetName()
+    {
+      Util.Log("TallyResolver<TKey, TVal>::GetName");
+           return "TallyResolver";
+    }
+
+    #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyWriter.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyWriter.cs 
b/clicache/integration-test/TallyWriter.cs
new file mode 100644
index 0000000..8ef6db0
--- /dev/null
+++ b/clicache/integration-test/TallyWriter.cs
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+
+  class TallyWriter : Apache.Geode.Client.CacheWriterAdapter<Object, Object>
+  {
+    #region Private members
+
+    private int m_creates = 0;
+    private int m_updates = 0;
+    private int m_invalidates = 0;
+    private int m_destroys = 0;
+    private Apache.Geode.Client.IGeodeSerializable m_callbackArg = null;
+    private int m_clears = 0;
+    private Apache.Geode.Client.IGeodeSerializable m_lastKey = null;
+    private Apache.Geode.Client.IGeodeSerializable m_lastValue = null;
+    private bool isWriterFailed = false;
+    private bool isWriterInvoke = false;
+    private bool isCallbackCalled = false;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Creates
+    {
+      get
+      {
+        return m_creates;
+      }
+    }
+    public int Clears
+    {
+      get
+      {
+        return m_clears;
+      }
+    }
+
+    public int Updates
+    {
+      get
+      {
+        return m_updates;
+      }
+    }
+
+    public int Invalidates
+    {
+      get
+      {
+        return m_invalidates;
+      }
+    }
+
+    public int Destroys
+    {
+      get
+      {
+        return m_destroys;
+      }
+    }
+
+
+    public Apache.Geode.Client.IGeodeSerializable LastKey
+    {
+      get
+      {
+        return m_lastKey;
+      }
+    }
+
+    public Apache.Geode.Client.IGeodeSerializable CallbackArgument
+    {
+      get
+      {
+        return m_callbackArg;
+      }
+    }
+
+
+    public Apache.Geode.Client.IGeodeSerializable LastValue
+    {
+      get
+      {
+        return m_lastValue;
+      }
+    }
+
+   public void SetWriterFailed( )
+   {
+    isWriterFailed = true;
+   }
+
+  public void SetCallBackArg( Apache.Geode.Client.IGeodeSerializable 
callbackArg )
+  {
+    m_callbackArg = callbackArg;
+  }
+
+  public void ResetWriterInvokation()
+  {
+    isWriterInvoke = false;
+    isCallbackCalled = false;
+  }
+
+  public  bool IsWriterInvoked
+  {
+    get
+    {
+      return isWriterInvoke;
+    }
+  }
+  public bool IsCallBackArgCalled
+  {
+    get
+    {
+      return isCallbackCalled;
+    }
+  }
+    #endregion
+
+    public int ExpectCreates(int expected)
+    {
+      int tries = 0;
+      while ((m_creates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_creates;
+    }
+
+    public int ExpectUpdates(int expected)
+    {
+      int tries = 0;
+      while ((m_updates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_updates;
+    }
+    
+    public void ShowTallies()
+    {
+      Util.Log("TallyWriter state: (updates = {0}, creates = {1}, invalidates 
= {2}, destroys = {3})",
+        Updates, Creates, Invalidates, Destroys);
+    }
+
+    public void CheckcallbackArg(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+      {
+
+        if(!isWriterInvoke)
+          isWriterInvoke = true;
+        if (m_callbackArg != null)
+        {
+          Apache.Geode.Client.IGeodeSerializable callbkArg = 
(Apache.Geode.Client.IGeodeSerializable)ev.CallbackArgument;
+          if (m_callbackArg.Equals(callbkArg))
+            isCallbackCalled = true;
+        }  
+      }
+
+    public static TallyWriter Create()
+    {
+      return new TallyWriter();
+    }
+
+    #region ICacheWriter Members
+
+    public override bool BeforeCreate(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_creates++;
+      Util.Log("TallyWriter::BeforeCreate");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+
+    public override bool BeforeDestroy(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_destroys++;
+      Util.Log("TallyWriter::BeforeDestroy");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+
+    public override bool 
BeforeRegionClear(Apache.Geode.Client.RegionEvent<Object, Object> ev)
+    {
+      m_clears++;
+      Util.Log("TallyWriter::BeforeRegionClear");
+      return true;
+    }
+
+    public override bool BeforeUpdate(Apache.Geode.Client.EntryEvent<Object, 
Object> ev)
+    {
+      m_updates++;
+      Util.Log("TallyWriter::BeforeUpdate");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+   #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/TallyWriterN.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/TallyWriterN.cs 
b/clicache/integration-test/TallyWriterN.cs
new file mode 100644
index 0000000..1f3aaa2
--- /dev/null
+++ b/clicache/integration-test/TallyWriterN.cs
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.DUnitFramework;
+  using Apache.Geode.Client;
+  class TallyWriter<TKey, TVal> : CacheWriterAdapter<TKey, TVal>
+  {
+    #region Private members
+
+    private int m_creates = 0;
+    private int m_updates = 0;
+    private int m_invalidates = 0;
+    private int m_destroys = 0;
+    private Object m_callbackArg = null;
+    private int m_clears = 0;
+    private Object m_lastKey = null;
+    private Object m_lastValue = null;
+    private bool isWriterFailed = false;
+    private bool isWriterInvoke = false;
+    private bool isCallbackCalled = false;
+
+    #endregion
+
+    #region Public accessors
+
+    public int Creates
+    {
+      get
+      {
+        return m_creates;
+      }
+    }
+    public int Clears
+    {
+      get
+      {
+        return m_clears;
+      }
+    }
+
+    public int Updates
+    {
+      get
+      {
+        return m_updates;
+      }
+    }
+
+    public int Invalidates
+    {
+      get
+      {
+        return m_invalidates;
+      }
+    }
+
+    public int Destroys
+    {
+      get
+      {
+        return m_destroys;
+      }
+    }
+
+
+    public Object LastKey
+    {
+      get
+      {
+        return m_lastKey;
+      }
+    }
+
+    public Object CallbackArgument
+    {
+      get
+      {
+        return m_callbackArg;
+      }
+    }
+
+
+    public Object LastValue
+    {
+      get
+      {
+        return m_lastValue;
+      }
+    }
+
+   public void SetWriterFailed( )
+   {
+    isWriterFailed = true;
+   }
+
+  public void SetCallBackArg( object callbackArg )
+  {
+    m_callbackArg = callbackArg;
+  }
+
+  public void ResetWriterInvokation()
+  {
+    isWriterInvoke = false;
+    isCallbackCalled = false;
+  }
+
+  public  bool IsWriterInvoked
+  {
+    get
+    {
+      return isWriterInvoke;
+    }
+  }
+  public bool IsCallBackArgCalled
+  {
+    get
+    {
+      return isCallbackCalled;
+    }
+  }
+    #endregion
+
+    public int ExpectCreates(int expected)
+    {
+      int tries = 0;
+      while ((m_creates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_creates;
+    }
+
+    public int ExpectUpdates(int expected)
+    {
+      int tries = 0;
+      while ((m_updates < expected) && (tries < 200))
+      {
+        Thread.Sleep(100);
+        tries++;
+      }
+      return m_updates;
+    }
+    
+    public void ShowTallies()
+    {
+      Util.Log("TallyWriter state: (updates = {0}, creates = {1}, invalidates 
= {2}, destroys = {3})",
+        Updates, Creates, Invalidates, Destroys);
+    }
+
+    public void CheckcallbackArg<TKey1, TVal1>(EntryEvent<TKey1, TVal1> ev)
+      {
+        Util.Log("TallyWriterN: Checking callback arg for EntryEvent " +
+          "key:{0} oldval: {1} newval:{2} cbArg:{3} for region:{4} and 
remoteOrigin:{5}",
+          ev.Key, ev.NewValue, ev.OldValue, ev.CallbackArgument, 
ev.Region.Name, ev.RemoteOrigin);
+
+        if(!isWriterInvoke)
+          isWriterInvoke = true;
+      /*
+        if (m_callbackArg != null)
+        {
+          IGeodeSerializable callbkArg1 = ev.CallbackArgument as 
IGeodeSerializable;
+          IGeodeSerializable callbkArg2 = m_callbackArg as IGeodeSerializable;
+          if (callbkArg1 != null && callbkArg1.Equals(callbkArg2))
+          {
+            isCallbackCalled = true;
+          }
+          string callbkArg3 = ev.CallbackArgument as string;
+          string callbkArg4 = m_callbackArg as string;
+          if (callbkArg3 != null && callbkArg3.Equals(callbkArg4))
+          {
+            isCallbackCalled = true;
+          }
+        }
+           * */
+        if (m_callbackArg != null && m_callbackArg.Equals(ev.CallbackArgument))
+        {
+          isCallbackCalled = true;
+        }
+      }
+
+    public static TallyWriter<TKey, TVal> Create()
+    {
+      return new TallyWriter<TKey, TVal>();
+    }
+
+    #region ICacheWriter Members
+
+    public override bool BeforeCreate(EntryEvent<TKey, TVal> ev)
+    {
+      m_creates++;
+      Util.Log("TallyWriter::BeforeCreate");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+
+    public override bool BeforeDestroy(EntryEvent<TKey, TVal> ev)
+    {
+      m_destroys++;
+      Util.Log("TallyWriter::BeforeDestroy");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+
+    public override bool BeforeRegionClear(RegionEvent<TKey, TVal> ev)
+    {
+      m_clears++;
+      Util.Log("TallyWriter::BeforeRegionClear");
+      return true;
+    }
+
+    public override bool BeforeUpdate(EntryEvent<TKey, TVal> ev)
+    {
+      m_updates++;
+      Util.Log("TallyWriter::BeforeUpdate");
+      CheckcallbackArg(ev);
+      return !isWriterFailed;
+    }
+   #endregion
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/ThinClientAppDomainFunctionExecutionTests.cs
----------------------------------------------------------------------
diff --git 
a/clicache/integration-test/ThinClientAppDomainFunctionExecutionTests.cs 
b/clicache/integration-test/ThinClientAppDomainFunctionExecutionTests.cs
new file mode 100644
index 0000000..0d9129c
--- /dev/null
+++ b/clicache/integration-test/ThinClientAppDomainFunctionExecutionTests.cs
@@ -0,0 +1,282 @@
+//=========================================================================
+// Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+// This product is protected by U.S. and international copyright
+// and intellectual property laws. Pivotal products are covered by
+// more patents listed at http://www.pivotal.io/patents.
+//========================================================================
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Threading;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using NUnit.Framework;
+  using Apache.Geode.DUnitFramework;
+  using Apache.Geode.Client.Tests;
+
+  using Apache.Geode.Client;
+  using Region = Apache.Geode.Client.IRegion<Object, Object>;
+
+  public class MyAppDomainResultCollector<TResult> : IResultCollector<TResult>
+  {
+    #region Private members
+    private bool m_resultReady = false;
+    ICollection<TResult> m_results = null;
+    private int m_addResultCount = 0;
+    private int m_getResultCount = 0;
+    private int m_endResultCount = 0;
+    #endregion
+    public int GetAddResultCount()
+    {
+      return m_addResultCount;
+    }
+    public int GetGetResultCount()
+    {
+      return m_getResultCount;
+    }
+    public int GetEndResultCount()
+    {
+      return m_endResultCount;
+    }
+    public MyAppDomainResultCollector()
+    {
+      m_results = new List<TResult>();
+    }
+    public void AddResult(TResult result)
+    {
+      Util.Log("MyAppDomainResultCollector " + result + " :  " + 
result.GetType());
+      m_addResultCount++;
+      m_results.Add(result);
+    }
+    public ICollection<TResult> GetResult()
+    {
+      return GetResult(50);
+    }
+
+    public ICollection<TResult> GetResult(UInt32 timeout)
+    {
+      m_getResultCount++;
+      if (m_resultReady == true)
+      {
+        return m_results;
+      }
+      else
+      {
+        for (int i = 0; i < timeout; i++)
+        {
+          Thread.Sleep(1000);
+          if (m_resultReady == true)
+          {
+            return m_results;
+          }
+
+        }
+        throw new FunctionExecutionException(
+                   "Result is not ready, endResults callback is called before 
invoking getResult() method");
+
+      }
+    }
+    public void EndResults()
+    {
+      m_endResultCount++;
+      m_resultReady = true;
+    }
+    public void ClearResults(/*bool unused*/)
+    {
+      m_results.Clear();
+      m_addResultCount = 0;
+      m_getResultCount = 0;
+      m_endResultCount = 0;
+    }
+  }
+
+
+  [TestFixture]
+  [Category("group3")]
+  [Category("unicast_only")]
+  [Category("generics")]
+  public class ThinClientAppDomainFunctionExecutionTests : 
ThinClientRegionSteps
+  {
+    #region Private members
+
+    private static string[] FunctionExecutionRegionNames = { 
"partition_region", "partition_region1" };
+    private static string poolName = "__TEST_POOL1__";
+    private static string serverGroup = "ServerGroup1";
+    private static string QERegionName = "partition_region";
+    private static string OnServerHAExceptionFunction = 
"OnServerHAExceptionFunction";
+    private static string OnServerHAShutdownFunction = 
"OnServerHAShutdownFunction";
+
+    #endregion
+
+    protected override ClientBase[] GetClients()
+    {
+      return new ClientBase[] { };
+    }
+
+    [TestFixtureSetUp]
+    public override void InitTests()
+    {
+      Util.Log("InitTests: AppDomain: " + AppDomain.CurrentDomain.Id);
+      Properties<string, string> config = new Properties<string, string>();
+      config.Insert("appdomain-enabled", "true");
+      CacheHelper.InitConfig(config);
+    }
+
+    [TearDown]
+    public override void EndTest()
+    {
+      Util.Log("EndTest: AppDomain: " + AppDomain.CurrentDomain.Id);
+      try
+      {
+        CacheHelper.ClearEndpoints();
+        CacheHelper.ClearLocators();
+      }
+      finally
+      {
+        CacheHelper.StopJavaServers();
+        CacheHelper.StopJavaLocators();
+      }
+      base.EndTest();
+    }
+
+    public void createRegionAndAttachPool(string regionName, string poolName)
+    {
+      CacheHelper.CreateTCRegion_Pool<object, object>(regionName, true, true, 
null, null, poolName, false, serverGroup);
+    }
+    public void createPool(string name, string locators, string serverGroup,
+      int redundancy, bool subscription, bool prSingleHop, bool threadLocal = 
false)
+    {
+      CacheHelper.CreatePool<object, object>(name, locators, serverGroup, 
redundancy, subscription, prSingleHop, threadLocal);
+    }
+ 
+    public void OnServerHAStepOne()
+    {
+
+      Region region = CacheHelper.GetVerifyRegion<object, 
object>(QERegionName);
+      for (int i = 0; i < 34; i++)
+      {
+        region["KEY--" + i] = "VALUE--" + i;
+      }
+
+      object[] routingObj = new object[17];
+
+      ArrayList args1 = new ArrayList();
+
+      int j = 0;
+      for (int i = 0; i < 34; i++)
+      {
+        if (i % 2 == 0) continue;
+        routingObj[j] = "KEY--" + i;
+        j++;
+      }
+      Util.Log("routingObj count= {0}.", routingObj.Length);
+
+      for (int i = 0; i < routingObj.Length; i++)
+      {
+        Console.WriteLine("routingObj[{0}]={1}.", i, (string)routingObj[i]);
+        args1.Add(routingObj[i]);
+      }
+
+      Boolean getResult = true;
+      //test data independant function execution with result onServer
+      Pool/*<TKey, TValue>*/ pool = 
CacheHelper.DCache.GetPoolManager().Find(poolName);
+
+      Apache.Geode.Client.Execution<object> exc = 
FunctionService<object>.OnServer(pool);
+      Assert.IsTrue(exc != null, "onServer Returned NULL");
+
+      IResultCollector<object> rc = 
exc.WithArgs<ArrayList>(args1).Execute(OnServerHAExceptionFunction, 15);
+
+      ICollection<object> executeFunctionResult = rc.GetResult();
+
+      List<object> resultList = new List<object>();
+
+      Console.WriteLine("executeFunctionResult.Length = {0}", 
executeFunctionResult.Count);
+
+      foreach (List<object> item in executeFunctionResult)
+      {
+        foreach (object item2 in item)
+        {
+          resultList.Add(item2);
+        }
+      }
+
+      Util.Log("on region: result count= {0}.", resultList.Count);
+      Assert.IsTrue(resultList.Count == 17, "result count check failed");
+      for (int i = 0; i < resultList.Count; i++)
+      {
+        Util.Log("on region:get:result[{0}]={1}.", i, (string)resultList[i]);
+        Assert.IsTrue(((string)resultList[i]) != null, "onServer Returned 
NULL");
+      }
+
+      rc = exc.WithArgs<ArrayList>(args1).Execute(OnServerHAShutdownFunction, 
15);
+
+      ICollection<object> executeFunctionResult1 = rc.GetResult();
+
+      List<object> resultList1 = new List<object>();
+
+      foreach (List<object> item in executeFunctionResult1)
+      {
+        foreach (object item2 in item)
+        {
+          resultList1.Add(item2);
+        }
+      }
+
+      Util.Log("on region: result count= {0}.", resultList1.Count);
+
+      Console.WriteLine("resultList1.Count = {0}", resultList1.Count);
+
+      Assert.IsTrue(resultList1.Count == 17, "result count check failed");
+      for (int i = 0; i < resultList1.Count; i++)
+      {
+        Util.Log("on region:get:result[{0}]={1}.", i, (string)resultList1[i]);
+        Assert.IsTrue(((string)resultList1[i]) != null, "onServer Returned 
NULL");
+      }
+
+      // Bring down the region
+      //region.LocalDestroyRegion();
+    }
+
+    [Test]
+    public void OnServerHAExecuteFunction()
+    {
+      Util.Log("OnServerHAExecuteFunction: AppDomain: " + 
AppDomain.CurrentDomain.Id);
+      CacheHelper.SetupJavaServers(true, "func_cacheserver1_pool.xml",
+      "func_cacheserver2_pool.xml", "func_cacheserver3_pool.xml");
+      CacheHelper.StartJavaLocator(1, "GFELOC");
+      Util.Log("Locator 1 started.");
+      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
+      Util.Log("Cacheserver 1 started.");
+      CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1);
+      Util.Log("Cacheserver 2 started.");
+      CacheHelper.StartJavaServerWithLocators(3, "GFECS3", 1);
+      Util.Log("Cacheserver 3 started.");
+
+      createPool(poolName, CacheHelper.Locators, serverGroup, 1, true, true, 
/*threadLocal*/true);
+      createRegionAndAttachPool(QERegionName, poolName);
+      Util.Log("Client 1 (pool locator) regions created");
+
+      OnServerHAStepOne();
+
+      Close();
+      Util.Log("Client 1 closed");
+
+      CacheHelper.StopJavaServer(1);
+      Util.Log("Cacheserver 1 stopped.");
+
+      CacheHelper.StopJavaServer(2);
+      Util.Log("Cacheserver 2 stopped.");
+
+      CacheHelper.StopJavaServer(3);
+      Util.Log("Cacheserver 3 stopped.");
+
+      CacheHelper.StopJavaLocator(1);
+      Util.Log("Locator 1 stopped.");
+
+      CacheHelper.ClearEndpoints();
+      CacheHelper.ClearLocators();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/ThinClientAppDomainQueryTests.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/ThinClientAppDomainQueryTests.cs 
b/clicache/integration-test/ThinClientAppDomainQueryTests.cs
new file mode 100644
index 0000000..90aabf7
--- /dev/null
+++ b/clicache/integration-test/ThinClientAppDomainQueryTests.cs
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using Apache.Geode.Client;
+  using Apache.Geode.Client.Tests;
+  using Apache.Geode.DUnitFramework;
+  using NUnit.Framework;
+  using QueryCategory = Apache.Geode.Client.Tests.QueryCategory;
+  using QueryStatics = Apache.Geode.Client.Tests.QueryStatics;
+  using QueryStrings = Apache.Geode.Client.Tests.QueryStrings;
+
+  [TestFixture]
+  [Category("group1")]
+  [Category("unicast_only")]
+  [Category("generics")]
+  internal class ThinClientAppDomainQueryTests : ThinClientRegionSteps
+  {
+    #region Private members
+
+    private UnitProcess m_client1;
+    private UnitProcess m_client2;
+
+    private static string[] QueryRegionNames = { "Portfolios", "Positions", 
"Portfolios2",
+      "Portfolios3" };
+
+    private static string QERegionName = "Portfolios";
+    private static string endpoint1;
+    private static string endpoint2;
+
+    #endregion Private members
+
+    protected override ClientBase[] GetClients()
+    {
+      return new ClientBase[] { };
+    }
+
+    [TestFixtureSetUp]
+    public override void InitTests()
+    {
+      Properties<string, string> config = new Properties<string, string>();
+      config.Insert("appdomain-enabled", "true");
+      CacheHelper.InitConfig(config);
+    }
+
+
+    [TearDown]
+    public override void EndTest()
+    {
+      CacheHelper.StopJavaServers();
+      base.EndTest();
+    }
+
+    #region Functions invoked by the tests
+
+    public void InitClient()
+    {
+      Serializable.RegisterTypeGeneric(Portfolio.CreateDeserializable, 
CacheHelper.DCache);
+      Serializable.RegisterTypeGeneric(Position.CreateDeserializable, 
CacheHelper.DCache);
+      
Serializable.RegisterPdxType(Apache.Geode.Client.Tests.PortfolioPdx.CreateDeserializable);
+      
Serializable.RegisterPdxType(Apache.Geode.Client.Tests.PositionPdx.CreateDeserializable);
+    }
+
+    public void CreateCache(string locators)
+    {
+      CacheHelper.CreateTCRegion_Pool<object, object>(QueryRegionNames[0], 
true, true,
+      null, locators, "__TESTPOOL1_", true);
+      CacheHelper.CreateTCRegion_Pool<object, object>(QueryRegionNames[1], 
true, true,
+        null, locators, "__TESTPOOL1_", true);
+      CacheHelper.CreateTCRegion_Pool<object, object>(QueryRegionNames[2], 
true, true,
+        null, locators, "__TESTPOOL1_", true);
+      CacheHelper.CreateTCRegion_Pool<object, object>(QueryRegionNames[3], 
true, true,
+        null, locators, "__TESTPOOL1_", true);
+
+      IRegion<object, object> region = CacheHelper.GetRegion<object, 
object>(QueryRegionNames[0]);
+      Apache.Geode.Client.RegionAttributes<object, object> regattrs = 
region.Attributes;
+      region.CreateSubRegion(QueryRegionNames[1], regattrs);
+    }
+
+    public void PopulateRegions()
+    {
+      IRegion<object, object> region0 = CacheHelper.GetRegion<object, 
object>(QueryRegionNames[0]);
+      IRegion<object, object> subRegion0 = (IRegion<object, 
object>)region0.GetSubRegion(QueryRegionNames[1]);
+      IRegion<object, object> region1 = CacheHelper.GetRegion<object, 
object>(QueryRegionNames[1]);
+      IRegion<object, object> region2 = CacheHelper.GetRegion<object, 
object>(QueryRegionNames[2]);
+      IRegion<object, object> region3 = CacheHelper.GetRegion<object, 
object>(QueryRegionNames[3]);
+
+      QueryHelper<object, object> qh = QueryHelper<object, 
object>.GetHelper(CacheHelper.DCache);
+      Util.Log("SetSize {0}, NumSets {1}.", qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+
+      qh.PopulatePortfolioPdxData(region0, qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+      qh.PopulatePositionPdxData(subRegion0, qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+      qh.PopulatePositionPdxData(region1, qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+      qh.PopulatePortfolioPdxData(region2, qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+      qh.PopulatePortfolioPdxData(region3, qh.PortfolioSetSize,
+        qh.PortfolioNumSets);
+    }
+
+    public void VerifyQueries()
+    {
+      bool ErrorOccurred = false;
+
+      QueryHelper<object, object> qh = QueryHelper<object, 
object>.GetHelper(CacheHelper.DCache);
+
+      QueryService<object, object> qs = 
CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_").GetQueryService<object,
 object>();
+
+      int qryIdx = 0;
+
+      foreach (QueryStrings qrystr in QueryStatics.ResultSetQueries)
+      {
+        if (qrystr.Category == QueryCategory.Unsupported)
+        {
+          Util.Log("Skipping query index {0} because it is unsupported.", 
qryIdx);
+          qryIdx++;
+          continue;
+        }
+
+        if (qryIdx == 2 || qryIdx == 3 || qryIdx == 4)
+        {
+          Util.Log("Skipping query index {0} for Pdx because it is function 
type.", qryIdx);
+          qryIdx++;
+          continue;
+        }
+
+        Util.Log("Evaluating query index {0}. Query string {1}", qryIdx, 
qrystr.Query);
+
+        Query<object> query = qs.NewQuery(qrystr.Query);
+
+        ISelectResults<object> results = query.Execute();
+
+        int expectedRowCount = qh.IsExpectedRowsConstantRS(qryIdx) ?
+          QueryStatics.ResultSetRowCounts[qryIdx] : 
QueryStatics.ResultSetRowCounts[qryIdx] * qh.PortfolioNumSets;
+
+        if (!qh.VerifyRS(results, expectedRowCount))
+        {
+          ErrorOccurred = true;
+          Util.Log("Query verify failed for query index {0}.", qryIdx);
+          qryIdx++;
+          continue;
+        }
+
+        ResultSet<object> rs = results as ResultSet<object>;
+
+        foreach (object item in rs)
+        {
+          PortfolioPdx port = item as PortfolioPdx;
+          if (port == null)
+          {
+            PositionPdx pos = item as PositionPdx;
+            if (pos == null)
+            {
+              string cs = item.ToString();
+              if (cs == null)
+              {
+                Util.Log("Query got other/unknown object.");
+              }
+              else
+              {
+                Util.Log("Query got string : {0}.", cs);
+              }
+            }
+            else
+            {
+              Util.Log("Query got Position object with secId {0}, shares 
{1}.", pos.secId, pos.getSharesOutstanding);
+            }
+          }
+          else
+          {
+            Util.Log("Query got Portfolio object with ID {0}, pkid {1}.", 
port.ID, port.Pkid);
+          }
+        }
+
+        qryIdx++;
+      }
+
+      Assert.IsFalse(ErrorOccurred, "One or more query validation errors 
occurred.");
+    }
+
+    public void VerifyUnsupporteQueries()
+    {
+      bool ErrorOccurred = false;
+
+      QueryHelper<object, object> qh = QueryHelper<object, 
object>.GetHelper(CacheHelper.DCache);
+
+      QueryService<object, object> qs = 
CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_").GetQueryService<object,
 object>();
+
+      int qryIdx = 0;
+
+      foreach (QueryStrings qrystr in QueryStatics.ResultSetQueries)
+      {
+        if (qrystr.Category != QueryCategory.Unsupported)
+        {
+          qryIdx++;
+          continue;
+        }
+
+        Util.Log("Evaluating unsupported query index {0}.", qryIdx);
+
+        Query<object> query = qs.NewQuery(qrystr.Query);
+
+        try
+        {
+          ISelectResults<object> results = query.Execute();
+
+          Util.Log("Query exception did not occur for index {0}.", qryIdx);
+          ErrorOccurred = true;
+          qryIdx++;
+        }
+        catch (GeodeException)
+        {
+          // ok, exception expected, do nothing.
+          qryIdx++;
+        }
+        catch (Exception)
+        {
+          Util.Log("Query unexpected exception occurred for index {0}.", 
qryIdx);
+          ErrorOccurred = true;
+          qryIdx++;
+        }
+      }
+
+      Assert.IsFalse(ErrorOccurred, "Query expected exceptions did not 
occur.");
+    }
+
+    #endregion Functions invoked by the tests
+
+    [Test]
+    public void RemoteQueryRS()
+    {
+      Util.Log("DoRemoteQueryRS: AppDomain: " + AppDomain.CurrentDomain.Id);
+      CacheHelper.SetupJavaServers(true, "remotequeryN.xml");
+      CacheHelper.StartJavaLocator(1, "GFELOC");
+      Util.Log("Locator started");
+      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
+      Util.Log("Cacheserver 1 started.");
+
+      CreateCache(CacheHelper.Locators);
+      Util.Log("CreateCache complete.");
+
+      PopulateRegions();
+      Util.Log("PopulateRegions complete.");
+
+      VerifyQueries();
+      Util.Log("VerifyQueries complete.");
+
+      VerifyUnsupporteQueries();
+      Util.Log("VerifyUnsupporteQueries complete.");
+
+      Close();
+
+      CacheHelper.StopJavaServer(1);
+      Util.Log("Cacheserver 1 stopped.");
+
+      CacheHelper.StopJavaLocator(1);
+      Util.Log("Locator stopped");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/integration-test/ThinClientCSTXN.cs
----------------------------------------------------------------------
diff --git a/clicache/integration-test/ThinClientCSTXN.cs 
b/clicache/integration-test/ThinClientCSTXN.cs
new file mode 100644
index 0000000..211a52c
--- /dev/null
+++ b/clicache/integration-test/ThinClientCSTXN.cs
@@ -0,0 +1,827 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace Apache.Geode.Client.UnitTests
+{
+  using NUnit.Framework;
+  using Apache.Geode.DUnitFramework;
+  using Apache.Geode.Client;
+  using Apache.Geode.Client.UnitTests;
+  using Region = Apache.Geode.Client.IRegion<Object, Object>;
+  using Apache.Geode.Client.Tests;
+  #region CSTX_COMMENTED - transaction listener and writer are disabled for now
+  /* 
+  class CSTXListener<TKey, TVal> : TransactionListenerAdapter<TKey, TVal>
+  {
+    public CSTXListener(string cacheName)
+    {
+      m_cacheName = cacheName; 
+    }
+    public override void AfterCommit(TransactionEvent<TKey, TVal> te)
+    {
+      if (te.Cache.Name != m_cacheName)
+        incorrectCacheName = true; 
+        
+      afterCommitEvents++;
+      afterCommitKeyEvents += te.Events.Length;
+    }
+
+    public override void AfterFailedCommit(TransactionEvent<TKey, TVal> te)
+    {
+      if (te.Cache.Name != m_cacheName)
+        incorrectCacheName = true;
+
+      afterFailedCommitEvents++;
+      afterFailedCommitKeyEvents += te.Events.Length;
+    }
+
+    public override void AfterRollback(TransactionEvent<TKey, TVal> te)
+    {
+      if (te.Cache.Name != m_cacheName)
+        incorrectCacheName = true;
+
+      afterRollbackEvents++;
+      afterRollbackKeyEvents += te.Events.Length;
+    }
+
+    public override void Close()
+    {
+      closeEvent++;
+    }
+    
+    public void ShowTallies()
+    {
+      Util.Log("CSTXListener state: (afterCommitEvents = {0}, 
afterRollbackEvents = {1}, afterFailedCommitEvents = {2}, 
afterCommitRegionEvents = {3}, afterRollbackRegionEvents = {4}, 
afterFailedCommitRegionEvents = {5}, closeEvent = {6})",
+        afterCommitEvents, afterRollbackEvents, afterFailedCommitEvents, 
afterCommitKeyEvents, afterRollbackKeyEvents, afterFailedCommitKeyEvents, 
closeEvent);
+    }
+    
+    public int AfterCommitEvents { get { return afterCommitEvents; } }
+    public int AfterRollbackEvents { get { return afterRollbackEvents; } }
+    public int AfterFailedCommitEvents { get { return afterFailedCommitEvents; 
} }
+    public int AfterCommitKeyEvents { get { return afterCommitKeyEvents; } }
+    public int AfterRollbackKeyEvents { get { return afterRollbackKeyEvents; } 
}
+    public int AfterFailedCommitKeyEvents { get { return 
afterFailedCommitKeyEvents; } }
+    public int CloseEvent { get { return closeEvent; } }
+    public bool IncorrectCacheName { get { return incorrectCacheName; } }
+    
+    private int afterCommitEvents = 0;
+
+    private int afterRollbackEvents = 0;
+    private int afterFailedCommitEvents = 0;
+    
+    private int afterCommitKeyEvents = 0;
+    private int afterRollbackKeyEvents = 0;
+    private int afterFailedCommitKeyEvents = 0;
+    private int closeEvent = 0;
+    
+    private string m_cacheName = null;
+
+    private bool incorrectCacheName = false;
+
+    
+  }
+  class CSTXWriter<TKey, TVal> : TransactionWriterAdapter<TKey, TVal>
+  {
+    public CSTXWriter(string cacheName, string instanceName)
+    {
+      m_instanceName = instanceName;
+      m_cacheName = cacheName; 
+    }
+    
+    public override void BeforeCommit(TransactionEvent<TKey, TVal> te)
+    {
+      if (te.Cache.Name != m_cacheName)
+        incorrectCacheName = true;
+
+      beforeCommitEvents++;
+      beforeCommitKeyEvents += te.Events.Length; 
+    }
+    public int BeforeCommitEvents { get { return beforeCommitEvents; } }
+    public int BeforeCommitKeyEvents { get { return beforeCommitKeyEvents; } }
+    public string InstanceName { get { return m_instanceName; } }
+    public bool IncorrectCacheName { get { return incorrectCacheName; } }
+    public void ShowTallies()
+    {
+      Util.Log("CSTXWriter state: (beforeCommitEvents = {0}, 
beforeCommitRegionEvents = {1}, instanceName = {2})",
+        beforeCommitEvents, beforeCommitKeyEvents, m_instanceName);
+    }
+    private int beforeCommitEvents = 0;
+    private int beforeCommitKeyEvents = 0;
+    private string m_cacheName = null;
+    private string m_instanceName;
+    
+    private bool incorrectCacheName = false;
+    
+  }
+  */
+  #endregion
+
+  [TestFixture]
+  [Category("group1")]
+  [Category("unicast_only")]
+  public class ThinClientCSTX : ThinClientRegionSteps
+  {
+    #region CSTX_COMMENTED - transaction listener and writer are disabled for 
now
+    /*private CSTXWriter<object, object> m_writer1;
+    private CSTXWriter<object, object> m_writer2;
+    private CSTXListener<object, object> m_listener1;
+    private CSTXListener<object, object> m_listener2;*/
+    #endregion
+
+    RegionOperation o_region1;
+    RegionOperation o_region2;
+    private TallyListener<object, object> m_listener;
+    private static string[] cstxRegions = new string[] { "cstx1", "cstx2", 
"cstx3" };
+    private UnitProcess m_client1;
+
+    protected override ClientBase[] GetClients()
+    {
+      m_client1 = new UnitProcess();
+      return new ClientBase[] { m_client1 };
+    }
+
+    public void CreateRegion(string regionName, string locators, bool listener)
+    {
+      if (listener)
+        m_listener = new TallyListener<object, object>();
+      else
+        m_listener = null;
+
+      Region region = null;
+      region = CacheHelper.CreateTCRegion_Pool<object, object>(regionName, 
false, false,
+        m_listener, locators, "__TESTPOOL1_", false);
+
+    }
+
+    #region CSTX_COMMENTED - transaction listener and writer are disabled for 
now
+    /*
+    public void ValidateCSTXListenerWriter()
+    {
+      Util.Log("tallies for listener 1");
+      m_listener1.ShowTallies();
+      Util.Log("tallies for writer 1");
+      m_writer1.ShowTallies();
+      Util.Log("tallies for listener 2");
+      m_listener2.ShowTallies();
+      Util.Log("tallies for writer 2");
+      m_writer2.ShowTallies();
+      
+       // listener 1
+      Assert.AreEqual(4, m_listener1.AfterCommitEvents, "Should be 4");
+      Assert.AreEqual(14, m_listener1.AfterCommitKeyEvents, "Should be 14");
+      Assert.AreEqual(0, m_listener1.AfterFailedCommitEvents, "Should be 0");
+      Assert.AreEqual(0, m_listener1.AfterFailedCommitKeyEvents, "Should be 
0");
+      Assert.AreEqual(2, m_listener1.AfterRollbackEvents, "Should be 2");
+      Assert.AreEqual(6, m_listener1.AfterRollbackKeyEvents, "Should be 6");
+      Assert.AreEqual(1, m_listener1.CloseEvent, "Should be 1");
+      Assert.AreEqual(false, m_listener1.IncorrectCacheName, "Incorrect cache 
name in the events");
+      
+      // listener 2
+      Assert.AreEqual(2, m_listener2.AfterCommitEvents, "Should be 2");
+      Assert.AreEqual(6, m_listener2.AfterCommitKeyEvents, "Should be 6");
+      Assert.AreEqual(0, m_listener2.AfterFailedCommitEvents, "Should be 0");
+      Assert.AreEqual(0, m_listener2.AfterFailedCommitKeyEvents, "Should be 
0");
+      Assert.AreEqual(2, m_listener2.AfterRollbackEvents, "Should be 2");
+      Assert.AreEqual(6, m_listener2.AfterRollbackKeyEvents, "Should be 6");
+      Assert.AreEqual(1, m_listener2.CloseEvent, "Should be 1");
+      Assert.AreEqual(false, m_listener2.IncorrectCacheName, "Incorrect cache 
name in the events");
+      
+      // writer 1 
+      Assert.AreEqual(3, m_writer1.BeforeCommitEvents, "Should be 3");
+      Assert.AreEqual(10, m_writer1.BeforeCommitKeyEvents, "Should be 10");
+      Assert.AreEqual(false, m_writer1.IncorrectCacheName, "Incorrect cache 
name in the events");
+      
+      // writer 2
+      Assert.AreEqual(1, m_writer2.BeforeCommitEvents, "Should be 1");
+      Assert.AreEqual(4, m_writer2.BeforeCommitKeyEvents, "Should be 4");
+      Assert.AreEqual(false, m_writer2.IncorrectCacheName, "Incorrect cache 
name in the events");
+    }
+    */
+    #endregion
+    public void ValidateListener()
+    {
+      o_region1 = new RegionOperation(cstxRegions[2]);
+      CacheHelper.CSTXManager.Begin();
+      o_region1.Region.Put("key3", "value1", null);
+      o_region1.Region.Put("key4", "value2", null);
+      o_region1.Region.Remove("key4");
+      CacheHelper.CSTXManager.Commit();
+      // server is conflating the events on the same key hence only 1 create
+      Assert.AreEqual(1, m_listener.Creates, "Should be 1 creates");
+      Assert.AreEqual(1, m_listener.Destroys, "Should be 1 destroys");
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1.Region.Put("key1", "value1", null);
+      o_region1.Region.Put("key2", "value2", null);
+      o_region1.Region.Invalidate("key1");
+      o_region1.Region.Invalidate("key3");
+      CacheHelper.CSTXManager.Commit();
+
+      // server is conflating the events on the same key hence only 1 
invalidate
+      Assert.AreEqual(3, m_listener.Creates, "Should be 3 creates");
+      Assert.AreEqual(1, m_listener.Invalidates, "Should be 1 invalidates");
+
+    }
+    public void SuspendResumeRollback()
+    {
+      o_region1 = new RegionOperation(cstxRegions[0]);
+      o_region2 = new RegionOperation(cstxRegions[1]);
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(1, null);
+
+      o_region2.PutOp(1, null);
+
+
+      
Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(CacheHelper.CSTXManager.TransactionId),
 false, "Transaction should not be suspended");
+      
Assert.AreEqual(CacheHelper.CSTXManager.Exists(CacheHelper.CSTXManager.TransactionId),
 true, "Transaction should exist");
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be two 
values in the region before commit");
+      Assert.AreEqual(2, o_region2.Region.Keys.Count, "There should be two 
values in the region before commit");
+
+      TransactionId tid = CacheHelper.CSTXManager.Suspend();
+
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), true, 
"Transaction should be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), true, "Transaction 
should exist");
+      Assert.AreEqual(0, o_region1.Region.Keys.Count, "There should be 0 
values in the region after suspend");
+      Assert.AreEqual(0, o_region2.Region.Keys.Count, "There should be 0 
values in the region after suspend");
+
+
+      CacheHelper.CSTXManager.Resume(tid);
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), false, 
"Transaction should not be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), true, "Transaction 
should exist");
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be two 
values in the region before commit");
+      Assert.AreEqual(2, o_region2.Region.Keys.Count, "There should be two 
values in the region before commit");
+
+      o_region2.PutOp(2, null);
+
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be four 
values in the region before commit");
+      Assert.AreEqual(4, o_region2.Region.Keys.Count, "There should be four 
values in the region before commit");
+
+      CacheHelper.CSTXManager.Rollback();
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), false, 
"Transaction should not be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), false, "Transaction 
should NOT exist");
+      Assert.AreEqual(CacheHelper.CSTXManager.TryResume(tid), false, 
"Transaction should not be resumed");
+      Assert.AreEqual(CacheHelper.CSTXManager.TryResume(tid, 3000), false, 
"Transaction should not be resumed");
+      Assert.AreEqual(0, o_region1.Region.Keys.Count, "There should be 0 
values in the region after rollback");
+      Assert.AreEqual(0, o_region2.Region.Keys.Count, "There should be 0 
values in the region after rollback");
+      bool resumeEx = false;
+      try
+      {
+        CacheHelper.CSTXManager.Resume(tid);
+      }
+      catch (IllegalStateException)
+      {
+        resumeEx = true;
+      }
+      Assert.AreEqual(resumeEx, true, "The transaction should not be resumed");
+
+    }
+
+    public void SuspendResumeInThread()
+    {
+      AutoResetEvent txEvent = new AutoResetEvent(false);
+      AutoResetEvent txIdUpdated = new AutoResetEvent(false);
+      SuspendTransactionThread susObj = new SuspendTransactionThread(false, 
txEvent, txIdUpdated);
+      Thread susThread = new Thread(new ThreadStart(susObj.ThreadStart));
+      susThread.Start();
+      txIdUpdated.WaitOne();
+
+      ResumeTransactionThread resObj = new ResumeTransactionThread(susObj.Tid, 
false, false, txEvent);
+      Thread resThread = new Thread(new ThreadStart(resObj.ThreadStart));
+      resThread.Start();
+
+      susThread.Join();
+      resThread.Join();
+      Assert.AreEqual(resObj.IsFailed, false, resObj.Error);
+
+      susObj = new SuspendTransactionThread(false, txEvent, txIdUpdated);
+      susThread = new Thread(new ThreadStart(susObj.ThreadStart));
+      susThread.Start();
+      txIdUpdated.WaitOne();
+
+      resObj = new ResumeTransactionThread(susObj.Tid, true, false, txEvent);
+      resThread = new Thread(new ThreadStart(resObj.ThreadStart));
+      resThread.Start();
+
+      susThread.Join();
+      resThread.Join();
+      Assert.AreEqual(resObj.IsFailed, false, resObj.Error);
+
+
+      susObj = new SuspendTransactionThread(true, txEvent, txIdUpdated);
+      susThread = new Thread(new ThreadStart(susObj.ThreadStart));
+      susThread.Start();
+      txIdUpdated.WaitOne();
+
+      resObj = new ResumeTransactionThread(susObj.Tid, false, true, txEvent);
+      resThread = new Thread(new ThreadStart(resObj.ThreadStart));
+      resThread.Start();
+
+      susThread.Join();
+      resThread.Join();
+      Assert.AreEqual(resObj.IsFailed, false, resObj.Error);
+
+
+      susObj = new SuspendTransactionThread(true, txEvent, txIdUpdated);
+      susThread = new Thread(new ThreadStart(susObj.ThreadStart));
+      susThread.Start();
+
+      txIdUpdated.WaitOne();
+      resObj = new ResumeTransactionThread(susObj.Tid, true, true, txEvent);
+      resThread = new Thread(new ThreadStart(resObj.ThreadStart));
+      resThread.Start();
+
+      susThread.Join();
+      resThread.Join();
+      Assert.AreEqual(resObj.IsFailed, false, resObj.Error);
+
+    }
+    public void SuspendResumeCommit()
+    {
+      o_region1 = new RegionOperation(cstxRegions[0]);
+      o_region2 = new RegionOperation(cstxRegions[1]);
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(1, null);
+
+      o_region2.PutOp(1, null);
+
+
+      
Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(CacheHelper.CSTXManager.TransactionId),
 false, "Transaction should not be suspended");
+      
Assert.AreEqual(CacheHelper.CSTXManager.Exists(CacheHelper.CSTXManager.TransactionId),
 true, "Transaction should exist");
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be two 
values in the region before commit");
+      Assert.AreEqual(2, o_region2.Region.Keys.Count, "There should be two 
values in the region before commit");
+
+      TransactionId tid = CacheHelper.CSTXManager.Suspend();
+
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), true, 
"Transaction should be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), true, "Transaction 
should exist");
+      Assert.AreEqual(0, o_region1.Region.Keys.Count, "There should be 0 
values in the region after suspend");
+      Assert.AreEqual(0, o_region2.Region.Keys.Count, "There should be 0 
values in the region after suspend");
+
+
+      CacheHelper.CSTXManager.Resume(tid);
+      Assert.AreEqual(CacheHelper.CSTXManager.TryResume(tid), false, "The 
transaction should not have been resumed again.");
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), false, 
"Transaction should not be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), true, "Transaction 
should exist");
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be two 
values in the region before commit");
+      Assert.AreEqual(2, o_region2.Region.Keys.Count, "There should be two 
values in the region before commit");
+
+      o_region2.PutOp(2, null);
+
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be four 
values in the region before commit");
+      Assert.AreEqual(4, o_region2.Region.Keys.Count, "There should be four 
values in the region before commit");
+
+      CacheHelper.CSTXManager.Commit();
+      Assert.AreEqual(CacheHelper.CSTXManager.IsSuspended(tid), false, 
"Transaction should not be suspended");
+      Assert.AreEqual(CacheHelper.CSTXManager.Exists(tid), false, "Transaction 
should NOT exist");
+      Assert.AreEqual(CacheHelper.CSTXManager.TryResume(tid), false, 
"Transaction should not be resumed");
+      Assert.AreEqual(CacheHelper.CSTXManager.TryResume(tid, 3000), false, 
"Transaction should not be resumed");
+      Assert.AreEqual(2, o_region1.Region.Keys.Count, "There should be four 
values in the region after commit");
+      Assert.AreEqual(4, o_region2.Region.Keys.Count, "There should be four 
values in the region after commit");
+      o_region1.DestroyOpWithPdxValue(1, null);
+      o_region2.DestroyOpWithPdxValue(2, null);
+      bool resumeEx = false;
+      try
+      {
+        CacheHelper.CSTXManager.Resume(tid);
+      }
+      catch (IllegalStateException)
+      {
+        resumeEx = true;
+      }
+      Assert.AreEqual(resumeEx, true, "The transaction should not be resumed");
+      Assert.AreEqual(CacheHelper.CSTXManager.Suspend(), null, "The 
transaction should not be suspended");
+    }
+
+    public void CallOp()
+    {
+      #region CSTX_COMMENTED - transaction listener and writer are disabled 
for now
+      /*
+      m_writer1 = new CSTXWriter<object, object>(CacheHelper.DCache.Name, 
"cstxWriter1");
+      m_writer2 = new CSTXWriter<object, object>(CacheHelper.DCache.Name, 
"cstxWriter2");
+      m_listener1 = new CSTXListener<object, object>(CacheHelper.DCache.Name);
+      m_listener2 = new CSTXListener<object, object>(CacheHelper.DCache.Name);
+      
+      CacheHelper.CSTXManager.AddListener<object, object>(m_listener1);
+      CacheHelper.CSTXManager.AddListener<object, object>(m_listener2);
+      CacheHelper.CSTXManager.SetWriter<object, object>(m_writer1);
+      
+      // test two listener one writer for commit on two regions
+      Util.Log(" test two listener one writer for commit on two regions");
+      */
+      #endregion
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1 = new RegionOperation(cstxRegions[0]);
+      o_region1.PutOp(2, null);
+
+      o_region2 = new RegionOperation(cstxRegions[1]);
+      o_region2.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Commit();
+      //two pdx put as well
+      Assert.AreEqual(2 + 2, o_region1.Region.Keys.Count, "Commit didn't put 
two values in the region");
+      Assert.AreEqual(2 + 2, o_region2.Region.Keys.Count, "Commit didn't put 
two values in the region");
+
+      #region CSTX_COMMENTED - transaction listener and writer are disabled 
for now
+      /*
+      Util.Log(" test two listener one writer for commit on two regions - 
complete");
+      //////////////////////////////////
+      
+      // region test two listener one writer for commit on one region
+      Util.Log(" region test two listener one writer for commit on one 
region");
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Commit();
+      Util.Log(" region test two listener one writer for commit on one region 
- complete");
+      //////////////////////////////////
+      // test two listener one writer for rollback on two regions
+      Util.Log(" test two listener one writer for rollback on two regions");
+      */
+      #endregion
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(2, null);
+
+      o_region2.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Rollback();
+      //two pdx put as well
+      Assert.AreEqual(2 + 2, o_region1.Region.Keys.Count, "Region has 
incorrect number of objects");
+      Assert.AreEqual(2 + 2, o_region2.Region.Keys.Count, "Region has 
incorrect number of objects");
+      o_region1.DestroyOpWithPdxValue(2, null);
+      o_region2.DestroyOpWithPdxValue(2, null);
+
+      #region CSTX_COMMENTED - transaction listener and writer are disabled 
for now
+      /*
+      
+      Util.Log(" test two listener one writer for rollback on two regions - 
complete");
+      //////////////////////////////////
+      
+      // test two listener one writer for rollback on on region
+      Util.Log(" test two listener one writer for rollback on on region");
+      CacheHelper.CSTXManager.Begin();
+     
+      o_region2.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Rollback();
+      Util.Log(" test two listener one writer for rollback on on region - 
complete");
+      //////////////////////////////////
+      
+      // test remove listener
+      Util.Log(" test remove listener");
+      CacheHelper.CSTXManager.RemoveListener<object, object>(m_listener2);
+      
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(2, null);
+
+      o_region2.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Commit();
+      Util.Log(" test remove listener - complete" );
+      //////////////////////////////////
+      
+      // test GetWriter
+      Util.Log("test GetWriter");
+      CSTXWriter<object, object> writer = (CSTXWriter<object, 
object>)CacheHelper.CSTXManager.GetWriter<object, object>();
+      Assert.AreEqual(writer.InstanceName, m_writer1.InstanceName, "GetWriter 
is not returning the object set by SetWriter");
+      Util.Log("test GetWriter - complete");
+      //////////////////////////////////
+      
+      // set a different writer 
+      Util.Log("set a different writer");
+      CacheHelper.CSTXManager.SetWriter<object, object>(m_writer2);
+      
+      CacheHelper.CSTXManager.Begin();
+      o_region1.PutOp(2, null);
+
+      o_region2.PutOp(2, null);
+
+      CacheHelper.CSTXManager.Commit();
+      Util.Log("set a different writer - complete");
+      //////////////////////////////////
+      */
+      #endregion
+    }
+
+    void runThinClientCSTXTest()
+    {
+      CacheHelper.SetupJavaServers(true, "client_server_transactions.xml");
+      CacheHelper.StartJavaLocator(1, "GFELOC");
+      Util.Log("Locator started");
+      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
+
+      Util.Log("Cacheserver 1 started.");
+
+      m_client1.Call(CacheHelper.InitClient);
+      Util.Log("Creating two regions in client1");
+      m_client1.Call(CreateRegion, cstxRegions[0], CacheHelper.Locators, 
false);
+      m_client1.Call(CreateRegion, cstxRegions[1], CacheHelper.Locators, 
false);
+      m_client1.Call(CreateRegion, cstxRegions[2], CacheHelper.Locators, true);
+
+      m_client1.Call(CallOp);
+      m_client1.Call(SuspendResumeCommit);
+      m_client1.Call(SuspendResumeRollback);
+      m_client1.Call(SuspendResumeInThread);
+
+
+      m_client1.Call(ValidateListener);
+
+      #region CSTX_COMMENTED - transaction listener and writer are disabled 
for now
+      /*
+      m_client1.Call(ValidateCSTXListenerWriter);
+      */
+      #endregion
+
+      m_client1.Call(CacheHelper.Close);
+
+      CacheHelper.StopJavaServer(1);
+
+      CacheHelper.StopJavaLocator(1);
+      Util.Log("Locator stopped");
+
+      CacheHelper.ClearLocators();
+      CacheHelper.ClearEndpoints();
+    }
+
+    void runThinClientPersistentTXTest()
+    {
+      CacheHelper.SetupJavaServers(true, 
"client_server_persistent_transactions.xml");
+      CacheHelper.StartJavaLocator(1, "GFELOC");
+      Util.Log("Locator started");
+      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, 
"--J=-Dgemfire.ALLOW_PERSISTENT_TRANSACTIONS=true");
+
+      Util.Log("Cacheserver 1 started.");
+
+      m_client1.Call(CacheHelper.InitClient);
+      Util.Log("Creating two regions in client1");
+      m_client1.Call(CreateRegion, cstxRegions[0], CacheHelper.Locators, 
false);
+
+      m_client1.Call(initializePdxSerializer);
+      m_client1.Call(doPutGetWithPdxSerializer);
+
+      m_client1.Call(CacheHelper.Close);
+
+      CacheHelper.StopJavaServer(1);
+
+      CacheHelper.StopJavaLocator(1);
+      Util.Log("Locator stopped");
+
+      CacheHelper.ClearLocators();
+      CacheHelper.ClearEndpoints();
+    }
+
+    [TearDown]
+    public override void EndTest()
+    {
+      base.EndTest();
+    }
+
+    //Successful
+    [Test]
+    public void ThinClientCSTXTest()
+    {
+      runThinClientCSTXTest();
+    }
+
+    [Test]
+    public void ThinClientPersistentTXTest()
+    {
+      runThinClientPersistentTXTest();
+    }
+
+    public class SuspendTransactionThread
+    {
+      public SuspendTransactionThread(bool sleep, AutoResetEvent txevent, 
AutoResetEvent txIdUpdated)
+      {
+        m_sleep = sleep;
+        m_txevent = txevent;
+        m_txIdUpdated = txIdUpdated;
+      }
+      public void ThreadStart()
+      {
+        RegionOperation o_region1 = new RegionOperation(cstxRegions[0]);
+        RegionOperation o_region2 = new RegionOperation(cstxRegions[1]);
+        CacheHelper.CSTXManager.Begin();
+
+        o_region1.PutOp(1, null);
+        o_region2.PutOp(1, null);
+
+        m_tid = CacheHelper.CSTXManager.TransactionId;
+        m_txIdUpdated.Set();
+
+        if (m_sleep)
+        {
+          m_txevent.WaitOne();
+          Thread.Sleep(5000);
+        }
+
+        m_tid = CacheHelper.CSTXManager.Suspend();
+      }
+
+      public TransactionId Tid
+      {
+        get
+        {
+          return m_tid;
+        }
+      }
+
+      private TransactionId m_tid = null;
+      private bool m_sleep = false;
+      private AutoResetEvent m_txevent = null;
+      AutoResetEvent m_txIdUpdated = null;
+    }
+
+    public class ResumeTransactionThread
+    {
+      public ResumeTransactionThread(TransactionId tid, bool isCommit, bool 
tryResumeWithSleep, AutoResetEvent txevent)
+      {
+        m_tryResumeWithSleep = tryResumeWithSleep;
+        m_txevent = txevent;
+        m_tid = tid;
+        m_isCommit = isCommit;
+      }
+
+      public void ThreadStart()
+      {
+        RegionOperation o_region1 = new RegionOperation(cstxRegions[0]);
+        RegionOperation o_region2 = new RegionOperation(cstxRegions[1]);
+        if (m_tryResumeWithSleep)
+        {
+          if (AssertCheckFail(CacheHelper.CSTXManager.IsSuspended(m_tid) == 
false, "Transaction should not be suspended"))
+            return;
+        }
+        else
+        {
+          if (AssertCheckFail(CacheHelper.CSTXManager.IsSuspended(m_tid) == 
true, "Transaction should be suspended"))
+            return;
+        }
+        if (AssertCheckFail(CacheHelper.CSTXManager.Exists(m_tid) == true, 
"Transaction should exist"))
+          return;
+        if (AssertCheckFail(0 == o_region1.Region.Keys.Count, "There should be 
0 values in the region after suspend"))
+          return;
+        if (AssertCheckFail(0 == o_region2.Region.Keys.Count, "There should be 
0 values in the region after suspend"))
+          return;
+
+        if (m_tryResumeWithSleep)
+        {
+          m_txevent.Set();
+          CacheHelper.CSTXManager.TryResume(m_tid, 30000);
+        }
+        else
+          CacheHelper.CSTXManager.Resume(m_tid);
+
+        if (AssertCheckFail(CacheHelper.CSTXManager.IsSuspended(m_tid) == 
false, "Transaction should not be suspended"))
+          return;
+        if (AssertCheckFail(CacheHelper.CSTXManager.Exists(m_tid) == true, 
"Transaction should exist"))
+          return;
+        if (AssertCheckFail(o_region1.Region.Keys.Count == 2, "There should be 
two values in the region after suspend"))
+          return;
+        if (AssertCheckFail(o_region2.Region.Keys.Count == 2, "There should be 
two values in the region after suspend"))
+          return;
+
+        o_region2.PutOp(2, null);
+
+        if (m_isCommit)
+        {
+          CacheHelper.CSTXManager.Commit();
+          if (AssertCheckFail(CacheHelper.CSTXManager.IsSuspended(m_tid) == 
false, "Transaction should not be suspended"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.Exists(m_tid) == false, 
"Transaction should NOT exist"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.TryResume(m_tid) == 
false, "Transaction should not be resumed"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.TryResume(m_tid, 3000) 
== false, "Transaction should not be resumed"))
+            return;
+          if (AssertCheckFail(2 == o_region1.Region.Keys.Count, "There should 
be four values in the region after commit"))
+            return;
+          if (AssertCheckFail(4 == o_region2.Region.Keys.Count, "There should 
be four values in the region after commit"))
+            return;
+          o_region1.DestroyOpWithPdxValue(1, null);
+          o_region2.DestroyOpWithPdxValue(2, null);
+        }
+        else
+        {
+          CacheHelper.CSTXManager.Rollback();
+          if (AssertCheckFail(CacheHelper.CSTXManager.IsSuspended(m_tid) == 
false, "Transaction should not be suspended"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.Exists(m_tid) == false, 
"Transaction should NOT exist"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.TryResume(m_tid) == 
false, "Transaction should not be resumed"))
+            return;
+          if (AssertCheckFail(CacheHelper.CSTXManager.TryResume(m_tid, 3000) 
== false, "Transaction should not be resumed"))
+            return;
+          if (AssertCheckFail(0 == o_region1.Region.Keys.Count, "There should 
be 0 values in the region after rollback"))
+            return;
+          if (AssertCheckFail(0 == o_region2.Region.Keys.Count, "There should 
be 0 values in the region after rollback"))
+            return;
+        }
+
+      }
+
+      public bool AssertCheckFail(bool cond, String error)
+      {
+        if (!cond)
+        {
+          m_isFailed = true;
+          m_error = error;
+          return true;
+        }
+        return false;
+      }
+
+      public TransactionId Tid
+      {
+        get { return m_tid; }
+      }
+      public bool IsFailed
+      {
+        get { return m_isFailed; }
+      }
+      public String Error
+      {
+        get { return m_error; }
+      }
+
+      private TransactionId m_tid = null;
+      private bool m_tryResumeWithSleep = false;
+      private bool m_isFailed = false;
+      private String m_error;
+      private bool m_isCommit = false;
+      private AutoResetEvent m_txevent = null;
+
+    }
+
+    public void initializePdxSerializer()
+    {
+      Serializable.RegisterPdxSerializer(new PdxSerializer());
+    }
+
+    public void doPutGetWithPdxSerializer()
+    {
+      CacheHelper.CSTXManager.Begin();
+      o_region1 = new RegionOperation(cstxRegions[0]);
+      for (int i = 0; i < 10; i++)
+      {
+        o_region1.Region[i] = i + 1;
+        object ret = o_region1.Region[i];
+        o_region1.Region[i + 10] = i + 10;
+        ret = o_region1.Region[i + 10];
+        o_region1.Region[i + 20] = i + 20;
+        ret = o_region1.Region[i + 20];
+      }
+      CacheHelper.CSTXManager.Commit();
+      Util.Log("Region keys count after commit for non-pdx keys = {0} ", 
o_region1.Region.Keys.Count);
+      Assert.AreEqual(30, o_region1.Region.Keys.Count, "Commit didn't put two 
values in the region");
+
+      CacheHelper.CSTXManager.Begin();
+      o_region1 = new RegionOperation(cstxRegions[0]);
+      for (int i = 100; i < 110; i++)
+      {
+        object put = new SerializePdx1(true);
+        o_region1.Region[i] = put;
+        put = new SerializePdx2(true);
+        o_region1.Region[i + 10] = put;
+        put = new SerializePdx3(true, i % 2);
+        o_region1.Region[i + 20] = put;
+      }
+      CacheHelper.CSTXManager.Commit();
+
+      for (int i = 100; i < 110; i++)
+      {
+        object put = new SerializePdx1(true);
+        object ret = o_region1.Region[i];
+        Assert.AreEqual(put, ret);
+        put = new SerializePdx2(true);
+        ret = o_region1.Region[i + 10];
+        Assert.AreEqual(put, ret);
+        put = new SerializePdx3(true, i % 2);
+        ret = o_region1.Region[i + 20];
+        Assert.AreEqual(put, ret);
+      }
+      Util.Log("Region keys count after pdx-keys commit = {0} ", 
o_region1.Region.Keys.Count);
+      Assert.AreEqual(60, o_region1.Region.Keys.Count, "Commit didn't put two 
values in the region");
+    }
+  }
+}

Reply via email to