diff --git a/OpenSim/Data/MySQL/MySQLGridData.cs b/OpenSim/Data/MySQL/MySQLGridData.cs
index fcbceb8b82..9dc3d1867a 100644
--- a/OpenSim/Data/MySQL/MySQLGridData.cs
+++ b/OpenSim/Data/MySQL/MySQLGridData.cs
@@ -29,8 +29,6 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
using libsecondlife;
using log4net;
using OpenSim.Framework;
@@ -49,6 +47,45 @@ namespace OpenSim.Data.MySQL
///
private MySQLManager database;
+
+ ///
+ /// Better DB manager. Swap-in replacement too.
+ ///
+ public Dictionary m_dbconnections = new Dictionary();
+
+ public int m_maxConnections = 10;
+ public int m_lastConnect;
+
+ public MySQLSuperManager GetLockedConnection()
+ {
+ int lockedCons = 0;
+ while (true)
+ {
+ m_lastConnect++;
+
+ // Overflow protection
+ if (m_lastConnect == int.MaxValue)
+ m_lastConnect = 0;
+
+ MySQLSuperManager x = m_dbconnections[m_lastConnect % m_maxConnections];
+ if (!x.Locked)
+ {
+ x.GetLock();
+ return x;
+ }
+
+ lockedCons++;
+ if (lockedCons > m_maxConnections)
+ {
+ lockedCons = 0;
+ System.Threading.Thread.Sleep(1000); // Wait some time before searching them again.
+ m_log.Debug(
+ "WARNING: All threads are in use. Probable cause: Something didnt release a mutex properly, or high volume of requests inbound.");
+ }
+ }
+ }
+
+
override public void Initialise()
{
m_log.Info("[MySQLGridData]: " + Name + " cannot be default-initialized!");
@@ -71,6 +108,16 @@ namespace OpenSim.Data.MySQL
if (connect != String.Empty)
{
database = new MySQLManager(connect);
+
+ m_log.Info("Creating " + m_maxConnections + " DB connections...");
+ for (int i = 0; i < m_maxConnections; i++)
+ {
+ m_log.Info("Connecting to DB... [" + i + "]");
+ MySQLSuperManager msm = new MySQLSuperManager();
+ msm.Manager = new MySQLManager(connect);
+ m_dbconnections.Add(i, msm);
+ }
+
}
else
{
@@ -85,6 +132,16 @@ namespace OpenSim.Data.MySQL
database = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
settingPooling, settingPort);
+
+ m_log.Info("Creating " + m_maxConnections + " DB connections...");
+ for (int i = 0; i < m_maxConnections; i++)
+ {
+ m_log.Info("Connecting to DB... [" + i + "]");
+ MySQLSuperManager msm = new MySQLSuperManager();
+ msm.Manager = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
+ settingPooling, settingPort);
+ m_dbconnections.Add(i, msm);
+ }
}
// This actually does the roll forward assembly stuff
@@ -184,10 +241,10 @@ namespace OpenSim.Data.MySQL
/// Array of sim profiles
override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
{
+ MySQLSuperManager dbm = GetLockedConnection();
+
try
{
- lock (database)
- {
Dictionary param = new Dictionary();
param["?xmin"] = xmin.ToString();
param["?ymin"] = ymin.ToString();
@@ -195,7 +252,7 @@ namespace OpenSim.Data.MySQL
param["?ymax"] = ymax.ToString();
IDbCommand result =
- database.Query(
+ dbm.Manager.Query(
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
param);
IDataReader reader = result.ExecuteReader();
@@ -204,7 +261,7 @@ namespace OpenSim.Data.MySQL
List rows = new List();
- while ((row = database.readSimRow(reader)) != null)
+ while ((row = dbm.Manager.readSimRow(reader)) != null)
{
rows.Add(row);
}
@@ -212,14 +269,17 @@ namespace OpenSim.Data.MySQL
result.Dispose();
return rows.ToArray();
- }
}
catch (Exception e)
{
- database.Reconnect();
+ dbm.Manager.Reconnect();
m_log.Error(e.ToString());
return null;
}
+ finally
+ {
+ dbm.Release();
+ }
}
///
@@ -229,29 +289,32 @@ namespace OpenSim.Data.MySQL
/// Sim profile
override public RegionProfileData GetProfileByHandle(ulong handle)
{
+ MySQLSuperManager dbm = GetLockedConnection();
+
try
{
- lock (database)
- {
Dictionary param = new Dictionary();
param["?handle"] = handle.ToString();
- IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param);
+ IDbCommand result = dbm.Manager.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param);
IDataReader reader = result.ExecuteReader();
- RegionProfileData row = database.readSimRow(reader);
+ RegionProfileData row = dbm.Manager.readSimRow(reader);
reader.Close();
result.Dispose();
return row;
}
- }
catch (Exception e)
{
- database.Reconnect();
+ dbm.Manager.Reconnect();
m_log.Error(e.ToString());
return null;
}
+ finally
+ {
+ dbm.Release();
+ }
}
///
@@ -261,70 +324,76 @@ namespace OpenSim.Data.MySQL
/// The sim profile
override public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
{
+ MySQLSuperManager dbm = GetLockedConnection();
+
try
{
- lock (database)
- {
Dictionary param = new Dictionary();
param["?uuid"] = uuid.ToString();
- IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = ?uuid", param);
+ IDbCommand result = dbm.Manager.Query("SELECT * FROM regions WHERE uuid = ?uuid", param);
IDataReader reader = result.ExecuteReader();
- RegionProfileData row = database.readSimRow(reader);
+ RegionProfileData row = dbm.Manager.readSimRow(reader);
reader.Close();
result.Dispose();
return row;
}
- }
catch (Exception e)
{
- database.Reconnect();
+ dbm.Manager.Reconnect();
m_log.Error(e.ToString());
return null;
+ } finally
+ {
+ dbm.Release();
}
}
///
/// Returns a sim profile from it's Region name string
///
- /// The region name search query
/// The sim profile
override public RegionProfileData GetProfileByString(string regionName)
{
+ MySQLSuperManager dbm = GetLockedConnection();
+
if (regionName.Length > 2)
{
try
{
- lock (database)
- {
- Dictionary param = new Dictionary();
- // Add % because this is a like query.
- param["?regionName"] = regionName + "%";
- // Order by statement will return shorter matches first. Only returns one record or no record.
- IDbCommand result = database.Query("SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1", param);
- IDataReader reader = result.ExecuteReader();
+ Dictionary param = new Dictionary();
+ // Add % because this is a like query.
+ param["?regionName"] = regionName + "%";
+ // Order by statement will return shorter matches first. Only returns one record or no record.
+ IDbCommand result =
+ dbm.Manager.Query(
+ "SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1",
+ param);
+ IDataReader reader = result.ExecuteReader();
- RegionProfileData row = database.readSimRow(reader);
- reader.Close();
- result.Dispose();
+ RegionProfileData row = dbm.Manager.readSimRow(reader);
+ reader.Close();
+ result.Dispose();
- return row;
- }
+ return row;
}
catch (Exception e)
{
- database.Reconnect();
+ dbm.Manager.Reconnect();
m_log.Error(e.ToString());
return null;
}
+ finally
+ {
+ dbm.Release();
+
+ }
}
- else
- {
- m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters");
- return null;
- }
+ dbm.Release();
+ m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters");
+ return null;
}
///
@@ -334,16 +403,17 @@ namespace OpenSim.Data.MySQL
/// Successful?
override public DataResponse AddProfile(RegionProfileData profile)
{
- lock (database)
- {
- if (database.insertRegion(profile))
+ MySQLSuperManager dbm = GetLockedConnection();
+ try {
+ if (dbm.Manager.insertRegion(profile))
{
return DataResponse.RESPONSE_OK;
}
- else
- {
- return DataResponse.RESPONSE_ERROR;
- }
+ return DataResponse.RESPONSE_ERROR;
+ }
+ finally
+ {
+ dbm.Release();
}
}
@@ -366,16 +436,18 @@ namespace OpenSim.Data.MySQL
//public DataResponse DeleteProfile(RegionProfileData profile)
public DataResponse DeleteProfile(string uuid)
{
- lock (database)
- {
- if (database.deleteRegion(uuid))
+ MySQLSuperManager dbm = GetLockedConnection();
+
+
+ try {
+ if (dbm.Manager.deleteRegion(uuid))
{
return DataResponse.RESPONSE_OK;
}
- else
- {
- return DataResponse.RESPONSE_ERROR;
- }
+ return DataResponse.RESPONSE_ERROR;
+ } finally
+ {
+ dbm.Release();
}
}
@@ -426,31 +498,33 @@ namespace OpenSim.Data.MySQL
///
override public ReservationData GetReservationAtPoint(uint x, uint y)
{
+ MySQLSuperManager dbm = GetLockedConnection();
+
try
{
- lock (database)
- {
Dictionary param = new Dictionary();
param["?x"] = x.ToString();
param["?y"] = y.ToString();
IDbCommand result =
- database.Query(
+ dbm.Manager.Query(
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
param);
IDataReader reader = result.ExecuteReader();
- ReservationData row = database.readReservationRow(reader);
+ ReservationData row = dbm.Manager.readReservationRow(reader);
reader.Close();
result.Dispose();
return row;
- }
}
catch (Exception e)
{
- database.Reconnect();
+ dbm.Manager.Reconnect();
m_log.Error(e.ToString());
return null;
+ } finally
+ {
+ dbm.Release();
}
}
}
diff --git a/OpenSim/Data/MySQL/MySQLManager.cs b/OpenSim/Data/MySQL/MySQLManager.cs
index d193c72625..15bdf443ff 100644
--- a/OpenSim/Data/MySQL/MySQLManager.cs
+++ b/OpenSim/Data/MySQL/MySQLManager.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Data.MySQL
///
/// A MySQL Database manager
///
- internal class MySQLManager
+ public class MySQLManager
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Data/MySQL/MySQLSuperManager.cs b/OpenSim/Data/MySQL/MySQLSuperManager.cs
index effdac75c5..4a9c7fa82b 100644
--- a/OpenSim/Data/MySQL/MySQLSuperManager.cs
+++ b/OpenSim/Data/MySQL/MySQLSuperManager.cs
@@ -1,14 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading;
+using System.Threading;
namespace OpenSim.Data.MySQL
{
- class MySQLSuperManager
+ public class MySQLSuperManager
{
public bool Locked;
- private Mutex m_lock = new Mutex(false);
+ private readonly Mutex m_lock = new Mutex(false);
public MySQLManager Manager;
public void GetLock()