diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index 451575f8ec..a2f6740da7 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -57,104 +57,113 @@ namespace OpenSim.Capabilities.Handlers m_LibraryService = libService; } + public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { -// lock (m_fetchLock) -// { -// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request); - // nasty temporary hack here, the linden client falsely - // identifies the uuid 00000000-0000-0000-0000-000000000000 - // as a string which breaks us - // - // correctly mark it as a uuid - // - request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); + // nasty temporary hack here, the linden client falsely + // identifies the uuid 00000000-0000-0000-0000-000000000000 + // as a string which breaks us + // + // correctly mark it as a uuid + // + request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); - // another hack 1 results in a - // System.ArgumentException: Object type System.Int32 cannot - // be converted to target type: System.Boolean - // - request = request.Replace("fetch_folders0", "fetch_folders0"); - request = request.Replace("fetch_folders1", "fetch_folders1"); + // another hack 1 results in a + // System.ArgumentException: Object type System.Int32 cannot + // be converted to target type: System.Boolean + // + request = request.Replace("fetch_folders0", "fetch_folders0"); + request = request.Replace("fetch_folders1", "fetch_folders1"); - Hashtable hash = new Hashtable(); + Hashtable hash = new Hashtable(); + try + { + hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + } + catch (LLSD.LLSDParseException e) + { + m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); + m_log.Error("Request: " + request); + } + + ArrayList foldersrequested = (ArrayList)hash["folders"]; + + string response = ""; + string bad_folders_response = ""; + + List folders = new List(); + for (int i = 0; i < foldersrequested.Count; i++) + { + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + try { - hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); } - catch (LLSD.LLSDParseException e) + catch (Exception e) { - m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); - m_log.Error("Request: " + request); + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + continue; } - - ArrayList foldersrequested = (ArrayList)hash["folders"]; - - string response = ""; - string bad_folders_response = ""; - for (int i = 0; i < foldersrequested.Count; i++) + folders.Add(llsdRequest); + } + + if (folders.Count > 0) + { + List invcollSet = Fetch(folders); + //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); + if (invcollSet == null) { - string inventoryitemstr = ""; - Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol."); + return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse); + } - LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + string inventoryitemstr = string.Empty; + foreach (InventoryCollectionWithDescendents icoll in invcollSet) + { + LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); - try - { - LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); - } - catch (Exception e) - { - m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); - } - LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); - - if (null == reply) - { - bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; - } - else - { - inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); - inventoryitemstr = inventoryitemstr.Replace("folders", ""); - inventoryitemstr = inventoryitemstr.Replace("", ""); - } + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); response += inventoryitemstr; } + } - if (response.Length == 0) + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) { - /* Viewers expect a bad_folders array when not available */ - if (bad_folders_response.Length != 0) - { - response = "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders"; - } + response = "bad_folders" + bad_folders_response + ""; } else { - if (bad_folders_response.Length != 0) - { - response = "folders" + response + "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders" + response + ""; - } + response = "folders"; } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } -// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); - //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); +// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); +// m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); - return response; + return response; -// } } /// @@ -203,18 +212,130 @@ namespace OpenSim.Capabilities.Handlers contents.descendents = descendents; contents.version = version; -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", -// invFetch.folder_id, -// invFetch.fetch_items, -// invFetch.fetch_folders, -// contents.items.Array.Count, -// contents.categories.Array.Count, -// invFetch.owner_id); + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", + // invFetch.folder_id, + // invFetch.fetch_items, + // invFetch.fetch_folders, + // contents.items.Array.Count, + // contents.categories.Array.Count, + // invFetch.owner_id); return reply; } + private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) + { + LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); + LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); + contents.agent_id = inv.OwnerID; + contents.owner_id = inv.OwnerID; + contents.folder_id = inv.FolderID; + + reply.folders.Array.Add(contents); + + if (inv.Folders != null) + { + foreach (InventoryFolderBase invFolder in inv.Folders) + { + contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); + } + + descendents += inv.Folders.Count; + } + + if (inv.Items != null) + { + foreach (InventoryItemBase invItem in inv.Items) + { + contents.items.Array.Add(ConvertInventoryItem(invItem)); + } + } + + contents.descendents = descendents; + contents.version = inv.Version; + + return reply; + } + /// + /// Old style. Soon to be deprecated. + /// + /// + /// + /// + /// + [Obsolete] + private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); + + string response = ""; + string bad_folders_response = ""; + + for (int i = 0; i < foldersrequested.Count; i++) + { + string inventoryitemstr = ""; + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + + try + { + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); + } + catch (Exception e) + { + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + } + + LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); + + if (null == reply) + { + bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; + } + else + { + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); + } + + response += inventoryitemstr; + } + + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) + { + response = "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders"; + } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } + + // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); + //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); + + return response; + + // } + } + /// /// Handle the caps inventory descendents fetch. /// @@ -226,6 +347,7 @@ namespace OpenSim.Capabilities.Handlers /// /// /// An empty InventoryCollection if the inventory look up failed + [Obsolete] private InventoryCollection Fetch( UUID agentID, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) @@ -264,7 +386,6 @@ namespace OpenSim.Capabilities.Handlers m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); return contents; } - contents = fetchedContents; InventoryFolderBase containingFolder = new InventoryFolderBase(); containingFolder.ID = folderID; @@ -273,9 +394,9 @@ namespace OpenSim.Capabilities.Handlers if (containingFolder != null) { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", -// containingFolder.Name, containingFolder.ID, agentID); + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", + // containingFolder.Name, containingFolder.ID, agentID); version = containingFolder.Version; @@ -410,6 +531,160 @@ namespace OpenSim.Capabilities.Handlers return contents; } + + private void AddLibraryFolders(List fetchFolders, List result) + { + InventoryFolderImpl fold; + if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + { + List libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); + fetchFolders.RemoveAll(f => libfolders.Contains(f)); + + foreach (LLSDFetchInventoryDescendents f in libfolders) + { + if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) + { + InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); + ret.Collection = new InventoryCollection(); + ret.Collection.Folders = new List(); + ret.Collection.Items = fold.RequestListOfItems(); + ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; + ret.Collection.FolderID = f.folder_id; + ret.Collection.Version = fold.Version; + + ret.Descendents = ret.Collection.Items.Count; + + result.Add(ret); + } + } + } + } + + private List Fetch(List fetchFolders) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); + + // FIXME MAYBE: We're not handling sortOrder! + + List result = new List(); + + AddLibraryFolders(fetchFolders, result); + + if (fetchFolders.Count > 0) + { + UUID[] fids = new UUID[fetchFolders.Count]; + int i = 0; + foreach (LLSDFetchInventoryDescendents f in fetchFolders) + fids[i++] = f.folder_id; + + InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); + + if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) + { + //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); + return null; + } + + i = 0; + // Do some post-processing. May need to fetch more from inv server for links + foreach (InventoryCollection contents in fetchedContents) + { + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); + coll.Collection = contents; + + // Find the original request + LLSDFetchInventoryDescendents freq = fetchFolders[i++]; + + // The inventory server isn't sending FolderID in the collection... + // Must fetch it individually + if (contents.FolderID == UUID.Zero) + { + InventoryFolderBase containingFolder = new InventoryFolderBase(); + containingFolder.ID = freq.folder_id; + containingFolder.Owner = freq.owner_id; + containingFolder = m_InventoryService.GetFolder(containingFolder); + + if (containingFolder != null) + { + contents.FolderID = containingFolder.ID; + contents.OwnerID = containingFolder.Owner; + contents.Version = containingFolder.Version; + } + else + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); + continue; + } + } + + if (freq.fetch_items && contents.Items != null) + { + List itemsToReturn = contents.Items; + List originalItems = new List(itemsToReturn); + + // descendents must only include the links, not the linked items we add + coll.Descendents = originalItems.Count; + + // Add target items for links in this folder before the links themselves. + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.Link) + { + InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); + + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + { + itemsToReturn.Insert(0, linkedItem); + } + } + } + + // Now scan for folder links and insert the items they target and those links at the head of the return data + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.LinkFolder) + { + InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(coll.Collection.OwnerID, item.AssetID); + List links = linkedFolderContents.Items; + + itemsToReturn.InsertRange(0, links); + + foreach (InventoryItemBase link in linkedFolderContents.Items) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", + // link.Name, (AssetType)link.AssetType, item.AssetID, contents.FolderID); + + InventoryItemBase linkedItem + = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); + + if (linkedItem != null) + itemsToReturn.Insert(0, linkedItem); + } + } + } + } + } + + result.Add(coll); + } + } + + return result; + } + + /// /// Convert an internal inventory folder object into an LLSD object. /// @@ -462,4 +737,10 @@ namespace OpenSim.Capabilities.Handlers return llsdItem; } } + + struct InventoryCollectionWithDescendents + { + public InventoryCollection Collection; + public int Descendents; + } } \ No newline at end of file diff --git a/OpenSim/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs index 70499022f8..59655eb3a7 100644 --- a/OpenSim/Framework/InventoryCollection.cs +++ b/OpenSim/Framework/InventoryCollection.cs @@ -37,6 +37,8 @@ namespace OpenSim.Framework { public List Folders; public List Items; - public UUID UserID; + public UUID OwnerID; + public UUID FolderID; + public int Version; } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index e402b0b784..30d1921de7 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -201,7 +201,7 @@ namespace OpenSim.Region.ClientStack.Linden Scene.EventManager.OnRegisterCaps += RegisterCaps; - int nworkers = 1; // was 2 + int nworkers = 2; // was 2 if (ProcessQueuedRequestsAsync && m_workerThreads == null) { m_workerThreads = new Thread[nworkers]; @@ -365,7 +365,11 @@ namespace OpenSim.Region.ClientStack.Linden requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); lock (responses) + { + if (responses.ContainsKey(requestID)) + m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054"); responses[requestID] = response; + } WebFetchInvDescModule.ProcessedRequestsCount++; } diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs index 01814a15c6..eb7d3a94b7 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs @@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library { InventoryFolderImpl folder = null; InventoryCollection inv = new InventoryCollection(); - inv.UserID = m_Library.Owner; + inv.OwnerID = m_Library.Owner; if (folderID != m_Library.ID) { @@ -87,6 +87,18 @@ namespace OpenSim.Region.CoreModules.Framework.Library return inv; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + } + /// /// Add a new folder to the user's inventory /// diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index e13ee42976..232cfdf7a9 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -389,6 +389,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return connector.GetFolderContent(userID, folderID); } + public InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs) + { + string invURL = GetInventoryServiceURL(userID); + + if (invURL == null) // not there, forward to local inventory connector to resolve + lock (m_Lock) + return m_LocalGridInventoryService.GetMultipleFoldersContent(userID, folderIDs); + + else + { + InventoryCollection[] coll = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + coll[i++] = GetFolderContent(userID, fid); + + return coll; + } + } + public List GetFolderItems(UUID userID, UUID folderID) { //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 499ca5e3c5..71dc337584 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (m_Inventories.TryGetValue(userID, out inv)) { c = new InventoryCollection(); - c.UserID = userID; + c.OwnerID = userID; c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index cbe0e37d87..75dd200a18 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -195,6 +195,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return invCol; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + + } + public List GetFolderItems(UUID userID, UUID folderID) { return m_InventoryService.GetFolderItems(userID, folderID); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 166e4a15e8..9beb382b4c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -204,6 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return invCol; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + return m_RemoteConnector.GetMultipleFoldersContent(principalID, folderIDs); + } + public List GetFolderItems(UUID userID, UUID folderID) { return m_RemoteConnector.GetFolderItems(userID, folderID); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 0288fa6bf3..4f01e36903 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -41,7 +41,9 @@ using OpenSim.Server.Handlers.Base; using log4net; using OpenMetaverse; -namespace OpenSim.Server.Handlers.Asset +using System.Threading; + +namespace OpenSim.Server.Handlers.Inventory { public class XInventoryInConnector : ServiceConnector { @@ -123,6 +125,8 @@ namespace OpenSim.Server.Handlers.Asset return HandleGetFolderForType(request); case "GETFOLDERCONTENT": return HandleGetFolderContent(request); + case "GETMULTIPLEFOLDERSCONTENT": + return HandleGetMultipleFoldersContent(request); case "GETFOLDERITEMS": return HandleGetFolderItems(request); case "ADDFOLDER": @@ -284,6 +288,8 @@ namespace OpenSim.Server.Handlers.Asset InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID); if (icoll != null) { + result["FID"] = icoll.FolderID.ToString(); + result["VERSION"] = icoll.Version.ToString(); Dictionary folders = new Dictionary(); int i = 0; if (icoll.Folders != null) @@ -314,7 +320,71 @@ namespace OpenSim.Server.Handlers.Asset return Util.UTF8NoBomEncoding.GetBytes(xmlString); } - byte[] HandleGetFolderItems(Dictionary request) + byte[] HandleGetMultipleFoldersContent(Dictionary request) + { + Dictionary resultSet = new Dictionary(); + UUID principal = UUID.Zero; + UUID.TryParse(request["PRINCIPAL"].ToString(), out principal); + string folderIDstr = request["FOLDERS"].ToString(); + int count = 0; + Int32.TryParse(request["COUNT"].ToString(), out count); + + UUID[] fids = new UUID[count]; + string[] uuids = folderIDstr.Split(','); + int i = 0; + foreach (string id in uuids) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(id, out fid)) + fids[i] = fid; + i += 1; + } + + count = 0; + InventoryCollection[] icollList = m_InventoryService.GetMultipleFoldersContent(principal, fids); + if (icollList != null && icollList.Length > 0) + { + foreach (InventoryCollection icoll in icollList) + { + Dictionary result = new Dictionary(); + result["FID"] = icoll.FolderID.ToString(); + result["VERSION"] = icoll.Version.ToString(); + result["OWNER"] = icoll.OwnerID.ToString(); + Dictionary folders = new Dictionary(); + i = 0; + if (icoll.Folders != null) + { + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; + } + i = 0; + if (icoll.Items != null) + { + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; + } + + resultSet["F_" + fids[count++]] = result; + //m_log.DebugFormat("[XXX]: Sending {0} {1}", fids[count-1], icoll.FolderID); + } + } + + string xmlString = ServerUtils.BuildXmlResponse(resultSet); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetFolderItems(Dictionary request) { Dictionary result = new Dictionary(); UUID principal = UUID.Zero; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 574de892ce..c694d276df 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -205,7 +205,7 @@ namespace OpenSim.Services.Connectors InventoryCollection inventory = new InventoryCollection(); inventory.Folders = new List(); inventory.Items = new List(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; try { @@ -235,7 +235,86 @@ 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}", folderIDs.Length); + 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); + } + + 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) { Dictionary ret = MakeRequest("GETFOLDERITEMS", diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 9ded1c4d28..0331c66d2e 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -340,7 +340,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { @@ -371,6 +371,18 @@ namespace OpenSim.Services.Connectors.SimianGrid return inventory; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + } + /// /// Gets the items inside a folder /// @@ -380,7 +392,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public List GetFolderItems(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 2c63240476..5f245e4dea 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -153,7 +153,14 @@ namespace OpenSim.Services.HypergridService //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) //{ //} - + + // NOGO + // + public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID) + { + return new InventoryCollection[0]; + } + //public List GetFolderItems(UUID principalID, UUID folderID) //{ //} diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs index 2805356cde..829f1699bd 100644 --- a/OpenSim/Services/Interfaces/IInventoryService.cs +++ b/OpenSim/Services/Interfaces/IInventoryService.cs @@ -76,6 +76,14 @@ namespace OpenSim.Services.Interfaces /// /// Inventory content. null if the request failed. InventoryCollection GetFolderContent(UUID userID, UUID folderID); + + /// + /// Gets everything (folders and items) inside a folder + /// + /// + /// + /// Inventory content. null if the request failed. + InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs); /// /// Gets the items inside a folder diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 362ff8f8c1..6582b75cf0 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -291,7 +291,7 @@ namespace OpenSim.Services.InventoryService // //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; inventory.Folders = new List(); inventory.Items = new List(); @@ -315,8 +315,27 @@ namespace OpenSim.Services.InventoryService inventory.Items.Add(ConvertToOpenSim(i)); } + InventoryFolderBase f = new InventoryFolderBase(folderID, principalID); + f = GetFolder(f); + if (f != null) + { + inventory.Version = f.Version; + inventory.OwnerID = f.Owner; + } + inventory.FolderID = folderID; + return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] multiple = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + multiple[i++] = GetFolderContent(principalID, fid); + + return multiple; + } public virtual List GetFolderItems(UUID principalID, UUID folderID) {