public void MergeRangeMappingAbortSourceLocalDoAndGSMPostLocalUndo()
        {
            bool shouldThrow = true;

            IStoreOperationFactory sof = new StubStoreOperationFactory()
            {
                CallBase = true,
                CreateReplaceMappingsOperationShardMapManagerStoreOperationCodeIStoreShardMapTupleOfIStoreMappingGuidArrayTupleOfIStoreMappingGuidArray =
                (_smm, _opcode, _ssm, _smo, _smn) =>
                {
                    StubReplaceMappingsOperation op = new StubReplaceMappingsOperation(_smm, _opcode, _ssm, _smo, _smn);
                    op.CallBase = true;
                    op.DoLocalSourceExecuteIStoreTransactionScope = (ts) =>
                    {
                        if (shouldThrow)
                        {
                            throw new StoreException("", ShardMapFaultHandlingTests.TransientSqlException);
                        }
                        else
                        {
                            // Call the base function, hack for this behavior is to save current operation, set current to null, restore current operation.
                            var original = op.DoLocalSourceExecuteIStoreTransactionScope;

                            op.DoLocalSourceExecuteIStoreTransactionScope = null;
                            try
                            {
                                return op.DoLocalSourceExecute(ts);
                            }
                            finally
                            {
                                op.DoLocalSourceExecuteIStoreTransactionScope = original;
                            }
                        }
                    };

                    op.UndoGlobalPostLocalExecuteIStoreTransactionScope = (ts) =>
                    {
                        if (shouldThrow)
                        {
                            throw new StoreException("", ShardMapFaultHandlingTests.TransientSqlException);
                        }
                        else
                        {
                            // Call the base function, hack for this behavior is to save current operation, set current to null, restore current operation.
                            var original = op.UndoGlobalPostLocalExecuteIStoreTransactionScope;

                            op.UndoGlobalPostLocalExecuteIStoreTransactionScope = null;
                            try
                            {
                                return op.UndoGlobalPostLocalExecute(ts);
                            }
                            finally
                            {
                                op.UndoGlobalPostLocalExecuteIStoreTransactionScope = original;
                            }
                        }
                    };

                    return op;
                }
            };

            ShardMapManager smm = new ShardMapManager(
                new SqlShardMapManagerCredentials(Globals.ShardMapManagerConnectionString),
                new SqlStoreConnectionFactory(),
                sof,
                new CacheStore(),
                ShardMapManagerLoadPolicy.Lazy,
                new RetryPolicy(1, TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero), RetryBehavior.DefaultRetryBehavior);

            RangeShardMap<int> rsm = smm.GetRangeShardMap<int>(ShardMapperTests.s_rangeShardMapName);

            Assert.IsNotNull(rsm);

            ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ShardMapperTests.s_shardedDBs[0]);

            Shard s = rsm.CreateShard(sl);

            Assert.IsNotNull(s);

            RangeMapping<int> r1 = rsm.CreateRangeMapping(new Range<int>(1, 20), s);
            RangeMapping<int> r2 = rsm.CreateRangeMapping(new Range<int>(20, 40), s);

            bool storeOperationFailed = false;
            try
            {
                RangeMapping<int> rMerged = rsm.MergeMappings(r1, r2);
            }
            catch (ShardManagementException sme)
            {
                Assert.AreEqual(ShardManagementErrorCategory.RangeShardMap, sme.ErrorCategory);
                Assert.AreEqual(ShardManagementErrorCode.StorageOperationFailure, sme.ErrorCode);
                storeOperationFailed = true;
            }

            Assert.IsTrue(storeOperationFailed);

            // Obtain the pending operations.
            var pendingOperations = ShardMapperTests.GetPendingStoreOperations();
            Assert.AreEqual(pendingOperations.Count(), 1);

            // Validation: Mapping range is not updated - lookup for point 10 returns mapping with version 0.
            RangeMapping<int> rValidateLeft = rsm.GetMappingForKey(5);
            RangeMapping<int> rValidateRight = rsm.GetMappingForKey(25);
            Assert.AreEqual(r1.Range, rValidateLeft.Range);
            Assert.AreEqual(r2.Range, rValidateRight.Range);

            #region OpenConnection with Validation

            // Validation should succeed since source mapping was never deleted.
            bool validationFailed = false;
            try
            {
                using (SqlConnection conn = rsm.OpenConnection(
                    rValidateLeft,
                    Globals.ShardUserConnectionString,
                    ConnectionOptions.Validate))
                {
                }

                using (SqlConnection conn = rsm.OpenConnection(
                    rValidateRight,
                    Globals.ShardUserConnectionString,
                    ConnectionOptions.Validate))
                {
                }
            }
            catch (ShardManagementException)
            {
                validationFailed = true;
            }

            Assert.AreEqual(false, validationFailed);

            #endregion OpenConnection with Validation

            shouldThrow = false;

            // Split the range mapping on the left.
            storeOperationFailed = false;

            try
            {
                rsm.SplitMapping(r1, 10);
            }
            catch (ShardManagementException)
            {
                storeOperationFailed = true;
            }

            Assert.IsFalse(storeOperationFailed);
        }
        public void MergeRangeMappingsAbortLSM()
        {
            IStoreOperationFactory sof = new StubStoreOperationFactory()
            {
                CallBase = true,
                CreateReplaceMappingsOperationShardMapManagerStoreOperationCodeIStoreShardMapTupleOfIStoreMappingGuidArrayTupleOfIStoreMappingGuidArray =
                (_smm, _opcode, _ssm, _smo, _smn) =>
                {
                    StubReplaceMappingsOperation op = new StubReplaceMappingsOperation(_smm, _opcode, _ssm, _smo, _smn);
                    op.CallBase = true;
                    op.DoLocalSourceExecuteIStoreTransactionScope = (ts) =>
                    {
                        throw new StoreException("", ShardMapFaultHandlingTests.TransientSqlException);
                    };

                    return op;
                }
            };

            ShardMapManager smm = new ShardMapManager(
                new SqlShardMapManagerCredentials(Globals.ShardMapManagerConnectionString),
                new SqlStoreConnectionFactory(),
                sof,
                new CacheStore(),
                ShardMapManagerLoadPolicy.Lazy,
                new RetryPolicy(1, TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero), RetryBehavior.DefaultRetryBehavior);

            RangeShardMap<int> rsm = smm.GetRangeShardMap<int>(ShardMapperTests.s_rangeShardMapName);

            Assert.IsNotNull(rsm);

            Shard s1 = rsm.CreateShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ShardMapperTests.s_shardedDBs[0]));
            Assert.IsNotNull(s1);

            RangeMapping<int> r1 = rsm.CreateRangeMapping(new Range<int>(1, 10), s1);

            RangeMapping<int> r2 = rsm.CreateRangeMapping(new Range<int>(10, 20), s1);

            bool storeOperationFailed = false;
            try
            {
                RangeMapping<int> rMerged = rsm.MergeMappings(r1, r2);
                Assert.IsNotNull(rMerged);
            }
            catch (ShardManagementException sme)
            {
                Assert.AreEqual(ShardManagementErrorCategory.RangeShardMap, sme.ErrorCategory);
                Assert.AreEqual(ShardManagementErrorCode.StorageOperationFailure, sme.ErrorCode);
                storeOperationFailed = true;
            }

            Assert.IsTrue(storeOperationFailed);

            // Validation: get all mappings for [1,20) should return 2 mappings.
            Assert.AreEqual(2, rsm.GetMappings().Count());
        }