Exemplo n.º 1
0
        public void Execute(DocumentDatabase database)
        {
            var resourceManagerIds = new HashSet <Guid>();
            var recovery           = new List <Action>();

            database.TransactionalStorage.Batch(accessor =>
            {
                foreach (var item in accessor.Lists.Read("Raven/Transactions/Pending", Etag.Empty, null, int.MaxValue))
                {
                    var transactionId = item.Key;
                    try
                    {
                        var ravenJToken         = item.Data["Changes"];
                        var changes             = ravenJToken.JsonDeserialization <List <DocumentInTransactionData> >();
                        var resourceManagerId   = item.Data.Value <string>("ResourceManagerId");
                        var recoveryInformation = item.Data.Value <byte[]>("RecoveryInformation");

                        if (database.InFlightTransactionalState.RecoverTransaction(transactionId, changes) == false)
                        {
                            continue;
                        }

                        Guid resourceId;
                        if (Guid.TryParse(resourceManagerId, out resourceId) == false ||
                            recoveryInformation == null)
                        {
                            try
                            {
                                database.InFlightTransactionalState.Prepare(transactionId, null, null);
                            }
                            catch (Exception e)
                            {
                                logger.WarnException(
                                    "Failed to prepare transaction " + transactionId +
                                    " on database restart, transaction was aborted", e);
                            }
                            continue;
                        }
                        try
                        {
                            database.InFlightTransactionalState.Prepare(transactionId, resourceId, recoveryInformation);
                        }
                        catch (Exception e)
                        {
                            logger.WarnException(
                                "Failed to prepare transaction " + transactionId +
                                " on database restart, transaction was aborted", e);
                            continue;
                        }
                        resourceManagerIds.Add(resourceId);
                        recovery.Add(() =>
                        {
                            try
                            {
                                var enlistmentNotification = new RecoveryEnlistment(database, transactionId);
                                TransactionManager.Reenlist(resourceId, recoveryInformation, enlistmentNotification);
                            }
                            catch (Exception e)
                            {
                                logger.WarnException("Could not apply recovered transaction " + transactionId + ", aborting transaction", e);
                            }
                        });
                    }
                    catch (Exception e)
                    {
                        logger.WarnException("Could not apply recovered transaction " + transactionId + ", aborting transaction", e);
                    }
                }

                accessor.Lists.RemoveAllBefore("Raven/Transactions/Pending", Etag.InvalidEtag);
            });

            foreach (var recoverTx in recovery)
            {
                recoverTx();
            }

            foreach (var resourceManagerId in resourceManagerIds)
            {
                try
                {
                    TransactionManager.RecoveryComplete(resourceManagerId);
                }
                catch (Exception e)
                {
                    logger.WarnException(
                        "Could not notify transaction manager that the recovery was completed for " + resourceManagerId,
                        e);
                }
            }
        }
        public void Execute(DocumentDatabase database)
        {

            var resourceManagerIds = new HashSet<Guid>();
            var recovery = new List<Action>();
            database.TransactionalStorage.Batch(accessor =>
            {
                foreach (var item in accessor.Lists.Read("Raven/Transactions/Pending", Etag.Empty, null, int.MaxValue))
                {
                    var transactionId = item.Key;
                    try
                    {
                        var ravenJToken = item.Data["Changes"];
                        var changes = ravenJToken.JsonDeserialization<List<DocumentInTransactionData>>();
                        var resourceManagerId = item.Data.Value<string>("ResourceManagerId");
                        var recoveryInformation = item.Data.Value<byte[]>("RecoveryInformation");

                        if(database.InFlightTransactionalState.RecoverTransaction(transactionId, changes) == false)
                            continue;
                   
                        Guid resourceId;
                        if (Guid.TryParse(resourceManagerId, out resourceId) == false || 
                            recoveryInformation == null)
                        {
                            try
                            {
                                database.InFlightTransactionalState.Prepare(transactionId, null, null);
                            }
                            catch (Exception e)
                            {
                                logger.WarnException(
                                    "Failed to prepare transaction " + transactionId +
                                    " on database restart, transaction was aborted", e);
                            }
                            continue;
                        }
                        try
                        {
                            database.InFlightTransactionalState.Prepare(transactionId, resourceId, recoveryInformation);
                        }
                        catch (Exception e)
                        {
                            logger.WarnException(
                                "Failed to prepare transaction " + transactionId +
                                " on database restart, transaction was aborted", e);
                            continue;
                        }
                        resourceManagerIds.Add(resourceId);
                        recovery.Add(() =>
                        {
                            try
                            {
                                var enlistmentNotification = new RecoveryEnlistment(database, transactionId);
                                TransactionManager.Reenlist(resourceId, recoveryInformation, enlistmentNotification);
                            }
                            catch (Exception e)
                            {
                                logger.WarnException("Could not apply recovered transaction " + transactionId + ", aborting transaction", e);
                            }
                        });
                    }
                    catch (Exception e)
                    {
                        logger.WarnException("Could not apply recovered transaction " + transactionId +", aborting transaction", e);
                    }
                }

                accessor.Lists.RemoveAllBefore("Raven/Transactions/Pending", Etag.InvalidEtag);
            });

            foreach (var recoverTx in recovery)
            {
                recoverTx();
            }

            foreach (var resourceManagerId in resourceManagerIds)
            {
                try
                {
                    TransactionManager.RecoveryComplete(resourceManagerId);
                }
                catch (Exception e)
                {
                    logger.WarnException(
                        "Could not notify transaction manager that the recovery was completed for " + resourceManagerId,
                        e);
                }
            }
        }