diff options
author | Mike Mazur | 2009-02-16 02:26:27 +0000 |
---|---|---|
committer | Mike Mazur | 2009-02-16 02:26:27 +0000 |
commit | 74a2bd237aed26b49d88045fe6afa526ed19c00d (patch) | |
tree | c72262c4343a6b95b8aa20616094e1b0fbc640a4 /OpenSim/Grid/AssetInventoryServer/Plugins/Simple | |
parent | - added Simple AssetInventoryServer plugin (asset storage only) (diff) | |
download | opensim-SC_OLD-74a2bd237aed26b49d88045fe6afa526ed19c00d.zip opensim-SC_OLD-74a2bd237aed26b49d88045fe6afa526ed19c00d.tar.gz opensim-SC_OLD-74a2bd237aed26b49d88045fe6afa526ed19c00d.tar.bz2 opensim-SC_OLD-74a2bd237aed26b49d88045fe6afa526ed19c00d.tar.xz |
Add OpenSim & Simple inventory storage plugins and Null metrics plugin.
Diffstat (limited to 'OpenSim/Grid/AssetInventoryServer/Plugins/Simple')
2 files changed, 630 insertions, 0 deletions
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml index 53534c4..f898145 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml | |||
@@ -10,4 +10,7 @@ | |||
10 | <Extension path="/OpenSim/AssetInventoryServer/StorageProvider"> | 10 | <Extension path="/OpenSim/AssetInventoryServer/StorageProvider"> |
11 | <Plugin id="SimpleAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.SimpleAssetStoragePlugin" /> | 11 | <Plugin id="SimpleAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.SimpleAssetStoragePlugin" /> |
12 | </Extension> | 12 | </Extension> |
13 | <Extension path="/OpenSim/AssetInventoryServer/InventoryProvider"> | ||
14 | <Plugin id="SimpleInventoryStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.SimpleInventoryStoragePlugin" /> | ||
15 | </Extension> | ||
13 | </Addin> | 16 | </Addin> |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs new file mode 100644 index 0000000..78dae35 --- /dev/null +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs | |||
@@ -0,0 +1,627 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Intel Corporation | ||
3 | * All rights reserved. | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * | ||
8 | * -- Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * -- Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * -- Neither the name of the Intel Corporation nor the names of its | ||
14 | * contributors may be used to endorse or promote products derived from | ||
15 | * this software without specific prior written permission. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS | ||
21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.IO; | ||
34 | using System.Text; | ||
35 | using ExtensionLoader; | ||
36 | using OpenMetaverse; | ||
37 | using OpenMetaverse.StructuredData; | ||
38 | using OpenSim.Framework; | ||
39 | |||
40 | namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple | ||
41 | { | ||
42 | public class SimpleInventoryStoragePlugin : IInventoryStorageProvider | ||
43 | { | ||
44 | const string EXTENSION_NAME = "SimpleInventoryStorage"; // Used for metrics reporting | ||
45 | const string DEFAULT_INVENTORY_DIR = "SimpleInventory"; | ||
46 | |||
47 | AssetInventoryServer server; | ||
48 | Dictionary<Uri, InventoryCollection> inventories = new Dictionary<Uri, InventoryCollection>(); | ||
49 | Dictionary<Uri, List<InventoryItem>> activeGestures = new Dictionary<Uri, List<InventoryItem>>(); | ||
50 | Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer(); | ||
51 | Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer(); | ||
52 | |||
53 | public SimpleInventoryStoragePlugin() | ||
54 | { | ||
55 | } | ||
56 | |||
57 | #region Required Interfaces | ||
58 | |||
59 | public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item) | ||
60 | { | ||
61 | item = null; | ||
62 | BackendResponse ret; | ||
63 | |||
64 | InventoryCollection collection; | ||
65 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | ||
66 | ret = BackendResponse.Success; | ||
67 | else | ||
68 | ret = BackendResponse.NotFound; | ||
69 | |||
70 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder) | ||
75 | { | ||
76 | folder = null; | ||
77 | BackendResponse ret; | ||
78 | |||
79 | InventoryCollection collection; | ||
80 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
81 | ret = BackendResponse.Success; | ||
82 | else | ||
83 | ret = BackendResponse.NotFound; | ||
84 | |||
85 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents) | ||
90 | { | ||
91 | contents = null; | ||
92 | BackendResponse ret; | ||
93 | |||
94 | InventoryCollection collection; | ||
95 | InventoryFolder folder; | ||
96 | |||
97 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
98 | { | ||
99 | contents = new InventoryCollection(); | ||
100 | contents.UserID = collection.UserID; | ||
101 | contents.Folders = new Dictionary<UUID, InventoryFolder>(); | ||
102 | contents.Items = new Dictionary<UUID, InventoryItem>(); | ||
103 | |||
104 | foreach (InventoryBase invBase in folder.Children.Values) | ||
105 | { | ||
106 | if (invBase is InventoryItem) | ||
107 | { | ||
108 | InventoryItem invItem = invBase as InventoryItem; | ||
109 | contents.Items.Add(invItem.ID, invItem); | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | InventoryFolder invFolder = invBase as InventoryFolder; | ||
114 | contents.Folders.Add(invFolder.ID, invFolder); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | ret = BackendResponse.Success; | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | ret = BackendResponse.NotFound; | ||
123 | } | ||
124 | |||
125 | server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders) | ||
130 | { | ||
131 | folders = null; | ||
132 | BackendResponse ret; | ||
133 | |||
134 | InventoryCollection collection; | ||
135 | if (inventories.TryGetValue(owner, out collection)) | ||
136 | { | ||
137 | folders = new List<InventoryFolder>(collection.Folders.Values); | ||
138 | return BackendResponse.Success; | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | ret = BackendResponse.NotFound; | ||
143 | } | ||
144 | |||
145 | server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory) | ||
150 | { | ||
151 | inventory = null; | ||
152 | BackendResponse ret; | ||
153 | |||
154 | if (inventories.TryGetValue(owner, out inventory)) | ||
155 | ret = BackendResponse.Success; | ||
156 | else | ||
157 | ret = BackendResponse.NotFound; | ||
158 | |||
159 | server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures) | ||
164 | { | ||
165 | gestures = null; | ||
166 | BackendResponse ret; | ||
167 | |||
168 | if (activeGestures.TryGetValue(owner, out gestures)) | ||
169 | ret = BackendResponse.Success; | ||
170 | else | ||
171 | ret = BackendResponse.NotFound; | ||
172 | |||
173 | server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | public BackendResponse TryCreateItem(Uri owner, InventoryItem item) | ||
178 | { | ||
179 | BackendResponse ret; | ||
180 | |||
181 | InventoryCollection collection; | ||
182 | if (inventories.TryGetValue(owner, out collection)) | ||
183 | { | ||
184 | // Delete this item first if it already exists | ||
185 | InventoryItem oldItem; | ||
186 | if (collection.Items.TryGetValue(item.ID, out oldItem)) | ||
187 | TryDeleteItem(owner, item.ID); | ||
188 | |||
189 | try | ||
190 | { | ||
191 | // Create the file | ||
192 | SaveItem(item); | ||
193 | |||
194 | // Add the item to the collection | ||
195 | lock (collection) collection.Items[item.ID] = item; | ||
196 | |||
197 | // Add the item to its parent folder | ||
198 | InventoryFolder parent; | ||
199 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | ||
200 | lock (parent.Children) parent.Children.Add(item.ID, item); | ||
201 | |||
202 | // Add active gestures to our list | ||
203 | if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1) | ||
204 | { | ||
205 | lock (activeGestures) | ||
206 | activeGestures[owner].Add(item); | ||
207 | } | ||
208 | |||
209 | ret = BackendResponse.Success; | ||
210 | } | ||
211 | catch (Exception ex) | ||
212 | { | ||
213 | Logger.Log.Error(ex.Message); | ||
214 | ret = BackendResponse.Failure; | ||
215 | } | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | return BackendResponse.NotFound; | ||
220 | } | ||
221 | |||
222 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder) | ||
227 | { | ||
228 | BackendResponse ret; | ||
229 | |||
230 | InventoryCollection collection; | ||
231 | if (inventories.TryGetValue(owner, out collection)) | ||
232 | { | ||
233 | // Delete this folder first if it already exists | ||
234 | InventoryFolder oldFolder; | ||
235 | if (collection.Folders.TryGetValue(folder.ID, out oldFolder)) | ||
236 | TryDeleteFolder(owner, folder.ID); | ||
237 | |||
238 | try | ||
239 | { | ||
240 | // Create the file | ||
241 | SaveFolder(folder); | ||
242 | |||
243 | // Add the folder to the collection | ||
244 | lock (collection) collection.Folders[folder.ID] = folder; | ||
245 | |||
246 | // Add the folder to its parent folder | ||
247 | InventoryFolder parent; | ||
248 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | ||
249 | lock (parent.Children) parent.Children.Add(folder.ID, folder); | ||
250 | |||
251 | ret = BackendResponse.Success; | ||
252 | } | ||
253 | catch (Exception ex) | ||
254 | { | ||
255 | Logger.Log.Error(ex.Message); | ||
256 | ret = BackendResponse.Failure; | ||
257 | } | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | ret = BackendResponse.NotFound; | ||
262 | } | ||
263 | |||
264 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now); | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder) | ||
269 | { | ||
270 | BackendResponse ret; | ||
271 | |||
272 | lock (inventories) | ||
273 | { | ||
274 | if (!inventories.ContainsKey(owner)) | ||
275 | { | ||
276 | InventoryCollection collection = new InventoryCollection(); | ||
277 | collection.UserID = rootFolder.Owner; | ||
278 | collection.Folders = new Dictionary<UUID, InventoryFolder>(); | ||
279 | collection.Folders.Add(rootFolder.ID, rootFolder); | ||
280 | collection.Items = new Dictionary<UUID, InventoryItem>(); | ||
281 | |||
282 | inventories.Add(owner, collection); | ||
283 | |||
284 | ret = BackendResponse.Success; | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | ret = BackendResponse.Failure; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | if (ret == BackendResponse.Success) | ||
293 | { | ||
294 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString()); | ||
295 | try | ||
296 | { | ||
297 | // Create the directory for this agent | ||
298 | Directory.CreateDirectory(path); | ||
299 | |||
300 | // Create an index.txt containing the UUID and URI for this agent | ||
301 | string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() }; | ||
302 | File.WriteAllLines(Path.Combine(path, "index.txt"), index); | ||
303 | |||
304 | // Create the root folder file | ||
305 | SaveFolder(rootFolder); | ||
306 | } | ||
307 | catch (Exception ex) | ||
308 | { | ||
309 | Logger.Log.Error(ex.Message); | ||
310 | ret = BackendResponse.Failure; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | public BackendResponse TryDeleteItem(Uri owner, UUID itemID) | ||
319 | { | ||
320 | BackendResponse ret; | ||
321 | |||
322 | InventoryCollection collection; | ||
323 | InventoryItem item; | ||
324 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | ||
325 | { | ||
326 | // Remove the item from its parent folder | ||
327 | InventoryFolder parent; | ||
328 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | ||
329 | lock (parent.Children) parent.Children.Remove(itemID); | ||
330 | |||
331 | // Remove the item from the collection | ||
332 | lock (collection) collection.Items.Remove(itemID); | ||
333 | |||
334 | // Remove from the active gestures list if applicable | ||
335 | if (item.InvType == (int)InventoryType.Gesture) | ||
336 | { | ||
337 | lock (activeGestures) | ||
338 | { | ||
339 | for (int i = 0; i < activeGestures[owner].Count; i++) | ||
340 | { | ||
341 | if (activeGestures[owner][i].ID == itemID) | ||
342 | { | ||
343 | activeGestures[owner].RemoveAt(i); | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | |||
350 | // Delete the file. We don't know exactly what the file name is, | ||
351 | // so search for it | ||
352 | string path = PathFromURI(owner); | ||
353 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly); | ||
354 | foreach (string match in matches) | ||
355 | { | ||
356 | try { File.Delete(match); } | ||
357 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); } | ||
358 | } | ||
359 | |||
360 | ret = BackendResponse.Success; | ||
361 | } | ||
362 | else | ||
363 | { | ||
364 | ret = BackendResponse.NotFound; | ||
365 | } | ||
366 | |||
367 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | public BackendResponse TryDeleteFolder(Uri owner, UUID folderID) | ||
372 | { | ||
373 | BackendResponse ret; | ||
374 | |||
375 | InventoryCollection collection; | ||
376 | InventoryFolder folder; | ||
377 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
378 | { | ||
379 | // Remove the folder from its parent folder | ||
380 | InventoryFolder parent; | ||
381 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | ||
382 | lock (parent.Children) parent.Children.Remove(folderID); | ||
383 | |||
384 | // Remove the folder from the collection | ||
385 | lock (collection) collection.Items.Remove(folderID); | ||
386 | |||
387 | // Delete the folder file. We don't know exactly what the file name is, | ||
388 | // so search for it | ||
389 | string path = PathFromURI(owner); | ||
390 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly); | ||
391 | foreach (string match in matches) | ||
392 | { | ||
393 | try { File.Delete(match); } | ||
394 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); } | ||
395 | } | ||
396 | |||
397 | ret = BackendResponse.Success; | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | ret = BackendResponse.NotFound; | ||
402 | } | ||
403 | |||
404 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | public BackendResponse TryPurgeFolder(Uri owner, UUID folderID) | ||
409 | { | ||
410 | BackendResponse ret; | ||
411 | |||
412 | InventoryCollection collection; | ||
413 | InventoryFolder folder; | ||
414 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
415 | { | ||
416 | // Delete all of the folder children | ||
417 | foreach (InventoryBase obj in new List<InventoryBase>(folder.Children.Values)) | ||
418 | { | ||
419 | if (obj is InventoryItem) | ||
420 | { | ||
421 | TryDeleteItem(owner, (obj as InventoryItem).ID); | ||
422 | } | ||
423 | else | ||
424 | { | ||
425 | InventoryFolder childFolder = obj as InventoryFolder; | ||
426 | TryPurgeFolder(owner, childFolder.ID); | ||
427 | TryDeleteFolder(owner, childFolder.ID); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | ret = BackendResponse.Success; | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | ret = BackendResponse.NotFound; | ||
436 | } | ||
437 | |||
438 | server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | ||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | #endregion Required Interfaces | ||
443 | |||
444 | void SaveItem(InventoryItem item) | ||
445 | { | ||
446 | string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID); | ||
447 | |||
448 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString()); | ||
449 | path = Path.Combine(path, filename); | ||
450 | |||
451 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | ||
452 | { | ||
453 | itemSerializer.Serialize(stream, item); | ||
454 | stream.Flush(); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | void SaveFolder(InventoryFolder folder) | ||
459 | { | ||
460 | string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID); | ||
461 | |||
462 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString()); | ||
463 | path = Path.Combine(path, filename); | ||
464 | |||
465 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | ||
466 | { | ||
467 | folderSerializer.Serialize(stream, folder); | ||
468 | stream.Flush(); | ||
469 | } | ||
470 | } | ||
471 | |||
472 | string SanitizeFilename(string filename) | ||
473 | { | ||
474 | string output = filename; | ||
475 | |||
476 | if (output.Length > 64) | ||
477 | output = output.Substring(0, 64); | ||
478 | |||
479 | foreach (char i in Path.GetInvalidFileNameChars()) | ||
480 | output = output.Replace(i, '_'); | ||
481 | |||
482 | return output; | ||
483 | } | ||
484 | |||
485 | static string PathFromURI(Uri uri) | ||
486 | { | ||
487 | byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString())); | ||
488 | StringBuilder digest = new StringBuilder(40); | ||
489 | |||
490 | // Convert the hash to a hex string | ||
491 | foreach (byte b in hash) | ||
492 | digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b); | ||
493 | |||
494 | return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString()); | ||
495 | } | ||
496 | |||
497 | void LoadFiles(string folder) | ||
498 | { | ||
499 | // Try to create the directory if it doesn't already exist | ||
500 | if (!Directory.Exists(folder)) | ||
501 | { | ||
502 | try { Directory.CreateDirectory(folder); } | ||
503 | catch (Exception ex) | ||
504 | { | ||
505 | Logger.Log.Warn(ex.Message); | ||
506 | return; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | try | ||
511 | { | ||
512 | string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR); | ||
513 | |||
514 | for (int i = 0; i < agentFolders.Length; i++) | ||
515 | { | ||
516 | string foldername = agentFolders[i]; | ||
517 | string indexPath = Path.Combine(foldername, "index.txt"); | ||
518 | UUID ownerID = UUID.Zero; | ||
519 | Uri owner = null; | ||
520 | |||
521 | try | ||
522 | { | ||
523 | string[] index = File.ReadAllLines(indexPath); | ||
524 | ownerID = UUID.Parse(index[0]); | ||
525 | owner = new Uri(index[1]); | ||
526 | } | ||
527 | catch (Exception ex) | ||
528 | { | ||
529 | Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message); | ||
530 | } | ||
531 | |||
532 | if (ownerID != UUID.Zero && owner != null) | ||
533 | { | ||
534 | // Initialize the active gestures list for this agent | ||
535 | activeGestures.Add(owner, new List<InventoryItem>()); | ||
536 | |||
537 | InventoryCollection collection = new InventoryCollection(); | ||
538 | collection.UserID = ownerID; | ||
539 | |||
540 | // Load all of the folders for this agent | ||
541 | string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly); | ||
542 | collection.Folders = new Dictionary<UUID,InventoryFolder>(folders.Length); | ||
543 | |||
544 | for (int j = 0; j < folders.Length; j++) | ||
545 | { | ||
546 | InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize( | ||
547 | new FileStream(folders[j], FileMode.Open, FileAccess.Read)); | ||
548 | collection.Folders[invFolder.ID] = invFolder; | ||
549 | } | ||
550 | |||
551 | // Iterate over the folders collection, adding children to their parents | ||
552 | foreach (InventoryFolder invFolder in collection.Folders.Values) | ||
553 | { | ||
554 | InventoryFolder parent; | ||
555 | if (collection.Folders.TryGetValue(invFolder.ParentID, out parent)) | ||
556 | parent.Children[invFolder.ID] = invFolder; | ||
557 | } | ||
558 | |||
559 | // Load all of the items for this agent | ||
560 | string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly); | ||
561 | collection.Items = new Dictionary<UUID, InventoryItem>(files.Length); | ||
562 | |||
563 | for (int j = 0; j < files.Length; j++) | ||
564 | { | ||
565 | InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize( | ||
566 | new FileStream(files[j], FileMode.Open, FileAccess.Read)); | ||
567 | collection.Items[invItem.ID] = invItem; | ||
568 | |||
569 | // Add items to their parent folders | ||
570 | InventoryFolder parent; | ||
571 | if (collection.Folders.TryGetValue(invItem.Folder, out parent)) | ||
572 | parent.Children[invItem.ID] = invItem; | ||
573 | |||
574 | // Add active gestures to our list | ||
575 | if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0) | ||
576 | activeGestures[owner].Add(invItem); | ||
577 | } | ||
578 | |||
579 | inventories.Add(owner, collection); | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | catch (Exception ex) | ||
584 | { | ||
585 | Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | #region IPlugin implementation | ||
590 | |||
591 | public void Initialise(AssetInventoryServer server) | ||
592 | { | ||
593 | this.server = server; | ||
594 | |||
595 | LoadFiles(DEFAULT_INVENTORY_DIR); | ||
596 | |||
597 | Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars", | ||
598 | inventories.Count); | ||
599 | } | ||
600 | |||
601 | /// <summary> | ||
602 | /// <para>Initialises asset interface</para> | ||
603 | /// </summary> | ||
604 | public void Initialise() | ||
605 | { | ||
606 | Logger.Log.InfoFormat("[ASSET]: {0} cannot be default-initialized!", Name); | ||
607 | throw new PluginNotInitialisedException(Name); | ||
608 | } | ||
609 | |||
610 | public void Dispose() | ||
611 | { | ||
612 | } | ||
613 | |||
614 | public string Version | ||
615 | { | ||
616 | // TODO: this should be something meaningful and not hardcoded? | ||
617 | get { return "0.1"; } | ||
618 | } | ||
619 | |||
620 | public string Name | ||
621 | { | ||
622 | get { return "AssetInventoryServer Simple inventory storage provider"; } | ||
623 | } | ||
624 | |||
625 | #endregion IPlugin implementation | ||
626 | } | ||
627 | } | ||