- added Simple AssetInventoryServer plugin (asset storage only)
- removed OpenSim storage and frontend classes in Extensions dir - put OpenSim plugins in OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim namespace0.6.3-post-fixes
parent
dbee7fcb21
commit
3f3dfd7ac1
|
@ -106,8 +106,8 @@ namespace OpenSim.Grid.AssetInventoryServer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/StorageProvider") as IAssetStorageProvider;
|
StorageProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/StorageProvider", "OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll") as IAssetStorageProvider;
|
||||||
MetricsProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/MetricsProvider") as IMetricsProvider;
|
MetricsProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/MetricsProvider", "") as IMetricsProvider;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ namespace OpenSim.Grid.AssetInventoryServer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/Frontend");
|
frontend = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/Frontend", "");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -179,13 +179,16 @@ namespace OpenSim.Grid.AssetInventoryServer
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private IAssetInventoryServerPlugin LoadAssetInventoryServerPlugin(string addinPath)
|
private IAssetInventoryServerPlugin LoadAssetInventoryServerPlugin(string addinPath, string provider)
|
||||||
{
|
{
|
||||||
PluginLoader<IAssetInventoryServerPlugin> loader = new PluginLoader<IAssetInventoryServerPlugin>(new AssetInventoryServerPluginInitialiser(this));
|
PluginLoader<IAssetInventoryServerPlugin> loader = new PluginLoader<IAssetInventoryServerPlugin>(new AssetInventoryServerPluginInitialiser(this));
|
||||||
|
|
||||||
//loader.Add ("/OpenSim/AssetInventoryServer/StorageProvider", new PluginProviderFilter (provider));
|
if (provider == String.Empty)
|
||||||
//loader.Add("/OpenSim/AssetInventoryServer/StorageProvider", new PluginCountConstraint(1));
|
|
||||||
loader.Add(addinPath);
|
loader.Add(addinPath);
|
||||||
|
else
|
||||||
|
loader.Add(addinPath, new PluginProviderFilter(provider));
|
||||||
|
//loader.Add(addinPath, new PluginCountConstraint(1));
|
||||||
|
|
||||||
loader.Load();
|
loader.Load();
|
||||||
|
|
||||||
return loader.Plugin;
|
return loader.Plugin;
|
||||||
|
|
|
@ -1,215 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2008 Intel Corporation
|
|
||||||
* All rights reserved.
|
|
||||||
* 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 Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``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 INTEL OR ITS
|
|
||||||
* 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.Net;
|
|
||||||
using System.IO;
|
|
||||||
using System.Xml;
|
|
||||||
using ExtensionLoader;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using HttpServer;
|
|
||||||
|
|
||||||
namespace OpenSim.Grid.AssetInventoryServer.Extensions
|
|
||||||
{
|
|
||||||
public class OpenSimFrontend : IExtension<AssetInventoryServer>
|
|
||||||
{
|
|
||||||
AssetInventoryServer server;
|
|
||||||
|
|
||||||
public OpenSimFrontend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(AssetInventoryServer server)
|
|
||||||
{
|
|
||||||
this.server = server;
|
|
||||||
|
|
||||||
// Asset request
|
|
||||||
server.HttpServer.AddHandler("get", null, @"^/assets/", AssetRequestHandler);
|
|
||||||
|
|
||||||
// Asset creation
|
|
||||||
server.HttpServer.AddHandler("post", null, @"^/assets/", AssetPostHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetRequestHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
|
|
||||||
{
|
|
||||||
UUID assetID;
|
|
||||||
// Split the URL up to get the asset ID out
|
|
||||||
string[] rawUrl = request.Uri.PathAndQuery.Split('/');
|
|
||||||
|
|
||||||
if (rawUrl.Length >= 3 && rawUrl[2].Length >= 36 && UUID.TryParse(rawUrl[2].Substring(0, 36), out assetID))
|
|
||||||
{
|
|
||||||
Metadata metadata;
|
|
||||||
byte[] assetData;
|
|
||||||
BackendResponse dataResponse;
|
|
||||||
|
|
||||||
if ((dataResponse = server.StorageProvider.TryFetchDataMetadata(assetID, out metadata, out assetData)) == BackendResponse.Success)
|
|
||||||
{
|
|
||||||
MemoryStream stream = new MemoryStream();
|
|
||||||
|
|
||||||
XmlWriterSettings settings = new XmlWriterSettings();
|
|
||||||
settings.Indent = true;
|
|
||||||
XmlWriter writer = XmlWriter.Create(stream, settings);
|
|
||||||
|
|
||||||
writer.WriteStartDocument();
|
|
||||||
writer.WriteStartElement("AssetBase");
|
|
||||||
writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
|
|
||||||
writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
|
|
||||||
writer.WriteStartElement("FullID");
|
|
||||||
writer.WriteStartElement("Guid");
|
|
||||||
writer.WriteString(assetID.ToString());
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("ID");
|
|
||||||
writer.WriteString(assetID.ToString());
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Data");
|
|
||||||
writer.WriteBase64(assetData, 0, assetData.Length);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Type");
|
|
||||||
writer.WriteValue(Utils.ContentTypeToSLAssetType(metadata.ContentType));
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Name");
|
|
||||||
writer.WriteString(metadata.Name);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Description");
|
|
||||||
writer.WriteString(metadata.Description);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Local");
|
|
||||||
writer.WriteValue(false);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteStartElement("Temporary");
|
|
||||||
writer.WriteValue(metadata.Temporary);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteEndElement();
|
|
||||||
writer.WriteEndDocument();
|
|
||||||
|
|
||||||
writer.Flush();
|
|
||||||
byte[] buffer = stream.GetBuffer();
|
|
||||||
|
|
||||||
response.Status = HttpStatusCode.OK;
|
|
||||||
response.ContentType = "application/xml";
|
|
||||||
response.ContentLength = stream.Length;
|
|
||||||
response.Body.Write(buffer, 0, (int)stream.Length);
|
|
||||||
response.Body.Flush();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Log.WarnFormat("Failed to fetch asset data or metadata for {0}: {1}", assetID, dataResponse);
|
|
||||||
response.Status = HttpStatusCode.NotFound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Log.Warn("Unrecognized OpenSim asset request: " + request.Uri.PathAndQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetPostHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
|
|
||||||
{
|
|
||||||
byte[] assetData = null;
|
|
||||||
Metadata metadata = new Metadata();
|
|
||||||
|
|
||||||
Logger.Log.Debug("Handling OpenSim asset upload");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (XmlReader reader = XmlReader.Create(request.Body))
|
|
||||||
{
|
|
||||||
reader.MoveToContent();
|
|
||||||
reader.ReadStartElement("AssetBase");
|
|
||||||
|
|
||||||
reader.ReadStartElement("FullID");
|
|
||||||
UUID.TryParse(reader.ReadElementContentAsString("Guid", String.Empty), out metadata.ID);
|
|
||||||
reader.ReadEndElement();
|
|
||||||
reader.ReadStartElement("ID");
|
|
||||||
reader.Skip();
|
|
||||||
reader.ReadEndElement();
|
|
||||||
|
|
||||||
// HACK: Broken on Mono. https://bugzilla.novell.com/show_bug.cgi?id=464229
|
|
||||||
//int readBytes = 0;
|
|
||||||
//byte[] buffer = new byte[1024];
|
|
||||||
//MemoryStream stream = new MemoryStream();
|
|
||||||
//BinaryWriter writer = new BinaryWriter(stream);
|
|
||||||
//while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, buffer.Length)) > 0)
|
|
||||||
// writer.Write(buffer, 0, readBytes);
|
|
||||||
//writer.Flush();
|
|
||||||
//assetData = stream.GetBuffer();
|
|
||||||
//Array.Resize<byte>(ref assetData, (int)stream.Length);
|
|
||||||
|
|
||||||
assetData = Convert.FromBase64String(reader.ReadElementContentAsString());
|
|
||||||
|
|
||||||
int type;
|
|
||||||
Int32.TryParse(reader.ReadElementContentAsString("Type", String.Empty), out type);
|
|
||||||
metadata.ContentType = Utils.SLAssetTypeToContentType(type);
|
|
||||||
metadata.Name = reader.ReadElementContentAsString("Name", String.Empty);
|
|
||||||
metadata.Description = reader.ReadElementContentAsString("Description", String.Empty);
|
|
||||||
Boolean.TryParse(reader.ReadElementContentAsString("Local", String.Empty), out metadata.Temporary);
|
|
||||||
Boolean.TryParse(reader.ReadElementContentAsString("Temporary", String.Empty), out metadata.Temporary);
|
|
||||||
|
|
||||||
reader.ReadEndElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetData != null && assetData.Length > 0)
|
|
||||||
{
|
|
||||||
metadata.SHA1 = OpenMetaverse.Utils.SHA1(assetData);
|
|
||||||
metadata.CreationDate = DateTime.Now;
|
|
||||||
|
|
||||||
BackendResponse storageResponse = server.StorageProvider.TryCreateAsset(metadata, assetData);
|
|
||||||
|
|
||||||
if (storageResponse == BackendResponse.Success)
|
|
||||||
response.Status = HttpStatusCode.Created;
|
|
||||||
else if (storageResponse == BackendResponse.NotFound)
|
|
||||||
response.Status = HttpStatusCode.NotFound;
|
|
||||||
else
|
|
||||||
response.Status = HttpStatusCode.InternalServerError;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Log.Warn("AssetPostHandler called with no asset data");
|
|
||||||
response.Status = HttpStatusCode.BadRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Warn("Failed to parse POST data (expecting AssetBase): " + ex.Message);
|
|
||||||
response.Status = HttpStatusCode.BadRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Log.Debug("Finished handling OpenSim asset upload, Status: " + response.Status.ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,311 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2008 Intel Corporation
|
|
||||||
* All rights reserved.
|
|
||||||
* 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 Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``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 INTEL OR ITS
|
|
||||||
* 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.Net;
|
|
||||||
using System.Data;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
using ExtensionLoader;
|
|
||||||
using ExtensionLoader.Config;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenMetaverse.StructuredData;
|
|
||||||
|
|
||||||
namespace OpenSim.Grid.AssetInventoryServer.Extensions
|
|
||||||
{
|
|
||||||
public class OpenSimMySQLStorage : IExtension<AssetInventoryServer>, IStorageProvider
|
|
||||||
{
|
|
||||||
const string EXTENSION_NAME = "OpenSimMySQLStorage"; // Used in metrics reporting
|
|
||||||
|
|
||||||
AssetInventoryServer server;
|
|
||||||
|
|
||||||
public OpenSimMySQLStorage()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Required Interfaces
|
|
||||||
|
|
||||||
public void Start(AssetInventoryServer server)
|
|
||||||
{
|
|
||||||
this.server = server;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbConnection.Open();
|
|
||||||
Logger.Log.Info("Connected to MySQL storage backend: " + dbConnection.ServerVersion);
|
|
||||||
}
|
|
||||||
catch (MySqlException ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("Connection to MySQL storage backend failed: " + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata)
|
|
||||||
{
|
|
||||||
metadata = null;
|
|
||||||
BackendResponse ret;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
IDataReader reader;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbConnection.Open();
|
|
||||||
|
|
||||||
IDbCommand command = dbConnection.CreateCommand();
|
|
||||||
command.CommandText = String.Format("SELECT name,description,assetType,temporary FROM assets WHERE id='{0}'", assetID.ToString());
|
|
||||||
reader = command.ExecuteReader();
|
|
||||||
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
metadata = new Metadata();
|
|
||||||
metadata.CreationDate = OpenMetaverse.Utils.Epoch;
|
|
||||||
metadata.SHA1 = null;
|
|
||||||
metadata.ID = assetID;
|
|
||||||
metadata.Name = reader.GetString(0);
|
|
||||||
metadata.Description = reader.GetString(1);
|
|
||||||
metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
|
|
||||||
metadata.Temporary = reader.GetBoolean(3);
|
|
||||||
|
|
||||||
ret = BackendResponse.Success;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = BackendResponse.NotFound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MySqlException ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
|
|
||||||
ret = BackendResponse.Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryFetchData(UUID assetID, out byte[] assetData)
|
|
||||||
{
|
|
||||||
assetData = null;
|
|
||||||
BackendResponse ret;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
IDataReader reader;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbConnection.Open();
|
|
||||||
|
|
||||||
IDbCommand command = dbConnection.CreateCommand();
|
|
||||||
command.CommandText = String.Format("SELECT data FROM assets WHERE id='{0}'", assetID.ToString());
|
|
||||||
reader = command.ExecuteReader();
|
|
||||||
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
assetData = (byte[])reader.GetValue(0);
|
|
||||||
ret = BackendResponse.Success;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = BackendResponse.NotFound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MySqlException ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
|
|
||||||
ret = BackendResponse.Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData)
|
|
||||||
{
|
|
||||||
metadata = null;
|
|
||||||
assetData = null;
|
|
||||||
BackendResponse ret;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
IDataReader reader;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbConnection.Open();
|
|
||||||
|
|
||||||
IDbCommand command = dbConnection.CreateCommand();
|
|
||||||
command.CommandText = String.Format("SELECT name,description,assetType,temporary,data FROM assets WHERE id='{0}'", assetID.ToString());
|
|
||||||
reader = command.ExecuteReader();
|
|
||||||
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
metadata = new Metadata();
|
|
||||||
metadata.CreationDate = OpenMetaverse.Utils.Epoch;
|
|
||||||
metadata.SHA1 = null;
|
|
||||||
metadata.ID = assetID;
|
|
||||||
metadata.Name = reader.GetString(0);
|
|
||||||
metadata.Description = reader.GetString(1);
|
|
||||||
metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
|
|
||||||
metadata.Temporary = reader.GetBoolean(3);
|
|
||||||
|
|
||||||
assetData = (byte[])reader.GetValue(4);
|
|
||||||
|
|
||||||
ret = BackendResponse.Success;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = BackendResponse.NotFound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MySqlException ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
|
|
||||||
ret = BackendResponse.Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now);
|
|
||||||
server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID)
|
|
||||||
{
|
|
||||||
assetID = metadata.ID = UUID.Random();
|
|
||||||
return TryCreateAsset(metadata, assetData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData)
|
|
||||||
{
|
|
||||||
BackendResponse ret;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbConnection.Open();
|
|
||||||
|
|
||||||
MySqlCommand command = new MySqlCommand(
|
|
||||||
"REPLACE INTO assets (name,description,assetType,local,temporary,data,id) VALUES " +
|
|
||||||
"(?name,?description,?assetType,?local,?temporary,?data,?id)", dbConnection);
|
|
||||||
|
|
||||||
command.Parameters.AddWithValue("?name", metadata.Name);
|
|
||||||
command.Parameters.AddWithValue("?description", metadata.Description);
|
|
||||||
command.Parameters.AddWithValue("?assetType", Utils.ContentTypeToSLAssetType(metadata.ContentType));
|
|
||||||
command.Parameters.AddWithValue("?local", 0);
|
|
||||||
command.Parameters.AddWithValue("?temporary", metadata.Temporary);
|
|
||||||
command.Parameters.AddWithValue("?data", assetData);
|
|
||||||
command.Parameters.AddWithValue("?id", metadata.ID.ToString());
|
|
||||||
|
|
||||||
int rowsAffected = command.ExecuteNonQuery();
|
|
||||||
if (rowsAffected == 1)
|
|
||||||
{
|
|
||||||
ret = BackendResponse.Success;
|
|
||||||
}
|
|
||||||
else if (rowsAffected == 2)
|
|
||||||
{
|
|
||||||
Logger.Log.Info("Replaced asset " + metadata.ID.ToString());
|
|
||||||
ret = BackendResponse.Success;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
|
|
||||||
ret = BackendResponse.Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MySqlException ex)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
|
|
||||||
ret = BackendResponse.Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server.MetricsProvider.LogAssetCreate(EXTENSION_NAME, ret, metadata.ID, assetData.Length, DateTime.Now);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ForEach(Action<Metadata> action, int start, int count)
|
|
||||||
{
|
|
||||||
int rowCount = 0;
|
|
||||||
|
|
||||||
using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Logger.Log.Error("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();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Required Interfaces
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -73,16 +73,6 @@ namespace OpenSim.Grid.AssetInventoryServer
|
||||||
void Initialise(AssetInventoryServer server);
|
void Initialise(AssetInventoryServer server);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IStorageProvider
|
|
||||||
{
|
|
||||||
BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata);
|
|
||||||
BackendResponse TryFetchData(UUID assetID, out byte[] assetData);
|
|
||||||
BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData);
|
|
||||||
BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData);
|
|
||||||
BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID);
|
|
||||||
int ForEach(Action<Metadata> action, int start, int count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IAssetStorageProvider : IAssetInventoryServerPlugin
|
public interface IAssetStorageProvider : IAssetInventoryServerPlugin
|
||||||
{
|
{
|
||||||
BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata);
|
BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata);
|
||||||
|
|
|
@ -39,7 +39,7 @@ using OpenMetaverse;
|
||||||
using HttpServer;
|
using HttpServer;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
|
||||||
namespace OpenSim.Grid.AssetInventoryServer.Plugins
|
namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim
|
||||||
{
|
{
|
||||||
public class OpenSimAssetFrontendPlugin : IAssetInventoryServerPlugin
|
public class OpenSimAssetFrontendPlugin : IAssetInventoryServerPlugin
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Grid.AssetInventoryServer.Extensions;
|
using OpenSim.Grid.AssetInventoryServer.Extensions;
|
||||||
using OpenSim.Data;
|
using OpenSim.Data;
|
||||||
|
|
||||||
namespace OpenSim.Grid.AssetInventoryServer.Plugins
|
namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim
|
||||||
{
|
{
|
||||||
public class OpenSimAssetStoragePlugin : IAssetStorageProvider
|
public class OpenSimAssetStoragePlugin : IAssetStorageProvider
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
</ExtensionPoint>
|
</ExtensionPoint>
|
||||||
|
|
||||||
<Extension path="/OpenSim/AssetInventoryServer/StorageProvider">
|
<Extension path="/OpenSim/AssetInventoryServer/StorageProvider">
|
||||||
<Plugin id="OpenSimAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSimAssetStoragePlugin" />
|
<Plugin id="OpenSimAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetStoragePlugin" />
|
||||||
</Extension>
|
</Extension>
|
||||||
<Extension path="/OpenSim/AssetInventoryServer/Frontend">
|
<Extension path="/OpenSim/AssetInventoryServer/Frontend">
|
||||||
<Plugin id="OpenSimAssetFrontend" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSimAssetFrontendPlugin" />
|
<Plugin id="OpenSimAssetFrontend" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetFrontendPlugin" />
|
||||||
</Extension>
|
</Extension>
|
||||||
</Addin>
|
</Addin>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Addin id="OpenSim.Grid.AssetInventoryServer.Plugins.Simple" version="0.1">
|
||||||
|
<Runtime>
|
||||||
|
<Import assembly="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" />
|
||||||
|
</Runtime>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<Addin id="OpenSim.Grid.AssetInventoryServer" version="0.1" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Extension path="/OpenSim/AssetInventoryServer/StorageProvider">
|
||||||
|
<Plugin id="SimpleAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.SimpleAssetStoragePlugin" />
|
||||||
|
</Extension>
|
||||||
|
</Addin>
|
|
@ -34,12 +34,13 @@ using System.IO;
|
||||||
using ExtensionLoader;
|
using ExtensionLoader;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
namespace OpenSim.Grid.AssetInventoryServer.Extensions
|
namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple
|
||||||
{
|
{
|
||||||
public class SimpleStorage : IExtension<AssetInventoryServer>, IStorageProvider
|
public class SimpleAssetStoragePlugin : IAssetStorageProvider
|
||||||
{
|
{
|
||||||
const string EXTENSION_NAME = ""; // Used in metrics reporting
|
const string EXTENSION_NAME = "SimpleAssetStorage"; // Used in metrics reporting
|
||||||
const string DEFAULT_DATA_DIR = "SimpleAssets";
|
const string DEFAULT_DATA_DIR = "SimpleAssets";
|
||||||
const string TEMP_DATA_DIR = "SimpleAssetsTemp";
|
const string TEMP_DATA_DIR = "SimpleAssetsTemp";
|
||||||
|
|
||||||
|
@ -47,30 +48,12 @@ namespace OpenSim.Grid.AssetInventoryServer.Extensions
|
||||||
Dictionary<UUID, Metadata> metadataStorage;
|
Dictionary<UUID, Metadata> metadataStorage;
|
||||||
Dictionary<UUID, string> filenames;
|
Dictionary<UUID, string> filenames;
|
||||||
|
|
||||||
public SimpleStorage()
|
public SimpleAssetStoragePlugin()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Required Interfaces
|
#region Required Interfaces
|
||||||
|
|
||||||
public void Start(AssetInventoryServer server)
|
|
||||||
{
|
|
||||||
this.server = server;
|
|
||||||
metadataStorage = new Dictionary<UUID, Metadata>();
|
|
||||||
filenames = new Dictionary<UUID, string>();
|
|
||||||
|
|
||||||
LoadFiles(DEFAULT_DATA_DIR, false);
|
|
||||||
LoadFiles(TEMP_DATA_DIR, true);
|
|
||||||
|
|
||||||
Logger.Log.InfoFormat("Initialized the store index with metadata for {0} assets",
|
|
||||||
metadataStorage.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
WipeTemporary();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata)
|
public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata)
|
||||||
{
|
{
|
||||||
metadata = null;
|
metadata = null;
|
||||||
|
@ -203,6 +186,49 @@ namespace OpenSim.Grid.AssetInventoryServer.Extensions
|
||||||
|
|
||||||
#endregion Required Interfaces
|
#endregion Required Interfaces
|
||||||
|
|
||||||
|
#region IPlugin implementation
|
||||||
|
|
||||||
|
public void Initialise(AssetInventoryServer server)
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
|
||||||
|
metadataStorage = new Dictionary<UUID, Metadata>();
|
||||||
|
filenames = new Dictionary<UUID, string>();
|
||||||
|
|
||||||
|
LoadFiles(DEFAULT_DATA_DIR, false);
|
||||||
|
LoadFiles(TEMP_DATA_DIR, true);
|
||||||
|
|
||||||
|
Logger.Log.InfoFormat("Initialized the store index with metadata for {0} assets",
|
||||||
|
metadataStorage.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Initialises asset interface</para>
|
||||||
|
/// </summary>
|
||||||
|
public void Initialise()
|
||||||
|
{
|
||||||
|
Logger.Log.InfoFormat("[ASSET]: {0} cannot be default-initialized!", Name);
|
||||||
|
throw new PluginNotInitialisedException(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
WipeTemporary();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
// TODO: this should be something meaningful and not hardcoded?
|
||||||
|
get { return "0.1"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "AssetInventoryServer Simple asset storage provider"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion IPlugin implementation
|
||||||
|
|
||||||
public void WipeTemporary()
|
public void WipeTemporary()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(TEMP_DATA_DIR))
|
if (Directory.Exists(TEMP_DATA_DIR))
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 Intel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
* 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 Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``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 INTEL OR ITS
|
||||||
|
* 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 OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple
|
||||||
|
{
|
||||||
|
public static class SimpleUtils
|
||||||
|
{
|
||||||
|
public static string ParseNameFromFilename(string filename)
|
||||||
|
{
|
||||||
|
filename = Path.GetFileName(filename);
|
||||||
|
|
||||||
|
int dot = filename.LastIndexOf('.');
|
||||||
|
int firstDash = filename.IndexOf('-');
|
||||||
|
|
||||||
|
if (dot - 37 > 0 && firstDash > 0)
|
||||||
|
return filename.Substring(0, firstDash);
|
||||||
|
else
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID ParseUUIDFromFilename(string filename)
|
||||||
|
{
|
||||||
|
int dot = filename.LastIndexOf('.');
|
||||||
|
|
||||||
|
if (dot > 35)
|
||||||
|
{
|
||||||
|
// Grab the last 36 characters of the filename
|
||||||
|
string uuidString = filename.Substring(dot - 36, 36);
|
||||||
|
UUID uuid;
|
||||||
|
UUID.TryParse(uuidString, out uuid);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID uuid;
|
||||||
|
if (UUID.TryParse(Path.GetFileName(filename), out uuid))
|
||||||
|
return uuid;
|
||||||
|
else
|
||||||
|
return UUID.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
prebuild.xml
32
prebuild.xml
|
@ -806,6 +806,38 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project name="OpenSim.Grid.AssetInventoryServer.Plugins.Simple" path="OpenSim/Grid/AssetInventoryServer/Plugins/Simple" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System" />
|
||||||
|
<Reference name="System.Data" />
|
||||||
|
<Reference name="OpenSim.Framework" />
|
||||||
|
<Reference name="OpenSim.Data" />
|
||||||
|
<Reference name="OpenSim.Grid.AssetInventoryServer" />
|
||||||
|
<Reference name="OpenMetaverseTypes"/>
|
||||||
|
<Reference name="OpenMetaverse.StructuredData2" />
|
||||||
|
<Reference name="HttpServer2"/>
|
||||||
|
|
||||||
|
<!-- Remove these eventually -->
|
||||||
|
<Reference name="MySql.Data" />
|
||||||
|
<Reference name="ExtensionLoader" />
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="false" />
|
||||||
|
<Match path="Resources" pattern="*.addin.xml" buildAction="EmbeddedResource" recurse="true" />
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
<Project name="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim" path="OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim" type="Library">
|
<Project name="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim" path="OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
|
Loading…
Reference in New Issue