From 5e7dba726896fcb84882b53952651742926e6efb Mon Sep 17 00:00:00 2001 From: Tleiades Hax Date: Fri, 26 Oct 2007 11:46:27 +0000 Subject: Very early first implementation of grid based assets. Run this on a major grid, and weep --- .../Framework/Communications/Cache/AssetCache.cs | 11 +- .../Communications/Cache/AssetServerBase.cs | 36 ++--- .../Communications/Cache/GridAssetClient.cs | 160 +++++++++++++++++++ .../RestClient/GenericAsyncResult.cs | 2 +- .../Communications/RestClient/RestClient.cs | 101 ++++++++++-- OpenSim/Framework/Data.MySQL/MySQLAssetData.cs | 30 ++-- OpenSim/Framework/General/Types/AssetBase.cs | 2 + OpenSim/Grid/AssetServer/Main.cs | 170 +++++++++++++-------- OpenSim/Grid/AssetServer/RestService.cs | 109 +++++++++++++ OpenSim/Region/Application/OpenSimMain.cs | 4 + bin/OpenSimAssetSet.xml | 130 +++++++++++++++- prebuild.xml | 5 +- 12 files changed, 637 insertions(+), 123 deletions(-) create mode 100644 OpenSim/Framework/Communications/Cache/GridAssetClient.cs create mode 100644 OpenSim/Grid/AssetServer/RestService.cs diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs index 271934f..95183ad 100644 --- a/OpenSim/Framework/Communications/Cache/AssetCache.cs +++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs @@ -36,6 +36,7 @@ using libsecondlife.Packets; using OpenSim.Framework.Interfaces; using OpenSim.Framework.Types; using OpenSim.Framework.Utilities; +using OpenSim.Framework.Console; namespace OpenSim.Framework.Communications.Cache { @@ -319,17 +320,19 @@ namespace OpenSim.Framework.Communications.Cache public void AssetNotFound(LLUUID assetID) { - /* if (this.RequestedTextures.ContainsKey(assetID)) { + MainLog.Instance.Warn("ASSET CACHE", "sending image not found for {0}", assetID); AssetRequest req = this.RequestedTextures[assetID]; ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); notFound.ImageID.ID = assetID; req.RequestUser.OutPacket(notFound); - //Console.WriteLine("sending image not found for " + assetID); - this.RequestedTextures.Remove(assetID); - }*/ + } + else + { + MainLog.Instance.Error("ASSET CACHE", "Cound not send image not found for {0}", assetID); + } } #region Assets diff --git a/OpenSim/Framework/Communications/Cache/AssetServerBase.cs b/OpenSim/Framework/Communications/Cache/AssetServerBase.cs index a3ec346..53efa16 100644 --- a/OpenSim/Framework/Communications/Cache/AssetServerBase.cs +++ b/OpenSim/Framework/Communications/Cache/AssetServerBase.cs @@ -108,23 +108,23 @@ namespace OpenSim.Framework.Communications.Cache public virtual List GetDefaultAssets() { List assets = new List(); - - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000001", "Bricks", "bricks.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000002", "Plywood", "plywood.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000003", "Rocks", "rocks.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000004", "Granite", "granite.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000005", "Hardwood", "hardwood.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-5005-000000000005", "Prim Base Texture", "plywood.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000006", "Map Base Texture", "map_base.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000007", "Map Texture", "map1.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000010", "Female Body Texture", "femalebody.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000011", "Female Bottom Texture", "femalebottom.jp2")); - assets.Add(CreateImageAsset("00000000-0000-0000-9999-000000000012", "Female Face Texture", "femaleface.jp2")); - - assets.Add(CreateAsset("77c41e39-38f9-f75a-024e-585989bbabbb", "Skin", "base_skin.dat", false)); - assets.Add(CreateAsset("66c41e39-38f9-f75a-024e-585989bfab73", "Shape", "base_shape.dat", false)); - assets.Add(CreateAsset("00000000-38f9-1111-024e-222222111110", "Shirt", "newshirt.dat", false)); - assets.Add(CreateAsset("00000000-38f9-1111-024e-222222111120", "Shirt", "newpants.dat", false)); + // These assets have been moved into the OpenSimAssetSet.XML file + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000001", "Bricks", "bricks.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000002", "Plywood", "plywood.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000003", "Rocks", "rocks.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000004", "Granite", "granite.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000005", "Hardwood", "hardwood.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-5005-000000000005", "Prim Base Texture", "plywood.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000006", "Map Base Texture", "map_base.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000007", "Map Texture", "map1.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000010", "Female Body Texture", "femalebody.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000011", "Female Bottom Texture", "femalebottom.jp2")); + //assets.Add(CreateImageAsset("00000000-0000-1111-9999-000000000012", "Female Face Texture", "femaleface.jp2")); + + //assets.Add(CreateAsset("77c41e39-38f9-f75a-024e-585989bbabbb", "Skin", "base_skin.dat", false)); + //assets.Add(CreateAsset("66c41e39-38f9-f75a-024e-585989bfab73", "Shape", "base_shape.dat", false)); + //assets.Add(CreateAsset("00000000-38f9-1111-024e-222222111110", "Shirt", "newshirt.dat", false)); + //assets.Add(CreateAsset("00000000-38f9-1111-024e-222222111120", "Shirt", "newpants.dat", false)); return assets; } @@ -185,4 +185,4 @@ namespace OpenSim.Framework.Communications.Cache } } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Communications/Cache/GridAssetClient.cs b/OpenSim/Framework/Communications/Cache/GridAssetClient.cs new file mode 100644 index 0000000..fc77431 --- /dev/null +++ b/OpenSim/Framework/Communications/Cache/GridAssetClient.cs @@ -0,0 +1,160 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.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. +* * Neither the name of the OpenSim Project nor the +* 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.IO; +using System.Threading; +using System.Reflection; +using System.Xml.Serialization; + +using libsecondlife; + +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Framework.Interfaces; +using OpenSim.Framework.Types; +using OpenSim.Framework.Utilities; +using OpenSim.Framework.Communications; + +namespace OpenSim.Framework.Communications.Cache +{ + public class GridAssetClient : IAssetServer + { + private string _assetServerUrl; + private IAssetReceiver _receiver; + + public GridAssetClient(string serverUrl) + { + _assetServerUrl = serverUrl; + } + + #region IAssetServer Members + + public void SetReceiver(IAssetReceiver receiver) + { + _receiver = receiver; + } + + public void FetchAsset(LLUUID assetID, bool isTexture) + { + Stream s = null; + try + { + + MainLog.Instance.Debug("ASSETCACHE", "Querying for {0}", assetID.ToString()); + + RestClient rc = new RestClient(_assetServerUrl); + rc.AddResourcePath("assets"); + rc.AddResourcePath(assetID.ToString()); + if (isTexture) + rc.AddQueryParameter("texture"); + + rc.RequestMethod = "GET"; + s = rc.Request(); + + if (s.Length > 0) + { + XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + AssetBase asset = (AssetBase)xs.Deserialize(s); + + _receiver.AssetReceived(asset, isTexture); + } + else + { + MainLog.Instance.Debug("ASSETCACHE", "Asset not found {0}", assetID.ToString()); + _receiver.AssetNotFound(assetID); + } + } + catch (Exception e) + { + MainLog.Instance.Error("ASSETCACHE", e.Message); + MainLog.Instance.Error("ASSETCACHE", e.StackTrace); + } + } + + public void UpdateAsset(AssetBase asset) + { + throw new Exception("The method or operation is not implemented."); + } + + public void StoreAndCommitAsset(AssetBase asset) + { + try + { + MemoryStream s = new MemoryStream(); + + XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + xs.Serialize(s, asset); + RestClient rc = new RestClient(_assetServerUrl); + rc.AddResourcePath("assets"); + rc.RequestMethod = "POST"; + rc.Request(s); + } + catch (Exception e) + { + MainLog.Instance.Error("ASSETS", e.Message); + } + } + + public void Close() + { + throw new Exception("The method or operation is not implemented."); + } + + public void LoadAsset(AssetBase info, bool image, string filename) + { + throw new Exception("The method or operation is not implemented."); + } + + public System.Collections.Generic.List GetDefaultAssets() + { + throw new Exception("The method or operation is not implemented."); + } + + public AssetBase CreateImageAsset(string assetIdStr, string name, string filename) + { + throw new Exception("The method or operation is not implemented."); + } + + public void ForEachDefaultAsset(Action action) + { + throw new Exception("The method or operation is not implemented."); + } + + public AssetBase CreateAsset(string assetIdStr, string name, string filename, bool isImage) + { + throw new Exception("The method or operation is not implemented."); + } + + public void ForEachXmlAsset(Action action) + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + } +} diff --git a/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs b/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs index 55456ae..c821fa4 100644 --- a/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs +++ b/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading; -namespace OpenSim.Framework.RestClient +namespace OpenSim.Framework.Communications { internal class SimpleAsyncResult : IAsyncResult { diff --git a/OpenSim/Framework/Communications/RestClient/RestClient.cs b/OpenSim/Framework/Communications/RestClient/RestClient.cs index 25fc61a..392669f 100644 --- a/OpenSim/Framework/Communications/RestClient/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient/RestClient.cs @@ -6,7 +6,9 @@ using System.Text; using System.Collections.Generic; using System.Threading; -namespace OpenSim.Framework.RestClient +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications { /// /// Implementation of a generic REST client @@ -25,8 +27,11 @@ namespace OpenSim.Framework.RestClient /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be /// invoked by the caller in either synchroneous mode or asynchroneous mode. /// - public class RestClient + public class RestClient { + + string realuri; + #region member variables /// /// The base Uri of the web-service e.g. http://www.google.com /// @@ -55,7 +60,7 @@ namespace OpenSim.Framework.RestClient /// /// MemoryStream representing the resultiong resource /// - MemoryStream _resource; + Stream _resource; /// /// WebRequest object, held as a member variable @@ -89,6 +94,9 @@ namespace OpenSim.Framework.RestClient /// private Exception _asyncException; + #endregion member variables + + #region constructors /// /// Instantiate a new RestClient /// @@ -100,8 +108,12 @@ namespace OpenSim.Framework.RestClient _resource = new MemoryStream(); _request = null; _response = null; + _lock = new object(); } + object _lock; + #endregion constructors + /// /// Add a path element to the query, e.g. assets /// @@ -125,6 +137,15 @@ namespace OpenSim.Framework.RestClient } /// + /// Add a query parameter to the Url + /// + /// Name of the parameter, e.g. min + public void AddQueryParameter(string name) + { + _parameterElements.Add(HttpUtility.UrlEncode(name), null); + } + + /// /// Web-Request method, e.g. GET, PUT, POST, DELETE /// public string RequestMethod @@ -185,9 +206,10 @@ namespace OpenSim.Framework.RestClient sb.Append(kv.Value); } } + realuri = sb.ToString(); return new Uri(sb.ToString()); } - + #region Async communications with server /// /// Async method, invoked when a block of data has been received from the service /// @@ -199,7 +221,6 @@ namespace OpenSim.Framework.RestClient Stream s = (Stream)ar.AsyncState; int read = s.EndRead(ar); - // Read the HTML page and then print it to the console. if (read > 0) { _resource.Write(_readbuf, 0, read); @@ -207,7 +228,6 @@ namespace OpenSim.Framework.RestClient // TODO! Implement timeout, without killing the server //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); - return; } else { @@ -261,32 +281,83 @@ namespace OpenSim.Framework.RestClient } } } + #endregion Async communications with server /// /// Perform synchroneous request /// public Stream Request() { + lock (_lock) + { + _request = (HttpWebRequest)WebRequest.Create(buildUri()); + _request.KeepAlive = false; + _request.ContentType = "application/xml"; + _request.Timeout = 200000; + _asyncException = null; + +// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); + _response = (HttpWebResponse)_request.GetResponse(); + Stream src = _response.GetResponseStream(); + int length = src.Read(_readbuf, 0, BufferSize); + while(length > 0) + { + _resource.Write(_readbuf, 0, length); + length = src.Read(_readbuf, 0, BufferSize); + } + + + // TODO! Implement timeout, without killing the server + // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted + //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + +// _allDone.WaitOne(); + if (_response != null) + _response.Close(); + if (_asyncException != null) + throw _asyncException; + + if (_resource != null) + { + _resource.Flush(); + _resource.Seek(0, SeekOrigin.Begin); + } + + return _resource; + } + } + + public Stream Request(Stream src) + { _request = (HttpWebRequest)WebRequest.Create(buildUri()); _request.KeepAlive = false; - _request.ContentType = "text/html"; - _request.Timeout = 200; + _request.ContentType = "application/xml"; + _request.Timeout = 900000; + _request.Method = RequestMethod; _asyncException = null; + _request.ContentLength = src.Length; - IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); + src.Seek(0, SeekOrigin.Begin); + Stream dst = _request.GetRequestStream(); + byte[] buf = new byte[1024]; + int length = src.Read(buf,0, 1024); + while (length > 0) + { + dst.Write(buf, 0, length); + length = src.Read(buf, 0, 1024); + } + _response = (HttpWebResponse)_request.GetResponse(); + +// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); // TODO! Implement timeout, without killing the server // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); - _allDone.WaitOne(); - if(_response != null) - _response.Close(); - if (_asyncException != null) - throw _asyncException; - return _resource; + return null; } + #region Async Invocation public IAsyncResult BeginRequest(AsyncCallback callback, object state) { diff --git a/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs b/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs index a8f0fdb..0112474 100644 --- a/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs +++ b/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs @@ -71,22 +71,24 @@ namespace OpenSim.Framework.Data.MySQL public AssetBase FetchAsset(LLUUID assetID) { AssetBase asset = null; - - MySqlCommand cmd = new MySqlCommand("SELECT name, description, assetType, invType, local, temporary, data FROM assets WHERE id=?id", _dbConnection.Connection); - MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16); - p.Value = assetID.GetBytes(); - using (MySqlDataReader dbReader = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow)) + lock (_dbConnection) { - if (dbReader.Read()) + MySqlCommand cmd = new MySqlCommand("SELECT name, description, assetType, invType, local, temporary, data FROM assets WHERE id=?id", _dbConnection.Connection); + MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16); + p.Value = assetID.GetBytes(); + using (MySqlDataReader dbReader = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow)) { - asset = new AssetBase(); - asset.Data = (byte[])dbReader["data"]; - asset.Description = (string)dbReader["description"]; - asset.FullID = assetID; - asset.InvType = (sbyte)dbReader["invType"]; - asset.Local = ((sbyte)dbReader["local"]) != 0 ? true : false; - asset.Name = (string)dbReader["name"]; - asset.Type = (sbyte)dbReader["assetType"]; + if (dbReader.Read()) + { + asset = new AssetBase(); + asset.Data = (byte[])dbReader["data"]; + asset.Description = (string)dbReader["description"]; + asset.FullID = assetID; + asset.InvType = (sbyte)dbReader["invType"]; + asset.Local = ((sbyte)dbReader["local"]) != 0 ? true : false; + asset.Name = (string)dbReader["name"]; + asset.Type = (sbyte)dbReader["assetType"]; + } } } return asset; diff --git a/OpenSim/Framework/General/Types/AssetBase.cs b/OpenSim/Framework/General/Types/AssetBase.cs index 628724d..c34887c 100644 --- a/OpenSim/Framework/General/Types/AssetBase.cs +++ b/OpenSim/Framework/General/Types/AssetBase.cs @@ -25,10 +25,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +using System; using libsecondlife; namespace OpenSim.Framework.Types { + [Serializable] public class AssetBase { public byte[] Data; diff --git a/OpenSim/Grid/AssetServer/Main.cs b/OpenSim/Grid/AssetServer/Main.cs index 9f1f9a2..dabacd4 100644 --- a/OpenSim/Grid/AssetServer/Main.cs +++ b/OpenSim/Grid/AssetServer/Main.cs @@ -28,15 +28,18 @@ using System; using System.IO; +using System.Reflection; using libsecondlife; +using Nini.Config; + +using OpenSim.Framework.Types; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Configuration; using OpenSim.Framework.Console; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Configuration; using OpenSim.Framework.Interfaces; using OpenSim.Framework.Utilities; +using OpenSim.Framework.Servers; /* using System.Text; @@ -57,7 +60,7 @@ namespace OpenSim.Grid.AssetServer public static OpenAsset_Main assetserver; private LogBase m_console; - private IAssetServer m_assetServer; + private IAssetProvider m_assetProvider; [STAThread] public static void Main(string[] args) @@ -97,11 +100,14 @@ namespace OpenSim.Grid.AssetServer m_console.Verbose("ASSET", "Setting up asset DB"); setupDB(m_config); + m_console.Verbose("ASSET", "Loading default asset set.."); + LoadDefaultAssets(); + m_console.Verbose("ASSET", "Starting HTTP process"); BaseHttpServer httpServer = new BaseHttpServer((int)m_config.HttpPort); - httpServer.AddStreamHandler(new GetAssetStreamHandler(this)); - httpServer.AddStreamHandler(new PostAssetStreamHandler( this )); + httpServer.AddStreamHandler(new GetAssetStreamHandler(this, m_assetProvider)); + httpServer.AddStreamHandler(new PostAssetStreamHandler(this, m_assetProvider)); httpServer.Start(); } @@ -111,14 +117,49 @@ namespace OpenSim.Grid.AssetServer return null; } + + public IAssetProvider LoadDatabasePlugin(string FileName) + { + MainLog.Instance.Verbose("ASSET SERVER", "LoadDatabasePlugin: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + IAssetProvider assetPlugin = null; + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IAssetProvider", true); + + if (typeInterface != null) + { + IAssetProvider plug = (IAssetProvider)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + assetPlugin = plug; + assetPlugin.Initialise(); + + MainLog.Instance.Verbose("ASSET SERVER", "Added " + assetPlugin.Name + " " + assetPlugin.Version); + break; + } + + typeInterface = null; + } + } + + pluginAssembly = null; + return assetPlugin; + } + public void setupDB(AssetConfig config) { try { - SQLAssetServer assetServer = new SQLAssetServer(config.DatabaseProvider ); - assetServer.LoadDefaultAssets(); + m_assetProvider = LoadDatabasePlugin(config.DatabaseProvider); + if (m_assetProvider == null) + { + MainLog.Instance.Error("ASSET", "Failed to load a database plugin, server halting"); + Environment.Exit(-1); + } +// assetServer.LoadDefaultAssets(); - m_assetServer = assetServer; +// m_assetServer = assetServer; } catch (Exception e) { @@ -127,84 +168,89 @@ namespace OpenSim.Grid.AssetServer } } - public void RunCmd(string cmd, string[] cmdparams) + public void LoadAsset(AssetBase info, bool image, string filename) { - switch (cmd) - { - case "help": - m_console.Notice("shutdown - shutdown this asset server (USE CAUTION!)"); - break; - - case "shutdown": - m_console.Close(); - Environment.Exit(0); - break; - } - } + //should request Asset from storage manager + //but for now read from file - public void Show(string ShowWhat) - { + string dataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assets"); //+ folder; + string fileName = Path.Combine(dataPath, filename); + FileInfo fInfo = new FileInfo(fileName); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); + byte[] idata = new byte[numBytes]; + BinaryReader br = new BinaryReader(fStream); + idata = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + info.Data = idata; + //info.loaded=true; } - } - public class GetAssetStreamHandler : BaseStreamHandler - { - OpenAsset_Main m_assetManager; - - override public byte[] Handle(string path, Stream request) + public AssetBase CreateAsset(string assetIdStr, string name, string filename, bool isImage) { - string param = GetParam(path); + AssetBase asset = new AssetBase( + new LLUUID(assetIdStr), + name + ); - byte[] assetdata = m_assetManager.GetAssetData(new LLUUID(param), false); - if (assetdata != null) + if (!String.IsNullOrEmpty(filename)) { - return assetdata; + MainLog.Instance.Verbose("ASSETS", "Loading: [{0}][{1}]", name, filename); + + LoadAsset(asset, isImage, filename); } else { - return new byte[]{}; + MainLog.Instance.Verbose("ASSETS", "Instantiated: [{0}]", name); } - } - public GetAssetStreamHandler(OpenAsset_Main assetManager) : base("/assets/", "GET") - { - m_assetManager = assetManager; + return asset; } - } - - public class PostAssetStreamHandler : BaseStreamHandler - { - OpenAsset_Main m_assetManager; - override public byte[] Handle(string path, Stream request) + public void LoadDefaultAssets() { - string param = GetParam(path); - LLUUID assetId = new LLUUID(param); - byte[] txBuffer = new byte[4096]; - - using( BinaryReader binReader = new BinaryReader( request ) ) + string filePath = Path.Combine(Util.configDir(), "OpenSimAssetSet.xml"); + if (File.Exists(filePath)) { - using (MemoryStream memoryStream = new MemoryStream(4096)) + XmlConfigSource source = new XmlConfigSource(filePath); + + for (int i = 0; i < source.Configs.Count; i++) { - int count; - while ((count = binReader.Read(txBuffer, 0, 4096)) > 0) - { - memoryStream.Write(txBuffer, 0, count); - } + string assetIdStr = source.Configs[i].GetString("assetID", LLUUID.Random().ToStringHyphenated()); + string name = source.Configs[i].GetString("name", ""); + sbyte type = (sbyte)source.Configs[i].GetInt("assetType", 0); + sbyte invType = (sbyte)source.Configs[i].GetInt("inventoryType", 0); + string fileName = source.Configs[i].GetString("fileName", ""); + + AssetBase newAsset = CreateAsset(assetIdStr, name, fileName, false); - byte[] assetData = memoryStream.ToArray(); + newAsset.Type = type; + newAsset.InvType = invType; -// m_assetManager.CreateAsset(assetId, assetData); + m_assetProvider.CreateAsset(newAsset); } } - - return new byte[]{}; } - public PostAssetStreamHandler( OpenAsset_Main assetManager ) - : base("/assets/", "POST") + + public void RunCmd(string cmd, string[] cmdparams) + { + switch (cmd) + { + case "help": + m_console.Notice("shutdown - shutdown this asset server (USE CAUTION!)"); + break; + + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + + public void Show(string ShowWhat) { - m_assetManager = assetManager; } } } diff --git a/OpenSim/Grid/AssetServer/RestService.cs b/OpenSim/Grid/AssetServer/RestService.cs new file mode 100644 index 0000000..88a1668 --- /dev/null +++ b/OpenSim/Grid/AssetServer/RestService.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using System.Xml; +using System.Xml.Serialization; +using System.Text; + +using libsecondlife; +using OpenSim.Framework.Types; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Interfaces; +using OpenSim.Framework.Console; + +namespace OpenSim.Grid.AssetServer +{ + public class GetAssetStreamHandler : BaseStreamHandler + { + OpenAsset_Main m_assetManager; + IAssetProvider m_assetProvider; + + override public byte[] Handle(string path, Stream request) + { + string param = GetParam(path); + byte[] result = new byte[] { }; + try { + + string[] p = param.Split(new char[] { '/', '?', '&' }, StringSplitOptions.RemoveEmptyEntries); + + if (p.Length > 0) + { + LLUUID assetID; + bool isTexture = false; + LLUUID.TryParse(p[0], out assetID); + if (p.Length > 1) + { + if (string.Compare(p[1], "texture", true) == 0) + isTexture = true; + } + + + AssetBase asset = m_assetProvider.FetchAsset(assetID); + if (asset != null) + { + MainLog.Instance.Debug("REST", "GET:/asset found {0}, {1}", assetID, asset.Name); + + XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8); + xw.Formatting = Formatting.Indented; + xs.Serialize(xw, asset); + xw.Flush(); + + ms.Seek(0, SeekOrigin.Begin); + StreamReader sr = new StreamReader(ms); + + result = ms.GetBuffer(); + Array.Resize(ref result, (int)ms.Length); + } + else + { + MainLog.Instance.Verbose("REST", "GET:/asset failed to find {0}", assetID); + } + } + } + catch (Exception e) + { + MainLog.Instance.Error(e.ToString()); + } + return result; + } + + public GetAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) + : base("GET", "/assets" ) + { + m_assetManager = assetManager; + m_assetProvider = assetProvider; + } + } + + public class PostAssetStreamHandler : BaseStreamHandler + { + OpenAsset_Main m_assetManager; + IAssetProvider m_assetProvider; + + override public byte[] Handle(string path, Stream request) + { + string param = GetParam(path); + + LLUUID assetId; + if(param.Length > 0) + LLUUID.TryParse(param, out assetId); + byte[] txBuffer = new byte[4096]; + + XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + AssetBase asset = (AssetBase)xs.Deserialize(request); + + MainLog.Instance.Verbose("REST", "StoreAndCommitAsset {0}", asset.FullID); + m_assetProvider.CreateAsset(asset); + + return new byte[] { }; + } + + public PostAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) + : base("POST", "/assets") + { + m_assetManager = assetManager; + m_assetProvider = assetProvider; + } + } +} diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index 55913a8..f550ee2 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -301,6 +301,10 @@ namespace OpenSim { assetServer = new LocalAssetServer(); } + else if (m_assetStorage == "grid") + { + assetServer = new GridAssetClient(m_networkServersInfo.AssetURL); + } else { SQLAssetServer sqlAssetServer = new SQLAssetServer(standaloneAssetPlugin); diff --git a/bin/OpenSimAssetSet.xml b/bin/OpenSimAssetSet.xml index ede5d30..07b8e8b 100644 --- a/bin/OpenSimAssetSet.xml +++ b/bin/OpenSimAssetSet.xml @@ -2,16 +2,16 @@
- - - + + +
- - - + + +
@@ -335,4 +335,120 @@
- \ No newline at end of file + +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+ diff --git a/prebuild.xml b/prebuild.xml index 57ace78..bc1cc78 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -808,8 +808,7 @@ - - + @@ -1053,3 +1052,5 @@ + + -- cgit v1.1