* Added new MySQLSuperManager support for the grid servers.
* In theory, login and a large number of grid functions should now at least be multithreaded.0.6.0-stable
parent
3faadb3f5c
commit
2133fa56e7
|
@ -29,8 +29,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
@ -49,6 +47,45 @@ namespace OpenSim.Data.MySQL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private MySQLManager database;
|
private MySQLManager database;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Better DB manager. Swap-in replacement too.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<int, MySQLSuperManager> m_dbconnections = new Dictionary<int, MySQLSuperManager>();
|
||||||
|
|
||||||
|
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()
|
override public void Initialise()
|
||||||
{
|
{
|
||||||
m_log.Info("[MySQLGridData]: " + Name + " cannot be default-initialized!");
|
m_log.Info("[MySQLGridData]: " + Name + " cannot be default-initialized!");
|
||||||
|
@ -71,6 +108,16 @@ namespace OpenSim.Data.MySQL
|
||||||
if (connect != String.Empty)
|
if (connect != String.Empty)
|
||||||
{
|
{
|
||||||
database = new MySQLManager(connect);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -85,6 +132,16 @@ namespace OpenSim.Data.MySQL
|
||||||
|
|
||||||
database = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
|
database = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
|
||||||
settingPooling, settingPort);
|
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
|
// This actually does the roll forward assembly stuff
|
||||||
|
@ -184,10 +241,10 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <returns>Array of sim profiles</returns>
|
/// <returns>Array of sim profiles</returns>
|
||||||
override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
|
override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
|
||||||
{
|
{
|
||||||
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (database)
|
|
||||||
{
|
|
||||||
Dictionary<string, string> param = new Dictionary<string, string>();
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
param["?xmin"] = xmin.ToString();
|
param["?xmin"] = xmin.ToString();
|
||||||
param["?ymin"] = ymin.ToString();
|
param["?ymin"] = ymin.ToString();
|
||||||
|
@ -195,7 +252,7 @@ namespace OpenSim.Data.MySQL
|
||||||
param["?ymax"] = ymax.ToString();
|
param["?ymax"] = ymax.ToString();
|
||||||
|
|
||||||
IDbCommand result =
|
IDbCommand result =
|
||||||
database.Query(
|
dbm.Manager.Query(
|
||||||
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
|
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
|
||||||
param);
|
param);
|
||||||
IDataReader reader = result.ExecuteReader();
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
@ -204,7 +261,7 @@ namespace OpenSim.Data.MySQL
|
||||||
|
|
||||||
List<RegionProfileData> rows = new List<RegionProfileData>();
|
List<RegionProfileData> rows = new List<RegionProfileData>();
|
||||||
|
|
||||||
while ((row = database.readSimRow(reader)) != null)
|
while ((row = dbm.Manager.readSimRow(reader)) != null)
|
||||||
{
|
{
|
||||||
rows.Add(row);
|
rows.Add(row);
|
||||||
}
|
}
|
||||||
|
@ -212,14 +269,17 @@ namespace OpenSim.Data.MySQL
|
||||||
result.Dispose();
|
result.Dispose();
|
||||||
|
|
||||||
return rows.ToArray();
|
return rows.ToArray();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
database.Reconnect();
|
dbm.Manager.Reconnect();
|
||||||
m_log.Error(e.ToString());
|
m_log.Error(e.ToString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dbm.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -229,29 +289,32 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <returns>Sim profile</returns>
|
/// <returns>Sim profile</returns>
|
||||||
override public RegionProfileData GetProfileByHandle(ulong handle)
|
override public RegionProfileData GetProfileByHandle(ulong handle)
|
||||||
{
|
{
|
||||||
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (database)
|
|
||||||
{
|
|
||||||
Dictionary<string, string> param = new Dictionary<string, string>();
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
param["?handle"] = handle.ToString();
|
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();
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
RegionProfileData row = database.readSimRow(reader);
|
RegionProfileData row = dbm.Manager.readSimRow(reader);
|
||||||
reader.Close();
|
reader.Close();
|
||||||
result.Dispose();
|
result.Dispose();
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
database.Reconnect();
|
dbm.Manager.Reconnect();
|
||||||
m_log.Error(e.ToString());
|
m_log.Error(e.ToString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dbm.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -261,70 +324,76 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <returns>The sim profile</returns>
|
/// <returns>The sim profile</returns>
|
||||||
override public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
|
override public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
|
||||||
{
|
{
|
||||||
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (database)
|
|
||||||
{
|
|
||||||
Dictionary<string, string> param = new Dictionary<string, string>();
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
param["?uuid"] = uuid.ToString();
|
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();
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
RegionProfileData row = database.readSimRow(reader);
|
RegionProfileData row = dbm.Manager.readSimRow(reader);
|
||||||
reader.Close();
|
reader.Close();
|
||||||
result.Dispose();
|
result.Dispose();
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
database.Reconnect();
|
dbm.Manager.Reconnect();
|
||||||
m_log.Error(e.ToString());
|
m_log.Error(e.ToString());
|
||||||
return null;
|
return null;
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
dbm.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a sim profile from it's Region name string
|
/// Returns a sim profile from it's Region name string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uuid">The region name search query</param>
|
|
||||||
/// <returns>The sim profile</returns>
|
/// <returns>The sim profile</returns>
|
||||||
override public RegionProfileData GetProfileByString(string regionName)
|
override public RegionProfileData GetProfileByString(string regionName)
|
||||||
{
|
{
|
||||||
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
|
|
||||||
if (regionName.Length > 2)
|
if (regionName.Length > 2)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (database)
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
{
|
// Add % because this is a like query.
|
||||||
Dictionary<string, string> param = new Dictionary<string, string>();
|
param["?regionName"] = regionName + "%";
|
||||||
// Add % because this is a like query.
|
// Order by statement will return shorter matches first. Only returns one record or no record.
|
||||||
param["?regionName"] = regionName + "%";
|
IDbCommand result =
|
||||||
// Order by statement will return shorter matches first. Only returns one record or no record.
|
dbm.Manager.Query(
|
||||||
IDbCommand result = database.Query("SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1", param);
|
"SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1",
|
||||||
IDataReader reader = result.ExecuteReader();
|
param);
|
||||||
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
RegionProfileData row = database.readSimRow(reader);
|
RegionProfileData row = dbm.Manager.readSimRow(reader);
|
||||||
reader.Close();
|
reader.Close();
|
||||||
result.Dispose();
|
result.Dispose();
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
database.Reconnect();
|
dbm.Manager.Reconnect();
|
||||||
m_log.Error(e.ToString());
|
m_log.Error(e.ToString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dbm.Release();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
dbm.Release();
|
||||||
{
|
m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters");
|
||||||
m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters");
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -334,16 +403,17 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <returns>Successful?</returns>
|
/// <returns>Successful?</returns>
|
||||||
override public DataResponse AddProfile(RegionProfileData profile)
|
override public DataResponse AddProfile(RegionProfileData profile)
|
||||||
{
|
{
|
||||||
lock (database)
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
{
|
try {
|
||||||
if (database.insertRegion(profile))
|
if (dbm.Manager.insertRegion(profile))
|
||||||
{
|
{
|
||||||
return DataResponse.RESPONSE_OK;
|
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(RegionProfileData profile)
|
||||||
public DataResponse DeleteProfile(string uuid)
|
public DataResponse DeleteProfile(string uuid)
|
||||||
{
|
{
|
||||||
lock (database)
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
{
|
|
||||||
if (database.deleteRegion(uuid))
|
|
||||||
|
try {
|
||||||
|
if (dbm.Manager.deleteRegion(uuid))
|
||||||
{
|
{
|
||||||
return DataResponse.RESPONSE_OK;
|
return DataResponse.RESPONSE_OK;
|
||||||
}
|
}
|
||||||
else
|
return DataResponse.RESPONSE_ERROR;
|
||||||
{
|
} finally
|
||||||
return DataResponse.RESPONSE_ERROR;
|
{
|
||||||
}
|
dbm.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,31 +498,33 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
override public ReservationData GetReservationAtPoint(uint x, uint y)
|
override public ReservationData GetReservationAtPoint(uint x, uint y)
|
||||||
{
|
{
|
||||||
|
MySQLSuperManager dbm = GetLockedConnection();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (database)
|
|
||||||
{
|
|
||||||
Dictionary<string, string> param = new Dictionary<string, string>();
|
Dictionary<string, string> param = new Dictionary<string, string>();
|
||||||
param["?x"] = x.ToString();
|
param["?x"] = x.ToString();
|
||||||
param["?y"] = y.ToString();
|
param["?y"] = y.ToString();
|
||||||
IDbCommand result =
|
IDbCommand result =
|
||||||
database.Query(
|
dbm.Manager.Query(
|
||||||
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
|
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
|
||||||
param);
|
param);
|
||||||
IDataReader reader = result.ExecuteReader();
|
IDataReader reader = result.ExecuteReader();
|
||||||
|
|
||||||
ReservationData row = database.readReservationRow(reader);
|
ReservationData row = dbm.Manager.readReservationRow(reader);
|
||||||
reader.Close();
|
reader.Close();
|
||||||
result.Dispose();
|
result.Dispose();
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
database.Reconnect();
|
dbm.Manager.Reconnect();
|
||||||
m_log.Error(e.ToString());
|
m_log.Error(e.ToString());
|
||||||
return null;
|
return null;
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
dbm.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace OpenSim.Data.MySQL
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A MySQL Database manager
|
/// A MySQL Database manager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class MySQLManager
|
public class MySQLManager
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
using System;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace OpenSim.Data.MySQL
|
namespace OpenSim.Data.MySQL
|
||||||
{
|
{
|
||||||
class MySQLSuperManager
|
public class MySQLSuperManager
|
||||||
{
|
{
|
||||||
public bool Locked;
|
public bool Locked;
|
||||||
private Mutex m_lock = new Mutex(false);
|
private readonly Mutex m_lock = new Mutex(false);
|
||||||
public MySQLManager Manager;
|
public MySQLManager Manager;
|
||||||
|
|
||||||
public void GetLock()
|
public void GetLock()
|
||||||
|
|
Loading…
Reference in New Issue