diff options
Diffstat (limited to 'OpenSim/Capabilities/Handlers')
-rw-r--r-- | OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs | 242 |
1 files changed, 140 insertions, 102 deletions
diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index b7f332d..8dd6235 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs | |||
@@ -603,136 +603,174 @@ namespace OpenSim.Capabilities.Handlers | |||
603 | // Do some post-processing. May need to fetch more from inv server for links | 603 | // Do some post-processing. May need to fetch more from inv server for links |
604 | foreach (InventoryCollection contents in fetchedContents) | 604 | foreach (InventoryCollection contents in fetchedContents) |
605 | { | 605 | { |
606 | // Find the original request | ||
607 | LLSDFetchInventoryDescendents freq = fetchFolders[i++]; | ||
608 | |||
606 | InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); | 609 | InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); |
607 | coll.Collection = contents; | 610 | coll.Collection = contents; |
608 | 611 | ||
609 | if (contents == null) | 612 | if (BadFolder(freq, contents, bad_folders)) |
610 | { | ||
611 | bad_folders.Add(fids[i++]); | ||
612 | continue; | 613 | continue; |
614 | |||
615 | // Next: link management | ||
616 | ProcessLinks(freq, coll); | ||
617 | |||
618 | result.Add(coll); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | return result; | ||
623 | } | ||
624 | |||
625 | private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders) | ||
626 | { | ||
627 | bool bad = false; | ||
628 | if (contents == null) | ||
629 | { | ||
630 | bad_folders.Add(freq.folder_id); | ||
631 | bad = true; | ||
632 | } | ||
633 | |||
634 | // The inventory server isn't sending FolderID in the collection... | ||
635 | // Must fetch it individually | ||
636 | if (contents.FolderID == UUID.Zero) | ||
637 | { | ||
638 | InventoryFolderBase containingFolder = new InventoryFolderBase(); | ||
639 | containingFolder.ID = freq.folder_id; | ||
640 | containingFolder.Owner = freq.owner_id; | ||
641 | containingFolder = m_InventoryService.GetFolder(containingFolder); | ||
642 | |||
643 | if (containingFolder != null) | ||
644 | { | ||
645 | contents.FolderID = containingFolder.ID; | ||
646 | contents.OwnerID = containingFolder.Owner; | ||
647 | contents.Version = containingFolder.Version; | ||
648 | } | ||
649 | else | ||
650 | { | ||
651 | // Was it really a request for folder Zero? | ||
652 | // This is an overkill, but Firestorm really asks for folder Zero. | ||
653 | // I'm leaving the code here for the time being, but commented. | ||
654 | if (freq.folder_id == UUID.Zero) | ||
655 | { | ||
656 | //coll.Collection.OwnerID = freq.owner_id; | ||
657 | //coll.Collection.FolderID = contents.FolderID; | ||
658 | //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); | ||
659 | //if (containingFolder != null) | ||
660 | //{ | ||
661 | // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); | ||
662 | // coll.Collection.Folders.Clear(); | ||
663 | // coll.Collection.Folders.Add(containingFolder); | ||
664 | // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) | ||
665 | // { | ||
666 | // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); | ||
667 | // lib.Name = m_LibraryService.LibraryRootFolder.Name; | ||
668 | // lib.Type = m_LibraryService.LibraryRootFolder.Type; | ||
669 | // lib.Version = m_LibraryService.LibraryRootFolder.Version; | ||
670 | // coll.Collection.Folders.Add(lib); | ||
671 | // } | ||
672 | // coll.Collection.Items.Clear(); | ||
673 | //} | ||
674 | } | ||
675 | else | ||
676 | { | ||
677 | m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); | ||
678 | bad_folders.Add(freq.folder_id); | ||
679 | bad = true; | ||
613 | } | 680 | } |
681 | } | ||
682 | } | ||
614 | 683 | ||
684 | return bad; | ||
685 | } | ||
615 | 686 | ||
616 | // Find the original request | 687 | private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) |
617 | LLSDFetchInventoryDescendents freq = fetchFolders[i++]; | 688 | { |
689 | InventoryCollection contents = coll.Collection; | ||
690 | |||
691 | if (freq.fetch_items && contents.Items != null) | ||
692 | { | ||
693 | List<InventoryItemBase> itemsToReturn = contents.Items; | ||
694 | |||
695 | // descendents must only include the links, not the linked items we add | ||
696 | coll.Descendents = itemsToReturn.Count; | ||
618 | 697 | ||
619 | // The inventory server isn't sending FolderID in the collection... | 698 | // Add target items for links in this folder before the links themselves. |
620 | // Must fetch it individually | 699 | List<UUID> itemIDs = new List<UUID>(); |
621 | if (contents.FolderID == UUID.Zero) | 700 | List<UUID> folderIDs = new List<UUID>(); |
701 | foreach (InventoryItemBase item in itemsToReturn) | ||
702 | { | ||
703 | //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); | ||
704 | if (item.AssetType == (int)AssetType.Link) | ||
705 | itemIDs.Add(item.AssetID); | ||
706 | |||
707 | else if (item.AssetType == (int)AssetType.LinkFolder) | ||
708 | folderIDs.Add(item.AssetID); | ||
709 | } | ||
710 | |||
711 | //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); | ||
712 | |||
713 | // Scan for folder links and insert the items they target and those links at the head of the return data | ||
714 | if (folderIDs.Count > 0) | ||
715 | { | ||
716 | InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); | ||
717 | foreach (InventoryCollection linkedFolderContents in linkedFolders) | ||
622 | { | 718 | { |
623 | InventoryFolderBase containingFolder = new InventoryFolderBase(); | 719 | List<InventoryItemBase> links = linkedFolderContents.Items; |
624 | containingFolder.ID = freq.folder_id; | ||
625 | containingFolder.Owner = freq.owner_id; | ||
626 | containingFolder = m_InventoryService.GetFolder(containingFolder); | ||
627 | 720 | ||
628 | if (containingFolder != null) | 721 | itemsToReturn.InsertRange(0, links); |
629 | { | 722 | |
630 | contents.FolderID = containingFolder.ID; | 723 | foreach (InventoryItemBase link in linkedFolderContents.Items) |
631 | contents.OwnerID = containingFolder.Owner; | ||
632 | contents.Version = containingFolder.Version; | ||
633 | } | ||
634 | else | ||
635 | { | 724 | { |
636 | // Was it really a request for folder Zero? | 725 | // Take care of genuinely broken links where the target doesn't exist |
637 | // This is an overkill, but Firestorm really asks for folder Zero. | 726 | // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, |
638 | // I'm leaving the code here for the time being, but commented. | 727 | // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles |
639 | if (fetchFolders[i - 1].folder_id == UUID.Zero) | 728 | // rather than having to keep track of every folder requested in the recursion. |
640 | { | 729 | if (link != null) |
641 | //coll.Collection.OwnerID = freq.owner_id; | ||
642 | //coll.Collection.FolderID = contents.FolderID; | ||
643 | //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); | ||
644 | //if (containingFolder != null) | ||
645 | //{ | ||
646 | // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); | ||
647 | // coll.Collection.Folders.Clear(); | ||
648 | // coll.Collection.Folders.Add(containingFolder); | ||
649 | // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) | ||
650 | // { | ||
651 | // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); | ||
652 | // lib.Name = m_LibraryService.LibraryRootFolder.Name; | ||
653 | // lib.Type = m_LibraryService.LibraryRootFolder.Type; | ||
654 | // lib.Version = m_LibraryService.LibraryRootFolder.Version; | ||
655 | // coll.Collection.Folders.Add(lib); | ||
656 | // } | ||
657 | // coll.Collection.Items.Clear(); | ||
658 | //} | ||
659 | } | ||
660 | else | ||
661 | { | 730 | { |
662 | m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); | 731 | //m_log.DebugFormat( |
663 | bad_folders.Add(freq.folder_id); | 732 | // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", |
664 | continue; | 733 | // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); |
734 | itemIDs.Add(link.ID); | ||
665 | } | 735 | } |
666 | } | 736 | } |
667 | } | 737 | } |
738 | } | ||
668 | 739 | ||
669 | if (freq.fetch_items && contents.Items != null) | 740 | if (itemIDs.Count > 0) |
741 | { | ||
742 | InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); | ||
743 | if (linked == null) | ||
670 | { | 744 | { |
671 | List<InventoryItemBase> itemsToReturn = contents.Items; | 745 | // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated |
672 | List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn); | 746 | m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); |
673 | 747 | linked = new InventoryItemBase[itemIDs.Count]; | |
674 | // descendents must only include the links, not the linked items we add | 748 | int i = 0; |
675 | coll.Descendents = originalItems.Count; | 749 | InventoryItemBase item = new InventoryItemBase(); |
676 | 750 | item.Owner = freq.owner_id; | |
677 | // Add target items for links in this folder before the links themselves. | 751 | foreach (UUID id in itemIDs) |
678 | foreach (InventoryItemBase item in originalItems) | ||
679 | { | 752 | { |
680 | if (item.AssetType == (int)AssetType.Link) | 753 | item.ID = id; |
681 | { | 754 | linked[i++] = m_InventoryService.GetItem(item); |
682 | InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); | ||
683 | |||
684 | // Take care of genuinely broken links where the target doesn't exist | ||
685 | // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, | ||
686 | // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||
687 | // rather than having to keep track of every folder requested in the recursion. | ||
688 | if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) | ||
689 | { | ||
690 | itemsToReturn.Insert(0, linkedItem); | ||
691 | } | ||
692 | } | ||
693 | } | 755 | } |
756 | } | ||
694 | 757 | ||
695 | // Now scan for folder links and insert the items they target and those links at the head of the return data | 758 | foreach (InventoryItemBase linkedItem in linked) |
696 | foreach (InventoryItemBase item in originalItems) | 759 | { |
760 | // Take care of genuinely broken links where the target doesn't exist | ||
761 | // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, | ||
762 | // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||
763 | // rather than having to keep track of every folder requested in the recursion. | ||
764 | if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) | ||
697 | { | 765 | { |
698 | if (item.AssetType == (int)AssetType.LinkFolder) | 766 | itemsToReturn.Insert(0, linkedItem); |
699 | { | ||
700 | InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(coll.Collection.OwnerID, item.AssetID); | ||
701 | List<InventoryItemBase> links = linkedFolderContents.Items; | ||
702 | |||
703 | itemsToReturn.InsertRange(0, links); | ||
704 | |||
705 | foreach (InventoryItemBase link in linkedFolderContents.Items) | ||
706 | { | ||
707 | // Take care of genuinely broken links where the target doesn't exist | ||
708 | // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, | ||
709 | // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles | ||
710 | // rather than having to keep track of every folder requested in the recursion. | ||
711 | if (link != null) | ||
712 | { | ||
713 | //m_log.DebugFormat( | ||
714 | // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", | ||
715 | // link.Name, (AssetType)link.AssetType, item.AssetID, contents.FolderID); | ||
716 | |||
717 | InventoryItemBase linkedItem | ||
718 | = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); | ||
719 | |||
720 | if (linkedItem != null) | ||
721 | itemsToReturn.Insert(0, linkedItem); | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | } | 767 | } |
726 | } | 768 | } |
727 | |||
728 | result.Add(coll); | ||
729 | } | 769 | } |
730 | } | 770 | } |
731 | 771 | ||
732 | return result; | ||
733 | } | 772 | } |
734 | 773 | ||
735 | |||
736 | /// <summary> | 774 | /// <summary> |
737 | /// Convert an internal inventory folder object into an LLSD object. | 775 | /// Convert an internal inventory folder object into an LLSD object. |
738 | /// </summary> | 776 | /// </summary> |