From a2f07ecd2e248966957a8ea70d772276359b02e8 Mon Sep 17 00:00:00 2001 From: Mike Mazur Date: Mon, 9 Mar 2009 07:29:34 +0000 Subject: Implemented FetchAssetMetadataSet in DB backends. This method fetches metadata for a subset of the entries in the assets database. This functionality is used in the ForEach calls in the asset storage providers in AssetInventoryServer. With this implemented, frontends such as the BrowseFrontend should now work. - MySQL: implemented, sanity tested - SQLite: implemented, sanity tested - MSSQL: implemented, not tested - NHibernate: not implemented --- OpenSim/Data/AssetDataBase.cs | 3 + OpenSim/Data/IAssetData.cs | 2 + OpenSim/Data/MSSQL/MSSQLAssetData.cs | 36 ++++ OpenSim/Data/MySQL/MySQLAssetData.cs | 51 ++++++ OpenSim/Data/NHibernate/NHibernateAssetData.cs | 15 ++ OpenSim/Data/SQLite/SQLiteAssetData.cs | 50 ++++++ .../Plugins/BrowseFrontendPlugin.cs | 185 ++++++++++----------- .../Plugins/OpenSim/OpenSimAssetStoragePlugin.cs | 48 ++---- OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs | 2 + 9 files changed, 256 insertions(+), 136 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs index 2cdbbe1..d699f17 100644 --- a/OpenSim/Data/AssetDataBase.cs +++ b/OpenSim/Data/AssetDataBase.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; @@ -37,6 +38,8 @@ namespace OpenSim.Data public abstract void UpdateAsset(AssetBase asset); public abstract bool ExistsAsset(UUID uuid); + public abstract List FetchAssetMetadataSet(int start, int count); + public abstract string Version { get; } public abstract string Name { get; } public abstract void Initialise(string connect); diff --git a/OpenSim/Data/IAssetData.cs b/OpenSim/Data/IAssetData.cs index 47e25f3..ddbc10f 100644 --- a/OpenSim/Data/IAssetData.cs +++ b/OpenSim/Data/IAssetData.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; @@ -36,6 +37,7 @@ namespace OpenSim.Data void CreateAsset(AssetBase asset); void UpdateAsset(AssetBase asset); bool ExistsAsset(UUID uuid); + List FetchAssetMetadataSet(int start, int count); void Initialise(string connect); } diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index 61db8f5..edacf08 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs @@ -28,6 +28,7 @@ using System; using System.Data; using System.Reflection; +using System.Collections.Generic; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -245,6 +246,41 @@ namespace OpenSim.Data.MSSQL return false; } + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + + using (AutoClosingSqlCommand command = database.Query("SELECT name,description,assetType,temporary,id FROM assets LIMIT @start, @count")) + { + command.Parameters.Add(database.CreateParameter("start", start)); + command.Parameters.Add(database.CreateParameter("count", count)); + + using (IDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + AssetMetadata metadata = new AssetMetadata(); + // Region Main + metadata.FullID = new UUID((Guid)reader["id"]); + metadata.Name = (string)reader["name"]; + metadata.Description = (string)reader["description"]; + metadata.Type = Convert.ToSByte(reader["assetType"]); + metadata.Temporary = Convert.ToBoolean(reader["temporary"]); + } + } + } + + return retList; + } + #endregion } } diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index 2211d4c..466f5db 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs @@ -28,6 +28,7 @@ using System; using System.Data; using System.Reflection; +using System.Collections.Generic; using log4net; using MySql.Data.MySqlClient; using OpenMetaverse; @@ -311,6 +312,56 @@ namespace OpenSim.Data.MySQL return assetExists; } + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + + lock (_dbConnection) + { + _dbConnection.CheckConnection(); + + MySqlCommand cmd = new MySqlCommand("SELECT name,description,assetType,temporary,id FROM assets LIMIT ?start, ?count", _dbConnection.Connection); + cmd.Parameters.AddWithValue("?start", start); + cmd.Parameters.AddWithValue("?count", count); + + try + { + using (MySqlDataReader dbReader = cmd.ExecuteReader()) + { + while (dbReader.Read()) + { + AssetMetadata metadata = new AssetMetadata(); + metadata.Name = (string) dbReader["name"]; + metadata.Description = (string) dbReader["description"]; + metadata.Type = (sbyte) dbReader["assetType"]; + metadata.Temporary = (bool) dbReader["temporary"]; // Not sure if this is correct. + metadata.FullID = new UUID((string) dbReader["id"]); + + // Current SHA1s are not stored/computed. + metadata.SHA1 = new byte[] {}; + + retList.Add(metadata); + } + } + } + catch (Exception e) + { + m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString() + Environment.NewLine + "Attempting reconnection"); + _dbConnection.Reconnect(); + } + } + + return retList; + } + #endregion /// diff --git a/OpenSim/Data/NHibernate/NHibernateAssetData.cs b/OpenSim/Data/NHibernate/NHibernateAssetData.cs index 387d3d4..4e8f708 100644 --- a/OpenSim/Data/NHibernate/NHibernateAssetData.cs +++ b/OpenSim/Data/NHibernate/NHibernateAssetData.cs @@ -26,6 +26,7 @@ */ using System.Reflection; +using System.Collections.Generic; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -109,6 +110,20 @@ namespace OpenSim.Data.NHibernate return (FetchAsset(uuid) != null); } + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + return retList; + } + public void DeleteAsset(UUID uuid) { diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index 1b42198..6a323e1 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -28,6 +28,7 @@ using System; using System.Data; using System.Reflection; +using System.Collections.Generic; using log4net; using Mono.Data.SqliteClient; using OpenMetaverse; @@ -49,6 +50,7 @@ namespace OpenSim.Data.SQLite /// Artificial constructor called upon plugin load /// private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; + private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count"; private const string DeleteAssetSQL = "delete from assets where UUID=:UUID"; private const string InsertAssetSQL = "insert into assets(UUID, Name, Description, Type, Local, Temporary, Data) values(:UUID, :Name, :Description, :Type, :Local, :Temporary, :Data)"; private const string UpdateAssetSQL = "update assets set Name=:Name, Description=:Description, Type=:Type, Local=:Local, Temporary=:Temporary, Data=:Data where UUID=:UUID"; @@ -256,6 +258,54 @@ namespace OpenSim.Data.SQLite return asset; } + private static AssetMetadata buildAssetMetadata(IDataReader row) + { + AssetMetadata metadata = new AssetMetadata(); + + metadata.FullID = new UUID((string) row["UUID"]); + metadata.Name = (string) row["Name"]; + metadata.Description = (string) row["Description"]; + metadata.Type = Convert.ToSByte(row["Type"]); + metadata.Temporary = Convert.ToBoolean(row["Temporary"]); // Not sure if this is correct. + + // Current SHA1s are not stored/computed. + metadata.SHA1 = new byte[] {}; + + return metadata; + } + + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetMetadataSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":start", start)); + cmd.Parameters.Add(new SqliteParameter(":count", count)); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + AssetMetadata metadata = buildAssetMetadata(reader); + retList.Add(metadata); + } + } + } + } + + return retList; + } /*********************************************************************** * diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/BrowseFrontendPlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/BrowseFrontendPlugin.cs index 6e7519d..34b0565 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/BrowseFrontendPlugin.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/BrowseFrontendPlugin.cs @@ -42,7 +42,7 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins public class BrowseFrontendPlugin : IAssetInventoryServerPlugin { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - //private AssetInventoryServer m_server; + private AssetInventoryServer m_server; public BrowseFrontendPlugin() { @@ -52,10 +52,10 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins public void Initialise(AssetInventoryServer server) { - //m_server = server; + m_server = server; // Request for / or /?... - //m_server.HttpServer.AddStreamHandler(new BrowseRequestHandler(server)); + m_server.HttpServer.AddStreamHandler(new BrowseRequestHandler(server)); m_log.Info("[BROWSEFRONTEND]: Browser Frontend loaded."); } @@ -86,102 +86,87 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins #endregion IPlugin implementation - //public class BrowseRequestHandler : IStreamedRequestHandler - //{ - // AssetInventoryServer m_server; - // string m_contentType; - // string m_httpMethod; - // string m_path; - - // public BrowseRequestHandler(AssetInventoryServer server) - // { - // m_server = server; - // m_contentType = null; - // m_httpMethod = "GET"; - // m_path = @"(^/$)|(^/\?.*)"; - // } - - // #region IStreamedRequestHandler implementation - - // public string ContentType - // { - // get { return m_contentType; } - // } - - // public string HttpMethod - // { - // get { return m_httpMethod; } - // } - - // public string Path - // { - // get { return m_path; } - // } - - // public byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) - // { - // const int ASSETS_PER_PAGE = 25; - // const string HEADER = "Asset Server"; - // const string TABLE_HEADER = - // ""; - // const string TABLE_FOOTER = "
NameDescriptionTypeIDTemporarySHA-1
"; - // const string FOOTER = ""; - - // UUID authToken = Utils.GetAuthToken(httpRequest); - - // StringBuilder html = new StringBuilder(); - // int start = 0; - // uint page = 0; - - // if (!String.IsNullOrEmpty(httpRequest.Url.Query)) - // { - // NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); - // if (!String.IsNullOrEmpty(query["page"]) && UInt32.TryParse(query["page"], out page)) - // start = (int)page * ASSETS_PER_PAGE; - // } - - // html.AppendLine(HEADER); - - // html.AppendLine("

"); - // if (page > 0) - // html.AppendFormat("< Previous Page | ", httpRequest.RawUrl, page - 1); - // html.AppendFormat("Next Page >", httpRequest.RawUrl, page + 1); - // html.AppendLine("

"); - - // html.AppendLine(TABLE_HEADER); - - // m_server.StorageProvider.ForEach( - // delegate(Metadata data) - // { - // if (m_server.AuthorizationProvider.IsMetadataAuthorized(authToken, data.ID)) - // { - // html.AppendLine(String.Format( - // "{0}{1}{2}{3}{4}{5}", - // data.Name, data.Description, data.ContentType, data.ID, data.Temporary, - // BitConverter.ToString(data.SHA1).Replace("-", String.Empty))); - // } - // else - // { - // html.AppendLine(String.Format( - // "[Protected Asset]  {0}{1} ", - // data.ID, data.Temporary)); - // } - // }, start, ASSETS_PER_PAGE - // ); - - // html.AppendLine(TABLE_FOOTER); - - // html.AppendLine(FOOTER); - - // byte[] responseData = System.Text.Encoding.UTF8.GetBytes(html.ToString()); - - // httpResponse.StatusCode = (int) HttpStatusCode.OK; - // httpResponse.Body.Write(responseData, 0, responseData.Length); - // httpResponse.Body.Flush(); - // return responseData; - // } - - // #endregion IStreamedRequestHandler implementation - //} + public class BrowseRequestHandler : BaseStreamHandler + { + AssetInventoryServer m_server; + + //public BrowseRequestHandler(AssetInventoryServer server) : base("GET", "(^/$|(^/\?.*)") + public BrowseRequestHandler(AssetInventoryServer server) : base("GET", "/") + { + m_server = server; + } + + public override string ContentType + { + get { return "text/html"; } + } + + #region IStreamedRequestHandler implementation + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + const int ASSETS_PER_PAGE = 25; + const string HEADER = "Asset Server"; + const string TABLE_HEADER = + ""; + const string TABLE_FOOTER = "
NameDescriptionTypeIDTemporarySHA-1
"; + const string FOOTER = ""; + + UUID authToken = Utils.GetAuthToken(httpRequest); + + StringBuilder html = new StringBuilder(); + int start = 0; + uint page = 0; + + if (!String.IsNullOrEmpty(httpRequest.Url.Query)) + { + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + if (!String.IsNullOrEmpty(query["page"]) && UInt32.TryParse(query["page"], out page)) + start = (int)page * ASSETS_PER_PAGE; + } + + html.AppendLine(HEADER); + + html.AppendLine("

"); + if (page > 0) + html.AppendFormat("< Previous Page | ", httpRequest.RawUrl, page - 1); + html.AppendFormat("Next Page >", httpRequest.RawUrl, page + 1); + html.AppendLine("

"); + + html.AppendLine(TABLE_HEADER); + + m_server.StorageProvider.ForEach( + delegate(AssetMetadata data) + { + if (m_server.AuthorizationProvider.IsMetadataAuthorized(authToken, data.FullID)) + { + html.AppendLine(String.Format( + "{0}{1}{2}{3}{4}{5}", + data.Name, data.Description, data.ContentType, data.ID, data.Temporary, + BitConverter.ToString(data.SHA1).Replace("-", String.Empty))); + } + else + { + html.AppendLine(String.Format( + "[Protected Asset]  {0}{1} ", + data.ID, data.Temporary)); + } + }, start, ASSETS_PER_PAGE + ); + + html.AppendLine(TABLE_FOOTER); + + html.AppendLine(FOOTER); + + byte[] responseData = System.Text.Encoding.UTF8.GetBytes(html.ToString()); + + httpResponse.StatusCode = (int) HttpStatusCode.OK; + //httpResponse.Body.Write(responseData, 0, responseData.Length); + //httpResponse.Body.Flush(); + return responseData; + } + + #endregion IStreamedRequestHandler implementation + } } } diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs index dcacab2..4b0dd7f 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs @@ -28,6 +28,7 @@ using System; using System.Reflection; using System.Data; +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -117,42 +118,17 @@ namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim { int rowCount = 0; - //using (MySqlConnection dbConnection = new MySqlConnection(m_openSimConfig.GetString("asset_database_connect"))) - //{ - // MySqlDataReader reader; - - // try - // { - // dbConnection.Open(); - - // MySqlCommand command = dbConnection.CreateCommand(); - // command.CommandText = String.Format("SELECT name,description,assetType,temporary,data,id FROM assets LIMIT {0}, {1}", - // start, count); - // reader = command.ExecuteReader(); - // } - // catch (MySqlException ex) - // { - // m_log.Error("[OPENSIMASSETSTORAGE]: Connection to MySQL backend failed: " + ex.Message); - // return 0; - // } - - // while (reader.Read()) - // { - // Metadata metadata = new Metadata(); - // metadata.CreationDate = OpenMetaverse.Utils.Epoch; - // metadata.Description = reader.GetString(1); - // metadata.ID = UUID.Parse(reader.GetString(5)); - // metadata.Name = reader.GetString(0); - // metadata.SHA1 = OpenMetaverse.Utils.SHA1((byte[])reader.GetValue(4)); - // metadata.Temporary = reader.GetBoolean(3); - // metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2)); - - // action(metadata); - // ++rowCount; - // } - - // reader.Close(); - //} + foreach (AssetMetadata metadata in m_assetProvider.FetchAssetMetadataSet(start, count)) + { + // We set the ContentType here because Utils is only in + // AssetInventoryServer. This should be moved to the DB + // backends when the equivalent of SLAssetTypeToContentType is + // in OpenSim.Framework or similar. + metadata.ContentType = Utils.SLAssetTypeToContentType(metadata.Type); + + action(metadata); + ++rowCount; + } return rowCount; } diff --git a/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs index fc84eac..d6bce5b 100644 --- a/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -48,6 +49,7 @@ namespace OpenSim.Tests.Common.Mock public void CreateAsset(AssetBase asset) {} public void UpdateAsset(AssetBase asset) {} public bool ExistsAsset(UUID uuid) { return false; } + public List FetchAssetMetadataSet(int start, int count) { return new List(count); } public void Initialise(string connect) {} } } -- cgit v1.1