aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/Cache
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Communications/Cache')
-rw-r--r--OpenSim/Framework/Communications/Cache/CachedUserInfo.cs140
1 files changed, 59 insertions, 81 deletions
diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
index 3a20b9e..8e3be81 100644
--- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
+++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
@@ -84,12 +84,6 @@ namespace OpenSim.Framework.Communications.Cache
84 public InventoryFolderImpl RootFolder { get { return m_rootFolder; } } 84 public InventoryFolderImpl RootFolder { get { return m_rootFolder; } }
85 private InventoryFolderImpl m_rootFolder; 85 private InventoryFolderImpl m_rootFolder;
86 86
87 /// <summary>
88 /// FIXME: This could be contained within a local variable - it doesn't need to be a field
89 /// </summary>
90 private IDictionary<LLUUID, IList<InventoryFolderImpl>> pendingCategorizationFolders
91 = new Dictionary<LLUUID, IList<InventoryFolderImpl>>();
92
93 public LLUUID SessionID 87 public LLUUID SessionID
94 { 88 {
95 get { return m_session_id; } 89 get { return m_session_id; }
@@ -130,55 +124,58 @@ namespace OpenSim.Framework.Communications.Cache
130 } 124 }
131 125
132 /// <summary> 126 /// <summary>
133 /// Store a folder pending arrival of its parent 127 /// Helper function for InventoryReceive() - Store a folder temporarily until we've received entire folder list
134 /// </summary> 128 /// </summary>
135 /// <param name="folder"></param> 129 /// <param name="folder"></param>
136 private void AddPendingFolder(InventoryFolderImpl folder) 130 private void AddFolderToDictionary(InventoryFolderImpl folder, IDictionary<LLUUID, IList<InventoryFolderImpl>> dictionary)
137 { 131 {
138 LLUUID parentFolderId = folder.ParentID; 132 LLUUID parentFolderId = folder.ParentID;
139 133
140 if (pendingCategorizationFolders.ContainsKey(parentFolderId)) 134 if (dictionary.ContainsKey(parentFolderId))
141 { 135 dictionary[parentFolderId].Add(folder);
142 pendingCategorizationFolders[parentFolderId].Add(folder);
143 }
144 else 136 else
145 { 137 {
146 IList<InventoryFolderImpl> folders = new List<InventoryFolderImpl>(); 138 IList<InventoryFolderImpl> folders = new List<InventoryFolderImpl>();
147 folders.Add(folder); 139 folders.Add(folder);
148 140 dictionary[parentFolderId] = folders;
149 pendingCategorizationFolders[parentFolderId] = folders;
150 } 141 }
151 } 142 }
152 143
153 144
154 /// <summary> 145 /// <summary>
155 /// Add any pending folders which were received before the given folder 146 /// Recursively, in depth-first order, add all the folders we've received (stored
147 /// in a dictionary indexed by parent ID) into the tree that describes user folder
148 /// heirarchy
156 /// </summary> 149 /// </summary>
157 /// <param name="parentId"> 150 /// <param name="parentId">
158 /// A <see cref="LLUUID"/> 151 /// A <see cref="LLUUID"/>
159 /// </param> 152 /// </param>
160 private void ResolvePendingFolders(InventoryFolderImpl newFolder) 153 private void ResolveReceivedFolders(InventoryFolderImpl parentFolder, IDictionary<LLUUID, IList<InventoryFolderImpl>> folderDictionary)
161 { 154 {
162 if (pendingCategorizationFolders.ContainsKey(newFolder.ID)) 155 if (folderDictionary.ContainsKey(parentFolder.ID))
163 { 156 {
164 List<InventoryFolderImpl> resolvedFolders = new List<InventoryFolderImpl>(); // Folders we've resolved with this invocation 157 List<InventoryFolderImpl> resolvedFolders = new List<InventoryFolderImpl>(); // Folders we've resolved with this invocation
165 foreach (InventoryFolderImpl folder in pendingCategorizationFolders[newFolder.ID]) 158 foreach (InventoryFolderImpl folder in folderDictionary[parentFolder.ID])
166 { 159 {
167 // m_log.DebugFormat( 160 lock (parentFolder.SubFolders)
168 // "[INVENTORY CACHE]: Resolving pending received folder {0} {1} into {2} {3}",
169 // folder.name, folder.folderID, parent.name, parent.folderID);
170 lock (newFolder.SubFolders)
171 { 161 {
172 if (!newFolder.SubFolders.ContainsKey(folder.ID)) 162 if (parentFolder.SubFolders.ContainsKey(folder.ID))
163 {
164 m_log.WarnFormat(
165 "[INVENTORY CACHE]: Received folder {0} {1} from inventory service which has already been received",
166 folder.Name, folder.ID);
167 }
168 else
173 { 169 {
174 resolvedFolders.Add(folder); 170 resolvedFolders.Add(folder);
175 newFolder.SubFolders.Add(folder.ID, folder); 171 parentFolder.SubFolders.Add(folder.ID, folder);
176 } 172 }
177 } 173 }
178 } 174 } // foreach (folder in pendingCategorizationFolders[parentFolder.ID])
179 pendingCategorizationFolders.Remove(newFolder.ID); 175
176 folderDictionary.Remove(parentFolder.ID);
180 foreach (InventoryFolderImpl folder in resolvedFolders) 177 foreach (InventoryFolderImpl folder in resolvedFolders)
181 ResolvePendingFolders(folder); 178 ResolveReceivedFolders(folder, folderDictionary);
182 } 179 }
183 } 180 }
184 181
@@ -204,25 +201,56 @@ namespace OpenSim.Framework.Communications.Cache
204 /// <param name="inventoryCollection"></param> 201 /// <param name="inventoryCollection"></param>
205 public void InventoryReceive(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items) 202 public void InventoryReceive(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items)
206 { 203 {
204
207 // FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these 205 // FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these
208 // are simply being swallowed 206 // are simply being swallowed
209 207
210 try 208 try
211 { 209 {
210 // collection of all received folders, indexed by their parent ID
211 IDictionary<LLUUID, IList<InventoryFolderImpl>> receivedFolders =
212 new Dictionary<LLUUID, IList<InventoryFolderImpl>>();
213
214 // Take all received folders, find the root folder, and put ther rest into
215 // the pendingCategorizationFolders collection
212 foreach (InventoryFolderImpl folder in folders) 216 foreach (InventoryFolderImpl folder in folders)
217 AddFolderToDictionary(folder, receivedFolders);
218
219 if (!receivedFolders.ContainsKey(LLUUID.Zero))
220 throw new Exception("Database did not return a root inventory folder");
221 else
213 { 222 {
214 FolderReceive(folder); 223 IList<InventoryFolderImpl> rootFolderList = receivedFolders[LLUUID.Zero];
224 m_rootFolder = rootFolderList[0];
225 if (rootFolderList.Count > 1)
226 {
227 for (int i = 1; i < rootFolderList.Count; i++)
228 {
229 m_log.WarnFormat(
230 "[INVENTORY CACHE]: Discarding extra root folder {0}. Using previously received root folder {1}",
231 rootFolderList[i].ID, RootFolder.ID);
232 }
233 }
234 receivedFolders.Remove(LLUUID.Zero);
215 } 235 }
236
237 // Now take the pendingCategorizationFolders collection, and turn that into a tree,
238 // with the root being RootFolder
239 if (RootFolder != null)
240 ResolveReceivedFolders(RootFolder, receivedFolders);
241
216 // Generate a warning for folders that are not part of the heirarchy 242 // Generate a warning for folders that are not part of the heirarchy
217 foreach ( KeyValuePair<LLUUID, IList<InventoryFolderImpl>> folderList in pendingCategorizationFolders) 243 foreach (KeyValuePair<LLUUID, IList<InventoryFolderImpl>> folderList in receivedFolders)
218 { 244 {
219 foreach (InventoryFolderImpl folder in folderList.Value) 245 foreach (InventoryFolderImpl folder in folderList.Value)
220 m_log.WarnFormat("[INVENTORY CACHE]: Malformed Database: Unresolved Pending Folder {0}", folder.Name); 246 m_log.WarnFormat("[INVENTORY CACHE]: Malformed Database: Unresolved Pending Folder {0}", folder.Name);
221 } 247 }
248
249 // Take all ther received items and put them into the folder tree heirarchy
250 // TBD: This operation is O(n^2), if we made a dictionary of all folders indexed by their ID, we could make
251 // this O(n)
222 foreach (InventoryItemBase item in items) 252 foreach (InventoryItemBase item in items)
223 {
224 ItemReceive(item); 253 ItemReceive(item);
225 }
226 } 254 }
227 catch (Exception e) 255 catch (Exception e)
228 { 256 {
@@ -244,56 +272,6 @@ namespace OpenSim.Framework.Communications.Cache
244 } 272 }
245 273
246 /// <summary> 274 /// <summary>
247 /// Callback invoked when a folder is received from an async request to the inventory service.
248 /// </summary>
249 /// <param name="userID"></param>
250 /// <param name="folderInfo"></param>
251 private void FolderReceive(InventoryFolderImpl newFolder)
252 {
253 // m_log.DebugFormat(
254 // "[INVENTORY CACHE]: Received folder {0} {1} for user {2}",
255 // folderInfo.Name, folderInfo.ID, userID);
256
257 if (RootFolder == null)
258 {
259 if (newFolder.ParentID == LLUUID.Zero)
260 {
261 m_rootFolder = newFolder;
262 }
263 else
264 {
265 AddPendingFolder(newFolder);
266 }
267 }
268 else
269 {
270 InventoryFolderImpl parentFolder = RootFolder.FindFolder(newFolder.ParentID);
271
272 if (parentFolder == null)
273 {
274 AddPendingFolder(newFolder);
275 }
276 else
277 {
278 lock (parentFolder.SubFolders)
279 {
280 if (!parentFolder.SubFolders.ContainsKey(newFolder.ID))
281 {
282 parentFolder.SubFolders.Add(newFolder.ID, newFolder);
283 }
284 else
285 {
286 m_log.WarnFormat(
287 "[INVENTORY CACHE]: Received folder {0} {1} from inventory service which has already been received",
288 newFolder.Name, newFolder.ID);
289 }
290 }
291 }
292 }
293 ResolvePendingFolders(newFolder);
294 }
295
296 /// <summary>
297 /// Callback invoked when an item is received from an async request to the inventory service. 275 /// Callback invoked when an item is received from an async request to the inventory service.
298 /// 276 ///
299 /// We're assuming here that items are always received after all the folders 277 /// We're assuming here that items are always received after all the folders