aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services')
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs285
1 files changed, 219 insertions, 66 deletions
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index 36d4ae2..f235446 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -33,22 +33,37 @@ using System.Reflection;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Console; 35using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications; 36
37using OpenSim.Framework.Monitoring;
37using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
38using OpenSim.Server.Base; 39using OpenSim.Server.Base;
39using OpenMetaverse; 40using OpenMetaverse;
40 41
41namespace OpenSim.Services.Connectors 42namespace OpenSim.Services.Connectors
42{ 43{
43 public class XInventoryServicesConnector : IInventoryService 44 public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService
44 { 45 {
45 private static readonly ILog m_log = 46 private static readonly ILog m_log =
46 LogManager.GetLogger( 47 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
48 49
50 /// <summary>
51 /// Number of requests made to the remote inventory service.
52 /// </summary>
53 public int RequestsMade { get; private set; }
54
49 private string m_ServerURI = String.Empty; 55 private string m_ServerURI = String.Empty;
50 56
51 private object m_Lock = new object(); 57 /// <summary>
58 /// Timeout for remote requests.
59 /// </summary>
60 /// <remarks>
61 /// In this case, -1 is default timeout (100 seconds), not infinite.
62 /// </remarks>
63 private int m_requestTimeoutSecs = -1;
64
65 private const double CACHE_EXPIRATION_SECONDS = 20.0;
66 private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache = new ExpiringCache<UUID,InventoryItemBase>();
52 67
53 public XInventoryServicesConnector() 68 public XInventoryServicesConnector()
54 { 69 {
@@ -60,20 +75,21 @@ namespace OpenSim.Services.Connectors
60 } 75 }
61 76
62 public XInventoryServicesConnector(IConfigSource source) 77 public XInventoryServicesConnector(IConfigSource source)
78 : base(source, "InventoryService")
63 { 79 {
64 Initialise(source); 80 Initialise(source);
65 } 81 }
66 82
67 public virtual void Initialise(IConfigSource source) 83 public virtual void Initialise(IConfigSource source)
68 { 84 {
69 IConfig assetConfig = source.Configs["InventoryService"]; 85 IConfig config = source.Configs["InventoryService"];
70 if (assetConfig == null) 86 if (config == null)
71 { 87 {
72 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); 88 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
73 throw new Exception("Inventory connector init error"); 89 throw new Exception("Inventory connector init error");
74 } 90 }
75 91
76 string serviceURI = assetConfig.GetString("InventoryServerURI", 92 string serviceURI = config.GetString("InventoryServerURI",
77 String.Empty); 93 String.Empty);
78 94
79 if (serviceURI == String.Empty) 95 if (serviceURI == String.Empty)
@@ -82,6 +98,21 @@ namespace OpenSim.Services.Connectors
82 throw new Exception("Inventory connector init error"); 98 throw new Exception("Inventory connector init error");
83 } 99 }
84 m_ServerURI = serviceURI; 100 m_ServerURI = serviceURI;
101
102 m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
103
104 StatsManager.RegisterStat(
105 new Stat(
106 "RequestsMade",
107 "Requests made",
108 "Number of requests made to the remove inventory service",
109 "requests",
110 "inventory",
111 serviceURI,
112 StatType.Pull,
113 MeasuresOfInterest.AverageChangeOverTime,
114 s => s.Value = RequestsMade,
115 StatVerbosity.Debug));
85 } 116 }
86 117
87 private bool CheckReturn(Dictionary<string, object> ret) 118 private bool CheckReturn(Dictionary<string, object> ret)
@@ -158,7 +189,7 @@ namespace OpenSim.Services.Connectors
158 return BuildFolder((Dictionary<string, object>)ret["folder"]); 189 return BuildFolder((Dictionary<string, object>)ret["folder"]);
159 } 190 }
160 191
161 public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 192 public InventoryFolderBase GetFolderForType(UUID principalID, FolderType type)
162 { 193 {
163 Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE", 194 Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE",
164 new Dictionary<string,object> { 195 new Dictionary<string,object> {
@@ -177,7 +208,7 @@ namespace OpenSim.Services.Connectors
177 InventoryCollection inventory = new InventoryCollection(); 208 InventoryCollection inventory = new InventoryCollection();
178 inventory.Folders = new List<InventoryFolderBase>(); 209 inventory.Folders = new List<InventoryFolderBase>();
179 inventory.Items = new List<InventoryItemBase>(); 210 inventory.Items = new List<InventoryItemBase>();
180 inventory.UserID = principalID; 211 inventory.OwnerID = principalID;
181 212
182 try 213 try
183 { 214 {
@@ -190,15 +221,17 @@ namespace OpenSim.Services.Connectors
190 if (!CheckReturn(ret)) 221 if (!CheckReturn(ret))
191 return null; 222 return null;
192 223
193 Dictionary<string,object> folders = 224 Dictionary<string,object> folders = ret.ContainsKey("FOLDERS") ?
194 (Dictionary<string,object>)ret["FOLDERS"]; 225 (Dictionary<string,object>)ret["FOLDERS"] : null;
195 Dictionary<string,object> items = 226 Dictionary<string,object> items = ret.ContainsKey("ITEMS") ?
196 (Dictionary<string,object>)ret["ITEMS"]; 227 (Dictionary<string, object>)ret["ITEMS"] : null;
197 228
198 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i 229 if (folders != null)
199 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o)); 230 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
200 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i 231 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
201 inventory.Items.Add(BuildItem((Dictionary<string, object>)o)); 232 if (items != null)
233 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
234 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
202 } 235 }
203 catch (Exception e) 236 catch (Exception e)
204 { 237 {
@@ -207,6 +240,87 @@ namespace OpenSim.Services.Connectors
207 240
208 return inventory; 241 return inventory;
209 } 242 }
243
244 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
245 {
246 InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
247 // m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", String.Join(",", folderIDs));
248 try
249 {
250 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
251 new Dictionary<string, object> {
252 { "PRINCIPAL", principalID.ToString() },
253 { "FOLDERS", String.Join(",", folderIDs) },
254 { "COUNT", folderIDs.Length.ToString() }
255 });
256
257 if (!CheckReturn(resultSet))
258 return null;
259
260 int i = 0;
261 foreach (KeyValuePair<string, object> kvp in resultSet)
262 {
263 InventoryCollection inventory = new InventoryCollection();
264 if (kvp.Key.StartsWith("F_"))
265 {
266 UUID fid = UUID.Zero;
267 if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
268 {
269 inventory.Folders = new List<InventoryFolderBase>();
270 inventory.Items = new List<InventoryItemBase>();
271
272 Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
273
274 if (ret.ContainsKey("FID"))
275 {
276 if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
277 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
278 }
279 else
280 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
281
282 inventory.Version = -1;
283 if (ret.ContainsKey("VERSION"))
284 Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
285 if (ret.ContainsKey("OWNER"))
286 UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
287
288 //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
289
290 Dictionary<string, object> folders =
291 (Dictionary<string, object>)ret["FOLDERS"];
292 Dictionary<string, object> items =
293 (Dictionary<string, object>)ret["ITEMS"];
294
295 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
296 {
297 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
298 }
299 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
300 {
301 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
302 }
303
304 inventoryArr[i] = inventory;
305 }
306 else
307 {
308 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
309 folderIDs[i], fid);
310 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys));
311 }
312
313 i += 1;
314 }
315 }
316 }
317 catch (Exception e)
318 {
319 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
320 }
321
322 return inventoryArr;
323 }
210 324
211 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 325 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
212 { 326 {
@@ -297,9 +411,13 @@ namespace OpenSim.Services.Connectors
297 411
298 public bool AddItem(InventoryItemBase item) 412 public bool AddItem(InventoryItemBase item)
299 { 413 {
414 if (item.Description == null)
415 item.Description = String.Empty;
300 if (item.CreatorData == null) 416 if (item.CreatorData == null)
301 item.CreatorData = String.Empty; 417 item.CreatorData = String.Empty;
302 Dictionary<string,object> ret = MakeRequest("ADDITEM", 418 if (item.CreatorId == null)
419 item.CreatorId = String.Empty;
420 Dictionary<string, object> ret = MakeRequest("ADDITEM",
303 new Dictionary<string,object> { 421 new Dictionary<string,object> {
304 { "AssetID", item.AssetID.ToString() }, 422 { "AssetID", item.AssetID.ToString() },
305 { "AssetType", item.AssetType.ToString() }, 423 { "AssetType", item.AssetType.ToString() },
@@ -398,6 +516,10 @@ namespace OpenSim.Services.Connectors
398 516
399 public InventoryItemBase GetItem(InventoryItemBase item) 517 public InventoryItemBase GetItem(InventoryItemBase item)
400 { 518 {
519 InventoryItemBase retrieved = null;
520 if (m_ItemCache.TryGetValue(item.ID, out retrieved))
521 return retrieved;
522
401 try 523 try
402 { 524 {
403 Dictionary<string, object> ret = MakeRequest("GETITEM", 525 Dictionary<string, object> ret = MakeRequest("GETITEM",
@@ -408,14 +530,78 @@ namespace OpenSim.Services.Connectors
408 if (!CheckReturn(ret)) 530 if (!CheckReturn(ret))
409 return null; 531 return null;
410 532
411 return BuildItem((Dictionary<string, object>)ret["item"]); 533 retrieved = BuildItem((Dictionary<string, object>)ret["item"]);
412 } 534 }
413 catch (Exception e) 535 catch (Exception e)
414 { 536 {
415 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); 537 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
416 } 538 }
417 539
418 return null; 540 m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
541
542 return retrieved;
543 }
544
545 public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
546 {
547 //m_log.DebugFormat("[XXX]: In GetMultipleItems {0}", String.Join(",", itemIDs));
548
549 InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
550 // Try to get them from the cache
551 List<UUID> pending = new List<UUID>();
552 InventoryItemBase item = null;
553 int i = 0;
554 foreach (UUID id in itemIDs)
555 {
556 if (m_ItemCache.TryGetValue(id, out item))
557 itemArr[i++] = item;
558 else
559 pending.Add(id);
560 }
561
562 if (pending.Count == 0) // we're done, everything was in the cache
563 return itemArr;
564
565 try
566 {
567 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
568 new Dictionary<string, object> {
569 { "PRINCIPAL", principalID.ToString() },
570 { "ITEMS", String.Join(",", pending.ToArray()) },
571 { "COUNT", pending.Count.ToString() }
572 });
573
574 if (!CheckReturn(resultSet))
575 {
576 if (i == 0)
577 return null;
578 else
579 return itemArr;
580 }
581
582 // carry over index i where we left above
583 foreach (KeyValuePair<string, object> kvp in resultSet)
584 {
585 InventoryCollection inventory = new InventoryCollection();
586 if (kvp.Key.StartsWith("item_"))
587 {
588 if (kvp.Value is Dictionary<string, object>)
589 {
590 item = BuildItem((Dictionary<string, object>)kvp.Value);
591 m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS);
592 itemArr[i++] = item;
593 }
594 else
595 itemArr[i++] = null;
596 }
597 }
598 }
599 catch (Exception e)
600 {
601 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message);
602 }
603
604 return itemArr;
419 } 605 }
420 606
421 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 607 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
@@ -484,45 +670,6 @@ namespace OpenSim.Services.Connectors
484 return 0; 670 return 0;
485 } 671 }
486 672
487 public InventoryCollection GetUserInventory(UUID principalID)
488 {
489 InventoryCollection inventory = new InventoryCollection();
490 inventory.Folders = new List<InventoryFolderBase>();
491 inventory.Items = new List<InventoryItemBase>();
492 inventory.UserID = principalID;
493
494 try
495 {
496 Dictionary<string, object> ret = MakeRequest("GETUSERINVENTORY",
497 new Dictionary<string, object> {
498 { "PRINCIPAL", principalID.ToString() }
499 });
500
501 if (!CheckReturn(ret))
502 return null;
503
504 Dictionary<string, object> folders =
505 (Dictionary<string, object>)ret["FOLDERS"];
506 Dictionary<string, object> items =
507 (Dictionary<string, object>)ret["ITEMS"];
508
509 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
510 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
511 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
512 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
513 }
514 catch (Exception e)
515 {
516 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e);
517 }
518
519 return inventory;
520 }
521
522 public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback)
523 {
524 }
525
526 public bool HasInventoryForUser(UUID principalID) 673 public bool HasInventoryForUser(UUID principalID)
527 { 674 {
528 return false; 675 return false;
@@ -533,13 +680,19 @@ namespace OpenSim.Services.Connectors
533 private Dictionary<string,object> MakeRequest(string method, 680 private Dictionary<string,object> MakeRequest(string method,
534 Dictionary<string,object> sendData) 681 Dictionary<string,object> sendData)
535 { 682 {
536 sendData["METHOD"] = method; 683 // Add "METHOD" as the first key in the dictionary. This ensures that it will be
684 // visible even when using partial logging ("debug http all 5").
685 Dictionary<string, object> temp = sendData;
686 sendData = new Dictionary<string,object>{ { "METHOD", method } };
687 foreach (KeyValuePair<string, object> kvp in temp)
688 sendData.Add(kvp.Key, kvp.Value);
689
690 RequestsMade++;
537 691
538 string reply = string.Empty; 692 string reply
539 lock (m_Lock) 693 = SynchronousRestFormsRequester.MakeRequest(
540 reply = SynchronousRestFormsRequester.MakeRequest("POST", 694 "POST", m_ServerURI + "/xinventory",
541 m_ServerURI + "/xinventory", 695 ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
542 ServerUtils.BuildQueryString(sendData));
543 696
544 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse( 697 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
545 reply); 698 reply);
@@ -607,4 +760,4 @@ namespace OpenSim.Services.Connectors
607 return item; 760 return item;
608 } 761 }
609 } 762 }
610} \ No newline at end of file 763}