diff options
author | Diva Canto | 2015-05-08 20:53:28 -0700 |
---|---|---|
committer | Diva Canto | 2015-05-08 20:53:28 -0700 |
commit | 0bf1209f908bb9a384ddb3a4255a75bf2317c478 (patch) | |
tree | 3ebc80806ecfe884352f6628132421d2edcdab04 /OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs | |
parent | Restore handling of bad folders. I'm not entirely sure this is part of the pr... (diff) | |
download | opensim-SC-0bf1209f908bb9a384ddb3a4255a75bf2317c478.zip opensim-SC-0bf1209f908bb9a384ddb3a4255a75bf2317c478.tar.gz opensim-SC-0bf1209f908bb9a384ddb3a4255a75bf2317c478.tar.bz2 opensim-SC-0bf1209f908bb9a384ddb3a4255a75bf2317c478.tar.xz |
Another major overhaul of inventory downloading, this time pertaining to inventory links. Added yet another function to IInventoryService to get multiple items at once, so that fetching collections of linked items is done once per folder instead of once per item.
Diffstat (limited to 'OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs')
-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> |