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 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-08-18 00:39:10 +00:00
GetWaitTimeout ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
Assembly assem = GetType ( ) . Assembly ;
Migration m = new Migration ( dbcon , assem , "EstateStore" ) ;
m . Update ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
Type t = typeof ( EstateSettings ) ;
m_Fields = t . GetFields ( BindingFlags . NonPublic |
BindingFlags . Instance |
BindingFlags . DeclaredOnly ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
foreach ( FieldInfo f in m_Fields )
{
if ( f . Name . Substring ( 0 , 2 ) = = "m_" )
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 ( )
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2008-07-18 02:40:47 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
using ( MySqlCommand cmd = new MySqlCommand ( m_waitTimeoutSelect , dbcon ) )
2008-07-18 02:40:47 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlDataReader dbReader = cmd . ExecuteReader ( CommandBehavior . SingleRow ) )
{
if ( dbReader . Read ( ) )
{
m_waitTimeout
= Convert . ToInt32 ( dbReader [ "@@wait_timeout" ] ) *
TimeSpan . TicksPerSecond + m_waitTimeoutLeeway ;
}
}
2008-08-18 00:39:10 +00:00
}
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
m_lastConnectionUse = DateTime . Now . Ticks ;
2008-08-18 00:39:10 +00:00
2010-02-04 21:19:30 +00:00
m_log . DebugFormat (
"[REGION DB]: Connection wait timeout {0} seconds" ,
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
2010-03-22 18:49:56 +00:00
public EstateSettings LoadEstateSettings ( UUID regionID , bool create )
2008-07-18 02:40:47 +00:00
{
2010-02-04 21:19:30 +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
2010-03-23 02:05:56 +00:00
using ( MySqlCommand cmd = new MySqlCommand ( ) )
{
cmd . CommandText = sql ;
cmd . Parameters . AddWithValue ( "?RegionID" , regionID . ToString ( ) ) ;
return DoLoad ( cmd , regionID , create ) ;
}
}
private EstateSettings DoLoad ( MySqlCommand cmd , UUID regionID , bool create )
{
EstateSettings es = new EstateSettings ( ) ;
es . OnSave + = StoreEstateSettings ;
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2009-11-02 19:19:55 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
2010-03-23 02:05:56 +00:00
cmd . Connection = dbcon ;
2010-03-22 18:49:56 +00:00
bool found = false ;
2010-03-23 02:05:56 +00:00
using ( IDataReader r = cmd . ExecuteReader ( ) )
2009-10-04 20:57:51 +00:00
{
2010-03-23 02:05:56 +00:00
if ( r . Read ( ) )
2009-11-02 19:19:55 +00:00
{
2010-03-23 02:05:56 +00:00
found = true ;
2010-02-04 21:19:30 +00:00
2010-03-23 02:05:56 +00:00
foreach ( string name in FieldList )
{
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
2010-02-04 21:19:30 +00:00
{
2010-03-23 02:05:56 +00:00
int v = Convert . ToInt32 ( r [ name ] ) ;
if ( v ! = 0 )
m_FieldMap [ name ] . SetValue ( es , true ) ;
2010-02-04 21:19:30 +00:00
else
2010-03-23 02:05:56 +00:00
m_FieldMap [ name ] . SetValue ( es , false ) ;
}
else if ( m_FieldMap [ name ] . GetValue ( es ) is UUID )
{
UUID uuid = UUID . Zero ;
UUID . TryParse ( r [ name ] . ToString ( ) , out uuid ) ;
m_FieldMap [ name ] . SetValue ( es , uuid ) ;
}
else
{
m_FieldMap [ name ] . SetValue ( es , r [ name ] ) ;
2010-02-04 21:19:30 +00:00
}
}
2008-07-18 02:40:47 +00:00
}
}
2010-03-22 18:49:56 +00:00
if ( ! found & & create )
2010-02-04 21:19:30 +00:00
{
// Migration case
List < string > names = new List < string > ( FieldList ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
names . Remove ( "EstateID" ) ;
2008-08-18 00:39:10 +00:00
2010-03-23 02:05:56 +00:00
string sql = "insert into estate_settings (" + String . Join ( "," , names . ToArray ( ) ) + ") values ( ?" + String . Join ( ", ?" , names . ToArray ( ) ) + ")" ;
2009-10-04 20:57:51 +00:00
2010-03-23 02:05:56 +00:00
using ( MySqlCommand cmd2 = dbcon . CreateCommand ( ) )
2009-11-02 19:19:55 +00:00
{
2010-03-23 02:05:56 +00:00
cmd2 . CommandText = sql ;
cmd2 . Parameters . Clear ( ) ;
2010-02-04 21:19:30 +00:00
foreach ( string name in FieldList )
{
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
{
if ( ( bool ) m_FieldMap [ name ] . GetValue ( es ) )
2010-03-23 02:05:56 +00:00
cmd2 . Parameters . AddWithValue ( "?" + name , "1" ) ;
2010-02-04 21:19:30 +00:00
else
2010-03-23 02:05:56 +00:00
cmd2 . Parameters . AddWithValue ( "?" + name , "0" ) ;
2010-02-04 21:19:30 +00:00
}
else
{
2010-03-23 02:05:56 +00:00
cmd2 . Parameters . AddWithValue ( "?" + name , m_FieldMap [ name ] . GetValue ( es ) . ToString ( ) ) ;
2010-02-04 21:19:30 +00:00
}
}
2010-03-23 02:05:56 +00:00
cmd2 . ExecuteNonQuery ( ) ;
2010-02-04 21:19:30 +00:00
2010-03-23 02:05:56 +00:00
cmd2 . CommandText = "select LAST_INSERT_ID() as id" ;
cmd2 . Parameters . Clear ( ) ;
2010-02-04 21:19:30 +00:00
2010-03-23 02:05:56 +00:00
using ( IDataReader r = cmd2 . ExecuteReader ( ) )
2010-02-04 21:19:30 +00:00
{
r . Read ( ) ;
es . EstateID = Convert . ToUInt32 ( r [ "id" ] ) ;
}
2010-03-23 02:05:56 +00:00
cmd2 . CommandText = "insert into estate_map values (?RegionID, ?EstateID)" ;
cmd2 . Parameters . AddWithValue ( "?RegionID" , regionID . ToString ( ) ) ;
cmd2 . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
2010-02-04 21:19:30 +00:00
// This will throw on dupe key
2010-03-23 02:05:56 +00:00
try { cmd2 . ExecuteNonQuery ( ) ; }
2010-02-04 21:19:30 +00:00
catch ( Exception ) { }
es . Save ( ) ;
2009-11-02 19:19:55 +00:00
}
}
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
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = sql ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
foreach ( string name in FieldList )
{
if ( m_FieldMap [ name ] . GetValue ( es ) is bool )
{
if ( ( bool ) m_FieldMap [ name ] . GetValue ( es ) )
cmd . Parameters . AddWithValue ( "?" + name , "1" ) ;
else
cmd . Parameters . AddWithValue ( "?" + name , "0" ) ;
}
else
{
cmd . Parameters . AddWithValue ( "?" + name , m_FieldMap [ name ] . GetValue ( es ) . ToString ( ) ) ;
}
}
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
cmd . ExecuteNonQuery ( ) ;
2008-07-18 02:40:47 +00:00
}
2009-10-04 20:57:51 +00:00
}
2008-07-18 02:40:47 +00:00
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 ( ) ;
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2009-11-02 19:19:55 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "select bannedUUID from estateban where EstateID = ?EstateID" ;
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
using ( IDataReader r = cmd . ExecuteReader ( ) )
{
while ( r . Read ( ) )
{
EstateBan eb = new EstateBan ( ) ;
UUID uuid = new UUID ( ) ;
UUID . TryParse ( r [ "bannedUUID" ] . ToString ( ) , out uuid ) ;
eb . BannedUserID = uuid ;
eb . BannedHostAddress = "0.0.0.0" ;
eb . BannedHostIPMask = "0.0.0.0" ;
es . AddBan ( eb ) ;
}
}
}
2008-07-18 02:40:47 +00:00
}
}
private void SaveBanList ( EstateSettings es )
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "delete from estateban where EstateID = ?EstateID" ;
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . ExecuteNonQuery ( ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . Parameters . Clear ( ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( ?EstateID, ?bannedUUID, '', '', '' )" ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
foreach ( EstateBan b in es . EstateBans )
{
cmd . Parameters . AddWithValue ( "?EstateID" , es . EstateID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?bannedUUID" , b . BannedUserID . ToString ( ) ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
cmd . ExecuteNonQuery ( ) ;
cmd . Parameters . Clear ( ) ;
}
}
2008-07-18 02:40:47 +00:00
}
}
2008-09-06 07:52:41 +00:00
void SaveUUIDList ( uint EstateID , string table , UUID [ ] data )
2008-07-18 02:40:47 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "delete from " + table + " where EstateID = ?EstateID" ;
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . ExecuteNonQuery ( ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . Parameters . Clear ( ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
cmd . CommandText = "insert into " + table + " (EstateID, uuid) values ( ?EstateID, ?uuid )" ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
foreach ( UUID uuid in data )
{
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?uuid" , uuid . ToString ( ) ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
cmd . ExecuteNonQuery ( ) ;
cmd . Parameters . Clear ( ) ;
}
}
2008-07-18 02:40:47 +00:00
}
}
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
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-18 02:40:47 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "select uuid from " + table + " where EstateID = ?EstateID" ;
cmd . Parameters . AddWithValue ( "?EstateID" , EstateID ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
using ( IDataReader r = cmd . ExecuteReader ( ) )
{
while ( r . Read ( ) )
{
// EstateBan eb = new EstateBan();
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
UUID uuid = new UUID ( ) ;
UUID . TryParse ( r [ "uuid" ] . ToString ( ) , out uuid ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
uuids . Add ( uuid ) ;
}
}
}
2008-07-18 02:40:47 +00:00
}
2008-08-18 00:39:10 +00:00
2008-07-18 02:40:47 +00:00
return uuids . ToArray ( ) ;
}
2010-03-23 02:05:56 +00:00
public EstateSettings LoadEstateSettings ( int estateID )
{
using ( MySqlCommand cmd = new MySqlCommand ( ) )
{
string sql = "select estate_settings." + String . Join ( ",estate_settings." , FieldList ) + " from estate_settings where EstateID = ?EstateID" ;
cmd . CommandText = sql ;
cmd . Parameters . AddWithValue ( "?EstateID" , estateID ) ;
return DoLoad ( cmd , UUID . Zero , false ) ;
}
}
public List < int > GetEstates ( string search )
{
List < int > result = new List < int > ( ) ;
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "select estateID from estate_settings where EstateName = ?EstateName" ;
cmd . Parameters . AddWithValue ( "?EstateName" , search ) ;
using ( IDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
result . Add ( Convert . ToInt32 ( reader [ "EstateID" ] ) ) ;
}
reader . Close ( ) ;
}
}
dbcon . Close ( ) ;
}
return result ;
}
public bool LinkRegion ( UUID regionID , int estateID )
{
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
using ( MySqlCommand cmd = dbcon . CreateCommand ( ) )
{
cmd . CommandText = "insert into estate_map values (?RegionID, ?EstateID)" ;
cmd . Parameters . AddWithValue ( "?RegionID" , regionID ) ;
cmd . Parameters . AddWithValue ( "?EstateID" , estateID ) ;
if ( cmd . ExecuteNonQuery ( ) = = 0 )
{
dbcon . Close ( ) ;
return false ;
}
}
dbcon . Close ( ) ;
}
return true ;
}
public List < UUID > GetRegions ( int estateID )
{
return new List < UUID > ( ) ;
}
public bool DeleteEstate ( int estateID )
{
return false ;
}
2008-07-18 02:40:47 +00:00
}
}