aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOren Hurvitz2014-03-31 11:53:12 +0300
committerOren Hurvitz2014-04-02 06:30:57 +0100
commitd1c3f8eef58b29eb8760eeb1ac03852a2387f927 (patch)
treeb8686f4ea01b6dac3740b9685734686e2178dd2d
parentfix orphaned code in sun module per mantis 7068 (diff)
downloadopensim-SC-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.zip
opensim-SC-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.tar.gz
opensim-SC-d1c3f8eef58b29eb8760eeb1ac03852a2387f927.tar.bz2
opensim-SC-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.
-rw-r--r--OpenSim/Data/AssetDataBase.cs3
-rw-r--r--OpenSim/Data/IAssetData.cs2
-rw-r--r--OpenSim/Data/IXAssetDataPlugin.cs2
-rw-r--r--OpenSim/Data/MSSQL/MSSQLAssetData.cs35
-rw-r--r--OpenSim/Data/MySQL/MySQLAssetData.cs42
-rw-r--r--OpenSim/Data/MySQL/MySQLXAssetData.cs40
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAssetData.cs35
-rw-r--r--OpenSim/Data/PGSQL/PGSQLXAssetData.cs37
-rw-r--r--OpenSim/Data/SQLite/SQLiteAssetData.cs37
-rw-r--r--OpenSim/Data/Tests/AssetTests.cs16
-rw-r--r--OpenSim/Framework/Util.cs50
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs12
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs69
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs17
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs5
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerConnector.cs3
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs74
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetsExistHandler.cs80
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs19
-rw-r--r--OpenSim/Services/AssetService/XAssetService.cs11
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs21
-rw-r--r--OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs104
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs20
-rw-r--r--OpenSim/Services/Interfaces/IAssetService.cs7
-rw-r--r--OpenSim/Tests/Common/Mock/BaseAssetRepository.cs9
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;
52using OpenMetaverse.StructuredData; 52using OpenMetaverse.StructuredData;
53using Amib.Threading; 53using Amib.Threading;
54using System.Collections.Concurrent; 54using System.Collections.Concurrent;
55using System.Collections.Specialized;
56using System.Web;
55 57
56namespace OpenSim.Framework 58namespace 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
28using Nini.Config;
29using log4net;
30using System;
31using System.Reflection;
32using System.IO;
33using System.Net;
34using System.Text;
35using System.Text.RegularExpressions;
36using System.Xml;
37using System.Xml.Serialization;
38using OpenSim.Server.Base;
39using OpenSim.Services.Interfaces;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenMetaverse;
43
44namespace 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;
36using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.Hypergrid; 37using OpenSim.Services.Connectors.Hypergrid;
38using OpenSim.Services.Connectors.SimianGrid; 38using OpenSim.Services.Connectors.SimianGrid;
39using OpenMetaverse;
39 40
40namespace OpenSim.Services.Connectors 41namespace 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
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenSim.Framework; 31using 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