aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
diff options
context:
space:
mode:
authorDiva Canto2015-05-08 20:53:28 -0700
committerDiva Canto2015-05-08 20:53:28 -0700
commit0bf1209f908bb9a384ddb3a4255a75bf2317c478 (patch)
tree3ebc80806ecfe884352f6628132421d2edcdab04 /OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
parentRestore handling of bad folders. I'm not entirely sure this is part of the pr... (diff)
downloadopensim-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.cs242
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>