2008-07-18 02:40:47 +00:00
/ *
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-07-18 02:40:47 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using System.Data ;
using System.Reflection ;
using log4net ;
using MySql.Data.MySqlClient ;
2009-02-12 09:53:12 +00:00
using OpenMetaverse ;
2008-07-18 02:40:47 +00:00
using OpenSim.Framework ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Interfaces ;
2008-07-18 02:40:47 +00:00
namespace OpenSim.Data.MySQL
{
public class MySQLEstateStore : IEstateDataStore
{
private static readonly ILog m_log =
LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
private const string m_waitTimeoutSelect = "select @@wait_timeout" ;
private MySqlConnection m_connection ;
private string m_connectionString ;
private long m_waitTimeout ;
private long m_waitTimeoutLeeway = 60 * TimeSpan . TicksPerSecond ;
2008-08-18 00:39:10 +00:00
private long m_lastConnectionUse ;
2008-07-18 02:40:47 +00:00
private FieldInfo [ ] m_Fields ;
private Dictionary < string , FieldInfo > m_FieldMap =
new Dictionary < string , FieldInfo > ( ) ;
public void Initialise ( string connectionString )
{
2008-07-19 09:35:48 +00:00
m_connectionString = connectionString ;
try
2009-02-17 14:12:57 +00:00
{
m_log . Info ( "[REGION DB]: MySql - connecting: " + Util . GetDisplayConnectionString ( m_connectionString ) ) ;
2008-07-19 09:35:48 +00:00
}
catch ( Exception e )
{
m_log . Debug ( "Exception: password not found in connection string\n" + e . ToString ( ) ) ;
}
2008-07-18 02:40:47 +00:00
m_connection = new MySqlConnection ( m_connectionString ) ;
m_connection . Open ( ) ;
2008-08-18 00:39:10 +00:00
GetWaitTimeout ( ) ;
2008-07-18 02:40:47 +00:00
Assembly assem = GetType ( ) . Assembly ;
Migration m = new Migration ( m_connection , assem , "EstateStore" ) ;
m . Update ( ) ;
Type t = typeof ( EstateSettings ) ;
m_Fields = t . GetFields ( BindingFlags . NonPublic |
BindingFlags . Instance |
BindingFlags . DeclaredOnly ) ;
foreach ( FieldInfo f in m_Fields )
2008-07-23 13:24:25 +00:00
{
if ( f . Name . Substring ( 0 , 2 ) = = "m_" )
2008-07-18 02:40:47 +00:00
m_FieldMap [ f . Name . Substring ( 2 ) ] = f ;
2008-07-23 13:24:25 +00:00
}
2008-07-18 02:40:47 +00:00
}
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
private string [ ] FieldList
{
get { return new List < string > ( m_FieldMap . Keys ) . ToArray ( ) ; }
}
protected void GetWaitTimeout ( )
{
MySqlCommand cmd = new MySqlCommand ( m_waitTimeoutSelect ,
m_connection ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
using ( MySqlDataReader dbReader =
cmd . ExecuteReader ( CommandBehavior . SingleRow ) )
{
if ( dbReader . Read ( ) )
{
2008-08-18 00:39:10 +00:00
m_waitTimeout
2008-07-18 02:40:47 +00:00
= Convert . ToInt32 ( dbReader [ "@@wait_timeout" ] ) *
TimeSpan . TicksPerSecond + m_waitTimeoutLeeway ;
2008-08-18 00:39:10 +00:00
}
2008-07-18 02:40:47 +00:00
dbReader . Close ( ) ;
cmd . Dispose ( ) ;
2008-08-18 00:39:10 +00:00
}
2009-02-12 09:53:12 +00:00
m_lastConnectionUse = DateTime . Now . Ticks ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
m_log . DebugFormat (
"[REGION DB]: Connection wait timeout {0} seconds" ,
2008-08-18 00:39:10 +00:00
m_waitTimeout / TimeSpan . TicksPerSecond ) ;
2008-07-18 02:40:47 +00:00
}
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
protected void CheckConnection ( )
{
2009-02-12 09:53:12 +00:00
long timeNow = DateTime . Now . Ticks ;
2008-07-18 02:40:47 +00:00
if ( timeNow - m_lastConnectionUse > m_waitTimeout | |
m_connection . State ! = ConnectionState . Open )
{
m_log . DebugFormat ( "[REGION DB]: Database connection has gone away - reconnecting" ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
lock ( m_connection )
{
m_connection . Close ( ) ;
m_connection = new MySqlConnection ( m_connectionString ) ;
2008-08-18 00:39:10 +00:00
m_connection . Open ( ) ;
2008-07-18 02:40:47 +00:00
}
}
2008-08-18 00:39:10 +00:00
m_lastConnectionUse = timeNow ;
}
2008-07-18 02:40:47 +00:00
2008-09-06 07:52:41 +00:00
public EstateSettings LoadEstateSettings ( UUID regionID )
2008-07-18 02:40:47 +00:00
{
EstateSettings es = new EstateSettings ( ) ;
2008-07-18 19:32:05 +00:00
es . OnSave + = StoreEstateSettings ;
2008-07-18 02:40:47 +00:00
2009-02-17 14:12:57 +00:00
string sql = "select estate_settings." + String . Join ( ",estate_settings." , FieldList ) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = ?RegionID" ;
2008-07-18 02:40:47 +00:00
CheckConnection ( ) ;
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
cmd . CommandText = sql ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?RegionID" , regionID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
IDataReader r = cmd . ExecuteReader ( ) ;
2008-07-23 13:24:25 +00:00
if ( r . Read ( ) )
2008-07-18 02:40:47 +00:00
{
foreach ( string name in FieldList )
{
2008-07-23 13:24:25 +00:00
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
2008-07-18 02:40:47 +00:00
{
int v = Convert . ToInt32 ( r [ name ] ) ;
2008-07-23 13:24:25 +00:00
if ( v ! = 0 )
2008-07-18 02:40:47 +00:00
m_FieldMap [ name ] . SetValue ( es , true ) ;
else
m_FieldMap [ name ] . SetValue ( es , false ) ;
}
2009-02-12 09:53:12 +00:00
else if ( m_FieldMap [ name ] . GetValue ( es ) is UUID )
2008-08-01 02:14:34 +00:00
{
2008-09-06 07:52:41 +00:00
UUID uuid = UUID . Zero ;
2008-08-01 02:14:34 +00:00
2008-09-06 07:52:41 +00:00
UUID . TryParse ( r [ name ] . ToString ( ) , out uuid ) ;
2008-08-01 02:14:34 +00:00
m_FieldMap [ name ] . SetValue ( es , uuid ) ;
}
2008-07-18 02:40:47 +00:00
else
{
m_FieldMap [ name ] . SetValue ( es , r [ name ] ) ;
}
}
r . Close ( ) ;
}
else
{
// Migration case
/ /
r . Close ( ) ;
List < string > names = new List < string > ( FieldList ) ;
names . Remove ( "EstateID" ) ;
2009-02-17 14:12:57 +00:00
sql = "insert into estate_settings (" + String . Join ( "," , names . ToArray ( ) ) + ") values ( ?" + String . Join ( ", ?" , names . ToArray ( ) ) + ")" ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
cmd . CommandText = sql ;
cmd . Parameters . Clear ( ) ;
foreach ( string name in FieldList )
{
2008-07-23 13:24:25 +00:00
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
2008-07-18 02:40:47 +00:00
{
2008-07-23 13:24:25 +00:00
if ( ( bool ) m_FieldMap [ name ] . GetValue ( es ) )
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , "1" ) ;
2008-07-18 02:40:47 +00:00
else
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , "0" ) ;
2008-07-18 02:40:47 +00:00
}
else
{
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , m_FieldMap [ name ] . GetValue ( es ) . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
}
}
cmd . ExecuteNonQuery ( ) ;
cmd . CommandText = "select LAST_INSERT_ID() as id" ;
cmd . Parameters . Clear ( ) ;
r = cmd . ExecuteReader ( ) ;
r . Read ( ) ;
es . EstateID = Convert . ToUInt32 ( r [ "id" ] ) ;
r . Close ( ) ;
cmd . CommandText = "insert into estate_map values (?RegionID, ?EstateID)" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?RegionID" , regionID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
// This will throw on dupe key
try
{
cmd . ExecuteNonQuery ( ) ;
}
catch ( Exception )
{
}
// Munge and transfer the ban list
/ /
cmd . Parameters . Clear ( ) ;
2009-02-17 14:12:57 +00:00
cmd . CommandText = "insert into estateban select " + es . EstateID . ToString ( ) + ", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = ?UUID" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?UUID" , regionID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
try
{
cmd . ExecuteNonQuery ( ) ;
}
catch ( Exception )
{
}
2008-07-18 19:32:05 +00:00
es . Save ( ) ;
2008-07-18 02:40:47 +00:00
}
LoadBanList ( es ) ;
es . EstateManagers = LoadUUIDList ( es . EstateID , "estate_managers" ) ;
es . EstateAccess = LoadUUIDList ( es . EstateID , "estate_users" ) ;
es . EstateGroups = LoadUUIDList ( es . EstateID , "estate_groups" ) ;
return es ;
}
public void StoreEstateSettings ( EstateSettings es )
{
2009-02-17 14:12:57 +00:00
string sql = "replace into estate_settings (" + String . Join ( "," , FieldList ) + ") values ( ?" + String . Join ( ", ?" , FieldList ) + ")" ;
2008-07-18 02:40:47 +00:00
CheckConnection ( ) ;
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
cmd . CommandText = sql ;
foreach ( string name in FieldList )
{
2008-07-23 13:24:25 +00:00
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
2008-07-18 02:40:47 +00:00
{
2008-07-23 13:24:25 +00:00
if ( ( bool ) m_FieldMap [ name ] . GetValue ( es ) )
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , "1" ) ;
2008-07-18 02:40:47 +00:00
else
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , "0" ) ;
2008-07-18 02:40:47 +00:00
}
else
{
2009-02-17 14:12:57 +00:00
cmd . Parameters . AddWithValue ( "?" + name , m_FieldMap [ name ] . GetValue ( es ) . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
}
}
cmd . ExecuteNonQuery ( ) ;
SaveBanList ( es ) ;
SaveUUIDList ( es . EstateID , "estate_managers" , es . EstateManagers ) ;
SaveUUIDList ( es . EstateID , "estate_users" , es . EstateAccess ) ;
SaveUUIDList ( es . EstateID , "estate_groups" , es . EstateGroups ) ;
}
private void LoadBanList ( EstateSettings es )
{
es . ClearBans ( ) ;
CheckConnection ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
cmd . CommandText = "select bannedUUID from estateban where EstateID = ?EstateID" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID ) ;
2008-07-18 02:40:47 +00:00
IDataReader r = cmd . ExecuteReader ( ) ;
2008-07-23 13:24:25 +00:00
while ( r . Read ( ) )
2008-07-18 02:40:47 +00:00
{
EstateBan eb = new EstateBan ( ) ;
2008-09-06 07:52:41 +00:00
UUID uuid = new UUID ( ) ;
UUID . TryParse ( r [ "bannedUUID" ] . ToString ( ) , out uuid ) ;
2008-07-18 02:40:47 +00:00
2009-02-21 09:39:33 +00:00
eb . BannedUserID = uuid ;
eb . BannedHostAddress = "0.0.0.0" ;
eb . BannedHostIPMask = "0.0.0.0" ;
2008-07-18 02:40:47 +00:00
es . AddBan ( eb ) ;
}
r . Close ( ) ;
}
private void SaveBanList ( EstateSettings es )
{
CheckConnection ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
cmd . CommandText = "delete from estateban where EstateID = ?EstateID" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
cmd . ExecuteNonQuery ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
cmd . Parameters . Clear ( ) ;
2009-02-18 18:48:59 +00:00
cmd . CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( ?EstateID, ?bannedUUID, '', '', '' )" ;
2008-08-18 00:39:10 +00:00
2008-07-23 13:24:25 +00:00
foreach ( EstateBan b in es . EstateBans )
2008-07-18 02:40:47 +00:00
{
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
2009-02-21 09:39:33 +00:00
cmd . Parameters . AddWithValue ( "?bannedUUID" , b . BannedUserID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
cmd . ExecuteNonQuery ( ) ;
cmd . Parameters . Clear ( ) ;
}
}
2008-09-06 07:52:41 +00:00
void SaveUUIDList ( uint EstateID , string table , UUID [ ] data )
2008-07-18 02:40:47 +00:00
{
CheckConnection ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
2008-08-18 00:39:10 +00:00
2009-02-17 14:12:57 +00:00
cmd . CommandText = "delete from " + table + " where EstateID = ?EstateID" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
cmd . ExecuteNonQuery ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
cmd . Parameters . Clear ( ) ;
2009-02-17 14:12:57 +00:00
cmd . CommandText = "insert into " + table + " (EstateID, uuid) values ( ?EstateID, ?uuid )" ;
2008-08-18 00:39:10 +00:00
2008-09-06 07:52:41 +00:00
foreach ( UUID uuid in data )
2008-07-18 02:40:47 +00:00
{
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?uuid" , uuid . ToString ( ) ) ;
2008-07-18 02:40:47 +00:00
cmd . ExecuteNonQuery ( ) ;
cmd . Parameters . Clear ( ) ;
}
}
2008-09-06 07:52:41 +00:00
UUID [ ] LoadUUIDList ( uint EstateID , string table )
2008-07-18 02:40:47 +00:00
{
2008-09-06 07:52:41 +00:00
List < UUID > uuids = new List < UUID > ( ) ;
2008-07-18 02:40:47 +00:00
CheckConnection ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
MySqlCommand cmd = m_connection . CreateCommand ( ) ;
2009-02-17 14:12:57 +00:00
cmd . CommandText = "select uuid from " + table + " where EstateID = ?EstateID" ;
2008-07-18 10:57:18 +00:00
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID ) ;
2008-07-18 02:40:47 +00:00
IDataReader r = cmd . ExecuteReader ( ) ;
2008-07-23 13:24:25 +00:00
while ( r . Read ( ) )
2008-07-18 02:40:47 +00:00
{
2008-07-18 10:57:18 +00:00
// EstateBan eb = new EstateBan();
2008-07-18 02:40:47 +00:00
2008-09-06 07:52:41 +00:00
UUID uuid = new UUID ( ) ;
UUID . TryParse ( r [ "uuid" ] . ToString ( ) , out uuid ) ;
2008-07-18 02:40:47 +00:00
uuids . Add ( uuid ) ;
}
r . Close ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
return uuids . ToArray ( ) ;
}
}
}