Added assets service method AssetsExist(), which returns whether the given list of assets exist.

This method is used to optimize sending assets with embedded assets: e.g., when a Hypergrid visitor takes an item into the inventory.
This commit is contained in:
Oren Hurvitz
2014-03-31 11:53:12 +03:00
parent ac16a667e1
commit d1c3f8eef5
25 changed files with 579 additions and 179 deletions

View File

@@ -153,9 +153,24 @@ namespace OpenSim.Services.AssetService
return true;
}
public virtual bool[] AssetsExist(string[] ids)
{
try
{
UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id));
return m_Database.AssetsExist(uuid);
}
catch (Exception e)
{
m_log.Error("[ASSET SERVICE]: Exception getting assets ", e);
return new bool[ids.Length];
}
}
public virtual string Store(AssetBase asset)
{
if (!m_Database.ExistsAsset(asset.FullID))
bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0];
if (!exists)
{
// m_log.DebugFormat(
// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
@@ -186,4 +201,4 @@ namespace OpenSim.Services.AssetService
return m_Database.Delete(id);
}
}
}
}

View File

@@ -175,9 +175,16 @@ namespace OpenSim.Services.AssetService
return true;
}
public virtual bool[] AssetsExist(string[] ids)
{
UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id));
return m_Database.AssetsExist(uuid);
}
public virtual string Store(AssetBase asset)
{
if (!m_Database.ExistsAsset(asset.FullID))
bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0];
if (!exists)
{
// m_log.DebugFormat(
// "[XASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
@@ -217,4 +224,4 @@ namespace OpenSim.Services.AssetService
m_ChainedAssetService.Delete(asset.ID);
}
}
}
}

View File

@@ -254,6 +254,27 @@ namespace OpenSim.Services.Connectors
return true;
}
public virtual bool[] AssetsExist(string[] ids)
{
string uri = m_ServerURI + "/get_assets_exist";
bool[] exist = null;
try
{
exist = SynchronousRestObjectRequester.MakeRequest<string[], bool[]>("POST", uri, ids);
}
catch (Exception)
{
// This is most likely to happen because the server doesn't support this function,
// so just silently return "doesn't exist" for all the assets.
}
if (exist == null)
exist = new bool[ids.Length];
return exist;
}
public string Store(AssetBase asset)
{
if (asset.Local)

View File

@@ -36,6 +36,7 @@ using OpenSim.Framework;
using OpenSim.Services.Interfaces;
using OpenSim.Services.Connectors.Hypergrid;
using OpenSim.Services.Connectors.SimianGrid;
using OpenMetaverse;
namespace OpenSim.Services.Connectors
{
@@ -83,39 +84,6 @@ namespace OpenSim.Services.Connectors
}
}
private bool StringToUrlAndAssetID(string id, out string url, out string assetID)
{
url = String.Empty;
assetID = String.Empty;
Uri assetUri;
if (Uri.TryCreate(id, UriKind.Absolute, out assetUri) &&
assetUri.Scheme == Uri.UriSchemeHttp)
{
// Simian
if (assetUri.Query != string.Empty)
{
NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query);
assetID = qscoll["id"];
if (assetID != null)
url = id.Replace(assetID, ""); // Malformed again, as simian expects
else
url = id; // !!! best effort
}
else // robust
{
url = "http://" + assetUri.Authority;
assetID = assetUri.LocalPath.Trim(new char[] { '/' });
}
return true;
}
m_log.DebugFormat("[HG ASSET SERVICE]: Malformed URL {0}", id);
return false;
}
private IAssetService GetConnector(string url)
{
IAssetService connector = null;
@@ -149,7 +117,7 @@ namespace OpenSim.Services.Connectors
string url = string.Empty;
string assetID = string.Empty;
if (StringToUrlAndAssetID(id, out url, out assetID))
if (Util.ParseForeignAssetID(id, out url, out assetID))
{
IAssetService connector = GetConnector(url);
return connector.Get(assetID);
@@ -163,7 +131,7 @@ namespace OpenSim.Services.Connectors
string url = string.Empty;
string assetID = string.Empty;
if (StringToUrlAndAssetID(id, out url, out assetID))
if (Util.ParseForeignAssetID(id, out url, out assetID))
{
IAssetService connector = GetConnector(url);
return connector.GetCached(assetID);
@@ -177,7 +145,7 @@ namespace OpenSim.Services.Connectors
string url = string.Empty;
string assetID = string.Empty;
if (StringToUrlAndAssetID(id, out url, out assetID))
if (Util.ParseForeignAssetID(id, out url, out assetID))
{
IAssetService connector = GetConnector(url);
return connector.GetMetadata(assetID);
@@ -196,7 +164,7 @@ namespace OpenSim.Services.Connectors
string url = string.Empty;
string assetID = string.Empty;
if (StringToUrlAndAssetID(id, out url, out assetID))
if (Util.ParseForeignAssetID(id, out url, out assetID))
{
IAssetService connector = GetConnector(url);
return connector.Get(assetID, sender, handler);
@@ -205,12 +173,72 @@ namespace OpenSim.Services.Connectors
return false;
}
private struct AssetAndIndex
{
public UUID assetID;
public int index;
public AssetAndIndex(UUID assetID, int index)
{
this.assetID = assetID;
this.index = index;
}
}
public virtual bool[] AssetsExist(string[] ids)
{
// This method is a bit complicated because it works even if the assets belong to different
// servers; that requires sending separate requests to each server.
// Group the assets by the server they belong to
var url2assets = new Dictionary<string, List<AssetAndIndex>>();
for (int i = 0; i < ids.Length; i++)
{
string url = string.Empty;
string assetID = string.Empty;
if (Util.ParseForeignAssetID(ids[i], out url, out assetID))
{
if (!url2assets.ContainsKey(url))
url2assets.Add(url, new List<AssetAndIndex>());
url2assets[url].Add(new AssetAndIndex(UUID.Parse(assetID), i));
}
}
// Query each of the servers in turn
bool[] exist = new bool[ids.Length];
foreach (string url in url2assets.Keys)
{
IAssetService connector = GetConnector(url);
lock (EndPointLock(connector))
{
List<AssetAndIndex> curAssets = url2assets[url];
string[] assetIDs = curAssets.ConvertAll(a => a.assetID.ToString()).ToArray();
bool[] curExist = connector.AssetsExist(assetIDs);
int i = 0;
foreach (AssetAndIndex ai in curAssets)
{
exist[ai.index] = curExist[i];
++i;
}
}
}
return exist;
}
public string Store(AssetBase asset)
{
string url = string.Empty;
string assetID = string.Empty;
if (StringToUrlAndAssetID(asset.ID, out url, out assetID))
if (Util.ParseForeignAssetID(asset.ID, out url, out assetID))
{
IAssetService connector = GetConnector(url);
// Restore the assetID to a simple UUID

View File

@@ -231,6 +231,26 @@ namespace OpenSim.Services.Connectors.SimianGrid
return true;
}
public bool[] AssetsExist(string[] ids)
{
if (String.IsNullOrEmpty(m_serverUrl))
{
m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
throw new InvalidOperationException();
}
bool[] exist = new bool[ids.Length];
for (int i = 0; i < ids.Length; i++)
{
AssetMetadata metadata = GetMetadata(ids[i]);
if (metadata != null)
exist[i] = true;
}
return exist;
}
/// <summary>
/// Creates a new asset
/// </summary>

View File

@@ -75,6 +75,13 @@ namespace OpenSim.Services.Interfaces
/// </param>
/// <returns>True if the id was parseable, false otherwise</returns>
bool Get(string id, Object sender, AssetRetrieved handler);
/// <summary>
/// Check if assets exist in the database.
/// </summary>
/// <param name="ids">The assets' IDs</param>
/// <returns>For each asset: true if it exists, false otherwise</returns>
bool[] AssetsExist(string[] ids);
/// <summary>
/// Creates a new asset