activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject svn commit: r1537094 - in /activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src: main/csharp/Transactions/RecoveryFileLogger.cs test/csharp/Transactions/RecoveryFileLoggerTest.cs
Date Wed, 30 Oct 2013 14:05:56 GMT
Author: tabish
Date: Wed Oct 30 14:05:56 2013
New Revision: 1537094

URL: http://svn.apache.org/r1537094
Log:
https://issues.apache.org/jira/browse/AMQNET-418

Modified:
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs?rev=1537094&r1=1537093&r2=1537094&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
(original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
Wed Oct 30 14:05:56 2013
@@ -30,16 +30,17 @@ namespace Apache.NMS.ActiveMQ.Transactio
 {
     public class RecoveryFileLogger : IRecoveryLogger
     {
+        private readonly object syncRoot = new object();
+
         private string location;
         private bool autoCreateLocation;
         private string resourceManagerId;
-        private readonly object syncRoot = new object();
 
         public RecoveryFileLogger()
         {
             // Set the path by default to the location of the executing assembly.
             // May need to change this to current working directory, not sure.
-            this.location = "";
+            this.location = string.Empty;
         }
 
         /// <summary>
@@ -59,14 +60,18 @@ namespace Apache.NMS.ActiveMQ.Transactio
         {
             get
             {
-                if(String.IsNullOrEmpty(this.location))
+                if(string.IsNullOrEmpty(this.location))
                 {
                     return Directory.GetCurrentDirectory();
                 }
 
                 return this.location;
             }
-            set { this.location = Uri.UnescapeDataString(value); }
+
+            set
+            {
+                this.location = Uri.UnescapeDataString(value);
+            }
         }
 
         /// <summary>
@@ -114,17 +119,17 @@ namespace Apache.NMS.ActiveMQ.Transactio
 
             try
             {
-                lock (syncRoot)
-                {
-                    RecoveryInformation info = new RecoveryInformation(xid, recoveryInformation);
-                    Tracer.Debug("Serializing Recovery Info to file: " + Filename);
+                string filename = this.CreateFilename(xid);
 
-                    IFormatter formatter = new BinaryFormatter();
-                    using (FileStream recoveryLog = new FileStream(Filename, FileMode.OpenOrCreate,
FileAccess.Write))
-                    {
-                        formatter.Serialize(recoveryLog, info);
-                    }
+                RecoveryInformation info = new RecoveryInformation(xid, recoveryInformation);
+                Tracer.Debug("Serializing Recovery Info to file: " + filename);
+
+                IFormatter formatter = new BinaryFormatter();
+                using (FileStream recoveryLog = new FileStream(filename, FileMode.OpenOrCreate,
FileAccess.Write))
+                {
+                    formatter.Serialize(recoveryLog, info);
                 }
+
             }
             catch (Exception ex)
             {
@@ -135,52 +140,61 @@ namespace Apache.NMS.ActiveMQ.Transactio
 
         public KeyValuePair<XATransactionId, byte[]>[] GetRecoverables()
         {
-            KeyValuePair<XATransactionId, byte[]>[] result = new KeyValuePair<XATransactionId,
byte[]>[0];
-            RecoveryInformation info = TryOpenRecoveryInfoFile();
+            IList<RecoveryInformation> infos = this.TryOpenRecoveryInfoFile();
+
+            KeyValuePair<XATransactionId, byte[]>[] results = new KeyValuePair<XATransactionId,
byte[]>[infos.Count];
 
-            if (info != null)
+            int index = 0;
+            foreach (RecoveryInformation info in infos)
             {
-                result = new KeyValuePair<XATransactionId, byte[]>[1];
-                result[0] = new KeyValuePair<XATransactionId, byte[]>(info.Xid, info.TxRecoveryInfo);
+                results[index++] = new KeyValuePair<XATransactionId, byte[]>(info.Xid,
info.TxRecoveryInfo);
             }
 
-            return result;
+            return results;
         }
 
         public void LogRecovered(XATransactionId xid)
         {
-            lock (syncRoot)
+            try
             {
-                try
-                {
-                    Tracer.Debug("Attempting to remove stale Recovery Info file: " + Filename);
-                    File.Delete(Filename);
-                }
-                catch(Exception ex)
-                {
-                    Tracer.Debug("Caught Exception while removing stale RecoveryInfo file:
" + ex.Message);
-                    return;
-                }
+                string filename = this.CreateFilename(xid);
+
+                Tracer.Debug("Attempting to remove stale Recovery Info file: " + filename);
+
+                File.Delete(filename);
+            }
+            catch (Exception ex)
+            {
+                Tracer.Debug("Caught Exception while removing stale RecoveryInfo file: "
+ ex.Message);
             }
         }
 
         public void Purge()
         {
-            lock (syncRoot)
+            lock (this.syncRoot)
             {
                 try
                 {
-                    Tracer.Debug("Attempting to remove stale Recovery Info file: " + Filename);
-                    File.Delete(Filename);
+                    IEnumerable<string> files = this.GetFilesForResourceManagerId();
+
+                    foreach (var file in files)
+                    {
+                        Tracer.Debug("Attempting to remove stale Recovery Info file: " +
file);
+                        File.Delete(file);
+                    }
                 }
-                catch(Exception ex)
+                catch (Exception ex)
                 {
                     Tracer.Debug("Caught Exception while removing stale RecoveryInfo file:
" + ex.Message);
-                    return;
                 }
             }
         }
 
+        private IEnumerable<string> GetFilesForResourceManagerId()
+        {
+            return Directory.GetFiles(this.Location, this.ResourceManagerId + "_*.bin");
+        }
+
         public string LoggerType
         {
             get { return "file"; }
@@ -188,9 +202,20 @@ namespace Apache.NMS.ActiveMQ.Transactio
 
         #region Recovery File Opeations
 
-        private string Filename
+        private string CreateFilename(XATransactionId xaTransactionId)
         {
-            get { return Location + Path.DirectorySeparatorChar + ResourceManagerId + ".bin";
}
+            return string.Format(
+                "{0}{1}{2}_{3}.bin", 
+                this.Location, 
+                Path.DirectorySeparatorChar, 
+                this.ResourceManagerId,
+                GetHexValue(xaTransactionId));
+        }
+        
+        private static string GetHexValue(XATransactionId xid)
+        {
+            string transactionIdHexValue = BitConverter.ToString(xid.GlobalTransactionId);
+            return transactionIdHexValue.Replace("-", string.Empty);
         }
 
         [Serializable]
@@ -234,33 +259,27 @@ namespace Apache.NMS.ActiveMQ.Transactio
             }
         }
 
-        private RecoveryInformation TryOpenRecoveryInfoFile()
+        private IList<RecoveryInformation> TryOpenRecoveryInfoFile()
         {
-            RecoveryInformation result = null;
+            List<RecoveryInformation> result = new List<RecoveryInformation>();
 
-            Tracer.Debug("Checking for Recoverable Transactions filename: " + Filename);
+            IEnumerable<string> files = this.GetFilesForResourceManagerId();
 
-            lock (syncRoot)
+            foreach (var file in files)
             {
+                Tracer.Debug("Checking for Recoverable Transactions filename: " + file);
                 try
                 {
-                    if (!File.Exists(Filename))
-                    {
-                        return null;
-                    }
-
-                    using(FileStream recoveryLog = new FileStream(Filename, FileMode.Open,
FileAccess.Read))
+                    using (FileStream recoveryLog = new FileStream(file, FileMode.Open, FileAccess.Read))
                     {
-                        Tracer.Debug("Found Recovery Log File: " + Filename);
+                        Tracer.Debug("Found Recovery Log File: " + file);
                         IFormatter formatter = new BinaryFormatter();
-                        result = formatter.Deserialize(recoveryLog) as RecoveryInformation;
+                        result.Add(formatter.Deserialize(recoveryLog) as RecoveryInformation);
                     }
                 }
-                catch(Exception ex)
+                catch (Exception ex)
                 {
-                    Tracer.ErrorFormat("Error while opening Recovery file {0} error message:
{1}", Filename, ex.Message);
-                    // Nothing to restore.
-                    return null;
+                    Tracer.ErrorFormat("Error while opening Recovery file {0} error message:
{1}", file, ex.Message);
                 }
             }
 

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs?rev=1537094&r1=1537093&r2=1537094&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs
(original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs
Wed Oct 30 14:05:56 2013
@@ -26,10 +26,12 @@ using Apache.NMS.ActiveMQ.Commands;
 
 namespace Apache.NMS.ActiveMQ.Test.Transactions
 {
+    using System.Threading;
+
     [TestFixture]
     public class RecoveryFileLoggerTest
     {
-        private string rmId;
+        private string resourceManagerId;
         private string nonExistantPath;
         private string autoCreatePath;
         private string nonDefaultLogLocation;
@@ -37,7 +39,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         [SetUp]
         public void SetUp()
         {
-            this.rmId = Guid.NewGuid().ToString();
+            this.resourceManagerId = Guid.NewGuid().ToString();
             this.nonExistantPath = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid().ToString());
 			this.nonDefaultLogLocation = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid().ToString());
 			this.autoCreatePath = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid().ToString());
@@ -48,12 +50,8 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         [TearDown]
         public void TearDown()
         {
-            if(Directory.Exists(autoCreatePath))
-            {
-                Directory.Delete(autoCreatePath);
-            }
-
-            Directory.Delete(nonDefaultLogLocation, true);
+            SafeDeleteDirectory(autoCreatePath, 1000);
+            SafeDeleteDirectory(nonDefaultLogLocation, 1000);
         }
 
         [Test]
@@ -61,7 +59,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         {
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
-            logger.Initialize(rmId);
+            logger.Initialize(this.resourceManagerId);
 
             Assert.AreEqual(Directory.GetCurrentDirectory(), logger.Location);
         }
@@ -72,7 +70,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
             logger.Location = nonDefaultLogLocation;
-            logger.Initialize(rmId);
+            logger.Initialize(this.resourceManagerId);
 
             Assert.AreEqual(nonDefaultLogLocation, logger.Location);
         }
@@ -86,7 +84,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
 
             logger.AutoCreateLocation = true;
             logger.Location = autoCreatePath;
-            logger.Initialize(rmId);
+            logger.Initialize(this.resourceManagerId);
 
             Assert.IsTrue(Directory.Exists(autoCreatePath));
             Assert.AreEqual(autoCreatePath, logger.Location);
@@ -102,7 +100,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
 
             try
             {
-                logger.Initialize(rmId);
+                logger.Initialize(this.resourceManagerId);
                 Assert.Fail("Should have detected an invalid dir and thrown an exception");
             }
             catch
@@ -116,7 +114,7 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
             logger.Location = nonDefaultLogLocation;
-            logger.Initialize(rmId);
+            logger.Initialize(this.resourceManagerId);
 
             Assert.IsTrue(logger.GetRecoverables().Length == 0);
         }
@@ -126,27 +124,14 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         {
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
-            byte[] globalId = new byte[32];
-            byte[] branchQ = new byte[32];
-            byte[] recoveryData = new byte[256];
-
-            Random gen = new Random();
-
-            gen.NextBytes(globalId);
-            gen.NextBytes(branchQ);
-            gen.NextBytes(recoveryData);
-
             logger.Location = nonDefaultLogLocation;
-            logger.Initialize(rmId);
-
-            XATransactionId xid = new XATransactionId();
-            xid.GlobalTransactionId = globalId;
-            xid.BranchQualifier = branchQ;
+            logger.Initialize(this.resourceManagerId);
 
-            logger.LogRecoveryInfo(xid, recoveryData);
+            TransactionData transactionData = new TransactionData();
+            logger.LogRecoveryInfo(transactionData.Transaction, transactionData.RecoveryData);
 
-            Assert.IsTrue(File.Exists(Path.Combine(logger.Location, rmId + ".bin")),
-                          "Recovery File was not created");
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData)),
+                "Recovery File was not created");
         }
 
         [Test]
@@ -154,36 +139,58 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         {
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
-            byte[] globalId = new byte[32];
-            byte[] branchQ = new byte[32];
-            byte[] recoveryData = new byte[256];
-
-            Random gen = new Random();
-
-            gen.NextBytes(globalId);
-            gen.NextBytes(branchQ);
-            gen.NextBytes(recoveryData);
+            logger.Location = this.nonDefaultLogLocation;
+            logger.Initialize(this.resourceManagerId);
+
+            TransactionData transactionData01 = new TransactionData();
+            logger.LogRecoveryInfo(transactionData01.Transaction, transactionData01.RecoveryData);
+            TransactionData transactionData02 = new TransactionData();
+            logger.LogRecoveryInfo(transactionData02.Transaction, transactionData02.RecoveryData);
+
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData01)), "Recovery
File was not created");
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData02)), "Recovery
File was not created");
+            Assert.AreEqual(2, logger.GetRecoverables().Length, "Did not recover the logged
record.");
+
+            KeyValuePair<XATransactionId, byte[]>[] records = logger.GetRecoverables();
+            Assert.AreEqual(2, records.Length);
+
+            foreach (var keyValuePair in records)
+            {
+                if (BitConverter.ToString(keyValuePair.Key.GlobalTransactionId) == BitConverter.ToString(transactionData01.Transaction.GlobalTransactionId))
+                {
+                    Assert.AreEqual(transactionData01.GlobalId, keyValuePair.Key.GlobalTransactionId,
"Incorrect Global TX Id returned");
+                    Assert.AreEqual(transactionData01.BranchQ, keyValuePair.Key.BranchQualifier,
"Incorrect Branch Qualifier returned");
+                    Assert.AreEqual(transactionData01.RecoveryData, keyValuePair.Value, "Incorrect
Recovery Information returned");
+                }
+                else if (BitConverter.ToString(keyValuePair.Key.GlobalTransactionId) == BitConverter.ToString(transactionData02.Transaction.GlobalTransactionId))
+                {
+                    Assert.AreEqual(transactionData02.GlobalId, keyValuePair.Key.GlobalTransactionId,
"Incorrect Global TX Id returned");
+                    Assert.AreEqual(transactionData02.BranchQ, keyValuePair.Key.BranchQualifier,
"Incorrect Branch Qualifier returned");
+                    Assert.AreEqual(transactionData02.RecoveryData, keyValuePair.Value, "Incorrect
Recovery Information returned");
+                }
+                else
+                {
+                    Assert.Fail("Transaction not found.");
+                }
+            }
+        }
+
+        [Test]
+        public void TestLogRecovered()
+        {
+            RecoveryFileLogger logger = new RecoveryFileLogger();
 
             logger.Location = nonDefaultLogLocation;
-            logger.Initialize(rmId);
+            logger.Initialize(this.resourceManagerId);
 
-            XATransactionId xid = new XATransactionId();
-            xid.GlobalTransactionId = globalId;
-            xid.BranchQualifier = branchQ;
-
-            logger.LogRecoveryInfo(xid, recoveryData);
-
-            Assert.IsTrue(File.Exists(Path.Combine(logger.Location, rmId + ".bin")),
-                          "Recovery File was not created");
-            Assert.IsTrue(logger.GetRecoverables().Length == 1,
-                          "Did not recover the logged record.");
+            TransactionData transactionData = new TransactionData();
+            logger.LogRecoveryInfo(transactionData.Transaction, transactionData.RecoveryData);
 
-            KeyValuePair<XATransactionId, byte[]>[] records = logger.GetRecoverables();
-            Assert.AreEqual(1, records.Length);
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData)), "Recovery
File was not created");
 
-            Assert.AreEqual(globalId, records[0].Key.GlobalTransactionId, "Incorrect Global
TX Id returned");
-            Assert.AreEqual(branchQ, records[0].Key.BranchQualifier, "Incorrect Branch Qualifier
returned");
-            Assert.AreEqual(recoveryData, records[0].Value, "Incorrect Recovery Information
returned");
+            logger.LogRecovered(transactionData.Transaction);
+
+            this.AssertFileIsDeleted(this.GetFilename(logger, transactionData), 1000);
         }
 
         [Test]
@@ -191,34 +198,116 @@ namespace Apache.NMS.ActiveMQ.Test.Trans
         {
             RecoveryFileLogger logger = new RecoveryFileLogger();
 
-            byte[] globalId = new byte[32];
-            byte[] branchQ = new byte[32];
-            byte[] recoveryData = new byte[256];
-
-            Random gen = new Random();
-
-            gen.NextBytes(globalId);
-            gen.NextBytes(branchQ);
-            gen.NextBytes(recoveryData);
-
             logger.Location = nonDefaultLogLocation;
-            logger.Initialize(rmId);
-
-            XATransactionId xid = new XATransactionId();
-            xid.GlobalTransactionId = globalId;
-            xid.BranchQualifier = branchQ;
+            logger.Initialize(this.resourceManagerId.ToString());
 
-            logger.LogRecoveryInfo(xid, recoveryData);
+            TransactionData transactionData01 = new TransactionData();
+            logger.LogRecoveryInfo(transactionData01.Transaction, transactionData01.RecoveryData);
+            TransactionData transactionData02 = new TransactionData();
+            logger.LogRecoveryInfo(transactionData02.Transaction, transactionData02.RecoveryData);
 
-            Assert.IsTrue(File.Exists(Path.Combine(logger.Location, rmId + ".bin")),
-                          "Recovery File was not created");
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData01)), "Recovery
File was not created");
+            Assert.IsTrue(File.Exists(this.GetFilename(logger, transactionData02)), "Recovery
File was not created");
 
             logger.Purge();
 
-            Assert.IsFalse(File.Exists(Path.Combine(logger.Location, rmId + ".bin")),
-                          "Recovery File was not created");
+            this.AssertFileIsDeleted(this.GetFilename(logger, transactionData01), 1000);
+            this.AssertFileIsDeleted(this.GetFilename(logger, transactionData02), 1000);
         }
 
+        private string GetFilename(RecoveryFileLogger logger, TransactionData transactionData)
+        {
+            return string.Format(
+                "{0}{1}{2}_{3}.bin",
+                logger.Location,
+                Path.DirectorySeparatorChar,
+                this.resourceManagerId.ToString(),
+                BitConverter.ToString(transactionData.Transaction.GlobalTransactionId).Replace("-",
string.Empty));
+        }
+
+        private void AssertFileIsDeleted(string filename, int timeout)
+        {
+            var expiration = DateTime.Now.Add(TimeSpan.FromMilliseconds(timeout));
+            while (File.Exists(filename))
+            {
+                if (expiration < DateTime.Now)
+                {
+                    Assert.Fail("Recovery File was not removed");
+                }
+
+                Thread.Sleep(5);
+            }
+        }
+
+        private void SafeDeleteDirectory(string directory, int timeout)
+        {
+            var expiration = DateTime.Now.Add(TimeSpan.FromMilliseconds(timeout));
+            while (true)
+            {
+                if (!Directory.Exists(directory))
+                {
+                    return;
+                }
+
+                try
+                {
+                    Directory.Delete(directory, true);
+                    return;
+                }
+                catch (Exception)
+                {
+                }
+
+                if (expiration < DateTime.Now)
+                {
+                    return;
+                }
+
+                Thread.Sleep(5);
+            }
+        }
+
+        private class TransactionData
+        {
+            private static readonly Random Random = new Random();
+
+            private readonly XATransactionId xid;
+
+            private readonly byte[] recoveryData = new byte[256];
+            private readonly byte[] globalId = new byte[32];
+            private readonly byte[] branchQ = new byte[32];
+
+            public TransactionData()
+            {
+                Random.NextBytes(this.globalId);
+                Random.NextBytes(this.branchQ);
+                Random.NextBytes(this.recoveryData);
+
+                this.xid = new XATransactionId();
+                this.xid.GlobalTransactionId = this.globalId;
+                this.xid.BranchQualifier = this.branchQ;
+            }
+
+            public XATransactionId Transaction
+            {
+                get { return this.xid; }
+            }
+
+            public byte[] RecoveryData
+            {
+                get { return this.recoveryData; }
+            }
+
+            public byte[] GlobalId
+            {
+                get { return this.globalId; }
+            }
+
+            public byte[] BranchQ
+            {
+                get { return this.branchQ; }
+            }
+        }
     }
 }
 



Mime
View raw message