Browse Source

Make the MySqlGeneric layer transaction aware

Melanie Thielker 7 years ago
parent
commit
680231d7e7
2 changed files with 155 additions and 83 deletions
  1. 50 25
      OpenSim/Data/MySQL/MySQLFramework.cs
  2. 105 58
      OpenSim/Data/MySQL/MySQLGenericTableHandler.cs

+ 50 - 25
OpenSim/Data/MySQL/MySQLFramework.cs

@@ -36,7 +36,7 @@ using MySql.Data.MySqlClient;
 namespace OpenSim.Data.MySQL
 {
     /// <summary>
-    /// A database interface class to a user profile storage system
+    /// Common code for a number of database modules
     /// </summary>
     public class MySqlFramework
     {
@@ -44,14 +44,24 @@ namespace OpenSim.Data.MySQL
                 log4net.LogManager.GetLogger(
                 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
-        protected string m_connectionString;
-        protected object m_dbLock = new object();
+        protected string m_connectionString = String.Empty;
+        protected MySqlTransaction m_trans = null;
 
+        // Constructor using a connection string. Instances constructed
+        // this way will open a new connection for each call.
         protected MySqlFramework(string connectionString)
         {
             m_connectionString = connectionString;
         }
 
+        // Constructor using a connection object. Instances constructed
+        // this way will use the connection object and never create
+        // new connections.
+        protected MySqlFramework(MySqlTransaction trans)
+        {
+            m_trans = trans;
+        }
+
         //////////////////////////////////////////////////////////////
         //
         // All non queries are funneled through one connection
@@ -59,33 +69,48 @@ namespace OpenSim.Data.MySQL
         //
         protected int ExecuteNonQuery(MySqlCommand cmd)
         {
-            lock (m_dbLock)
+            if (m_trans == null)
             {
                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
                 {
-                    try
-                    {
-                        dbcon.Open();
-                        cmd.Connection = dbcon;
+                    dbcon.Open();
+                    return ExecuteNonQueryWithConnection(cmd, dbcon);
+                }
+            }
+            else
+            {
+                return ExecuteNonQueryWithTransaction(cmd, m_trans);
+            }
+        }
 
-                        try
-                        {
-                            return cmd.ExecuteNonQuery();
-                        }
-                        catch (Exception e)
-                        {
-                            m_log.Error(e.Message, e);
-                            m_log.Error(Environment.StackTrace.ToString());
-                            return 0;
-                        }
-                    }
-                    catch (Exception e)
-                    {
-                        m_log.Error(e.Message, e);
-                        return 0;
-                    }
+        private int ExecuteNonQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans)
+        {
+            cmd.Transaction = trans;
+            return ExecuteNonQueryWithConnection(cmd, trans.Connection);
+        }
+
+        private int ExecuteNonQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon)
+        {
+            try
+            {
+                cmd.Connection = dbcon;
+
+                try
+                {
+                    return cmd.ExecuteNonQuery();
                 }
+                catch (Exception e)
+                {
+                    m_log.Error(e.Message, e);
+                    m_log.Error(Environment.StackTrace.ToString());
+                    return 0;
+                }
+            }
+            catch (Exception e)
+            {
+                m_log.Error(e.Message, e);
+                return 0;
             }
         }
     }
-}
+}

+ 105 - 58
OpenSim/Data/MySQL/MySQLGenericTableHandler.cs

@@ -53,14 +53,27 @@ namespace OpenSim.Data.MySQL
             get { return GetType().Assembly; }
         }
 
+        public MySQLGenericTableHandler(MySqlTransaction trans,
+                string realm, string storeName) : base(trans)
+        {
+            m_Realm = realm;
+
+            CommonConstruct(storeName);
+        }
+
         public MySQLGenericTableHandler(string connectionString,
                 string realm, string storeName) : base(connectionString)
         {
             m_Realm = realm;
-            m_connectionString = connectionString;
 
+            CommonConstruct(storeName);
+        }
+
+        protected void CommonConstruct(string storeName)
+        {
             if (storeName != String.Empty)
             {
+                // We always use a new connection for any Migrations
                 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
                 {
                     dbcon.Open();
@@ -110,6 +123,11 @@ namespace OpenSim.Data.MySQL
         }
 
         public virtual T[] Get(string[] fields, string[] keys)
+        {
+            return Get(fields, keys, String.Empty);
+        }
+
+        public virtual T[] Get(string[] fields, string[] keys, string options)
         {
             if (fields.Length != keys.Length)
                 return new T[0];
@@ -126,8 +144,8 @@ namespace OpenSim.Data.MySQL
 
                 string where = String.Join(" and ", terms.ToArray());
 
-                string query = String.Format("select * from {0} where {1}",
-                                             m_Realm, where);
+                string query = String.Format("select * from {0} where {1} {2}",
+                                             m_Realm, where, options);
 
                 cmd.CommandText = query;
 
@@ -136,73 +154,93 @@ namespace OpenSim.Data.MySQL
         }
 
         protected T[] DoQuery(MySqlCommand cmd)
+        {
+            if (m_trans == null)
+            {
+                using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+                {
+                    dbcon.Open();
+
+                    return DoQueryWithConnection(cmd, dbcon);
+                }
+            }
+            else
+            {
+                return DoQueryWithTransaction(cmd, m_trans);
+            }
+        }
+
+        protected T[] DoQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans)
+        {
+            cmd.Transaction = trans;
+
+            return DoQueryWithConnection(cmd, trans.Connection);
+        }
+
+        protected T[] DoQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon)
         {
             List<T> result = new List<T>();
 
-            using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+            cmd.Connection = dbcon;
+
+            using (IDataReader reader = cmd.ExecuteReader())
             {
-                dbcon.Open();
-                cmd.Connection = dbcon;
+                if (reader == null)
+                    return new T[0];
 
-                using (IDataReader reader = cmd.ExecuteReader())
-                {
-                    if (reader == null)
-                        return new T[0];
+                CheckColumnNames(reader);
 
-                    CheckColumnNames(reader);
+                while (reader.Read())
+                {
+                    T row = new T();
 
-                    while (reader.Read())
+                    foreach (string name in m_Fields.Keys)
                     {
-                        T row = new T();
-
-                        foreach (string name in m_Fields.Keys)
+                        if (reader[name] is DBNull)
                         {
-                            if (reader[name] is DBNull)
-                            {
-                                continue;
-                            }
-                            if (m_Fields[name].FieldType == typeof(bool))
-                            {
-                                int v = Convert.ToInt32(reader[name]);
-                                m_Fields[name].SetValue(row, v != 0 ? true : false);
-                            }
-                            else if (m_Fields[name].FieldType == typeof(UUID))
-                            {
-                                m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name]));
-                            }
-                            else if (m_Fields[name].FieldType == typeof(int))
-                            {
-                                int v = Convert.ToInt32(reader[name]);
-                                m_Fields[name].SetValue(row, v);
-                            }
-                            else if (m_Fields[name].FieldType == typeof(uint))
-                            {
-                                uint v = Convert.ToUInt32(reader[name]);
-                                m_Fields[name].SetValue(row, v);
-                            }
-                            else
-                            {
-                                m_Fields[name].SetValue(row, reader[name]);
-                            }
+                            continue;
                         }
-
-                        if (m_DataField != null)
+                        if (m_Fields[name].FieldType == typeof(bool))
+                        {
+                            int v = Convert.ToInt32(reader[name]);
+                            m_Fields[name].SetValue(row, v != 0 ? true : false);
+                        }
+                        else if (m_Fields[name].FieldType == typeof(UUID))
+                        {
+                            m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name]));
+                        }
+                        else if (m_Fields[name].FieldType == typeof(int))
+                        {
+                            int v = Convert.ToInt32(reader[name]);
+                            m_Fields[name].SetValue(row, v);
+                        }
+                        else if (m_Fields[name].FieldType == typeof(uint))
+                        {
+                            uint v = Convert.ToUInt32(reader[name]);
+                            m_Fields[name].SetValue(row, v);
+                        }
+                        else
                         {
-                            Dictionary<string, string> data =
-                                new Dictionary<string, string>();
+                            m_Fields[name].SetValue(row, reader[name]);
+                        }
+                    }
 
-                            foreach (string col in m_ColumnNames)
-                            {
-                                data[col] = reader[col].ToString();
-                                if (data[col] == null)
-                                    data[col] = String.Empty;
-                            }
+                    if (m_DataField != null)
+                    {
+                        Dictionary<string, string> data =
+                            new Dictionary<string, string>();
 
-                            m_DataField.SetValue(row, data);
+                        foreach (string col in m_ColumnNames)
+                        {
+                            data[col] = reader[col].ToString();
+                            if (data[col] == null)
+                                data[col] = String.Empty;
                         }
 
-                        result.Add(row);
+                        m_DataField.SetValue(row, data);
                     }
+
+                    result.Add(row);
                 }
             }
 
@@ -357,14 +395,23 @@ namespace OpenSim.Data.MySQL
 
         public object DoQueryScalar(MySqlCommand cmd)
         {
-            using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+            if (m_trans == null)
             {
-                dbcon.Open();
-                cmd.Connection = dbcon;
+                using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+                {
+                    dbcon.Open();
+                    cmd.Connection = dbcon;
+
+                    return cmd.ExecuteScalar();
+                }
+            }
+            else
+            {
+                cmd.Connection = m_trans.Connection;
+                cmd.Transaction = m_trans;
 
                 return cmd.ExecuteScalar();
             }
         }
-
     }
 }