aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDiva Canto2015-05-07 19:24:08 -0700
committerDiva Canto2015-05-07 19:24:08 -0700
commitc74cef0f4261191962959e42c7e349adafd42a04 (patch)
tree95ad098d2606b7d37a6b287816d9f6a02311860d /OpenSim
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-c74cef0f4261191962959e42c7e349adafd42a04.zip
opensim-SC_OLD-c74cef0f4261191962959e42c7e349adafd42a04.tar.gz
opensim-SC_OLD-c74cef0f4261191962959e42c7e349adafd42a04.tar.bz2
opensim-SC_OLD-c74cef0f4261191962959e42c7e349adafd42a04.tar.xz
Major change in the way inventory is downloaded: added a method throughout IIventoryService that fetches sets of folders at once. Also added folder id in the InventoryCollection data structure, so that we don't need to go to inventory server again just for that. This reduces the chatter between sims and inventory server by... a lot. On my tests, this reduces initial inventory download down to 30% of what it currently is.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs449
-rw-r--r--OpenSim/Framework/InventoryCollection.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs14
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs19
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs5
-rw-r--r--OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs74
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs81
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs16
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs9
-rw-r--r--OpenSim/Services/Interfaces/IInventoryService.cs8
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs21
14 files changed, 626 insertions, 95 deletions
diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
index 451575f..a2f6740 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
@@ -57,104 +57,113 @@ namespace OpenSim.Capabilities.Handlers
57 m_LibraryService = libService; 57 m_LibraryService = libService;
58 } 58 }
59 59
60
60 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 61 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 { 62 {
62// lock (m_fetchLock)
63// {
64// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
65 63
66 // nasty temporary hack here, the linden client falsely 64 // nasty temporary hack here, the linden client falsely
67 // identifies the uuid 00000000-0000-0000-0000-000000000000 65 // identifies the uuid 00000000-0000-0000-0000-000000000000
68 // as a string which breaks us 66 // as a string which breaks us
69 // 67 //
70 // correctly mark it as a uuid 68 // correctly mark it as a uuid
71 // 69 //
72 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>"); 70 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
73 71
74 // another hack <integer>1</integer> results in a 72 // another hack <integer>1</integer> results in a
75 // System.ArgumentException: Object type System.Int32 cannot 73 // System.ArgumentException: Object type System.Int32 cannot
76 // be converted to target type: System.Boolean 74 // be converted to target type: System.Boolean
77 // 75 //
78 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>"); 76 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
79 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>"); 77 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
80 78
81 Hashtable hash = new Hashtable(); 79 Hashtable hash = new Hashtable();
80 try
81 {
82 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
83 }
84 catch (LLSD.LLSDParseException e)
85 {
86 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
87 m_log.Error("Request: " + request);
88 }
89
90 ArrayList foldersrequested = (ArrayList)hash["folders"];
91
92 string response = "";
93 string bad_folders_response = "";
94
95 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
96 for (int i = 0; i < foldersrequested.Count; i++)
97 {
98 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
99
100 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
101
82 try 102 try
83 { 103 {
84 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); 104 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
85 } 105 }
86 catch (LLSD.LLSDParseException e) 106 catch (Exception e)
87 { 107 {
88 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); 108 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
89 m_log.Error("Request: " + request); 109 continue;
90 } 110 }
91
92 ArrayList foldersrequested = (ArrayList)hash["folders"];
93
94 string response = "";
95 string bad_folders_response = "";
96 111
97 for (int i = 0; i < foldersrequested.Count; i++) 112 folders.Add(llsdRequest);
98 { 113 }
99 string inventoryitemstr = "";
100 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
101 114
102 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); 115 if (folders.Count > 0)
116 {
117 List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders);
118 //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
119 if (invcollSet == null)
120 {
121 m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
122 return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
123 }
103 124
104 try 125 string inventoryitemstr = string.Empty;
105 { 126 foreach (InventoryCollectionWithDescendents icoll in invcollSet)
106 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); 127 {
107 } 128 LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
108 catch (Exception e)
109 {
110 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
111 }
112 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
113 129
114 if (null == reply) 130 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
115 { 131 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
116 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>"; 132 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
117 }
118 else
119 {
120 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
121 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
122 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
123 }
124 133
125 response += inventoryitemstr; 134 response += inventoryitemstr;
126 } 135 }
136 }
127 137
128 if (response.Length == 0) 138 if (response.Length == 0)
139 {
140 /* Viewers expect a bad_folders array when not available */
141 if (bad_folders_response.Length != 0)
129 { 142 {
130 /* Viewers expect a bad_folders array when not available */ 143 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
131 if (bad_folders_response.Length != 0)
132 {
133 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
134 }
135 else
136 {
137 response = "<llsd><map><key>folders</key><array /></map></llsd>";
138 }
139 } 144 }
140 else 145 else
141 { 146 {
142 if (bad_folders_response.Length != 0) 147 response = "<llsd><map><key>folders</key><array /></map></llsd>";
143 {
144 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
145 }
146 else
147 {
148 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
149 }
150 } 148 }
149 }
150 else
151 {
152 if (bad_folders_response.Length != 0)
153 {
154 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
155 }
156 else
157 {
158 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
159 }
160 }
151 161
152// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); 162// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
153 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); 163// m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
154 164
155 return response; 165 return response;
156 166
157// }
158 } 167 }
159 168
160 /// <summary> 169 /// <summary>
@@ -203,18 +212,130 @@ namespace OpenSim.Capabilities.Handlers
203 contents.descendents = descendents; 212 contents.descendents = descendents;
204 contents.version = version; 213 contents.version = version;
205 214
206// m_log.DebugFormat( 215 //m_log.DebugFormat(
207// "[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}", 216 // "[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}",
208// invFetch.folder_id, 217 // invFetch.folder_id,
209// invFetch.fetch_items, 218 // invFetch.fetch_items,
210// invFetch.fetch_folders, 219 // invFetch.fetch_folders,
211// contents.items.Array.Count, 220 // contents.items.Array.Count,
212// contents.categories.Array.Count, 221 // contents.categories.Array.Count,
213// invFetch.owner_id); 222 // invFetch.owner_id);
214 223
215 return reply; 224 return reply;
216 } 225 }
217 226
227 private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
228 {
229 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
230 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
231 contents.agent_id = inv.OwnerID;
232 contents.owner_id = inv.OwnerID;
233 contents.folder_id = inv.FolderID;
234
235 reply.folders.Array.Add(contents);
236
237 if (inv.Folders != null)
238 {
239 foreach (InventoryFolderBase invFolder in inv.Folders)
240 {
241 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
242 }
243
244 descendents += inv.Folders.Count;
245 }
246
247 if (inv.Items != null)
248 {
249 foreach (InventoryItemBase invItem in inv.Items)
250 {
251 contents.items.Array.Add(ConvertInventoryItem(invItem));
252 }
253 }
254
255 contents.descendents = descendents;
256 contents.version = inv.Version;
257
258 return reply;
259 }
260 /// <summary>
261 /// Old style. Soon to be deprecated.
262 /// </summary>
263 /// <param name="request"></param>
264 /// <param name="httpRequest"></param>
265 /// <param name="httpResponse"></param>
266 /// <returns></returns>
267 [Obsolete]
268 private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
269 {
270 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
271
272 string response = "";
273 string bad_folders_response = "";
274
275 for (int i = 0; i < foldersrequested.Count; i++)
276 {
277 string inventoryitemstr = "";
278 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
279
280 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
281
282 try
283 {
284 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
285 }
286 catch (Exception e)
287 {
288 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
289 }
290
291 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
292
293 if (null == reply)
294 {
295 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
296 }
297 else
298 {
299 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
300 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
301 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
302 }
303
304 response += inventoryitemstr;
305 }
306
307 if (response.Length == 0)
308 {
309 /* Viewers expect a bad_folders array when not available */
310 if (bad_folders_response.Length != 0)
311 {
312 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
313 }
314 else
315 {
316 response = "<llsd><map><key>folders</key><array /></map></llsd>";
317 }
318 }
319 else
320 {
321 if (bad_folders_response.Length != 0)
322 {
323 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
324 }
325 else
326 {
327 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
328 }
329 }
330
331 // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
332 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
333
334 return response;
335
336 // }
337 }
338
218 /// <summary> 339 /// <summary>
219 /// Handle the caps inventory descendents fetch. 340 /// Handle the caps inventory descendents fetch.
220 /// </summary> 341 /// </summary>
@@ -226,6 +347,7 @@ namespace OpenSim.Capabilities.Handlers
226 /// <param name="sortOrder"></param> 347 /// <param name="sortOrder"></param>
227 /// <param name="version"></param> 348 /// <param name="version"></param>
228 /// <returns>An empty InventoryCollection if the inventory look up failed</returns> 349 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
350 [Obsolete]
229 private InventoryCollection Fetch( 351 private InventoryCollection Fetch(
230 UUID agentID, UUID folderID, UUID ownerID, 352 UUID agentID, UUID folderID, UUID ownerID,
231 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) 353 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
@@ -264,7 +386,6 @@ namespace OpenSim.Capabilities.Handlers
264 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); 386 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
265 return contents; 387 return contents;
266 } 388 }
267
268 contents = fetchedContents; 389 contents = fetchedContents;
269 InventoryFolderBase containingFolder = new InventoryFolderBase(); 390 InventoryFolderBase containingFolder = new InventoryFolderBase();
270 containingFolder.ID = folderID; 391 containingFolder.ID = folderID;
@@ -273,9 +394,9 @@ namespace OpenSim.Capabilities.Handlers
273 394
274 if (containingFolder != null) 395 if (containingFolder != null)
275 { 396 {
276// m_log.DebugFormat( 397 //m_log.DebugFormat(
277// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", 398 // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
278// containingFolder.Name, containingFolder.ID, agentID); 399 // containingFolder.Name, containingFolder.ID, agentID);
279 400
280 version = containingFolder.Version; 401 version = containingFolder.Version;
281 402
@@ -410,6 +531,160 @@ namespace OpenSim.Capabilities.Handlers
410 return contents; 531 return contents;
411 532
412 } 533 }
534
535 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
536 {
537 InventoryFolderImpl fold;
538 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
539 {
540 List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
541 fetchFolders.RemoveAll(f => libfolders.Contains(f));
542
543 foreach (LLSDFetchInventoryDescendents f in libfolders)
544 {
545 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
546 {
547 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
548 ret.Collection = new InventoryCollection();
549 ret.Collection.Folders = new List<InventoryFolderBase>();
550 ret.Collection.Items = fold.RequestListOfItems();
551 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
552 ret.Collection.FolderID = f.folder_id;
553 ret.Collection.Version = fold.Version;
554
555 ret.Descendents = ret.Collection.Items.Count;
556
557 result.Add(ret);
558 }
559 }
560 }
561 }
562
563 private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders)
564 {
565 //m_log.DebugFormat(
566 // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
567
568 // FIXME MAYBE: We're not handling sortOrder!
569
570 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
571
572 AddLibraryFolders(fetchFolders, result);
573
574 if (fetchFolders.Count > 0)
575 {
576 UUID[] fids = new UUID[fetchFolders.Count];
577 int i = 0;
578 foreach (LLSDFetchInventoryDescendents f in fetchFolders)
579 fids[i++] = f.folder_id;
580
581 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
582
583 if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
584 {
585 //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
586 return null;
587 }
588
589 i = 0;
590 // Do some post-processing. May need to fetch more from inv server for links
591 foreach (InventoryCollection contents in fetchedContents)
592 {
593 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
594 coll.Collection = contents;
595
596 // Find the original request
597 LLSDFetchInventoryDescendents freq = fetchFolders[i++];
598
599 // The inventory server isn't sending FolderID in the collection...
600 // Must fetch it individually
601 if (contents.FolderID == UUID.Zero)
602 {
603 InventoryFolderBase containingFolder = new InventoryFolderBase();
604 containingFolder.ID = freq.folder_id;
605 containingFolder.Owner = freq.owner_id;
606 containingFolder = m_InventoryService.GetFolder(containingFolder);
607
608 if (containingFolder != null)
609 {
610 contents.FolderID = containingFolder.ID;
611 contents.OwnerID = containingFolder.Owner;
612 contents.Version = containingFolder.Version;
613 }
614 else
615 {
616 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
617 continue;
618 }
619 }
620
621 if (freq.fetch_items && contents.Items != null)
622 {
623 List<InventoryItemBase> itemsToReturn = contents.Items;
624 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
625
626 // descendents must only include the links, not the linked items we add
627 coll.Descendents = originalItems.Count;
628
629 // Add target items for links in this folder before the links themselves.
630 foreach (InventoryItemBase item in originalItems)
631 {
632 if (item.AssetType == (int)AssetType.Link)
633 {
634 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
635
636 // Take care of genuinely broken links where the target doesn't exist
637 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
638 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
639 // rather than having to keep track of every folder requested in the recursion.
640 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
641 {
642 itemsToReturn.Insert(0, linkedItem);
643 }
644 }
645 }
646
647 // Now scan for folder links and insert the items they target and those links at the head of the return data
648 foreach (InventoryItemBase item in originalItems)
649 {
650 if (item.AssetType == (int)AssetType.LinkFolder)
651 {
652 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(coll.Collection.OwnerID, item.AssetID);
653 List<InventoryItemBase> links = linkedFolderContents.Items;
654
655 itemsToReturn.InsertRange(0, links);
656
657 foreach (InventoryItemBase link in linkedFolderContents.Items)
658 {
659 // Take care of genuinely broken links where the target doesn't exist
660 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
661 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
662 // rather than having to keep track of every folder requested in the recursion.
663 if (link != null)
664 {
665 //m_log.DebugFormat(
666 // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
667 // link.Name, (AssetType)link.AssetType, item.AssetID, contents.FolderID);
668
669 InventoryItemBase linkedItem
670 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
671
672 if (linkedItem != null)
673 itemsToReturn.Insert(0, linkedItem);
674 }
675 }
676 }
677 }
678 }
679
680 result.Add(coll);
681 }
682 }
683
684 return result;
685 }
686
687
413 /// <summary> 688 /// <summary>
414 /// Convert an internal inventory folder object into an LLSD object. 689 /// Convert an internal inventory folder object into an LLSD object.
415 /// </summary> 690 /// </summary>
@@ -462,4 +737,10 @@ namespace OpenSim.Capabilities.Handlers
462 return llsdItem; 737 return llsdItem;
463 } 738 }
464 } 739 }
740
741 struct InventoryCollectionWithDescendents
742 {
743 public InventoryCollection Collection;
744 public int Descendents;
745 }
465} \ No newline at end of file 746} \ No newline at end of file
diff --git a/OpenSim/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs
index 7049902..59655eb 100644
--- a/OpenSim/Framework/InventoryCollection.cs
+++ b/OpenSim/Framework/InventoryCollection.cs
@@ -37,6 +37,8 @@ namespace OpenSim.Framework
37 { 37 {
38 public List<InventoryFolderBase> Folders; 38 public List<InventoryFolderBase> Folders;
39 public List<InventoryItemBase> Items; 39 public List<InventoryItemBase> Items;
40 public UUID UserID; 40 public UUID OwnerID;
41 public UUID FolderID;
42 public int Version;
41 } 43 }
42} 44}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index e402b0b..30d1921 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
201 201
202 Scene.EventManager.OnRegisterCaps += RegisterCaps; 202 Scene.EventManager.OnRegisterCaps += RegisterCaps;
203 203
204 int nworkers = 1; // was 2 204 int nworkers = 2; // was 2
205 if (ProcessQueuedRequestsAsync && m_workerThreads == null) 205 if (ProcessQueuedRequestsAsync && m_workerThreads == null)
206 { 206 {
207 m_workerThreads = new Thread[nworkers]; 207 m_workerThreads = new Thread[nworkers];
@@ -365,7 +365,11 @@ namespace OpenSim.Region.ClientStack.Linden
365 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 365 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
366 366
367 lock (responses) 367 lock (responses)
368 {
369 if (responses.ContainsKey(requestID))
370 m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054");
368 responses[requestID] = response; 371 responses[requestID] = response;
372 }
369 373
370 WebFetchInvDescModule.ProcessedRequestsCount++; 374 WebFetchInvDescModule.ProcessedRequestsCount++;
371 } 375 }
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
index 01814a1..eb7d3a9 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
65 { 65 {
66 InventoryFolderImpl folder = null; 66 InventoryFolderImpl folder = null;
67 InventoryCollection inv = new InventoryCollection(); 67 InventoryCollection inv = new InventoryCollection();
68 inv.UserID = m_Library.Owner; 68 inv.OwnerID = m_Library.Owner;
69 69
70 if (folderID != m_Library.ID) 70 if (folderID != m_Library.ID)
71 { 71 {
@@ -87,6 +87,18 @@ namespace OpenSim.Region.CoreModules.Framework.Library
87 return inv; 87 return inv;
88 } 88 }
89 89
90 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
91 {
92 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
93 int i = 0;
94 foreach (UUID fid in folderIDs)
95 {
96 invColl[i++] = GetFolderContent(principalID, fid);
97 }
98
99 return invColl;
100 }
101
90 /// <summary> 102 /// <summary>
91 /// Add a new folder to the user's inventory 103 /// Add a new folder to the user's inventory
92 /// </summary> 104 /// </summary>
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index e13ee42..232cfdf 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
389 return connector.GetFolderContent(userID, folderID); 389 return connector.GetFolderContent(userID, folderID);
390 } 390 }
391 391
392 public InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs)
393 {
394 string invURL = GetInventoryServiceURL(userID);
395
396 if (invURL == null) // not there, forward to local inventory connector to resolve
397 lock (m_Lock)
398 return m_LocalGridInventoryService.GetMultipleFoldersContent(userID, folderIDs);
399
400 else
401 {
402 InventoryCollection[] coll = new InventoryCollection[folderIDs.Length];
403 int i = 0;
404 foreach (UUID fid in folderIDs)
405 coll[i++] = GetFolderContent(userID, fid);
406
407 return coll;
408 }
409 }
410
392 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 411 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
393 { 412 {
394 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); 413 //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 499ca5e..71dc337 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
106 if (m_Inventories.TryGetValue(userID, out inv)) 106 if (m_Inventories.TryGetValue(userID, out inv))
107 { 107 {
108 c = new InventoryCollection(); 108 c = new InventoryCollection();
109 c.UserID = userID; 109 c.OwnerID = userID;
110 110
111 c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) 111 c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f)
112 { 112 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index cbe0e37..75dd200 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
195 return invCol; 195 return invCol;
196 } 196 }
197 197
198 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
199 {
200 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
201 int i = 0;
202 foreach (UUID fid in folderIDs)
203 {
204 invColl[i++] = GetFolderContent(principalID, fid);
205 }
206
207 return invColl;
208
209 }
210
198 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 211 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
199 { 212 {
200 return m_InventoryService.GetFolderItems(userID, folderID); 213 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 166e4a1..9beb382 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
204 return invCol; 204 return invCol;
205 } 205 }
206 206
207 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
208 {
209 return m_RemoteConnector.GetMultipleFoldersContent(principalID, folderIDs);
210 }
211
207 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 212 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
208 { 213 {
209 return m_RemoteConnector.GetFolderItems(userID, folderID); 214 return m_RemoteConnector.GetFolderItems(userID, folderID);
diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
index 0288fa6..4f01e36 100644
--- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
+++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
@@ -41,7 +41,9 @@ using OpenSim.Server.Handlers.Base;
41using log4net; 41using log4net;
42using OpenMetaverse; 42using OpenMetaverse;
43 43
44namespace OpenSim.Server.Handlers.Asset 44using System.Threading;
45
46namespace OpenSim.Server.Handlers.Inventory
45{ 47{
46 public class XInventoryInConnector : ServiceConnector 48 public class XInventoryInConnector : ServiceConnector
47 { 49 {
@@ -123,6 +125,8 @@ namespace OpenSim.Server.Handlers.Asset
123 return HandleGetFolderForType(request); 125 return HandleGetFolderForType(request);
124 case "GETFOLDERCONTENT": 126 case "GETFOLDERCONTENT":
125 return HandleGetFolderContent(request); 127 return HandleGetFolderContent(request);
128 case "GETMULTIPLEFOLDERSCONTENT":
129 return HandleGetMultipleFoldersContent(request);
126 case "GETFOLDERITEMS": 130 case "GETFOLDERITEMS":
127 return HandleGetFolderItems(request); 131 return HandleGetFolderItems(request);
128 case "ADDFOLDER": 132 case "ADDFOLDER":
@@ -284,6 +288,8 @@ namespace OpenSim.Server.Handlers.Asset
284 InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID); 288 InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID);
285 if (icoll != null) 289 if (icoll != null)
286 { 290 {
291 result["FID"] = icoll.FolderID.ToString();
292 result["VERSION"] = icoll.Version.ToString();
287 Dictionary<string, object> folders = new Dictionary<string, object>(); 293 Dictionary<string, object> folders = new Dictionary<string, object>();
288 int i = 0; 294 int i = 0;
289 if (icoll.Folders != null) 295 if (icoll.Folders != null)
@@ -314,7 +320,71 @@ namespace OpenSim.Server.Handlers.Asset
314 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 320 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
315 } 321 }
316 322
317 byte[] HandleGetFolderItems(Dictionary<string,object> request) 323 byte[] HandleGetMultipleFoldersContent(Dictionary<string, object> request)
324 {
325 Dictionary<string, object> resultSet = new Dictionary<string, object>();
326 UUID principal = UUID.Zero;
327 UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
328 string folderIDstr = request["FOLDERS"].ToString();
329 int count = 0;
330 Int32.TryParse(request["COUNT"].ToString(), out count);
331
332 UUID[] fids = new UUID[count];
333 string[] uuids = folderIDstr.Split(',');
334 int i = 0;
335 foreach (string id in uuids)
336 {
337 UUID fid = UUID.Zero;
338 if (UUID.TryParse(id, out fid))
339 fids[i] = fid;
340 i += 1;
341 }
342
343 count = 0;
344 InventoryCollection[] icollList = m_InventoryService.GetMultipleFoldersContent(principal, fids);
345 if (icollList != null && icollList.Length > 0)
346 {
347 foreach (InventoryCollection icoll in icollList)
348 {
349 Dictionary<string, object> result = new Dictionary<string, object>();
350 result["FID"] = icoll.FolderID.ToString();
351 result["VERSION"] = icoll.Version.ToString();
352 result["OWNER"] = icoll.OwnerID.ToString();
353 Dictionary<string, object> folders = new Dictionary<string, object>();
354 i = 0;
355 if (icoll.Folders != null)
356 {
357 foreach (InventoryFolderBase f in icoll.Folders)
358 {
359 folders["folder_" + i.ToString()] = EncodeFolder(f);
360 i++;
361 }
362 result["FOLDERS"] = folders;
363 }
364 i = 0;
365 if (icoll.Items != null)
366 {
367 Dictionary<string, object> items = new Dictionary<string, object>();
368 foreach (InventoryItemBase it in icoll.Items)
369 {
370 items["item_" + i.ToString()] = EncodeItem(it);
371 i++;
372 }
373 result["ITEMS"] = items;
374 }
375
376 resultSet["F_" + fids[count++]] = result;
377 //m_log.DebugFormat("[XXX]: Sending {0} {1}", fids[count-1], icoll.FolderID);
378 }
379 }
380
381 string xmlString = ServerUtils.BuildXmlResponse(resultSet);
382
383 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
384 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
385 }
386
387 byte[] HandleGetFolderItems(Dictionary<string, object> request)
318 { 388 {
319 Dictionary<string,object> result = new Dictionary<string,object>(); 389 Dictionary<string,object> result = new Dictionary<string,object>();
320 UUID principal = UUID.Zero; 390 UUID principal = UUID.Zero;
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index 574de89..c694d27 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -205,7 +205,7 @@ namespace OpenSim.Services.Connectors
205 InventoryCollection inventory = new InventoryCollection(); 205 InventoryCollection inventory = new InventoryCollection();
206 inventory.Folders = new List<InventoryFolderBase>(); 206 inventory.Folders = new List<InventoryFolderBase>();
207 inventory.Items = new List<InventoryItemBase>(); 207 inventory.Items = new List<InventoryItemBase>();
208 inventory.UserID = principalID; 208 inventory.OwnerID = principalID;
209 209
210 try 210 try
211 { 211 {
@@ -235,7 +235,86 @@ namespace OpenSim.Services.Connectors
235 235
236 return inventory; 236 return inventory;
237 } 237 }
238
239 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
240 {
241 InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
242 //m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", folderIDs.Length);
243 try
244 {
245 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
246 new Dictionary<string, object> {
247 { "PRINCIPAL", principalID.ToString() },
248 { "FOLDERS", String.Join(",", folderIDs) },
249 { "COUNT", folderIDs.Length.ToString() }
250 });
251
252 if (!CheckReturn(resultSet))
253 return null;
238 254
255 int i = 0;
256 foreach (KeyValuePair<string, object> kvp in resultSet)
257 {
258 InventoryCollection inventory = new InventoryCollection();
259 if (kvp.Key.StartsWith("F_"))
260 {
261 UUID fid = UUID.Zero;
262 if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
263 {
264 inventory.Folders = new List<InventoryFolderBase>();
265 inventory.Items = new List<InventoryItemBase>();
266
267 Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
268
269 if (ret.ContainsKey("FID"))
270 {
271 if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
272 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
273 }
274 else
275 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
276
277 inventory.Version = -1;
278 if (ret.ContainsKey("VERSION"))
279 Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
280 if (ret.ContainsKey("OWNER"))
281 UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
282
283 //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
284
285 Dictionary<string, object> folders =
286 (Dictionary<string, object>)ret["FOLDERS"];
287 Dictionary<string, object> items =
288 (Dictionary<string, object>)ret["ITEMS"];
289
290 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
291 {
292 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
293 }
294 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
295 {
296 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
297 }
298
299 inventoryArr[i] = inventory;
300 }
301 else
302 {
303 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
304 folderIDs[i], fid);
305 }
306
307 i += 1;
308 }
309 }
310 }
311 catch (Exception e)
312 {
313 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
314 }
315
316 return inventoryArr;
317 }
239 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 318 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
240 { 319 {
241 Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS", 320 Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
index 9ded1c4..0331c66 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -340,7 +340,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
340 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 340 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
341 { 341 {
342 InventoryCollection inventory = new InventoryCollection(); 342 InventoryCollection inventory = new InventoryCollection();
343 inventory.UserID = userID; 343 inventory.OwnerID = userID;
344 344
345 NameValueCollection requestArgs = new NameValueCollection 345 NameValueCollection requestArgs = new NameValueCollection
346 { 346 {
@@ -371,6 +371,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
371 return inventory; 371 return inventory;
372 } 372 }
373 373
374 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
375 {
376 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
377 int i = 0;
378 foreach (UUID fid in folderIDs)
379 {
380 invColl[i++] = GetFolderContent(principalID, fid);
381 }
382
383 return invColl;
384 }
385
374 /// <summary> 386 /// <summary>
375 /// Gets the items inside a folder 387 /// Gets the items inside a folder
376 /// </summary> 388 /// </summary>
@@ -380,7 +392,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
380 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 392 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
381 { 393 {
382 InventoryCollection inventory = new InventoryCollection(); 394 InventoryCollection inventory = new InventoryCollection();
383 inventory.UserID = userID; 395 inventory.OwnerID = userID;
384 396
385 NameValueCollection requestArgs = new NameValueCollection 397 NameValueCollection requestArgs = new NameValueCollection
386 { 398 {
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
index 2c63240..5f245e4 100644
--- a/OpenSim/Services/HypergridService/HGInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -153,7 +153,14 @@ namespace OpenSim.Services.HypergridService
153 //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) 153 //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
154 //{ 154 //{
155 //} 155 //}
156 156
157 // NOGO
158 //
159 public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID)
160 {
161 return new InventoryCollection[0];
162 }
163
157 //public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 164 //public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
158 //{ 165 //{
159 //} 166 //}
diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs
index 2805356..829f169 100644
--- a/OpenSim/Services/Interfaces/IInventoryService.cs
+++ b/OpenSim/Services/Interfaces/IInventoryService.cs
@@ -76,6 +76,14 @@ namespace OpenSim.Services.Interfaces
76 /// <param name="folderID"></param> 76 /// <param name="folderID"></param>
77 /// <returns>Inventory content. null if the request failed.</returns> 77 /// <returns>Inventory content. null if the request failed.</returns>
78 InventoryCollection GetFolderContent(UUID userID, UUID folderID); 78 InventoryCollection GetFolderContent(UUID userID, UUID folderID);
79
80 /// <summary>
81 /// Gets everything (folders and items) inside a folder
82 /// </summary>
83 /// <param name="userId"></param>
84 /// <param name="folderIDs"></param>
85 /// <returns>Inventory content. null if the request failed.</returns>
86 InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs);
79 87
80 /// <summary> 88 /// <summary>
81 /// Gets the items inside a folder 89 /// Gets the items inside a folder
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 362ff8f..6582b75 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -291,7 +291,7 @@ namespace OpenSim.Services.InventoryService
291 // 291 //
292 //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); 292 //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
293 InventoryCollection inventory = new InventoryCollection(); 293 InventoryCollection inventory = new InventoryCollection();
294 inventory.UserID = principalID; 294 inventory.OwnerID = principalID;
295 inventory.Folders = new List<InventoryFolderBase>(); 295 inventory.Folders = new List<InventoryFolderBase>();
296 inventory.Items = new List<InventoryItemBase>(); 296 inventory.Items = new List<InventoryItemBase>();
297 297
@@ -315,8 +315,27 @@ namespace OpenSim.Services.InventoryService
315 inventory.Items.Add(ConvertToOpenSim(i)); 315 inventory.Items.Add(ConvertToOpenSim(i));
316 } 316 }
317 317
318 InventoryFolderBase f = new InventoryFolderBase(folderID, principalID);
319 f = GetFolder(f);
320 if (f != null)
321 {
322 inventory.Version = f.Version;
323 inventory.OwnerID = f.Owner;
324 }
325 inventory.FolderID = folderID;
326
318 return inventory; 327 return inventory;
319 } 328 }
329
330 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
331 {
332 InventoryCollection[] multiple = new InventoryCollection[folderIDs.Length];
333 int i = 0;
334 foreach (UUID fid in folderIDs)
335 multiple[i++] = GetFolderContent(principalID, fid);
336
337 return multiple;
338 }
320 339
321 public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 340 public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
322 { 341 {