diff options
author | Oren Hurvitz | 2014-03-31 11:53:12 +0300 |
---|---|---|
committer | Oren Hurvitz | 2014-04-02 06:30:57 +0100 |
commit | d1c3f8eef58b29eb8760eeb1ac03852a2387f927 (patch) | |
tree | b8686f4ea01b6dac3740b9685734686e2178dd2d | |
parent | fix orphaned code in sun module per mantis 7068 (diff) | |
download | opensim-SC_OLD-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.zip opensim-SC_OLD-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.tar.gz opensim-SC_OLD-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.tar.bz2 opensim-SC_OLD-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.tar.xz |
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.
Diffstat (limited to '')
25 files changed, 575 insertions, 175 deletions
diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs index e1a810c..1bb432c 100644 --- a/OpenSim/Data/AssetDataBase.cs +++ b/OpenSim/Data/AssetDataBase.cs | |||
@@ -37,9 +37,8 @@ namespace OpenSim.Data | |||
37 | public abstract class AssetDataBase : IAssetDataPlugin | 37 | public abstract class AssetDataBase : IAssetDataPlugin |
38 | { | 38 | { |
39 | public abstract AssetBase GetAsset(UUID uuid); | 39 | public abstract AssetBase GetAsset(UUID uuid); |
40 | |||
41 | public abstract void StoreAsset(AssetBase asset); | 40 | public abstract void StoreAsset(AssetBase asset); |
42 | public abstract bool ExistsAsset(UUID uuid); | 41 | public abstract bool[] AssetsExist(UUID[] uuids); |
43 | 42 | ||
44 | public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); | 43 | public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); |
45 | 44 | ||
diff --git a/OpenSim/Data/IAssetData.cs b/OpenSim/Data/IAssetData.cs index f31b215c..a41e310 100644 --- a/OpenSim/Data/IAssetData.cs +++ b/OpenSim/Data/IAssetData.cs | |||
@@ -35,7 +35,7 @@ namespace OpenSim.Data | |||
35 | { | 35 | { |
36 | AssetBase GetAsset(UUID uuid); | 36 | AssetBase GetAsset(UUID uuid); |
37 | void StoreAsset(AssetBase asset); | 37 | void StoreAsset(AssetBase asset); |
38 | bool ExistsAsset(UUID uuid); | 38 | bool[] AssetsExist(UUID[] uuids); |
39 | List<AssetMetadata> FetchAssetMetadataSet(int start, int count); | 39 | List<AssetMetadata> FetchAssetMetadataSet(int start, int count); |
40 | void Initialise(string connect); | 40 | void Initialise(string connect); |
41 | bool Delete(string id); | 41 | bool Delete(string id); |
diff --git a/OpenSim/Data/IXAssetDataPlugin.cs b/OpenSim/Data/IXAssetDataPlugin.cs index 74ad6f4..2d24797 100644 --- a/OpenSim/Data/IXAssetDataPlugin.cs +++ b/OpenSim/Data/IXAssetDataPlugin.cs | |||
@@ -39,7 +39,7 @@ namespace OpenSim.Data | |||
39 | { | 39 | { |
40 | AssetBase GetAsset(UUID uuid); | 40 | AssetBase GetAsset(UUID uuid); |
41 | void StoreAsset(AssetBase asset); | 41 | void StoreAsset(AssetBase asset); |
42 | bool ExistsAsset(UUID uuid); | 42 | bool[] AssetsExist(UUID[] uuids); |
43 | List<AssetMetadata> FetchAssetMetadataSet(int start, int count); | 43 | List<AssetMetadata> FetchAssetMetadataSet(int start, int count); |
44 | void Initialise(string connect); | 44 | void Initialise(string connect); |
45 | bool Delete(string id); | 45 | bool Delete(string id); |
diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index f3e008d..ce70396 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs | |||
@@ -225,17 +225,38 @@ namespace OpenSim.Data.MSSQL | |||
225 | // } | 225 | // } |
226 | 226 | ||
227 | /// <summary> | 227 | /// <summary> |
228 | /// Check if asset exist in m_database | 228 | /// Check if the assets exist in the database. |
229 | /// </summary> | 229 | /// </summary> |
230 | /// <param name="uuid"></param> | 230 | /// <param name="uuids">The assets' IDs</param> |
231 | /// <returns>true if exist.</returns> | 231 | /// <returns>For each asset: true if it exists, false otherwise</returns> |
232 | override public bool ExistsAsset(UUID uuid) | 232 | public override bool[] AssetsExist(UUID[] uuids) |
233 | { | 233 | { |
234 | if (GetAsset(uuid) != null) | 234 | if (uuids.Length == 0) |
235 | return new bool[0]; | ||
236 | |||
237 | HashSet<UUID> exist = new HashSet<UUID>(); | ||
238 | |||
239 | string ids = "'" + string.Join("','", uuids) + "'"; | ||
240 | string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids); | ||
241 | |||
242 | using (SqlConnection conn = new SqlConnection(m_connectionString)) | ||
243 | using (SqlCommand cmd = new SqlCommand(sql, conn)) | ||
235 | { | 244 | { |
236 | return true; | 245 | conn.Open(); |
246 | using (SqlDataReader reader = cmd.ExecuteReader()) | ||
247 | { | ||
248 | while (reader.Read()) | ||
249 | { | ||
250 | UUID id = DBGuid.FromDB(reader["id"]); | ||
251 | exist.Add(id); | ||
252 | } | ||
253 | } | ||
237 | } | 254 | } |
238 | return false; | 255 | |
256 | bool[] results = new bool[uuids.Length]; | ||
257 | for (int i = 0; i < uuids.Length; i++) | ||
258 | results[i] = exist.Contains(uuids[i]); | ||
259 | return results; | ||
239 | } | 260 | } |
240 | 261 | ||
241 | /// <summary> | 262 | /// <summary> |
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index 21362b9..c96139d 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs | |||
@@ -257,46 +257,44 @@ namespace OpenSim.Data.MySQL | |||
257 | } | 257 | } |
258 | 258 | ||
259 | /// <summary> | 259 | /// <summary> |
260 | /// Check if the asset exists in the database | 260 | /// Check if the assets exist in the database. |
261 | /// </summary> | 261 | /// </summary> |
262 | /// <param name="uuid">The asset UUID</param> | 262 | /// <param name="uuidss">The assets' IDs</param> |
263 | /// <returns>true if it exists, false otherwise.</returns> | 263 | /// <returns>For each asset: true if it exists, false otherwise</returns> |
264 | override public bool ExistsAsset(UUID uuid) | 264 | public override bool[] AssetsExist(UUID[] uuids) |
265 | { | 265 | { |
266 | // m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid); | 266 | if (uuids.Length == 0) |
267 | return new bool[0]; | ||
267 | 268 | ||
268 | bool assetExists = false; | 269 | HashSet<UUID> exist = new HashSet<UUID>(); |
270 | |||
271 | string ids = "'" + string.Join("','", uuids) + "'"; | ||
272 | string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids); | ||
269 | 273 | ||
270 | lock (m_dbLock) | 274 | lock (m_dbLock) |
271 | { | 275 | { |
272 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | 276 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
273 | { | 277 | { |
274 | dbcon.Open(); | 278 | dbcon.Open(); |
275 | using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon)) | 279 | using (MySqlCommand cmd = new MySqlCommand(sql, dbcon)) |
276 | { | 280 | { |
277 | cmd.Parameters.AddWithValue("?id", uuid.ToString()); | 281 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) |
278 | |||
279 | try | ||
280 | { | 282 | { |
281 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) | 283 | while (dbReader.Read()) |
282 | { | 284 | { |
283 | if (dbReader.Read()) | 285 | UUID id = DBGuid.FromDB(dbReader["id"]); |
284 | { | 286 | exist.Add(id); |
285 | // m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid); | ||
286 | assetExists = true; | ||
287 | } | ||
288 | } | 287 | } |
289 | } | 288 | } |
290 | catch (Exception e) | ||
291 | { | ||
292 | m_log.Error( | ||
293 | string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e); | ||
294 | } | ||
295 | } | 289 | } |
296 | } | 290 | } |
297 | } | 291 | } |
298 | 292 | ||
299 | return assetExists; | 293 | bool[] results = new bool[uuids.Length]; |
294 | for (int i = 0; i < uuids.Length; i++) | ||
295 | results[i] = exist.Contains(uuids[i]); | ||
296 | |||
297 | return results; | ||
300 | } | 298 | } |
301 | 299 | ||
302 | /// <summary> | 300 | /// <summary> |
diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs index 91389ce..1bf6a9a 100644 --- a/OpenSim/Data/MySQL/MySQLXAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLXAssetData.cs | |||
@@ -397,45 +397,43 @@ namespace OpenSim.Data.MySQL | |||
397 | } | 397 | } |
398 | 398 | ||
399 | /// <summary> | 399 | /// <summary> |
400 | /// Check if the asset exists in the database | 400 | /// Check if the assets exist in the database. |
401 | /// </summary> | 401 | /// </summary> |
402 | /// <param name="uuid">The asset UUID</param> | 402 | /// <param name="uuids">The asset UUID's</param> |
403 | /// <returns>true if it exists, false otherwise.</returns> | 403 | /// <returns>For each asset: true if it exists, false otherwise</returns> |
404 | public bool ExistsAsset(UUID uuid) | 404 | public bool[] AssetsExist(UUID[] uuids) |
405 | { | 405 | { |
406 | // m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid); | 406 | if (uuids.Length == 0) |
407 | return new bool[0]; | ||
408 | |||
409 | HashSet<UUID> exists = new HashSet<UUID>(); | ||
407 | 410 | ||
408 | bool assetExists = false; | 411 | string ids = "'" + string.Join("','", uuids) + "'"; |
412 | string sql = string.Format("SELECT ID FROM assets WHERE ID IN ({0})", ids); | ||
409 | 413 | ||
410 | lock (m_dbLock) | 414 | lock (m_dbLock) |
411 | { | 415 | { |
412 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | 416 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
413 | { | 417 | { |
414 | dbcon.Open(); | 418 | dbcon.Open(); |
415 | using (MySqlCommand cmd = new MySqlCommand("SELECT ID FROM XAssetsMeta WHERE ID=?ID", dbcon)) | 419 | using (MySqlCommand cmd = new MySqlCommand(sql, dbcon)) |
416 | { | 420 | { |
417 | cmd.Parameters.AddWithValue("?ID", uuid.ToString()); | 421 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) |
418 | |||
419 | try | ||
420 | { | 422 | { |
421 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) | 423 | while (dbReader.Read()) |
422 | { | 424 | { |
423 | if (dbReader.Read()) | 425 | UUID id = DBGuid.FromDB(dbReader["ID"]); |
424 | { | 426 | exists.Add(id); |
425 | // m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid); | ||
426 | assetExists = true; | ||
427 | } | ||
428 | } | 427 | } |
429 | } | 428 | } |
430 | catch (Exception e) | ||
431 | { | ||
432 | m_log.Error(string.Format("[XASSETS DB]: MySql failure fetching asset {0}", uuid), e); | ||
433 | } | ||
434 | } | 429 | } |
435 | } | 430 | } |
436 | } | 431 | } |
437 | 432 | ||
438 | return assetExists; | 433 | bool[] results = new bool[uuids.Length]; |
434 | for (int i = 0; i < uuids.Length; i++) | ||
435 | results[i] = exists.Contains(uuids[i]); | ||
436 | return results; | ||
439 | } | 437 | } |
440 | 438 | ||
441 | 439 | ||
diff --git a/OpenSim/Data/PGSQL/PGSQLAssetData.cs b/OpenSim/Data/PGSQL/PGSQLAssetData.cs index ab74856..ca18dc9 100644 --- a/OpenSim/Data/PGSQL/PGSQLAssetData.cs +++ b/OpenSim/Data/PGSQL/PGSQLAssetData.cs | |||
@@ -231,17 +231,38 @@ namespace OpenSim.Data.PGSQL | |||
231 | // } | 231 | // } |
232 | 232 | ||
233 | /// <summary> | 233 | /// <summary> |
234 | /// Check if asset exist in m_database | 234 | /// Check if the assets exist in the database. |
235 | /// </summary> | 235 | /// </summary> |
236 | /// <param name="uuid"></param> | 236 | /// <param name="uuids">The assets' IDs</param> |
237 | /// <returns>true if exist.</returns> | 237 | /// <returns>For each asset: true if it exists, false otherwise</returns> |
238 | override public bool ExistsAsset(UUID uuid) | 238 | public override bool[] AssetsExist(UUID[] uuids) |
239 | { | 239 | { |
240 | if (GetAsset(uuid) != null) | 240 | if (uuids.Length == 0) |
241 | return new bool[0]; | ||
242 | |||
243 | HashSet<UUID> exist = new HashSet<UUID>(); | ||
244 | |||
245 | string ids = "'" + string.Join("','", uuids) + "'"; | ||
246 | string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids); | ||
247 | |||
248 | using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) | ||
249 | using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) | ||
241 | { | 250 | { |
242 | return true; | 251 | conn.Open(); |
252 | using (NpgsqlDataReader reader = cmd.ExecuteReader()) | ||
253 | { | ||
254 | while (reader.Read()) | ||
255 | { | ||
256 | UUID id = DBGuid.FromDB(reader["id"]); | ||
257 | exist.Add(id); | ||
258 | } | ||
259 | } | ||
243 | } | 260 | } |
244 | return false; | 261 | |
262 | bool[] results = new bool[uuids.Length]; | ||
263 | for (int i = 0; i < uuids.Length; i++) | ||
264 | results[i] = exist.Contains(uuids[i]); | ||
265 | return results; | ||
245 | } | 266 | } |
246 | 267 | ||
247 | /// <summary> | 268 | /// <summary> |
diff --git a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs index e959619..c6cebff 100644 --- a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs +++ b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs | |||
@@ -407,6 +407,43 @@ namespace OpenSim.Data.PGSQL | |||
407 | } | 407 | } |
408 | 408 | ||
409 | /// <summary> | 409 | /// <summary> |
410 | /// Check if the assets exist in the database. | ||
411 | /// </summary> | ||
412 | /// <param name="uuids">The assets' IDs</param> | ||
413 | /// <returns>For each asset: true if it exists, false otherwise</returns> | ||
414 | public bool[] AssetsExist(UUID[] uuids) | ||
415 | { | ||
416 | if (uuids.Length == 0) | ||
417 | return new bool[0]; | ||
418 | |||
419 | HashSet<UUID> exist = new HashSet<UUID>(); | ||
420 | |||
421 | string ids = "'" + string.Join("','", uuids) + "'"; | ||
422 | string sql = string.Format(@"SELECT ""ID"" FROM XAssetsMeta WHERE ""ID"" IN ({0})", ids); | ||
423 | |||
424 | using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) | ||
425 | { | ||
426 | conn.Open(); | ||
427 | using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) | ||
428 | { | ||
429 | using (NpgsqlDataReader reader = cmd.ExecuteReader()) | ||
430 | { | ||
431 | while (reader.Read()) | ||
432 | { | ||
433 | UUID id = DBGuid.FromDB(reader["id"]); | ||
434 | exist.Add(id); | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | |||
440 | bool[] results = new bool[uuids.Length]; | ||
441 | for (int i = 0; i < uuids.Length; i++) | ||
442 | results[i] = exist.Contains(uuids[i]); | ||
443 | return results; | ||
444 | } | ||
445 | |||
446 | /// <summary> | ||
410 | /// Check if the asset exists in the database | 447 | /// Check if the asset exists in the database |
411 | /// </summary> | 448 | /// </summary> |
412 | /// <param name="uuid">The asset UUID</param> | 449 | /// <param name="uuid">The asset UUID</param> |
diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index c32982e..1f32376 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs | |||
@@ -152,7 +152,7 @@ namespace OpenSim.Data.SQLite | |||
152 | } | 152 | } |
153 | 153 | ||
154 | //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); | 154 | //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); |
155 | if (ExistsAsset(asset.FullID)) | 155 | if (AssetsExist(new[] { asset.FullID })[0]) |
156 | { | 156 | { |
157 | //LogAssetLoad(asset); | 157 | //LogAssetLoad(asset); |
158 | 158 | ||
@@ -214,32 +214,39 @@ namespace OpenSim.Data.SQLite | |||
214 | // } | 214 | // } |
215 | 215 | ||
216 | /// <summary> | 216 | /// <summary> |
217 | /// Check if an asset exist in database | 217 | /// Check if the assets exist in the database. |
218 | /// </summary> | 218 | /// </summary> |
219 | /// <param name="uuid">The asset UUID</param> | 219 | /// <param name="uuids">The assets' IDs</param> |
220 | /// <returns>True if exist, or false.</returns> | 220 | /// <returns>For each asset: true if it exists, false otherwise</returns> |
221 | override public bool ExistsAsset(UUID uuid) | 221 | public override bool[] AssetsExist(UUID[] uuids) |
222 | { | 222 | { |
223 | lock (this) | 223 | if (uuids.Length == 0) |
224 | return new bool[0]; | ||
225 | |||
226 | HashSet<UUID> exist = new HashSet<UUID>(); | ||
227 | |||
228 | string ids = "'" + string.Join("','", uuids) + "'"; | ||
229 | string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids); | ||
230 | |||
231 | lock (this) | ||
224 | { | 232 | { |
225 | using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) | 233 | using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) |
226 | { | 234 | { |
227 | cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); | ||
228 | using (IDataReader reader = cmd.ExecuteReader()) | 235 | using (IDataReader reader = cmd.ExecuteReader()) |
229 | { | 236 | { |
230 | if (reader.Read()) | 237 | while (reader.Read()) |
231 | { | ||
232 | reader.Close(); | ||
233 | return true; | ||
234 | } | ||
235 | else | ||
236 | { | 238 | { |
237 | reader.Close(); | 239 | UUID id = new UUID((string)reader["UUID"]); |
238 | return false; | 240 | exist.Add(id); |
239 | } | 241 | } |
240 | } | 242 | } |
241 | } | 243 | } |
242 | } | 244 | } |
245 | |||
246 | bool[] results = new bool[uuids.Length]; | ||
247 | for (int i = 0; i < uuids.Length; i++) | ||
248 | results[i] = exist.Contains(uuids[i]); | ||
249 | return results; | ||
243 | } | 250 | } |
244 | 251 | ||
245 | /// <summary> | 252 | /// <summary> |
diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs index 8cb2ee0..d778d1c 100644 --- a/OpenSim/Data/Tests/AssetTests.cs +++ b/OpenSim/Data/Tests/AssetTests.cs | |||
@@ -107,10 +107,11 @@ namespace OpenSim.Data.Tests | |||
107 | public void T001_LoadEmpty() | 107 | public void T001_LoadEmpty() |
108 | { | 108 | { |
109 | TestHelpers.InMethod(); | 109 | TestHelpers.InMethod(); |
110 | 110 | ||
111 | Assert.That(m_db.ExistsAsset(uuid1), Is.False); | 111 | bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 }); |
112 | Assert.That(m_db.ExistsAsset(uuid2), Is.False); | 112 | Assert.IsFalse(exist[0]); |
113 | Assert.That(m_db.ExistsAsset(uuid3), Is.False); | 113 | Assert.IsFalse(exist[1]); |
114 | Assert.IsFalse(exist[2]); | ||
114 | } | 115 | } |
115 | 116 | ||
116 | [Test] | 117 | [Test] |
@@ -159,9 +160,10 @@ namespace OpenSim.Data.Tests | |||
159 | AssetBase a3b = m_db.GetAsset(uuid3); | 160 | AssetBase a3b = m_db.GetAsset(uuid3); |
160 | Assert.That(a3b, Constraints.PropertyCompareConstraint(a3a)); | 161 | Assert.That(a3b, Constraints.PropertyCompareConstraint(a3a)); |
161 | 162 | ||
162 | Assert.That(m_db.ExistsAsset(uuid1), Is.True); | 163 | bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 }); |
163 | Assert.That(m_db.ExistsAsset(uuid2), Is.True); | 164 | Assert.IsTrue(exist[0]); |
164 | Assert.That(m_db.ExistsAsset(uuid3), Is.True); | 165 | Assert.IsTrue(exist[1]); |
166 | Assert.IsTrue(exist[2]); | ||
165 | 167 | ||
166 | List<AssetMetadata> metadatas = m_db.FetchAssetMetadataSet(0, 1000); | 168 | List<AssetMetadata> metadatas = m_db.FetchAssetMetadataSet(0, 1000); |
167 | 169 | ||
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index c7a7341..b133ff3 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -52,6 +52,8 @@ using OpenMetaverse; | |||
52 | using OpenMetaverse.StructuredData; | 52 | using OpenMetaverse.StructuredData; |
53 | using Amib.Threading; | 53 | using Amib.Threading; |
54 | using System.Collections.Concurrent; | 54 | using System.Collections.Concurrent; |
55 | using System.Collections.Specialized; | ||
56 | using System.Web; | ||
55 | 57 | ||
56 | namespace OpenSim.Framework | 58 | namespace OpenSim.Framework |
57 | { | 59 | { |
@@ -866,6 +868,54 @@ namespace OpenSim.Framework | |||
866 | } | 868 | } |
867 | 869 | ||
868 | /// <summary> | 870 | /// <summary> |
871 | /// Parses a foreign asset ID. | ||
872 | /// </summary> | ||
873 | /// <param name="id">A possibly-foreign asset ID: http://grid.example.com:8002/00000000-0000-0000-0000-000000000000 </param> | ||
874 | /// <param name="url">The URL: http://grid.example.com:8002</param> | ||
875 | /// <param name="assetID">The asset ID: 00000000-0000-0000-0000-000000000000. Returned even if 'id' isn't foreign.</param> | ||
876 | /// <returns>True: this is a foreign asset ID; False: it isn't</returns> | ||
877 | public static bool ParseForeignAssetID(string id, out string url, out string assetID) | ||
878 | { | ||
879 | url = String.Empty; | ||
880 | assetID = String.Empty; | ||
881 | |||
882 | UUID uuid; | ||
883 | if (UUID.TryParse(id, out uuid)) | ||
884 | { | ||
885 | assetID = uuid.ToString(); | ||
886 | return false; | ||
887 | } | ||
888 | |||
889 | if ((id.Length == 0) || (id[0] != 'h' && id[0] != 'H')) | ||
890 | return false; | ||
891 | |||
892 | Uri assetUri; | ||
893 | if (!Uri.TryCreate(id, UriKind.Absolute, out assetUri) || assetUri.Scheme != Uri.UriSchemeHttp) | ||
894 | return false; | ||
895 | |||
896 | // Simian | ||
897 | if (assetUri.Query != string.Empty) | ||
898 | { | ||
899 | NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query); | ||
900 | assetID = qscoll["id"]; | ||
901 | if (assetID != null) | ||
902 | url = id.Replace(assetID, ""); // Malformed again, as simian expects | ||
903 | else | ||
904 | url = id; // !!! best effort | ||
905 | } | ||
906 | else // robust | ||
907 | { | ||
908 | url = "http://" + assetUri.Authority; | ||
909 | assetID = assetUri.LocalPath.Trim(new char[] { '/' }); | ||
910 | } | ||
911 | |||
912 | if (!UUID.TryParse(assetID, out uuid)) | ||
913 | return false; | ||
914 | |||
915 | return true; | ||
916 | } | ||
917 | |||
918 | /// <summary> | ||
869 | /// Removes all invalid path chars (OS dependent) | 919 | /// Removes all invalid path chars (OS dependent) |
870 | /// </summary> | 920 | /// </summary> |
871 | /// <param name="path">path</param> | 921 | /// <param name="path">path</param> |
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index c7bd3d0..f06d70d 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -1038,6 +1038,18 @@ namespace OpenSim.Region.CoreModules.Asset | |||
1038 | return true; | 1038 | return true; |
1039 | } | 1039 | } |
1040 | 1040 | ||
1041 | public bool[] AssetsExist(string[] ids) | ||
1042 | { | ||
1043 | bool[] exist = new bool[ids.Length]; | ||
1044 | |||
1045 | for (int i = 0; i < ids.Length; i++) | ||
1046 | { | ||
1047 | exist[i] = Check(ids[i]); | ||
1048 | } | ||
1049 | |||
1050 | return exist; | ||
1051 | } | ||
1052 | |||
1041 | public string Store(AssetBase asset) | 1053 | public string Store(AssetBase asset) |
1042 | { | 1054 | { |
1043 | if (asset.FullID == UUID.Zero) | 1055 | if (asset.FullID == UUID.Zero) |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index d4fb1ba..532bc74 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -145,11 +145,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
145 | string id = m_scene.AssetService.Store(asset1); | 145 | string id = m_scene.AssetService.Store(asset1); |
146 | if (id == string.Empty) | 146 | if (id == string.Empty) |
147 | { | 147 | { |
148 | m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); | 148 | m_log.DebugFormat("[HG ASSET MAPPER]: Failed to post asset {0} to asset server {1}: the server did not accept the asset", asset.ID, url); |
149 | success = false; | 149 | success = false; |
150 | } | 150 | } |
151 | else | 151 | else |
152 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); | 152 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted asset {0} to asset server {1}", asset1.ID, url); |
153 | } | 153 | } |
154 | return success; | 154 | return success; |
155 | } | 155 | } |
@@ -279,36 +279,65 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
279 | 279 | ||
280 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) | 280 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) |
281 | { | 281 | { |
282 | // Post the item from the local AssetCache onto the remote asset server | 282 | m_log.DebugFormat("[HG ASSET MAPPER]: Starting to send asset {0} with children to asset server {1}", assetID, userAssetURL); |
283 | // and place an entry in m_assetMap | 283 | |
284 | // Find all the embedded assets | ||
284 | 285 | ||
285 | m_log.Debug("[HG ASSET MAPPER]: Posting object " + assetID + " to asset server " + userAssetURL); | ||
286 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | 286 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); |
287 | if (asset != null) | 287 | if (asset == null) |
288 | { | 288 | { |
289 | Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); | 289 | m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID); |
290 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | 290 | return; |
291 | uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids); | 291 | } |
292 | bool success = false; | 292 | |
293 | foreach (UUID uuid in ids.Keys) | 293 | Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); |
294 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | ||
295 | uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids); | ||
296 | |||
297 | // Check which assets already exist in the destination server | ||
298 | |||
299 | string url = userAssetURL; | ||
300 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
301 | url = url + "/"; | ||
302 | |||
303 | string[] remoteAssetIDs = new string[ids.Count]; | ||
304 | int i = 0; | ||
305 | foreach (UUID id in ids.Keys) | ||
306 | remoteAssetIDs[i++] = url + id.ToString(); | ||
307 | |||
308 | bool[] exist = m_scene.AssetService.AssetsExist(remoteAssetIDs); | ||
309 | |||
310 | var existSet = new HashSet<string>(); | ||
311 | i = 0; | ||
312 | foreach (UUID id in ids.Keys) | ||
313 | { | ||
314 | if (exist[i]) | ||
315 | existSet.Add(id.ToString()); | ||
316 | ++i; | ||
317 | } | ||
318 | |||
319 | // Send only those assets which don't already exist in the destination server | ||
320 | |||
321 | bool success = true; | ||
322 | |||
323 | foreach (UUID uuid in ids.Keys) | ||
324 | { | ||
325 | if (!existSet.Contains(uuid.ToString())) | ||
294 | { | 326 | { |
295 | asset = m_scene.AssetService.Get(uuid.ToString()); | 327 | asset = m_scene.AssetService.Get(uuid.ToString()); |
296 | if (asset == null) | 328 | if (asset == null) |
297 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); | 329 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); |
298 | else | 330 | else |
299 | success = PostAsset(userAssetURL, asset); | 331 | success &= PostAsset(userAssetURL, asset); |
300 | } | 332 | } |
301 | |||
302 | // maybe all pieces got there... | ||
303 | if (!success) | ||
304 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); | ||
305 | else | 333 | else |
306 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); | 334 | m_log.DebugFormat("[HG ASSET MAPPER]: Didn't post asset {0} because it already exists in asset server {1}", uuid, userAssetURL); |
307 | |||
308 | } | 335 | } |
309 | else | ||
310 | m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID); | ||
311 | 336 | ||
337 | if (!success) | ||
338 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems sending asset {0} with children to asset server {1}", assetID, userAssetURL); | ||
339 | else | ||
340 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully sent asset {0} with children to asset server {1}", assetID, userAssetURL); | ||
312 | } | 341 | } |
313 | 342 | ||
314 | #endregion | 343 | #endregion |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 9f58175..ff8b051 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs | |||
@@ -312,6 +312,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
312 | } | 312 | } |
313 | } | 313 | } |
314 | 314 | ||
315 | public virtual bool[] AssetsExist(string[] ids) | ||
316 | { | ||
317 | int numHG = 0; | ||
318 | foreach (string id in ids) | ||
319 | { | ||
320 | if (IsHG(id)) | ||
321 | ++numHG; | ||
322 | } | ||
323 | |||
324 | if (numHG == 0) | ||
325 | return m_GridService.AssetsExist(ids); | ||
326 | else if (numHG == ids.Length) | ||
327 | return m_HGService.AssetsExist(ids); | ||
328 | else | ||
329 | throw new Exception("[HG ASSET CONNECTOR]: AssetsExist: all the assets must be either local or foreign"); | ||
330 | } | ||
331 | |||
315 | public string Store(AssetBase asset) | 332 | public string Store(AssetBase asset) |
316 | { | 333 | { |
317 | bool isHG = IsHG(asset.ID); | 334 | bool isHG = IsHG(asset.ID); |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 52b1039..97b7559 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs | |||
@@ -253,6 +253,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
253 | }); | 253 | }); |
254 | } | 254 | } |
255 | 255 | ||
256 | public bool[] AssetsExist(string[] ids) | ||
257 | { | ||
258 | return m_AssetService.AssetsExist(ids); | ||
259 | } | ||
260 | |||
256 | public string Store(AssetBase asset) | 261 | public string Store(AssetBase asset) |
257 | { | 262 | { |
258 | if (m_Cache != null) | 263 | if (m_Cache != null) |
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs index cc4325a..9b86986 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs | |||
@@ -86,6 +86,7 @@ namespace OpenSim.Server.Handlers.Asset | |||
86 | server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); | 86 | server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); |
87 | server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); | 87 | server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); |
88 | server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowedRemoteDeleteTypes)); | 88 | server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowedRemoteDeleteTypes)); |
89 | server.AddStreamHandler(new AssetsExistHandler(m_AssetService)); | ||
89 | 90 | ||
90 | MainConsole.Instance.Commands.AddCommand("Assets", false, | 91 | MainConsole.Instance.Commands.AddCommand("Assets", false, |
91 | "show asset", | 92 | "show asset", |
@@ -212,4 +213,4 @@ namespace OpenSim.Server.Handlers.Asset | |||
212 | } | 213 | } |
213 | } | 214 | } |
214 | } | 215 | } |
215 | } \ No newline at end of file | 216 | } |
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs index 8b23a83..ed3b4af 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs | |||
@@ -64,45 +64,61 @@ namespace OpenSim.Server.Handlers.Asset | |||
64 | if (p.Length == 0) | 64 | if (p.Length == 0) |
65 | return result; | 65 | return result; |
66 | 66 | ||
67 | if (p.Length > 1 && p[1] == "data") | 67 | if (p.Length > 1) |
68 | { | 68 | { |
69 | result = m_AssetService.GetData(p[0]); | 69 | string id = p[0]; |
70 | if (result == null) | 70 | string cmd = p[1]; |
71 | |||
72 | if (cmd == "data") | ||
71 | { | 73 | { |
72 | httpResponse.StatusCode = (int)HttpStatusCode.NotFound; | 74 | result = m_AssetService.GetData(id); |
73 | httpResponse.ContentType = "text/plain"; | 75 | if (result == null) |
74 | result = new byte[0]; | 76 | { |
77 | httpResponse.StatusCode = (int)HttpStatusCode.NotFound; | ||
78 | httpResponse.ContentType = "text/plain"; | ||
79 | result = new byte[0]; | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | httpResponse.StatusCode = (int)HttpStatusCode.OK; | ||
84 | httpResponse.ContentType = "application/octet-stream"; | ||
85 | } | ||
75 | } | 86 | } |
76 | else | 87 | else if (cmd == "metadata") |
77 | { | 88 | { |
78 | httpResponse.StatusCode = (int)HttpStatusCode.OK; | 89 | AssetMetadata metadata = m_AssetService.GetMetadata(id); |
79 | httpResponse.ContentType = "application/octet-stream"; | ||
80 | } | ||
81 | } | ||
82 | else if (p.Length > 1 && p[1] == "metadata") | ||
83 | { | ||
84 | AssetMetadata metadata = m_AssetService.GetMetadata(p[0]); | ||
85 | 90 | ||
86 | if (metadata != null) | 91 | if (metadata != null) |
87 | { | 92 | { |
88 | XmlSerializer xs = | 93 | XmlSerializer xs = |
89 | new XmlSerializer(typeof(AssetMetadata)); | 94 | new XmlSerializer(typeof(AssetMetadata)); |
90 | result = ServerUtils.SerializeResult(xs, metadata); | 95 | result = ServerUtils.SerializeResult(xs, metadata); |
91 | 96 | ||
92 | httpResponse.StatusCode = (int)HttpStatusCode.OK; | 97 | httpResponse.StatusCode = (int)HttpStatusCode.OK; |
93 | httpResponse.ContentType = | 98 | httpResponse.ContentType = |
94 | SLUtil.SLAssetTypeToContentType(metadata.Type); | 99 | SLUtil.SLAssetTypeToContentType(metadata.Type); |
100 | } | ||
101 | else | ||
102 | { | ||
103 | httpResponse.StatusCode = (int)HttpStatusCode.NotFound; | ||
104 | httpResponse.ContentType = "text/plain"; | ||
105 | result = new byte[0]; | ||
106 | } | ||
95 | } | 107 | } |
96 | else | 108 | else |
97 | { | 109 | { |
98 | httpResponse.StatusCode = (int)HttpStatusCode.NotFound; | 110 | // Unknown request |
111 | httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; | ||
99 | httpResponse.ContentType = "text/plain"; | 112 | httpResponse.ContentType = "text/plain"; |
100 | result = new byte[0]; | 113 | result = new byte[0]; |
101 | } | 114 | } |
102 | } | 115 | } |
103 | else | 116 | else if (p.Length == 1) |
104 | { | 117 | { |
105 | AssetBase asset = m_AssetService.Get(p[0]); | 118 | // Get the entire asset (metadata + data) |
119 | |||
120 | string id = p[0]; | ||
121 | AssetBase asset = m_AssetService.Get(id); | ||
106 | 122 | ||
107 | if (asset != null) | 123 | if (asset != null) |
108 | { | 124 | { |
@@ -120,6 +136,14 @@ namespace OpenSim.Server.Handlers.Asset | |||
120 | result = new byte[0]; | 136 | result = new byte[0]; |
121 | } | 137 | } |
122 | } | 138 | } |
139 | else | ||
140 | { | ||
141 | // Unknown request | ||
142 | httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; | ||
143 | httpResponse.ContentType = "text/plain"; | ||
144 | result = new byte[0]; | ||
145 | } | ||
146 | |||
123 | return result; | 147 | return result; |
124 | } | 148 | } |
125 | } | 149 | } |
diff --git a/OpenSim/Server/Handlers/Asset/AssetsExistHandler.cs b/OpenSim/Server/Handlers/Asset/AssetsExistHandler.cs new file mode 100644 index 0000000..6d01f86 --- /dev/null +++ b/OpenSim/Server/Handlers/Asset/AssetsExistHandler.cs | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using Nini.Config; | ||
29 | using log4net; | ||
30 | using System; | ||
31 | using System.Reflection; | ||
32 | using System.IO; | ||
33 | using System.Net; | ||
34 | using System.Text; | ||
35 | using System.Text.RegularExpressions; | ||
36 | using System.Xml; | ||
37 | using System.Xml.Serialization; | ||
38 | using OpenSim.Server.Base; | ||
39 | using OpenSim.Services.Interfaces; | ||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Framework.Servers.HttpServer; | ||
42 | using OpenMetaverse; | ||
43 | |||
44 | namespace OpenSim.Server.Handlers.Asset | ||
45 | { | ||
46 | public class AssetsExistHandler : BaseStreamHandler | ||
47 | { | ||
48 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
49 | |||
50 | private IAssetService m_AssetService; | ||
51 | |||
52 | public AssetsExistHandler(IAssetService service) : | ||
53 | base("POST", "/get_assets_exist") | ||
54 | { | ||
55 | m_AssetService = service; | ||
56 | } | ||
57 | |||
58 | protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||
59 | { | ||
60 | XmlSerializer xs; | ||
61 | |||
62 | string[] ids; | ||
63 | try | ||
64 | { | ||
65 | xs = new XmlSerializer(typeof(string[])); | ||
66 | ids = (string[])xs.Deserialize(request); | ||
67 | } | ||
68 | catch (Exception) | ||
69 | { | ||
70 | httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; | ||
71 | return null; | ||
72 | } | ||
73 | |||
74 | bool[] exist = m_AssetService.AssetsExist(ids); | ||
75 | |||
76 | xs = new XmlSerializer(typeof(bool[])); | ||
77 | return ServerUtils.SerializeResult(xs, exist); | ||
78 | } | ||
79 | } | ||
80 | } | ||
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index 08fd3f8..0aefa16 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs | |||
@@ -153,9 +153,24 @@ namespace OpenSim.Services.AssetService | |||
153 | return true; | 153 | return true; |
154 | } | 154 | } |
155 | 155 | ||
156 | public virtual bool[] AssetsExist(string[] ids) | ||
157 | { | ||
158 | try | ||
159 | { | ||
160 | UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id)); | ||
161 | return m_Database.AssetsExist(uuid); | ||
162 | } | ||
163 | catch (Exception e) | ||
164 | { | ||
165 | m_log.Error("[ASSET SERVICE]: Exception getting assets ", e); | ||
166 | return new bool[ids.Length]; | ||
167 | } | ||
168 | } | ||
169 | |||
156 | public virtual string Store(AssetBase asset) | 170 | public virtual string Store(AssetBase asset) |
157 | { | 171 | { |
158 | if (!m_Database.ExistsAsset(asset.FullID)) | 172 | bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0]; |
173 | if (!exists) | ||
159 | { | 174 | { |
160 | // m_log.DebugFormat( | 175 | // m_log.DebugFormat( |
161 | // "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); | 176 | // "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); |
@@ -186,4 +201,4 @@ namespace OpenSim.Services.AssetService | |||
186 | return m_Database.Delete(id); | 201 | return m_Database.Delete(id); |
187 | } | 202 | } |
188 | } | 203 | } |
189 | } \ No newline at end of file | 204 | } |
diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs index 6047616..f58b769 100644 --- a/OpenSim/Services/AssetService/XAssetService.cs +++ b/OpenSim/Services/AssetService/XAssetService.cs | |||
@@ -175,9 +175,16 @@ namespace OpenSim.Services.AssetService | |||
175 | return true; | 175 | return true; |
176 | } | 176 | } |
177 | 177 | ||
178 | public virtual bool[] AssetsExist(string[] ids) | ||
179 | { | ||
180 | UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id)); | ||
181 | return m_Database.AssetsExist(uuid); | ||
182 | } | ||
183 | |||
178 | public virtual string Store(AssetBase asset) | 184 | public virtual string Store(AssetBase asset) |
179 | { | 185 | { |
180 | if (!m_Database.ExistsAsset(asset.FullID)) | 186 | bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0]; |
187 | if (!exists) | ||
181 | { | 188 | { |
182 | // m_log.DebugFormat( | 189 | // m_log.DebugFormat( |
183 | // "[XASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); | 190 | // "[XASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); |
@@ -217,4 +224,4 @@ namespace OpenSim.Services.AssetService | |||
217 | m_ChainedAssetService.Delete(asset.ID); | 224 | m_ChainedAssetService.Delete(asset.ID); |
218 | } | 225 | } |
219 | } | 226 | } |
220 | } \ No newline at end of file | 227 | } |
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 8b04d7f..32415e9 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs | |||
@@ -254,6 +254,27 @@ namespace OpenSim.Services.Connectors | |||
254 | return true; | 254 | return true; |
255 | } | 255 | } |
256 | 256 | ||
257 | public virtual bool[] AssetsExist(string[] ids) | ||
258 | { | ||
259 | string uri = m_ServerURI + "/get_assets_exist"; | ||
260 | |||
261 | bool[] exist = null; | ||
262 | try | ||
263 | { | ||
264 | exist = SynchronousRestObjectRequester.MakeRequest<string[], bool[]>("POST", uri, ids); | ||
265 | } | ||
266 | catch (Exception) | ||
267 | { | ||
268 | // This is most likely to happen because the server doesn't support this function, | ||
269 | // so just silently return "doesn't exist" for all the assets. | ||
270 | } | ||
271 | |||
272 | if (exist == null) | ||
273 | exist = new bool[ids.Length]; | ||
274 | |||
275 | return exist; | ||
276 | } | ||
277 | |||
257 | public string Store(AssetBase asset) | 278 | public string Store(AssetBase asset) |
258 | { | 279 | { |
259 | if (asset.Local) | 280 | if (asset.Local) |
diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index c395178..3710c86 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs | |||
@@ -36,6 +36,7 @@ using OpenSim.Framework; | |||
36 | using OpenSim.Services.Interfaces; | 36 | using OpenSim.Services.Interfaces; |
37 | using OpenSim.Services.Connectors.Hypergrid; | 37 | using OpenSim.Services.Connectors.Hypergrid; |
38 | using OpenSim.Services.Connectors.SimianGrid; | 38 | using OpenSim.Services.Connectors.SimianGrid; |
39 | using OpenMetaverse; | ||
39 | 40 | ||
40 | namespace OpenSim.Services.Connectors | 41 | namespace OpenSim.Services.Connectors |
41 | { | 42 | { |
@@ -83,39 +84,6 @@ namespace OpenSim.Services.Connectors | |||
83 | } | 84 | } |
84 | } | 85 | } |
85 | 86 | ||
86 | private bool StringToUrlAndAssetID(string id, out string url, out string assetID) | ||
87 | { | ||
88 | url = String.Empty; | ||
89 | assetID = String.Empty; | ||
90 | |||
91 | Uri assetUri; | ||
92 | |||
93 | if (Uri.TryCreate(id, UriKind.Absolute, out assetUri) && | ||
94 | assetUri.Scheme == Uri.UriSchemeHttp) | ||
95 | { | ||
96 | // Simian | ||
97 | if (assetUri.Query != string.Empty) | ||
98 | { | ||
99 | NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query); | ||
100 | assetID = qscoll["id"]; | ||
101 | if (assetID != null) | ||
102 | url = id.Replace(assetID, ""); // Malformed again, as simian expects | ||
103 | else | ||
104 | url = id; // !!! best effort | ||
105 | } | ||
106 | else // robust | ||
107 | { | ||
108 | url = "http://" + assetUri.Authority; | ||
109 | assetID = assetUri.LocalPath.Trim(new char[] { '/' }); | ||
110 | } | ||
111 | |||
112 | return true; | ||
113 | } | ||
114 | |||
115 | m_log.DebugFormat("[HG ASSET SERVICE]: Malformed URL {0}", id); | ||
116 | return false; | ||
117 | } | ||
118 | |||
119 | private IAssetService GetConnector(string url) | 87 | private IAssetService GetConnector(string url) |
120 | { | 88 | { |
121 | IAssetService connector = null; | 89 | IAssetService connector = null; |
@@ -149,7 +117,7 @@ namespace OpenSim.Services.Connectors | |||
149 | string url = string.Empty; | 117 | string url = string.Empty; |
150 | string assetID = string.Empty; | 118 | string assetID = string.Empty; |
151 | 119 | ||
152 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 120 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
153 | { | 121 | { |
154 | IAssetService connector = GetConnector(url); | 122 | IAssetService connector = GetConnector(url); |
155 | return connector.Get(assetID); | 123 | return connector.Get(assetID); |
@@ -163,7 +131,7 @@ namespace OpenSim.Services.Connectors | |||
163 | string url = string.Empty; | 131 | string url = string.Empty; |
164 | string assetID = string.Empty; | 132 | string assetID = string.Empty; |
165 | 133 | ||
166 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 134 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
167 | { | 135 | { |
168 | IAssetService connector = GetConnector(url); | 136 | IAssetService connector = GetConnector(url); |
169 | return connector.GetCached(assetID); | 137 | return connector.GetCached(assetID); |
@@ -177,7 +145,7 @@ namespace OpenSim.Services.Connectors | |||
177 | string url = string.Empty; | 145 | string url = string.Empty; |
178 | string assetID = string.Empty; | 146 | string assetID = string.Empty; |
179 | 147 | ||
180 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 148 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
181 | { | 149 | { |
182 | IAssetService connector = GetConnector(url); | 150 | IAssetService connector = GetConnector(url); |
183 | return connector.GetMetadata(assetID); | 151 | return connector.GetMetadata(assetID); |
@@ -196,7 +164,7 @@ namespace OpenSim.Services.Connectors | |||
196 | string url = string.Empty; | 164 | string url = string.Empty; |
197 | string assetID = string.Empty; | 165 | string assetID = string.Empty; |
198 | 166 | ||
199 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 167 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
200 | { | 168 | { |
201 | IAssetService connector = GetConnector(url); | 169 | IAssetService connector = GetConnector(url); |
202 | return connector.Get(assetID, sender, handler); | 170 | return connector.Get(assetID, sender, handler); |
@@ -205,12 +173,72 @@ namespace OpenSim.Services.Connectors | |||
205 | return false; | 173 | return false; |
206 | } | 174 | } |
207 | 175 | ||
176 | |||
177 | private struct AssetAndIndex | ||
178 | { | ||
179 | public UUID assetID; | ||
180 | public int index; | ||
181 | |||
182 | public AssetAndIndex(UUID assetID, int index) | ||
183 | { | ||
184 | this.assetID = assetID; | ||
185 | this.index = index; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | public virtual bool[] AssetsExist(string[] ids) | ||
190 | { | ||
191 | // This method is a bit complicated because it works even if the assets belong to different | ||
192 | // servers; that requires sending separate requests to each server. | ||
193 | |||
194 | // Group the assets by the server they belong to | ||
195 | |||
196 | var url2assets = new Dictionary<string, List<AssetAndIndex>>(); | ||
197 | |||
198 | for (int i = 0; i < ids.Length; i++) | ||
199 | { | ||
200 | string url = string.Empty; | ||
201 | string assetID = string.Empty; | ||
202 | |||
203 | if (Util.ParseForeignAssetID(ids[i], out url, out assetID)) | ||
204 | { | ||
205 | if (!url2assets.ContainsKey(url)) | ||
206 | url2assets.Add(url, new List<AssetAndIndex>()); | ||
207 | url2assets[url].Add(new AssetAndIndex(UUID.Parse(assetID), i)); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | // Query each of the servers in turn | ||
212 | |||
213 | bool[] exist = new bool[ids.Length]; | ||
214 | |||
215 | foreach (string url in url2assets.Keys) | ||
216 | { | ||
217 | IAssetService connector = GetConnector(url); | ||
218 | lock (EndPointLock(connector)) | ||
219 | { | ||
220 | List<AssetAndIndex> curAssets = url2assets[url]; | ||
221 | string[] assetIDs = curAssets.ConvertAll(a => a.assetID.ToString()).ToArray(); | ||
222 | bool[] curExist = connector.AssetsExist(assetIDs); | ||
223 | |||
224 | int i = 0; | ||
225 | foreach (AssetAndIndex ai in curAssets) | ||
226 | { | ||
227 | exist[ai.index] = curExist[i]; | ||
228 | ++i; | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | |||
233 | return exist; | ||
234 | } | ||
235 | |||
208 | public string Store(AssetBase asset) | 236 | public string Store(AssetBase asset) |
209 | { | 237 | { |
210 | string url = string.Empty; | 238 | string url = string.Empty; |
211 | string assetID = string.Empty; | 239 | string assetID = string.Empty; |
212 | 240 | ||
213 | if (StringToUrlAndAssetID(asset.ID, out url, out assetID)) | 241 | if (Util.ParseForeignAssetID(asset.ID, out url, out assetID)) |
214 | { | 242 | { |
215 | IAssetService connector = GetConnector(url); | 243 | IAssetService connector = GetConnector(url); |
216 | // Restore the assetID to a simple UUID | 244 | // Restore the assetID to a simple UUID |
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 6f8d9ed..01cbf91 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs | |||
@@ -231,6 +231,26 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
231 | return true; | 231 | return true; |
232 | } | 232 | } |
233 | 233 | ||
234 | public bool[] AssetsExist(string[] ids) | ||
235 | { | ||
236 | if (String.IsNullOrEmpty(m_serverUrl)) | ||
237 | { | ||
238 | m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured"); | ||
239 | throw new InvalidOperationException(); | ||
240 | } | ||
241 | |||
242 | bool[] exist = new bool[ids.Length]; | ||
243 | |||
244 | for (int i = 0; i < ids.Length; i++) | ||
245 | { | ||
246 | AssetMetadata metadata = GetMetadata(ids[i]); | ||
247 | if (metadata != null) | ||
248 | exist[i] = true; | ||
249 | } | ||
250 | |||
251 | return exist; | ||
252 | } | ||
253 | |||
234 | /// <summary> | 254 | /// <summary> |
235 | /// Creates a new asset | 255 | /// Creates a new asset |
236 | /// </summary> | 256 | /// </summary> |
diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 3c469c6..8f1e039 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs | |||
@@ -75,6 +75,13 @@ namespace OpenSim.Services.Interfaces | |||
75 | /// </param> | 75 | /// </param> |
76 | /// <returns>True if the id was parseable, false otherwise</returns> | 76 | /// <returns>True if the id was parseable, false otherwise</returns> |
77 | bool Get(string id, Object sender, AssetRetrieved handler); | 77 | bool Get(string id, Object sender, AssetRetrieved handler); |
78 | |||
79 | /// <summary> | ||
80 | /// Check if assets exist in the database. | ||
81 | /// </summary> | ||
82 | /// <param name="ids">The assets' IDs</param> | ||
83 | /// <returns>For each asset: true if it exists, false otherwise</returns> | ||
84 | bool[] AssetsExist(string[] ids); | ||
78 | 85 | ||
79 | /// <summary> | 86 | /// <summary> |
80 | /// Creates a new asset | 87 | /// Creates a new asset |
diff --git a/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs b/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs index cfefd38..e6e08cd 100644 --- a/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs +++ b/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs | |||
@@ -25,6 +25,7 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
28 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
29 | using OpenMetaverse; | 30 | using OpenMetaverse; |
30 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
@@ -37,7 +38,7 @@ namespace OpenSim.Tests.Common.Mock | |||
37 | 38 | ||
38 | public AssetBase FetchAsset(UUID uuid) | 39 | public AssetBase FetchAsset(UUID uuid) |
39 | { | 40 | { |
40 | if (ExistsAsset(uuid)) | 41 | if (AssetsExist(new[] { uuid })[0]) |
41 | return Assets[uuid]; | 42 | return Assets[uuid]; |
42 | else | 43 | else |
43 | return null; | 44 | return null; |
@@ -53,9 +54,9 @@ namespace OpenSim.Tests.Common.Mock | |||
53 | CreateAsset(asset); | 54 | CreateAsset(asset); |
54 | } | 55 | } |
55 | 56 | ||
56 | public bool ExistsAsset(UUID uuid) | 57 | public bool[] AssetsExist(UUID[] uuids) |
57 | { | 58 | { |
58 | return Assets.ContainsKey(uuid); | 59 | return Array.ConvertAll(uuids, id => Assets.ContainsKey(id)); |
59 | } | 60 | } |
60 | } | 61 | } |
61 | } \ No newline at end of file | 62 | } \ No newline at end of file |