2007-07-16 15:40:11 +00:00
/ *
2008-03-18 05:16:43 +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-03-18 05:16:43 +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 .
* /
2007-07-16 15:40:11 +00:00
using System ;
2007-10-08 10:30:15 +00:00
using System.Collections.Generic ;
2008-04-21 07:09:17 +00:00
using System.Reflection ;
using log4net ;
2007-10-08 10:30:15 +00:00
using MySql.Data.MySqlClient ;
2009-02-12 09:53:12 +00:00
using OpenMetaverse ;
2008-04-02 16:00:40 +00:00
using OpenSim.Framework ;
2007-07-16 15:40:11 +00:00
2008-04-02 15:36:01 +00:00
namespace OpenSim.Data.MySQL
2007-07-16 15:40:11 +00:00
{
/// <summary>
/// A MySQL interface for the inventory server
/// </summary>
2008-07-31 09:24:28 +00:00
public class MySQLInventoryData : IInventoryDataPlugin
2007-07-16 15:40:11 +00:00
{
2008-05-16 01:22:11 +00:00
private static readonly ILog m_log
2008-04-21 07:09:17 +00:00
= LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-02-05 19:44:27 +00:00
2007-07-16 15:40:11 +00:00
/// <summary>
/// The database manager
/// </summary>
2007-10-08 10:30:15 +00:00
private MySQLManager database ;
2007-07-16 15:40:11 +00:00
2008-08-18 00:39:10 +00:00
public void Initialise ( )
{
2008-07-31 09:24:28 +00:00
m_log . Info ( "[MySQLInventoryData]: " + Name + " cannot be default-initialized!" ) ;
throw new PluginNotInitialisedException ( Name ) ;
}
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// <para>Initialises Inventory interface</para>
/// <para>
/// <list type="bullet">
/// <item>Loads and initialises the MySQL storage plugin</item>
/// <item>warns and uses the obsolete mysql_connection.ini if connect string is empty.</item>
/// <item>Check for migration</item>
/// </list>
/// </para>
2008-06-26 01:12:28 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="connect">connect string</param>
2008-04-23 20:48:23 +00:00
public void Initialise ( string connect )
{
2008-05-30 08:35:57 +00:00
if ( connect ! = String . Empty )
2008-05-28 18:12:32 +00:00
{
database = new MySQLManager ( connect ) ;
}
else
{
m_log . Warn ( "Reverting to deprecated mysql_connection.ini file for connection info" ) ;
IniFile GridDataMySqlFile = new IniFile ( "mysql_connection.ini" ) ;
string settingHostname = GridDataMySqlFile . ParseFileReadValue ( "hostname" ) ;
string settingDatabase = GridDataMySqlFile . ParseFileReadValue ( "database" ) ;
string settingUsername = GridDataMySqlFile . ParseFileReadValue ( "username" ) ;
string settingPassword = GridDataMySqlFile . ParseFileReadValue ( "password" ) ;
string settingPooling = GridDataMySqlFile . ParseFileReadValue ( "pooling" ) ;
string settingPort = GridDataMySqlFile . ParseFileReadValue ( "port" ) ;
2008-08-18 00:39:10 +00:00
2008-05-28 18:12:32 +00:00
database =
new MySQLManager ( settingHostname , settingDatabase , settingUsername , settingPassword , settingPooling ,
settingPort ) ;
}
2008-06-12 15:47:33 +00:00
// This actually does the roll forward assembly stuff
Assembly assem = GetType ( ) . Assembly ;
2008-06-12 18:44:58 +00:00
Migration m = new Migration ( database . Connection , assem , "InventoryStore" ) ;
2008-06-12 15:47:33 +00:00
m . Update ( ) ;
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
2007-07-16 15:40:11 +00:00
/// <summary>
/// The name of this DB provider
/// </summary>
/// <returns>Name of DB provider</returns>
2008-07-31 09:24:28 +00:00
public string Name
2007-07-16 15:40:11 +00:00
{
2008-07-31 09:24:28 +00:00
get { return "MySQL Inventory Data Interface" ; }
2007-07-16 15:40:11 +00:00
}
/// <summary>
/// Closes this DB provider
/// </summary>
2008-06-26 01:12:28 +00:00
/// <remarks>do nothing</remarks>
2008-07-31 09:24:28 +00:00
public void Dispose ( )
2007-07-16 15:40:11 +00:00
{
// Do nothing.
}
/// <summary>
/// Returns the version of this DB provider
/// </summary>
2008-06-26 12:38:03 +00:00
/// <returns>A string containing the DB provider version</returns>
2008-07-31 09:24:28 +00:00
public string Version
2007-07-16 15:40:11 +00:00
{
2008-07-31 09:24:28 +00:00
get { return database . getVersion ( ) ; }
2007-07-16 15:40:11 +00:00
}
/// <summary>
/// Returns a list of items in a specified folder
/// </summary>
/// <param name="folderID">The folder to search</param>
/// <returns>A list containing inventory items</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryItemBase > getInventoryInFolder ( UUID folderID )
2007-07-16 15:40:11 +00:00
{
try
{
lock ( database )
{
2007-10-08 10:30:15 +00:00
List < InventoryItemBase > items = new List < InventoryItemBase > ( ) ;
2007-07-16 15:40:11 +00:00
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand ( "SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
MySqlDataReader reader = result . ExecuteReader ( ) ;
while ( reader . Read ( ) )
2008-11-13 22:53:49 +00:00
{
2009-11-02 19:19:55 +00:00
// A null item (because something went wrong) breaks everything in the folder
InventoryItemBase item = readInventoryItem ( reader ) ;
if ( item ! = null )
items . Add ( item ) ;
}
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
reader . Close ( ) ;
result . Dispose ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
return items ;
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
/// <summary>
/// Returns a list of the root folders within a users inventory
/// </summary>
/// <param name="user">The user whos inventory is to be searched</param>
/// <returns>A list of folder objects</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getUserRootFolders ( UUID user )
2007-07-16 15:40:11 +00:00
{
try
{
lock ( database )
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand (
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , user . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?zero" , UUID . Zero . ToString ( ) ) ;
MySqlDataReader reader = result . ExecuteReader ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
reader . Close ( ) ;
result . Dispose ( ) ;
return items ;
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
return null ;
2007-07-22 11:44:36 +00:00
}
}
2008-08-18 00:39:10 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// see <see cref="InventoryItemBase.getUserRootFolder"/>
2008-06-26 01:12:28 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="user">The user UUID</param>
2008-06-26 01:12:28 +00:00
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public InventoryFolderBase getUserRootFolder ( UUID user )
2007-09-27 14:57:43 +00:00
{
try
{
lock ( database )
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand (
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , user . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?zero" , UUID . Zero . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
2009-11-02 19:19:55 +00:00
MySqlDataReader reader = result . ExecuteReader ( ) ;
2007-10-08 10:30:15 +00:00
2009-11-02 19:19:55 +00:00
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
2007-12-27 21:41:48 +00:00
2009-11-02 19:19:55 +00:00
InventoryFolderBase rootFolder = null ;
2007-12-08 14:27:12 +00:00
2009-11-02 19:19:55 +00:00
// There should only ever be one root folder for a user. However, if there's more
// than one we'll simply use the first one rather than failing. It would be even
// nicer to print some message to this effect, but this feels like it's too low a
// to put such a message out, and it's too minor right now to spare the time to
// suitably refactor.
if ( items . Count > 0 )
{
rootFolder = items [ 0 ] ;
2007-12-08 14:27:12 +00:00
}
2009-11-02 19:19:55 +00:00
reader . Close ( ) ;
result . Dispose ( ) ;
return rootFolder ;
2007-09-27 14:57:43 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-09-27 14:57:43 +00:00
return null ;
}
}
2007-07-16 15:40:11 +00:00
/// <summary>
2007-12-08 14:27:12 +00:00
/// Return a list of folders in a users inventory contained within the specified folder.
/// This method is only used in tests - in normal operation the user always have one,
/// and only one, root folder.
2007-07-16 15:40:11 +00:00
/// </summary>
/// <param name="parentID">The folder to search</param>
/// <returns>A list of inventory folders</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getInventoryFolders ( UUID parentID )
2007-07-16 15:40:11 +00:00
{
try
{
lock ( database )
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , parentID . ToString ( ) ) ;
MySqlDataReader reader = result . ExecuteReader ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
reader . Close ( ) ;
result . Dispose ( ) ;
return items ;
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
2007-10-08 10:30:15 +00:00
/// <summary>
/// Reads a one item from an SQL result
/// </summary>
/// <param name="reader">The SQL Result</param>
/// <returns>the item read</returns>
2008-05-01 16:03:53 +00:00
private static InventoryItemBase readInventoryItem ( MySqlDataReader reader )
2007-10-08 10:30:15 +00:00
{
try
{
InventoryItemBase item = new InventoryItemBase ( ) ;
2009-05-08 12:28:22 +00:00
// TODO: this is to handle a case where NULLs creep in there, which we are not sure is indemic to the system, or legacy. It would be nice to live fix these.
if ( reader [ "creatorID" ] = = null )
{
item . CreatorId = UUID . Zero . ToString ( ) ;
}
else
{
item . CreatorId = ( string ) reader [ "creatorID" ] ;
}
2009-04-08 17:50:57 +00:00
2008-11-13 22:53:49 +00:00
// Be a bit safer in parsing these because the
// database doesn't enforce them to be not null, and
// the inventory still works if these are weird in the
// db
UUID Owner = UUID . Zero ;
UUID GroupID = UUID . Zero ;
UUID . TryParse ( ( string ) reader [ "avatarID" ] , out Owner ) ;
UUID . TryParse ( ( string ) reader [ "groupID" ] , out GroupID ) ;
2009-09-30 16:00:09 +00:00
item . Owner = Owner ;
2008-11-13 22:53:49 +00:00
item . GroupID = GroupID ;
2009-09-30 16:00:09 +00:00
// Rest of the parsing. If these UUID's fail, we're dead anyway
2008-09-06 07:52:41 +00:00
item . ID = new UUID ( ( string ) reader [ "inventoryID" ] ) ;
item . AssetID = new UUID ( ( string ) reader [ "assetID" ] ) ;
2008-04-07 23:15:35 +00:00
item . AssetType = ( int ) reader [ "assetType" ] ;
2008-09-06 07:52:41 +00:00
item . Folder = new UUID ( ( string ) reader [ "parentFolderID" ] ) ;
2008-04-07 23:15:35 +00:00
item . Name = ( string ) reader [ "inventoryName" ] ;
item . Description = ( string ) reader [ "inventoryDescription" ] ;
item . NextPermissions = ( uint ) reader [ "inventoryNextPermissions" ] ;
item . CurrentPermissions = ( uint ) reader [ "inventoryCurrentPermissions" ] ;
item . InvType = ( int ) reader [ "invType" ] ;
item . BasePermissions = ( uint ) reader [ "inventoryBasePermissions" ] ;
2008-05-16 01:22:11 +00:00
item . EveryOnePermissions = ( uint ) reader [ "inventoryEveryOnePermissions" ] ;
2008-11-14 18:54:38 +00:00
item . GroupPermissions = ( uint ) reader [ "inventoryGroupPermissions" ] ;
2008-05-06 22:41:38 +00:00
item . SalePrice = ( int ) reader [ "salePrice" ] ;
2009-08-09 07:01:21 +00:00
item . SaleType = unchecked ( ( byte ) ( Convert . ToSByte ( reader [ "saleType" ] ) ) ) ;
2008-05-01 20:47:33 +00:00
item . CreationDate = ( int ) reader [ "creationDate" ] ;
item . GroupOwned = Convert . ToBoolean ( reader [ "groupOwned" ] ) ;
2008-05-16 01:22:11 +00:00
item . Flags = ( uint ) reader [ "flags" ] ;
2008-04-30 16:08:24 +00:00
2007-10-08 10:30:15 +00:00
return item ;
}
catch ( MySqlException e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
return null ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Returns a specified inventory item
/// </summary>
/// <param name="item">The item to return</param>
/// <returns>An inventory item</returns>
2008-09-06 07:52:41 +00:00
public InventoryItemBase getInventoryItem ( UUID itemID )
2007-07-16 15:40:11 +00:00
{
try
{
lock ( database )
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand ( "SELECT * FROM inventoryitems WHERE inventoryID = ?uuid" , database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , itemID . ToString ( ) ) ;
MySqlDataReader reader = result . ExecuteReader ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
InventoryItemBase item = null ;
if ( reader . Read ( ) )
item = readInventoryItem ( reader ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
reader . Close ( ) ;
result . Dispose ( ) ;
return item ;
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
return null ;
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
/// <summary>
/// Reads a list of inventory folders returned by a query.
/// </summary>
/// <param name="reader">A MySQL Data Reader</param>
/// <returns>A List containing inventory folders</returns>
2008-05-01 16:03:53 +00:00
protected static InventoryFolderBase readInventoryFolder ( MySqlDataReader reader )
2007-10-08 10:30:15 +00:00
{
try
{
InventoryFolderBase folder = new InventoryFolderBase ( ) ;
2008-09-06 07:52:41 +00:00
folder . Owner = new UUID ( ( string ) reader [ "agentID" ] ) ;
folder . ParentID = new UUID ( ( string ) reader [ "parentFolderID" ] ) ;
folder . ID = new UUID ( ( string ) reader [ "folderID" ] ) ;
2008-04-07 23:27:05 +00:00
folder . Name = ( string ) reader [ "folderName" ] ;
folder . Type = ( short ) reader [ "type" ] ;
folder . Version = ( ushort ) ( ( int ) reader [ "version" ] ) ;
2007-10-08 10:30:15 +00:00
return folder ;
}
catch ( Exception e )
{
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
return null ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Returns a specified inventory folder
/// </summary>
2009-08-09 07:01:21 +00:00
/// <param name="folderID">The folder to return</param>
2007-07-16 15:40:11 +00:00
/// <returns>A folder class</returns>
2008-09-06 07:52:41 +00:00
public InventoryFolderBase getInventoryFolder ( UUID folderID )
2007-07-16 15:40:11 +00:00
{
try
{
lock ( database )
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand result =
new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE folderID = ?uuid" , database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
MySqlDataReader reader = result . ExecuteReader ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
InventoryFolderBase folder = null ;
if ( reader . Read ( ) )
folder = readInventoryFolder ( reader ) ;
reader . Close ( ) ;
result . Dispose ( ) ;
2007-07-16 15:40:11 +00:00
2009-11-02 19:19:55 +00:00
return folder ;
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
/// <summary>
/// Adds a specified item to the database
/// </summary>
/// <param name="item">The inventory item</param>
public void addInventoryItem ( InventoryItemBase item )
{
2007-10-30 09:05:31 +00:00
string sql =
2008-04-30 19:28:36 +00:00
"REPLACE INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName"
+ ", inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType"
2008-11-14 18:54:38 +00:00
+ ", creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, inventoryGroupPermissions, salePrice, saleType"
2008-04-30 19:28:36 +00:00
+ ", creationDate, groupID, groupOwned, flags) VALUES " ;
2007-10-30 09:05:31 +00:00
sql + =
2008-04-30 19:28:36 +00:00
"(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription"
+ ", ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID"
2008-11-14 18:54:38 +00:00
+ ", ?inventoryBasePermissions, ?inventoryEveryOnePermissions, ?inventoryGroupPermissions, ?salePrice, ?saleType, ?creationDate"
2008-04-30 19:28:36 +00:00
+ ", ?groupID, ?groupOwned, ?flags)" ;
2007-10-08 10:30:15 +00:00
2009-09-30 16:00:09 +00:00
string itemName = item . Name ;
2009-07-24 20:01:17 +00:00
if ( item . Name . Length > 64 )
{
itemName = item . Name . Substring ( 0 , 64 ) ;
m_log . Warn ( "[INVENTORY DB]: Name field truncated from " + item . Name . Length + " to " + itemName . Length + " characters on add item" ) ;
}
string itemDesc = item . Description ;
if ( item . Description . Length > 128 )
{
itemDesc = item . Description . Substring ( 0 , 128 ) ;
m_log . Warn ( "[INVENTORY DB]: Description field truncated from " + item . Description . Length + " to " + itemDesc . Length + " characters on add item" ) ;
2009-09-30 16:00:09 +00:00
}
2009-07-24 20:01:17 +00:00
2007-10-08 10:30:15 +00:00
try
2007-07-16 15:40:11 +00:00
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2007-10-08 10:30:15 +00:00
MySqlCommand result = new MySqlCommand ( sql , database . Connection ) ;
2008-04-07 23:15:35 +00:00
result . Parameters . AddWithValue ( "?inventoryID" , item . ID . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?assetID" , item . AssetID . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?assetType" , item . AssetType . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?parentFolderID" , item . Folder . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?avatarID" , item . Owner . ToString ( ) ) ;
2009-07-24 20:01:17 +00:00
result . Parameters . AddWithValue ( "?inventoryName" , itemName ) ;
result . Parameters . AddWithValue ( "?inventoryDescription" , itemDesc ) ;
2008-04-07 23:15:35 +00:00
result . Parameters . AddWithValue ( "?inventoryNextPermissions" , item . NextPermissions . ToString ( ) ) ;
2007-10-30 09:05:31 +00:00
result . Parameters . AddWithValue ( "?inventoryCurrentPermissions" ,
2008-04-07 23:15:35 +00:00
item . CurrentPermissions . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?invType" , item . InvType ) ;
2009-04-08 17:50:57 +00:00
result . Parameters . AddWithValue ( "?creatorID" , item . CreatorId ) ;
2008-04-07 23:15:35 +00:00
result . Parameters . AddWithValue ( "?inventoryBasePermissions" , item . BasePermissions ) ;
result . Parameters . AddWithValue ( "?inventoryEveryOnePermissions" , item . EveryOnePermissions ) ;
2008-11-14 18:54:38 +00:00
result . Parameters . AddWithValue ( "?inventoryGroupPermissions" , item . GroupPermissions ) ;
2008-04-30 16:08:24 +00:00
result . Parameters . AddWithValue ( "?salePrice" , item . SalePrice ) ;
2009-08-09 07:01:21 +00:00
result . Parameters . AddWithValue ( "?saleType" , unchecked ( ( sbyte ) item . SaleType ) ) ;
2008-04-30 16:08:24 +00:00
result . Parameters . AddWithValue ( "?creationDate" , item . CreationDate ) ;
result . Parameters . AddWithValue ( "?groupID" , item . GroupID ) ;
result . Parameters . AddWithValue ( "?groupOwned" , item . GroupOwned ) ;
result . Parameters . AddWithValue ( "?flags" , item . Flags ) ;
2008-05-16 01:22:11 +00:00
2008-04-18 22:46:03 +00:00
lock ( database )
{
result . ExecuteNonQuery ( ) ;
}
2008-05-16 01:22:11 +00:00
2007-10-08 10:30:15 +00:00
result . Dispose ( ) ;
2009-03-22 16:12:48 +00:00
result = new MySqlCommand ( "update inventoryfolders set version=version+1 where folderID = ?folderID" , database . Connection ) ;
result . Parameters . AddWithValue ( "?folderID" , item . Folder . ToString
( ) ) ;
lock ( database )
{
result . ExecuteNonQuery ( ) ;
}
result . Dispose ( ) ;
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
}
}
/// <summary>
/// Updates the specified inventory item
/// </summary>
/// <param name="item">Inventory item to update</param>
public void updateInventoryItem ( InventoryItemBase item )
{
addInventoryItem ( item ) ;
}
2007-08-16 16:31:32 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// Detele the specified inventory item
2007-08-16 16:31:32 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="item">The inventory item UUID to delete</param>
2008-09-06 07:52:41 +00:00
public void deleteInventoryItem ( UUID itemID )
2007-08-16 16:31:32 +00:00
{
2007-10-08 10:30:15 +00:00
try
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2007-10-30 09:05:31 +00:00
MySqlCommand cmd =
new MySqlCommand ( "DELETE FROM inventoryitems WHERE inventoryID=?uuid" , database . Connection ) ;
2007-12-20 05:43:02 +00:00
cmd . Parameters . AddWithValue ( "?uuid" , itemID . ToString ( ) ) ;
2008-05-16 01:22:11 +00:00
2008-04-18 22:46:03 +00:00
lock ( database )
{
cmd . ExecuteNonQuery ( ) ;
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
database . Reconnect ( ) ;
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
2007-08-16 16:31:32 +00:00
}
2009-03-21 17:46:58 +00:00
public InventoryItemBase queryInventoryItem ( UUID itemID )
{
return getInventoryItem ( itemID ) ;
}
2009-03-23 00:11:34 +00:00
public InventoryFolderBase queryInventoryFolder ( UUID folderID )
{
return getInventoryFolder ( folderID ) ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Creates a new inventory folder
/// </summary>
/// <param name="folder">Folder to create</param>
public void addInventoryFolder ( InventoryFolderBase folder )
{
2007-10-30 09:05:31 +00:00
string sql =
"REPLACE INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES " ;
2007-10-08 10:30:15 +00:00
sql + = "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version)" ;
2009-09-30 16:00:09 +00:00
string folderName = folder . Name ;
2009-07-24 20:01:17 +00:00
if ( folderName . Length > 64 )
{
folderName = folderName . Substring ( 0 , 64 ) ;
m_log . Warn ( "[INVENTORY DB]: Name field truncated from " + folder . Name . Length + " to " + folderName . Length + " characters on add folder" ) ;
2009-09-30 16:00:09 +00:00
}
2009-07-24 20:01:17 +00:00
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2007-10-08 10:30:15 +00:00
MySqlCommand cmd = new MySqlCommand ( sql , database . Connection ) ;
2008-04-07 23:27:05 +00:00
cmd . Parameters . AddWithValue ( "?folderID" , folder . ID . ToString ( ) ) ;
2008-04-08 23:26:31 +00:00
cmd . Parameters . AddWithValue ( "?agentID" , folder . Owner . ToString ( ) ) ;
2008-04-07 23:27:05 +00:00
cmd . Parameters . AddWithValue ( "?parentFolderID" , folder . ParentID . ToString ( ) ) ;
2009-07-24 20:01:17 +00:00
cmd . Parameters . AddWithValue ( "?folderName" , folderName ) ;
2009-08-15 15:54:48 +00:00
cmd . Parameters . AddWithValue ( "?type" , folder . Type ) ;
2008-04-07 23:27:05 +00:00
cmd . Parameters . AddWithValue ( "?version" , folder . Version ) ;
2007-10-30 09:05:31 +00:00
2007-10-08 10:30:15 +00:00
try
{
2008-02-12 22:24:12 +00:00
lock ( database )
{
cmd . ExecuteNonQuery ( ) ;
}
2007-10-08 10:30:15 +00:00
}
catch ( Exception e )
2007-07-16 15:40:11 +00:00
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
}
}
/// <summary>
/// Updates an inventory folder
/// </summary>
/// <param name="folder">Folder to update</param>
public void updateInventoryFolder ( InventoryFolderBase folder )
{
addInventoryFolder ( folder ) ;
}
2007-10-06 08:23:51 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// Move an inventory folder
2007-12-15 04:57:14 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="folder">Folder to move</param>
/// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks>
2007-12-15 04:57:14 +00:00
public void moveInventoryFolder ( InventoryFolderBase folder )
{
string sql =
"UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID" ;
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2007-12-15 04:57:14 +00:00
MySqlCommand cmd = new MySqlCommand ( sql , database . Connection ) ;
2008-04-07 23:27:05 +00:00
cmd . Parameters . AddWithValue ( "?folderID" , folder . ID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?parentFolderID" , folder . ParentID . ToString ( ) ) ;
2007-12-15 04:57:14 +00:00
try
{
2008-02-12 22:24:12 +00:00
lock ( database )
{
cmd . ExecuteNonQuery ( ) ;
}
2007-12-15 04:57:14 +00:00
}
catch ( Exception e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-12-15 04:57:14 +00:00
}
}
2007-10-06 08:23:51 +00:00
2007-10-08 10:30:15 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// Append a list of all the child folders of a parent folder
2007-10-08 10:30:15 +00:00
/// </summary>
/// <param name="folders">list where folders will be appended</param>
/// <param name="parentID">ID of parent</param>
2008-09-06 07:52:41 +00:00
protected void getInventoryFolders ( ref List < InventoryFolderBase > folders , UUID parentID )
2007-10-08 10:30:15 +00:00
{
List < InventoryFolderBase > subfolderList = getInventoryFolders ( parentID ) ;
foreach ( InventoryFolderBase f in subfolderList )
folders . Add ( f ) ;
}
2007-10-30 09:05:31 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-07-31 09:24:28 +00:00
/// See IInventoryDataPlugin
2008-06-26 01:12:28 +00:00
/// </summary>
/// <param name="parentID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getFolderHierarchy ( UUID parentID )
2007-10-08 10:30:15 +00:00
{
2008-08-10 16:44:25 +00:00
/ * Note : There are subtle changes between this implementation of getFolderHierarchy and the previous one
* - We will only need to hit the database twice instead of n times .
* - We assume the database is well - formed - no stranded / dangling folders , all folders in heirarchy owned
* by the same person , each user only has 1 inventory heirarchy
2008-08-18 00:39:10 +00:00
* - The returned list is not ordered , instead of breadth - first ordered
2008-08-10 16:44:25 +00:00
There are basically 2 usage cases for getFolderHeirarchy :
1 ) Getting the user ' s entire inventory heirarchy when they log in
2008-08-18 00:39:10 +00:00
2 ) Finding a subfolder heirarchy to delete when emptying the trash .
2008-08-10 16:44:25 +00:00
This implementation will pull all inventory folders from the database , and then prune away any folder that
is not part of the requested sub - heirarchy . The theory is that it is cheaper to make 1 request from the
database than to make n requests . This pays off only if requested heirarchy is large .
By making this choice , we are making the worst case better at the cost of making the best case worse .
This way is generally better because we don ' t have to rebuild the connection / sql query per subfolder ,
even if we end up getting more data from the SQL server than we need .
- Francis
* /
try
{
List < InventoryFolderBase > folders = new List < InventoryFolderBase > ( ) ;
2009-11-02 19:19:55 +00:00
Dictionary < UUID , List < InventoryFolderBase > > hashtable
= new Dictionary < UUID , List < InventoryFolderBase > > ( ) ; ;
2008-08-10 16:44:25 +00:00
List < InventoryFolderBase > parentFolder = new List < InventoryFolderBase > ( ) ;
lock ( database )
{
2009-11-02 19:19:55 +00:00
MySqlCommand result ;
MySqlDataReader reader ;
bool buildResultsFromHashTable = false ;
2008-08-10 16:44:25 +00:00
database . CheckConnection ( ) ;
2007-10-08 10:30:15 +00:00
2008-08-10 16:44:25 +00:00
/ * Fetch the parent folder from the database to determine the agent ID , and if
* we ' re querying the root of the inventory folder tree * /
2009-11-02 19:19:55 +00:00
result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE folderID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , parentID . ToString ( ) ) ;
reader = result . ExecuteReader ( ) ;
while ( reader . Read ( ) ) // Should be at most 1 result
parentFolder . Add ( readInventoryFolder ( reader ) ) ;
reader . Close ( ) ;
result . Dispose ( ) ;
2007-10-08 10:30:15 +00:00
2008-08-10 16:44:25 +00:00
if ( parentFolder . Count > = 1 ) // No result means parent folder does not exist
{
2008-09-06 07:52:41 +00:00
if ( parentFolder [ 0 ] . ParentID = = UUID . Zero ) // We are querying the root folder
2008-08-10 16:44:25 +00:00
{
/* Get all of the agent's folders from the database, put them in a list and return it */
2009-11-02 19:19:55 +00:00
result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE agentID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , parentFolder [ 0 ] . Owner . ToString ( ) ) ;
reader = result . ExecuteReader ( ) ;
while ( reader . Read ( ) )
2008-08-10 16:44:25 +00:00
{
2009-11-02 19:19:55 +00:00
InventoryFolderBase curFolder = readInventoryFolder ( reader ) ;
if ( curFolder . ID ! = parentID ) // Do not need to add the root node of the tree to the list
folders . Add ( curFolder ) ;
2008-08-10 16:44:25 +00:00
}
2009-11-02 19:19:55 +00:00
reader . Close ( ) ;
result . Dispose ( ) ;
2008-08-10 16:44:25 +00:00
} // if we are querying the root folder
else // else we are querying a subtree of the inventory folder tree
{
/ * Get all of the agent ' s folders from the database , put them all in a hash table
* indexed by their parent ID * /
2009-11-02 19:19:55 +00:00
result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE agentID = ?uuid" ,
database . Connection ) ;
result . Parameters . AddWithValue ( "?uuid" , parentFolder [ 0 ] . Owner . ToString ( ) ) ;
reader = result . ExecuteReader ( ) ;
while ( reader . Read ( ) )
2008-08-10 16:44:25 +00:00
{
2009-11-02 19:19:55 +00:00
InventoryFolderBase curFolder = readInventoryFolder ( reader ) ;
if ( hashtable . ContainsKey ( curFolder . ParentID ) ) // Current folder already has a sibling
hashtable [ curFolder . ParentID ] . Add ( curFolder ) ; // append to sibling list
else // else current folder has no known (yet) siblings
2008-08-10 16:44:25 +00:00
{
2009-11-02 19:19:55 +00:00
List < InventoryFolderBase > siblingList = new List < InventoryFolderBase > ( ) ;
siblingList . Add ( curFolder ) ;
// Current folder has no known (yet) siblings
hashtable . Add ( curFolder . ParentID , siblingList ) ;
2008-08-10 16:44:25 +00:00
}
2009-11-02 19:19:55 +00:00
} // while more items to read from the database
reader . Close ( ) ;
result . Dispose ( ) ;
2008-08-10 16:44:25 +00:00
// Set flag so we know we need to build the results from the hash table after
// we unlock the database
buildResultsFromHashTable = true ;
} // else we are querying a subtree of the inventory folder tree
} // if folder parentID exists
if ( buildResultsFromHashTable )
{
/ * We have all of the user ' s folders stored in a hash table indexed by their parent ID
* and we need to return the requested subtree . We will build the requested subtree
* by performing a breadth - first - search on the hash table * /
if ( hashtable . ContainsKey ( parentID ) )
folders . AddRange ( hashtable [ parentID ] ) ;
for ( int i = 0 ; i < folders . Count ; i + + ) // **Note: folders.Count is *not* static
if ( hashtable . ContainsKey ( folders [ i ] . ID ) )
folders . AddRange ( hashtable [ folders [ i ] . ID ] ) ;
}
2008-08-12 00:08:41 +00:00
} // lock (database)
2008-08-10 16:44:25 +00:00
return folders ;
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2008-08-10 16:44:25 +00:00
return null ;
}
2007-10-08 10:30:15 +00:00
}
2008-06-26 01:12:28 +00:00
/// <summary>
/// Delete a folder from database
/// </summary>
/// <param name="folderID">the folder UUID</param>
2008-09-06 07:52:41 +00:00
protected void deleteOneFolder ( UUID folderID )
2007-10-08 10:30:15 +00:00
{
try
2008-05-16 01:22:11 +00:00
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand cmd =
new MySqlCommand ( "DELETE FROM inventoryfolders WHERE folderID=?uuid" , database . Connection ) ;
cmd . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2009-11-02 19:19:55 +00:00
lock ( database )
{
cmd . ExecuteNonQuery ( ) ;
2008-02-12 22:24:12 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
}
2008-06-26 01:12:28 +00:00
/// <summary>
/// Delete all item in a folder
/// </summary>
/// <param name="folderID">the folder UUID</param>
2008-09-06 07:52:41 +00:00
protected void deleteItemsInFolder ( UUID folderID )
2007-10-08 10:30:15 +00:00
{
try
{
2008-07-03 22:30:16 +00:00
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
MySqlCommand cmd =
new MySqlCommand ( "DELETE FROM inventoryitems WHERE parentFolderID=?uuid" , database . Connection ) ;
cmd . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2009-11-02 19:19:55 +00:00
lock ( database )
{
cmd . ExecuteNonQuery ( ) ;
2008-02-12 22:24:12 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
database . Reconnect ( ) ;
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
}
2007-10-06 08:23:51 +00:00
/// <summary>
2008-04-23 17:04:15 +00:00
/// Deletes an inventory folder
2007-10-06 08:23:51 +00:00
/// </summary>
/// <param name="folderId">Id of folder to delete</param>
2008-09-06 07:52:41 +00:00
public void deleteInventoryFolder ( UUID folderID )
2007-10-06 08:23:51 +00:00
{
2008-02-12 22:24:12 +00:00
List < InventoryFolderBase > subFolders = getFolderHierarchy ( folderID ) ;
2007-10-08 10:30:15 +00:00
2008-02-12 22:24:12 +00:00
//Delete all sub-folders
foreach ( InventoryFolderBase f in subFolders )
{
2008-04-07 23:27:05 +00:00
deleteOneFolder ( f . ID ) ;
deleteItemsInFolder ( f . ID ) ;
2007-10-08 10:30:15 +00:00
}
2008-02-12 22:24:12 +00:00
//Delete the actual row
deleteOneFolder ( folderID ) ;
deleteItemsInFolder ( folderID ) ;
2007-10-06 08:23:51 +00:00
}
2008-09-24 21:12:21 +00:00
public List < InventoryItemBase > fetchActiveGestures ( UUID avatarID )
{
2009-11-02 19:19:55 +00:00
MySqlDataReader result = null ;
MySqlCommand sqlCmd = null ;
2008-09-24 21:12:21 +00:00
lock ( database )
{
try
{
database . CheckConnection ( ) ;
2009-11-02 19:19:55 +00:00
sqlCmd = new MySqlCommand (
2009-10-04 20:57:51 +00:00
"SELECT * FROM inventoryitems WHERE avatarId = ?uuid AND assetType = ?type and flags = 1" ,
2009-11-02 19:19:55 +00:00
database . Connection ) ;
sqlCmd . Parameters . AddWithValue ( "?uuid" , avatarID . ToString ( ) ) ;
sqlCmd . Parameters . AddWithValue ( "?type" , ( int ) AssetType . Gesture ) ;
result = sqlCmd . ExecuteReader ( ) ;
2009-10-04 20:57:51 +00:00
2009-11-02 19:19:55 +00:00
List < InventoryItemBase > list = new List < InventoryItemBase > ( ) ;
while ( result . Read ( ) )
{
InventoryItemBase item = readInventoryItem ( result ) ;
if ( item ! = null )
list . Add ( item ) ;
2008-11-13 22:53:49 +00:00
}
2009-11-02 19:19:55 +00:00
return list ;
2008-09-24 21:12:21 +00:00
}
catch ( Exception e )
{
database . Reconnect ( ) ;
2009-11-02 19:19:55 +00:00
m_log . Error ( e . ToString ( ) ) ;
2008-09-24 21:12:21 +00:00
return null ;
}
2009-11-02 19:19:55 +00:00
finally
{
if ( result ! = null ) result . Close ( ) ;
if ( sqlCmd ! = null ) sqlCmd . Dispose ( ) ;
}
2008-09-24 21:12:21 +00:00
}
}
2007-07-16 15:40:11 +00:00
}
2008-03-18 05:16:43 +00:00
}