From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- .../Inventory/XInventoryServicesConnector.cs | 405 ++++++++++++++------- 1 file changed, 277 insertions(+), 128 deletions(-) (limited to 'OpenSim/Services/Connectors/Inventory') diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 44f5e01..7cecd93 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -33,22 +33,37 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.Monitoring; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class XInventoryServicesConnector : IInventoryService + public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Number of requests made to the remote inventory service. + /// + public int RequestsMade { get; private set; } + private string m_ServerURI = String.Empty; - private object m_Lock = new object(); + /// + /// Timeout for remote requests. + /// + /// + /// In this case, -1 is default timeout (100 seconds), not infinite. + /// + private int m_requestTimeoutSecs = -1; + + private const double CACHE_EXPIRATION_SECONDS = 20.0; + private static ExpiringCache m_ItemCache = new ExpiringCache(); public XInventoryServicesConnector() { @@ -60,20 +75,21 @@ namespace OpenSim.Services.Connectors } public XInventoryServicesConnector(IConfigSource source) + : base(source, "InventoryService") { Initialise(source); } public virtual void Initialise(IConfigSource source) { - IConfig assetConfig = source.Configs["InventoryService"]; - if (assetConfig == null) + IConfig config = source.Configs["InventoryService"]; + if (config == null) { m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); throw new Exception("Inventory connector init error"); } - string serviceURI = assetConfig.GetString("InventoryServerURI", + string serviceURI = config.GetString("InventoryServerURI", String.Empty); if (serviceURI == String.Empty) @@ -82,6 +98,45 @@ namespace OpenSim.Services.Connectors throw new Exception("Inventory connector init error"); } m_ServerURI = serviceURI; + + m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs); + + StatsManager.RegisterStat( + new Stat( + "RequestsMade", + "Requests made", + "Number of requests made to the remove inventory service", + "requests", + "inventory", + serviceURI, + StatType.Pull, + MeasuresOfInterest.AverageChangeOverTime, + s => s.Value = RequestsMade, + StatVerbosity.Debug)); + } + + private bool CheckReturn(Dictionary ret) + { + if (ret == null) + return false; + + if (ret.Count == 0) + return false; + + if (ret.ContainsKey("RESULT")) + { + if (ret["RESULT"] is string) + { + bool result; + + if (bool.TryParse((string)ret["RESULT"], out result)) + return result; + + return false; + } + } + + return true; } public bool CreateUserInventory(UUID principalID) @@ -91,12 +146,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return false; - if (ret.Count == 0) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public List GetInventorySkeleton(UUID principalID) @@ -106,9 +156,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; Dictionary folders = (Dictionary)ret["FOLDERS"]; @@ -135,15 +183,13 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); } - public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + public InventoryFolderBase GetFolderForType(UUID principalID, FolderType type) { Dictionary ret = MakeRequest("GETFOLDERFORTYPE", new Dictionary { @@ -151,9 +197,7 @@ namespace OpenSim.Services.Connectors { "TYPE", ((int)type).ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); @@ -164,7 +208,7 @@ namespace OpenSim.Services.Connectors InventoryCollection inventory = new InventoryCollection(); inventory.Folders = new List(); inventory.Items = new List(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; try { @@ -174,20 +218,20 @@ namespace OpenSim.Services.Connectors { "FOLDER", folderID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; - Dictionary folders = - (Dictionary)ret["FOLDERS"]; - Dictionary items = - (Dictionary)ret["ITEMS"]; - - foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i - inventory.Folders.Add(BuildFolder((Dictionary)o)); - foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i - inventory.Items.Add(BuildItem((Dictionary)o)); + Dictionary folders = ret.ContainsKey("FOLDERS") ? + (Dictionary)ret["FOLDERS"] : null; + Dictionary items = ret.ContainsKey("ITEMS") ? + (Dictionary)ret["ITEMS"] : null; + + if (folders != null) + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + inventory.Folders.Add(BuildFolder((Dictionary)o)); + if (items != null) + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + inventory.Items.Add(BuildItem((Dictionary)o)); } catch (Exception e) { @@ -196,6 +240,87 @@ namespace OpenSim.Services.Connectors return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length]; + // m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", String.Join(",", folderIDs)); + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "FOLDERS", String.Join(",", folderIDs) }, + { "COUNT", folderIDs.Length.ToString() } + }); + + if (!CheckReturn(resultSet)) + return null; + + int i = 0; + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("F_")) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i]) + { + inventory.Folders = new List(); + inventory.Items = new List(); + + Dictionary ret = (Dictionary)kvp.Value; + + if (ret.ContainsKey("FID")) + { + if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID)) + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString()); + } + else + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response"); + + inventory.Version = -1; + if (ret.ContainsKey("VERSION")) + Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version); + if (ret.ContainsKey("OWNER")) + UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID); + + //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID); + + Dictionary folders = + (Dictionary)ret["FOLDERS"]; + Dictionary items = + (Dictionary)ret["ITEMS"]; + + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + { + inventory.Folders.Add(BuildFolder((Dictionary)o)); + } + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + { + inventory.Items.Add(BuildItem((Dictionary)o)); + } + + inventoryArr[i] = inventory; + } + else + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}", + folderIDs[i], fid); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys)); + } + + i += 1; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message); + } + + return inventoryArr; + } public List GetFolderItems(UUID principalID, UUID folderID) { @@ -205,9 +330,7 @@ namespace OpenSim.Services.Connectors { "FOLDER", folderID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; Dictionary items = (Dictionary)ret["ITEMS"]; @@ -230,10 +353,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool UpdateFolder(InventoryFolderBase folder) @@ -248,10 +368,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool MoveFolder(InventoryFolderBase folder) @@ -263,10 +380,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", folder.Owner.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool DeleteFolders(UUID principalID, List folderIDs) @@ -282,10 +396,7 @@ namespace OpenSim.Services.Connectors { "FOLDERS", slist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool PurgeFolder(InventoryFolderBase folder) @@ -295,17 +406,18 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool AddItem(InventoryItemBase item) { + if (item.Description == null) + item.Description = String.Empty; if (item.CreatorData == null) item.CreatorData = String.Empty; - Dictionary ret = MakeRequest("ADDITEM", + if (item.CreatorId == null) + item.CreatorId = String.Empty; + Dictionary ret = MakeRequest("ADDITEM", new Dictionary { { "AssetID", item.AssetID.ToString() }, { "AssetType", item.AssetType.ToString() }, @@ -330,10 +442,7 @@ namespace OpenSim.Services.Connectors { "CreationDate", item.CreationDate.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool UpdateItem(InventoryItemBase item) @@ -365,10 +474,13 @@ namespace OpenSim.Services.Connectors { "CreationDate", item.CreationDate.ToString() } }); - if (ret == null) - return false; + bool result = CheckReturn(ret); + if (result) + { + m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS); + } - return bool.Parse(ret["RESULT"].ToString()); + return result; } public bool MoveItems(UUID principalID, List items) @@ -389,10 +501,7 @@ namespace OpenSim.Services.Connectors { "DESTLIST", destlist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool DeleteItems(UUID principalID, List itemIDs) @@ -408,14 +517,17 @@ namespace OpenSim.Services.Connectors { "ITEMS", slist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public InventoryItemBase GetItem(InventoryItemBase item) { + InventoryItemBase retrieved = null; + if (m_ItemCache.TryGetValue(item.ID, out retrieved)) + { + return retrieved; + } + try { Dictionary ret = MakeRequest("GETITEM", @@ -423,19 +535,81 @@ namespace OpenSim.Services.Connectors { "ID", item.ID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; - return BuildItem((Dictionary)ret["item"]); + retrieved = BuildItem((Dictionary)ret["item"]); } catch (Exception e) { m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); } - return null; + m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS); + + return retrieved; + } + + public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + //m_log.DebugFormat("[XXX]: In GetMultipleItems {0}", String.Join(",", itemIDs)); + + InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length]; + // Try to get them from the cache + List pending = new List(); + InventoryItemBase item = null; + int i = 0; + foreach (UUID id in itemIDs) + { + if (m_ItemCache.TryGetValue(id, out item)) + itemArr[i++] = item; + else + pending.Add(id); + } + + if (pending.Count == 0) // we're done, everything was in the cache + return itemArr; + + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEITEMS", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "ITEMS", String.Join(",", pending.ToArray()) }, + { "COUNT", pending.Count.ToString() } + }); + + if (!CheckReturn(resultSet)) + { + if (i == 0) + return null; + else + return itemArr; + } + + // carry over index i where we left above + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("item_")) + { + if (kvp.Value is Dictionary) + { + item = BuildItem((Dictionary)kvp.Value); + m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS); + itemArr[i++] = item; + } + else + itemArr[i++] = null; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message); + } + + return itemArr; } public InventoryFolderBase GetFolder(InventoryFolderBase folder) @@ -447,9 +621,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); @@ -469,7 +641,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) + if (!CheckReturn(ret)) return null; List items = new List(); @@ -488,51 +660,22 @@ namespace OpenSim.Services.Connectors { "ASSET", assetID.ToString() } }); + // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int if (ret == null) return 0; - return int.Parse(ret["RESULT"].ToString()); - } - - public InventoryCollection GetUserInventory(UUID principalID) - { - InventoryCollection inventory = new InventoryCollection(); - inventory.Folders = new List(); - inventory.Items = new List(); - inventory.UserID = principalID; - - try + if (ret.ContainsKey("RESULT")) { - Dictionary ret = MakeRequest("GETUSERINVENTORY", - new Dictionary { - { "PRINCIPAL", principalID.ToString() } - }); - - if (ret == null) - return null; - if (ret.Count == 0) - return null; - - Dictionary folders = - (Dictionary)ret["FOLDERS"]; - Dictionary items = - (Dictionary)ret["ITEMS"]; + if (ret["RESULT"] is string) + { + int intResult; - foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i - inventory.Folders.Add(BuildFolder((Dictionary)o)); - foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i - inventory.Items.Add(BuildItem((Dictionary)o)); + if (int.TryParse ((string)ret["RESULT"], out intResult)) + return intResult; + } } - catch (Exception e) - { - m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e); - } - - return inventory; - } - public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback) - { + return 0; } public bool HasInventoryForUser(UUID principalID) @@ -545,13 +688,19 @@ namespace OpenSim.Services.Connectors private Dictionary MakeRequest(string method, Dictionary sendData) { - sendData["METHOD"] = method; + // Add "METHOD" as the first key in the dictionary. This ensures that it will be + // visible even when using partial logging ("debug http all 5"). + Dictionary temp = sendData; + sendData = new Dictionary{ { "METHOD", method } }; + foreach (KeyValuePair kvp in temp) + sendData.Add(kvp.Key, kvp.Value); + + RequestsMade++; - string reply = string.Empty; - lock (m_Lock) - reply = SynchronousRestFormsRequester.MakeRequest("POST", - m_ServerURI + "/xinventory", - ServerUtils.BuildQueryString(sendData)); + string reply + = SynchronousRestFormsRequester.MakeRequest( + "POST", m_ServerURI + "/xinventory", + ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); @@ -619,4 +768,4 @@ namespace OpenSim.Services.Connectors return item; } } -} \ No newline at end of file +} -- cgit v1.1