/*
 * 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.Collections.Generic;
using System.Threading;

namespace Apache.Geode.Client.UnitTests
{
  using NUnit.Framework;
  using Apache.Geode.DUnitFramework;
  using Apache.Geode.Client;


  using AssertionException = Apache.Geode.Client.AssertionException;
  [TestFixture]
  [Category("group2")]
  [Category("unicast_only")]
  [Category("generics")]
  public class ThinClientDurableTests : ThinClientRegionSteps
  {
    #region Private members

    private UnitProcess m_client1, m_client2, m_feeder;
    private string[] m_regexes = { "D-Key-.*", "Key-.*" };
    private string[] m_mixKeys = { "Key-1", "D-Key-1", "L-Key", "LD-Key" };
    private string[] keys = { "Key-1", "Key-2", "Key-3", "Key-4", "Key-5" };

    private static string DurableClientId1 = "DurableClientId1";
    private static string DurableClientId2 = "DurableClientId2";

    private static DurableListener<object, object> m_checker1, m_checker2;

    #endregion

    protected override ClientBase[] GetClients()
    {
      m_client1 = new UnitProcess();
      m_client2 = new UnitProcess();
      m_feeder = new UnitProcess();
      return new ClientBase[] { m_client1, m_client2, m_feeder };
    }

    [TestFixtureTearDown]
    public override void EndTests()
    {
      CacheHelper.StopJavaServers();
      base.EndTests();
    }

    [TearDown]
    public override void EndTest()
    {
      try
      {
        m_client1.Call(CacheHelper.Close);
        m_client2.Call(CacheHelper.Close);
        m_feeder.Call(CacheHelper.Close);
        CacheHelper.ClearEndpoints();
        CacheHelper.ClearLocators();
      }
      finally
      {
        CacheHelper.StopJavaServers();
      }
      base.EndTest();
    }

    #region Common Functions

    public void InitFeeder(string locators, int redundancyLevel)
    {
      CacheHelper.CreatePool<object, object>("__TESTPOOL1_", locators, (string)null, redundancyLevel, false);
      CacheHelper.CreateTCRegion_Pool<object, object>(RegionNames[0], false, true, null,
        locators, "__TESTPOOL1_", false);
    }

    public void InitFeeder2(string locators, int redundancyLevel)
    {
      CacheHelper.CreatePool<object, object>("__TESTPOOL1_", locators, (string)null, redundancyLevel, false);
      CacheHelper.CreateTCRegion_Pool<object, object>(RegionNames[0], false, true, null,
        locators, "__TESTPOOL1_", false);

      CacheHelper.CreatePool<object, object>("__TESTPOOL2_", locators, (string)null, redundancyLevel, false);
      CacheHelper.CreateTCRegion_Pool<object, object>(RegionNames[1], false, true, null,
        locators, "__TESTPOOL2_", false);
    }

    public void InitDurableClientWithTwoPools(string locators,
    int redundancyLevel, string durableClientId, TimeSpan durableTimeout, int expectedQ0, int expectedQ1)
    {
      DurableListener<object, object> checker = null;
      CacheHelper.InitConfigForDurable_Pool2(locators, redundancyLevel,
          durableClientId, durableTimeout, TimeSpan.FromSeconds(35), "__TESTPOOL1_");
      CacheHelper.CreateTCRegion_Pool(RegionNames[0], false, true, checker,
          CacheHelper.Locators, "__TESTPOOL1_", true);

      CacheHelper.InitConfigForDurable_Pool2(locators, redundancyLevel,
          durableClientId, durableTimeout, TimeSpan.FromSeconds(35), "__TESTPOOL2_");
      CacheHelper.CreateTCRegion_Pool(RegionNames[1], false, true, checker,
          CacheHelper.Locators, "__TESTPOOL2_", true);

      IRegion<object, object> region0 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[1]);

      try
      {
        region0.GetSubscriptionService().RegisterAllKeys(true);
        region1.GetSubscriptionService().RegisterAllKeys(true);
      }
      catch (Exception other)
      {
        Assert.Fail("RegisterAllKeys threw unexpected exception: {0}", other.Message);
      }

      Pool pool0 = CacheHelper.DCache.GetPoolManager().Find(region0.Attributes.PoolName);
      int pendingEventCount0 = pool0.PendingEventCount;
      Util.Log("pendingEventCount0 for pool = {0} {1} ", pendingEventCount0, region0.Attributes.PoolName);
      string msg = string.Format("Expected Value ={0}, Actual = {1}", expectedQ0, pendingEventCount0);
      Assert.AreEqual(expectedQ0, pendingEventCount0, msg);

      Pool pool1 = CacheHelper.DCache.GetPoolManager().Find(region1.Attributes.PoolName);
      int pendingEventCount1 = pool1.PendingEventCount;
      Util.Log("pendingEventCount1 for pool = {0} {1} ", pendingEventCount1, region1.Attributes.PoolName);
      string msg1 = string.Format("Expected Value ={0}, Actual = {1}", expectedQ1, pendingEventCount1);
      Assert.AreEqual(expectedQ1, pendingEventCount1, msg1);

      CacheHelper.DCache.ReadyForEvents();
      Thread.Sleep(10000);

      CacheHelper.DCache.Close(true);
    }

    public void ClearChecker(int client)
    {
      if (client == 1)
      {
        ThinClientDurableTests.m_checker1 = null;
      }
      else // client == 2
      {
        ThinClientDurableTests.m_checker2 = null;
      }
    }

    public void InitDurableClient(int client, string locators, int redundancyLevel,
      string durableClientId, TimeSpan durableTimeout)
    {
      // Create DurableListener for first time and use same afterward.
      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        if (ThinClientDurableTests.m_checker1 == null)
        {
          ThinClientDurableTests.m_checker1 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2 
      {
        if (ThinClientDurableTests.m_checker2 == null)
        {
          ThinClientDurableTests.m_checker2 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker2;
      }
      CacheHelper.InitConfigForDurable_Pool(locators, redundancyLevel,
        durableClientId, durableTimeout);
      CacheHelper.CreateTCRegion_Pool<object, object>(RegionNames[0], false, true, checker,
        CacheHelper.Locators, "__TESTPOOL1_", true);

      CacheHelper.DCache.ReadyForEvents();
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);
      region1.GetSubscriptionService().RegisterRegex(m_regexes[0], true);
      region1.GetSubscriptionService().RegisterRegex(m_regexes[1], false);
      //CacheableKey[] ldkeys = { new CacheableString(m_mixKeys[3]) };
      ICollection<object> lkeys = new List<object>();
      lkeys.Add((object)m_mixKeys[3]);
      region1.GetSubscriptionService().RegisterKeys(lkeys, true, false);

      ICollection<object> ldkeys = new List<object>(); ;
      ldkeys.Add((object)m_mixKeys[2]);
      region1.GetSubscriptionService().RegisterKeys(ldkeys, false, false);
    }

    public void InitClientXml(string cacheXml)
    {
      CacheHelper.InitConfig(cacheXml);
    }

    public void ReadyForEvents()
    {
      CacheHelper.DCache.ReadyForEvents();
    }

    public void PendingEventCount(IRegion<object, object> region, int expectedPendingQSize, bool exception)
    {
      Util.Log("PendingEventCount regionName = {0} ", region);
      string poolName = region.Attributes.PoolName;
      if (poolName != null)
      {
        Util.Log("PendingEventCount poolName = {0} ", poolName);
        Pool pool = CacheHelper.DCache.GetPoolManager().Find(poolName);
        if (exception)
        {
          try
          {
            int pendingEventCount = pool.PendingEventCount;
            Util.Log("PendingEventCount Should have got exception ");
            Assert.Fail("PendingEventCount Should have got exception");
          }
          catch (IllegalStateException ex)
          {
            Util.Log("Got expected exception for PendingEventCount {0} ", ex.Message);
          }
        }
        else
        {
          int pendingEventCount = pool.PendingEventCount;
          Util.Log("pendingEventCount = {0} ", pendingEventCount);
          string msg = string.Format("Expected Value ={0}, Actual = {1}", expectedPendingQSize, pendingEventCount);
          Assert.AreEqual(expectedPendingQSize, pendingEventCount, msg);
        }
      }
    }

    public void FeederUpdate(int value, int sleep)
    {
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);

      region1[m_mixKeys[0]] = value;
      Thread.Sleep(sleep);
      region1[m_mixKeys[1]] = value;
      Thread.Sleep(sleep);
      region1[m_mixKeys[2]] = value;
      Thread.Sleep(sleep);
      region1[m_mixKeys[3]] = value;
      Thread.Sleep(sleep);

      region1.Remove(m_mixKeys[0]);
      Thread.Sleep(sleep);
      region1.Remove(m_mixKeys[1]);
      Thread.Sleep(sleep);
      region1.Remove(m_mixKeys[2]);
      Thread.Sleep(sleep);
      region1.Remove(m_mixKeys[3]);
      Thread.Sleep(sleep);
    }

    public void FeederUpdate2(int pool1, int pool2)
    {
      IRegion<object, object> region0 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[1]);

      for (int i = 0; i < pool1; i++)
      {
        region0[i] = i;
      }

      for (int i = 0; i < pool2; i++)
      {
        region1[i] = i;
      }
    }

    public void ClientDown(bool keepalive)
    {
      if (keepalive)
      {
        CacheHelper.CloseKeepAlive();
      }
      else
      {
        CacheHelper.Close();
      }
    }

    public void CrashClient()
    {
      // TODO:  crash client here.
    }

    public void KillServer()
    {
      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");
    }

    public delegate void KillServerDelegate();

    #endregion


    public void VerifyTotal(int client, int keys, int total)
    {
      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2
      {
        checker = ThinClientDurableTests.m_checker2;
      }

      if (checker != null)
      {
        checker.validate(keys, total);
      }
      else
      {
        Assert.Fail("Checker is NULL!");
      }
    }

    public void VerifyBasic(int client, int keyCount, int eventCount, int durableValue, int nonDurableValue)
    {//1 4 8 1 1 
      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2
      {
        checker = ThinClientDurableTests.m_checker2;
      }

      if (checker != null)
      {
        try
        {
          checker.validateBasic(keyCount, eventCount, durableValue, nonDurableValue);//4 8 1 1 
        }
        catch (AssertionException e)
        {
          Util.Log("VERIFICATION FAILED for client {0}: {1} ", client, e);
          throw e;
        }
      }
      else
      {
        Assert.Fail("Checker is NULL!");
      }
    }

    #region Basic Durable Test


    void runDurableAndNonDurableBasic()
    {
      CacheHelper.SetupJavaServers(true,
        "cacheserver_notify_subscription.xml", "cacheserver_notify_subscription2.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");

      for (int redundancy = 0; redundancy <= 1; redundancy++)
      {
        for (int closeType = 1; closeType <= 2; closeType++)
        {
          for (int downtime = 0; downtime <= 1; downtime++) // downtime updates
          {
            Util.Log("Starting loop with closeType = {0}, redundancy = {1}, downtime = {2} ", closeType, redundancy, downtime);

            CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
            Util.Log("Cacheserver 1 started.");

            if (redundancy == 1)
            {
              CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1);
              Util.Log("Cacheserver 2 started.");
            }

            m_feeder.Call(InitFeeder, CacheHelper.Locators, 0);
            Util.Log("Feeder initialized.");

            m_client1.Call(ClearChecker, 1);
            m_client2.Call(ClearChecker, 2);

            m_client1.Call(InitDurableClient, 1, CacheHelper.Locators, redundancy, DurableClientId1, TimeSpan.FromSeconds(300));
            m_client2.Call(InitDurableClient, 2, CacheHelper.Locators, redundancy, DurableClientId2, TimeSpan.FromSeconds(3));

            Util.Log("Clients initialized.");

            m_feeder.Call(FeederUpdate, 1, 10);

            Util.Log("Feeder performed first update.");
            Thread.Sleep(45000); // wait for HA Q to drain and notify ack to go out.

            switch (closeType)
            {
              case 1:

                m_client1.Call(ClientDown, true);
                m_client2.Call(ClientDown, true);

                Util.Log("Clients downed with keepalive true.");
                break;
              case 2:

                m_client1.Call(ClientDown, false);
                m_client2.Call(ClientDown, false);

                Util.Log("Clients downed with keepalive false.");
                break;
              case 3:

                m_client1.Call(CrashClient);

                m_client2.Call(CrashClient);

                Util.Log("Clients downed as crash.");
                break;
              default:
                break;
            }

            if (downtime == 1)
            {
              m_feeder.Call(FeederUpdate, 2, 10);

              Util.Log("Feeder performed update during downtime.");
              Thread.Sleep(20000); // wait for HA Q to drain and notify ack to go out.
            }

            m_client1.Call(InitDurableClient, 1, CacheHelper.Locators, redundancy, DurableClientId1, TimeSpan.FromSeconds(300));

            // Sleep for 45 seconds since durable timeout is 30 seconds so that client2 times out
            Thread.Sleep(45000);

            m_client2.Call(InitDurableClient, 2, CacheHelper.Locators, redundancy, DurableClientId2, TimeSpan.FromSeconds(30));

            Util.Log("Clients brought back up.");

            if (closeType != 2 && downtime == 1)
            {
              m_client1.Call(VerifyBasic, 1, 4, 12, 2, 1);

              m_client2.Call(VerifyBasic, 2, 4, 8, 1, 1);

            }
            else
            {

              m_client1.Call(VerifyBasic, 1, 4, 8, 1, 1);

              m_client2.Call(VerifyBasic, 2, 4, 8, 1, 1);

            }

            Util.Log("Verification completed.");

            m_feeder.Call(ClientDown, false);

            m_client1.Call(ClientDown, false);

            m_client2.Call(ClientDown, false);

            Util.Log("Feeder and Clients closed.");

            CacheHelper.StopJavaServer(1);
            Util.Log("Cacheserver 1 stopped.");

            if (redundancy == 1)
            {
              CacheHelper.StopJavaServer(2);
              Util.Log("Cacheserver 2 stopped.");
            }

            Util.Log("Completed loop with closeType = {0}, redundancy = {1}, downtime = {2} ", closeType, redundancy, downtime);

          } // end for int downtime
        } // end for int closeType
      } // end for int redundancy
      CacheHelper.StopJavaLocator(1);
    }

    // Basic Durable Test to check durable event recieving for different combination
    // of Close type ( Keep Alive = true / false ) , Intermediate update and rudundancy

    [Test]
    public void DurableAndNonDurableBasic()
    {
      runDurableAndNonDurableBasic();
    } // end [Test] DurableAndNonDurableBasic

    #endregion

    #region Durable Intrest Test

    public void InitDurableClientRemoveInterest(int client, string locators,
      int redundancyLevel, string durableClientId, TimeSpan durableTimeout)
    {
      // Client Registered Durable Intrest on two keys. We need to unregister them all here.

      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        if (ThinClientDurableTests.m_checker1 == null)
        {
          ThinClientDurableTests.m_checker1 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2
      {
        if (ThinClientDurableTests.m_checker2 == null)
        {
          ThinClientDurableTests.m_checker2 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker2;
      }
      CacheHelper.InitConfigForDurable_Pool(locators, redundancyLevel,
        durableClientId, durableTimeout);
      CacheHelper.CreateTCRegion_Pool(RegionNames[0], false, true, checker,
        CacheHelper.Locators, "__TESTPOOL1_", true);

      CacheHelper.DCache.ReadyForEvents();
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);

      // Unregister Regex only durable
      region1.GetSubscriptionService().RegisterRegex(m_regexes[0], true);
      region1.GetSubscriptionService().UnregisterRegex(m_regexes[0]);

      // Unregister list only durable
      string[] ldkeys = new string[] { m_mixKeys[3] };
      region1.GetSubscriptionService().RegisterKeys(ldkeys, true, false);
      region1.GetSubscriptionService().UnregisterKeys(ldkeys);
    }

    public void InitDurableClientNoInterest(int client, string locators,
      int redundancyLevel, string durableClientId, TimeSpan durableTimeout)
    {
      // we use "client" to either create a DurableListener or use the existing ones
      // if the clients are initialized for the second time
      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        if (ThinClientDurableTests.m_checker1 == null)
        {
          ThinClientDurableTests.m_checker1 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2
      {
        if (ThinClientDurableTests.m_checker2 == null)
        {
          ThinClientDurableTests.m_checker2 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker2;
      }
      CacheHelper.InitConfigForDurable_Pool(locators, redundancyLevel,
        durableClientId, durableTimeout);
      CacheHelper.CreateTCRegion_Pool(RegionNames[0], false, true, checker,
        CacheHelper.Locators, "__TESTPOOL1_", true);
      CacheHelper.DCache.ReadyForEvents();
    }

    void runDurableInterest()
    {
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      m_feeder.Call(InitFeeder, CacheHelper.Locators, 0);
      Util.Log("Feeder started.");

      m_client1.Call(ClearChecker, 1);
      m_client2.Call(ClearChecker, 2);
      m_client1.Call(InitDurableClient, 1, CacheHelper.Locators,
        0, DurableClientId1, TimeSpan.FromSeconds(60));
      m_client2.Call(InitDurableClient, 2, CacheHelper.Locators,
        0, DurableClientId2, TimeSpan.FromSeconds(60));
      Util.Log("Clients started.");

      m_feeder.Call(FeederUpdate, 1, 10);
      Util.Log("Feeder performed first update.");

      Thread.Sleep(15000);

      m_client1.Call(ClientDown, true);
      m_client2.Call(ClientDown, true);
      Util.Log("Clients downed with keepalive true.");

      m_client1.Call(InitDurableClientNoInterest, 1, CacheHelper.Locators,
        0, DurableClientId1, TimeSpan.FromSeconds(60));
      Util.Log("Client 1 started with no interest.");

      m_client2.Call(InitDurableClientRemoveInterest, 2, CacheHelper.Locators,
        0, DurableClientId2, TimeSpan.FromSeconds(60));
      Util.Log("Client 2 started with remove interest.");

      m_feeder.Call(FeederUpdate, 2, 10);
      Util.Log("Feeder performed second update.");

      Thread.Sleep(10000);

      // only durable Intrest will remain.
      m_client1.Call(VerifyBasic, 1, 4, 12, 2, 1);

      // no second update should be recieved.
      m_client2.Call(VerifyBasic, 2, 4, 8, 1, 1);
      Util.Log("Verification completed.");

      m_feeder.Call(ClientDown, false);
      m_client1.Call(ClientDown, false);
      m_client2.Call(ClientDown, false);
      Util.Log("Feeder and Clients closed.");

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearEndpoints();
      CacheHelper.ClearLocators();
    }

    //This is to test whether durable registered intrests remains on reconnect. and 
    // Unregister works on reconnect.

    [Test]
    public void DurableInterest()
    {
      runDurableInterest();
    } // end [Test] DurableInterest
    #endregion

    #region Durable Failover Test


    public void InitDurableClientForFailover(int client, string locators,
      int redundancyLevel, string durableClientId, TimeSpan durableTimeout)
    {
      // we use "client" to either create a DurableListener or use the existing ones
      // if the clients are initialized for the second time
      DurableListener<object, object> checker = null;
      if (client == 1)
      {
        if (ThinClientDurableTests.m_checker1 == null)
        {
          ThinClientDurableTests.m_checker1 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker1;
      }
      else // client == 2
      {
        if (ThinClientDurableTests.m_checker2 == null)
        {
          ThinClientDurableTests.m_checker2 = DurableListener<object, object>.Create();
        }
        checker = ThinClientDurableTests.m_checker2;
      }
      CacheHelper.InitConfigForDurable_Pool(locators, redundancyLevel,
        durableClientId, durableTimeout, TimeSpan.FromSeconds(35));
      CacheHelper.CreateTCRegion_Pool(RegionNames[0], false, true, checker,
        CacheHelper.Locators, "__TESTPOOL1_", true);
      CacheHelper.DCache.ReadyForEvents();
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(RegionNames[0]);

      try
      {
        region1.GetSubscriptionService().RegisterRegex(m_regexes[0], true);
        region1.GetSubscriptionService().RegisterRegex(m_regexes[1], false);
      }
      catch (Exception other)
      {
        Assert.Fail("RegisterKeys threw unexpected exception: {0}", other.Message);
      }
    }

    public void FeederUpdateForFailover(string region, int value, int sleep)
    {
      //update only 2 keys.
      IRegion<object, object> region1 = CacheHelper.GetVerifyRegion<object, object>(region);

      region1[m_mixKeys[0]] = value;
      Thread.Sleep(sleep);
      region1[m_mixKeys[1]] = value;
      Thread.Sleep(sleep);

    }

    void runDurableFailover()
    {
      CacheHelper.SetupJavaServers(true,
        "cacheserver_notify_subscription.xml", "cacheserver_notify_subscription2.xml");

      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");

      for (int clientDown = 0; clientDown <= 1; clientDown++)
      {
        for (int redundancy = 0; redundancy <= 1; redundancy++)
        {
          Util.Log("Starting loop with clientDown = {0}, redundancy = {1}", clientDown, redundancy);

          CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
          Util.Log("Cacheserver 1 started.");

          m_feeder.Call(InitFeeder, CacheHelper.Locators, 0);
          Util.Log("Feeder started with redundancy level as 0.");

          m_client1.Call(ClearChecker, 1);
          m_client1.Call(InitDurableClientForFailover, 1, CacheHelper.Locators,
            redundancy, DurableClientId1, TimeSpan.FromSeconds(300));
          Util.Log("Client started with redundancy level as {0}.", redundancy);

          m_feeder.Call(FeederUpdateForFailover, RegionNames[0], 1, 10);
          Util.Log("Feeder updates 1 completed.");

          CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1);
          Util.Log("Cacheserver 2 started.");

          //Time for redundancy thread to detect.
          Thread.Sleep(35000);

          if (clientDown == 1)
          {
            m_client1.Call(ClientDown, true);
          }

          CacheHelper.StopJavaServer(1);
          Util.Log("Cacheserver 1 stopped.");

          //Time for failover
          Thread.Sleep(5000);

          m_feeder.Call(FeederUpdateForFailover, RegionNames[0], 2, 10);
          Util.Log("Feeder updates 2 completed.");

          //Restart Client
          if (clientDown == 1)
          {
            m_client1.Call(InitDurableClientForFailover, 1, CacheHelper.Locators,
              redundancy, DurableClientId1, TimeSpan.FromSeconds(300));
            Util.Log("Client Restarted with redundancy level as {0}.", redundancy);
          }

          //Verify
          if (clientDown == 1)
          {
            if (redundancy == 0) // Events missed
            {
              m_client1.Call(VerifyBasic, 1, 2, 2, 1, 1);
            }
            else // redundancy == 1 Only Durable Events should be recieved.
            {
              m_client1.Call(VerifyBasic, 1, 2, 3, 2, 1);
            }
          }
          else  // In normal failover all events should be recieved.
          {
            m_client1.Call(VerifyBasic, 1, 2, 4, 2, 2);
          }

          Util.Log("Verification completed.");

          m_feeder.Call(ClientDown, false);
          m_client1.Call(ClientDown, false);
          Util.Log("Feeder and Client closed.");

          CacheHelper.StopJavaServer(2);
          Util.Log("Cacheserver 2 stopped.");

          Util.Log("Completed loop with clientDown = {0}, redundancy = {1}", clientDown, redundancy);
        }// for redundancy
      } // for clientDown
      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearEndpoints();
      CacheHelper.ClearLocators();
    }

    void RunDurableClient(int expectedPendingQSize)
    {
      var pp = Properties<string, string>.Create();
      pp.Insert("durable-client-id", "DurableClientId");
      pp.Insert("durable-timeout", "30s");

      var cacheFactory = new CacheFactory(pp);
      var cache = cacheFactory.Create();
      cache.GetPoolFactory().SetSubscriptionEnabled(true);
      cache.GetPoolFactory().SetSubscriptionAckInterval(TimeSpan.FromMilliseconds(5000));
      cache.GetPoolFactory().SetSubscriptionMessageTrackingTimeout(TimeSpan.FromMilliseconds(5000));
      Util.Log("Created the Geode Cache Programmatically");

      RegionFactory regionFactory = cache.CreateRegionFactory(RegionShortcut.CACHING_PROXY);
      IRegion<object, object> region = regionFactory.Create<object, object>("DistRegionAck");
      Util.Log("Created the DistRegionAck Region Programmatically");

      QueryService qService = cache.GetQueryService();
      CqAttributesFactory<object, object> cqFac = new CqAttributesFactory<object, object>();

      ICqListener<object, object> cqLstner = new MyCqListener1<object, object>();
      cqFac.AddCqListener(cqLstner);
      CqAttributes<object, object> cqAttr = cqFac.Create();
      Util.Log("Attached CqListener");
      String query = "select * from /DistRegionAck";
      CqQuery<object, object> qry = qService.NewCq("MyCq", query, cqAttr, true);
      Util.Log("Created new CqQuery");

      qry.Execute();
      Util.Log("Executed new CqQuery");
      Thread.Sleep(10000);

      PendingEventCount(region, expectedPendingQSize, false);

      //Send ready for Event message to Server( only for Durable Clients ).
      //Server will send queued events to client after recieving this.
      cache.ReadyForEvents();

      Util.Log("Sent ReadyForEvents message to server");
      Thread.Sleep(10000);
      // Close the Geode Cache with keepalive = true.  Server will queue events for
      // durable registered keys and will deliver all events when client will reconnect
      // within timeout period and send "readyForEvents()"

      PendingEventCount(region, 0, true);

      cache.Close(true);

      Util.Log("Closed the Geode Cache with keepalive as true");
    }

    void runDurableClientWithTwoPools()
    {
      CacheHelper.SetupJavaServers(true, "cacheserver_notify_subscription.xml");
      CacheHelper.StartJavaLocator(1, "GFELOC");
      Util.Log("Locator started");
      CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1);
      Util.Log("Cacheserver 1 started.");

      m_feeder.Call(InitFeeder2, CacheHelper.Locators, 0);
      Util.Log("Feeder started.");

      m_client1.Call(InitDurableClientWithTwoPools, CacheHelper.Locators, 0, DurableClientId1, TimeSpan.FromSeconds(30), -2, -2);
      Util.Log("DurableClient with Two Pools Initialized");

      m_feeder.Call(FeederUpdate2, 5, 10);
      Util.Log("Feeder performed first update.");
      Thread.Sleep(15000);

      m_client1.Call(InitDurableClientWithTwoPools, CacheHelper.Locators, 0, DurableClientId1, TimeSpan.FromSeconds(30), 6, 11); //+1 for marker, so 5+1, 10+1 etc
      Util.Log("DurableClient with Two Pools after first update");

      m_feeder.Call(FeederUpdate2, 10, 5);
      Util.Log("Feeder performed second update.");
      Thread.Sleep(15000);

      m_client1.Call(InitDurableClientWithTwoPools, CacheHelper.Locators, 0, DurableClientId1, TimeSpan.FromSeconds(30), 16, 16);
      Util.Log("DurableClient with Two Pools after second update");

      Thread.Sleep(45000); //45 > 30 secs.
      m_client1.Call(InitDurableClientWithTwoPools, CacheHelper.Locators, 0, DurableClientId1, TimeSpan.FromSeconds(30), -1, -1);
      Util.Log("DurableClient with Two Pools after timeout");

      m_feeder.Call(ClientDown, false);
      Util.Log("Feeder and Clients closed.");

      CacheHelper.StopJavaServer(1);
      Util.Log("Cacheserver 1 stopped.");

      CacheHelper.StopJavaLocator(1);
      Util.Log("Locator stopped");

      CacheHelper.ClearEndpoints();
      CacheHelper.ClearLocators();
    }

    void RunFeeder()
    {
      var cacheFactory = new CacheFactory();
      Util.Log("Feeder connected to the Geode Distributed System");

      Cache cache = cacheFactory.Create();
      Util.Log("Created the Geode Cache");

      RegionFactory regionFactory = cache.CreateRegionFactory(RegionShortcut.PROXY);
      Util.Log("Created the RegionFactory");

      // Create the Region Programmatically.
      IRegion<object, object> region = regionFactory.Create<object, object>("DistRegionAck");
      Util.Log("Created the Region Programmatically.");

      PendingEventCount(region, 0, true);

      for (int i = 0; i < 10; i++)
      {
        region[i] = i;
      }
      Thread.Sleep(10000);
      Util.Log("put on 0-10 keys done.");

      // Close the Geode Cache
      cache.Close();
      Util.Log("Closed the Geode Cache");
    }

    void RunFeeder1()
    {
      CacheFactory cacheFactory = new CacheFactory();
      Util.Log("Feeder connected to the Geode Distributed System");

      Cache cache = cacheFactory.Create();
      Util.Log("Created the Geode Cache");

      RegionFactory regionFactory = cache.CreateRegionFactory(RegionShortcut.PROXY);
      Util.Log("Created the RegionFactory");

      // Create the Region Programmatically.
      IRegion<object, object> region = regionFactory.Create<object, object>("DistRegionAck");
      Util.Log("Created the Region Programmatically.");

      PendingEventCount(region, 0, true);

      for (int i = 10; i < 20; i++)
      {
        region[i] = i;
      }
      Thread.Sleep(10000);
      Util.Log("put on 10-20 keys done.");

      // Close the Geode Cache
      cache.Close();
      Util.Log("Closed the Geode Cache");
    }

    void VerifyEvents()
    {
      Util.Log("MyCqListener1.m_cntEvents = {0} ", MyCqListener1<object, object>.m_cntEvents);
      Assert.AreEqual(MyCqListener1<object, object>.m_cntEvents, 20, "Incorrect events, expected 20");
    }

    void runCQDurable()
    {
      CacheHelper.SetupJavaServers(false, "serverDurableClient.xml");
      CacheHelper.StartJavaServer(1, "GFECS1");
      m_client1.Call(RunDurableClient, -2); // 1st time no Q, hence check -2 as PendingEventCount.
      m_client2.Call(RunFeeder);
      m_client1.Call(RunDurableClient, 10);
      m_client2.Call(RunFeeder1);
      m_client1.Call(RunDurableClient, 10);
      m_client1.Call(VerifyEvents);
      Thread.Sleep(45 * 1000); // sleep 45 secs > 30 secs, check -1 as PendingEventCount.
      m_client1.Call(RunDurableClient, -1);
      CacheHelper.StopJavaServer(1);
    }

    [Test]
    public void DurableFailover()
    {
      runDurableFailover();
    } // end [Test] DurableFailover

    [Test]
    public void CQDurable()
    {
      runCQDurable();

      runDurableClientWithTwoPools();
    }
    #endregion
  }
}
