diff options
Diffstat (limited to 'OpenSim/Framework/Communications/Cache')
-rw-r--r-- | OpenSim/Framework/Communications/Cache/CachedUserInfo.cs | 140 |
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 |