aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/AssetInventoryServer/Extensions
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Grid/AssetInventoryServer/Extensions')
-rw-r--r--OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLInventory.cs804
-rw-r--r--OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs602
2 files changed, 0 insertions, 1406 deletions
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLInventory.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLInventory.cs
deleted file mode 100644
index 07bf92f..0000000
--- a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLInventory.cs
+++ /dev/null
@@ -1,804 +0,0 @@
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
30using System;
31using System.Collections.Generic;
32using System.Net;
33using System.Data;
34using MySql.Data.MySqlClient;
35using ExtensionLoader;
36using ExtensionLoader.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40namespace OpenSim.Grid.AssetInventoryServer.Extensions
41{
42 public class OpenSimMySQLInventory : IExtension<AssetInventoryServer>, IInventoryProvider
43 {
44 const string EXTENSION_NAME = "OpenSimMySQLInventory"; // Used in metrics reporting
45
46 AssetInventoryServer server;
47
48 public OpenSimMySQLInventory()
49 {
50 }
51
52 #region Required Interfaces
53
54 public void Start(AssetInventoryServer server)
55 {
56 this.server = server;
57
58 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
59 {
60 try
61 {
62 dbConnection.Open();
63 Logger.Log.Info("Connected to MySQL inventory backend: " + dbConnection.ServerVersion);
64 }
65 catch (MySqlException ex)
66 {
67 Logger.Log.Error("Connection to MySQL inventory backend failed: " + ex.Message);
68 }
69 }
70 }
71
72 public void Stop()
73 {
74 }
75
76 public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item)
77 {
78 item = null;
79 BackendResponse ret;
80
81 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
82 {
83 IDataReader reader;
84
85 try
86 {
87 dbConnection.Open();
88
89 IDbCommand command = dbConnection.CreateCommand();
90 command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
91 "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
92 "creationDate,groupID,groupOwned,flags,avatarID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE inventoryID='{0}'",
93 itemID.ToString());
94 reader = command.ExecuteReader();
95
96 if (reader.Read())
97 {
98 item = new InventoryItem();
99 item.ID = itemID;
100 item.AssetID = UUID.Parse(reader.GetString(0));
101 item.AssetType = reader.GetInt32(1);
102 item.Name = reader.GetString(2);
103 item.Description = reader.GetString(3);
104 item.NextPermissions = (uint)reader.GetInt32(4);
105 item.CurrentPermissions = (uint)reader.GetInt32(5);
106 item.InvType = reader.GetInt32(6);
107 item.Creator = UUID.Parse(reader.GetString(7));
108 item.BasePermissions = (uint)reader.GetInt32(8);
109 item.EveryOnePermissions = (uint)reader.GetInt32(9);
110 item.SalePrice = reader.GetInt32(10);
111 item.SaleType = reader.GetByte(11);
112 item.CreationDate = reader.GetInt32(12);
113 item.GroupID = UUID.Parse(reader.GetString(13));
114 item.GroupOwned = reader.GetBoolean(14);
115 item.Flags = (uint)reader.GetInt32(15);
116 item.Owner = UUID.Parse(reader.GetString(16));
117 item.Folder = UUID.Parse(reader.GetString(17));
118 item.GroupPermissions = (uint)reader.GetInt32(18);
119
120 ret = BackendResponse.Success;
121 }
122 else
123 {
124 ret = BackendResponse.NotFound;
125 }
126 }
127 catch (MySqlException ex)
128 {
129 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
130 ret = BackendResponse.Failure;
131 }
132 }
133
134 server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
135 return ret;
136 }
137
138 public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder)
139 {
140 folder = null;
141 BackendResponse ret;
142
143 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
144 {
145 IDataReader reader;
146
147 try
148 {
149 dbConnection.Open();
150
151 IDbCommand command = dbConnection.CreateCommand();
152 command.CommandText = String.Format("SELECT folderName,type,version,agentID,parentFolderID FROM inventoryfolders WHERE folderID='{0}'",
153 folderID.ToString());
154 reader = command.ExecuteReader();
155
156 if (reader.Read())
157 {
158 folder = new InventoryFolder();
159 folder.Children = null; // This call only returns data for the folder itself, no children data
160 folder.ID = folderID;
161 folder.Name = reader.GetString(0);
162 folder.Type = reader.GetInt16(1);
163 folder.Version = (ushort)reader.GetInt16(2);
164 folder.Owner = UUID.Parse(reader.GetString(3));
165 folder.ParentID = UUID.Parse(reader.GetString(4));
166
167 ret = BackendResponse.Success;
168 }
169 else
170 {
171 ret = BackendResponse.NotFound;
172 }
173 }
174 catch (MySqlException ex)
175 {
176 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
177 ret = BackendResponse.Failure;
178 }
179 }
180
181 server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
182 return ret;
183 }
184
185 public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents)
186 {
187 contents = null;
188 BackendResponse ret;
189
190 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
191 {
192 IDataReader reader;
193
194 try
195 {
196 dbConnection.Open();
197
198 contents = new InventoryCollection();
199
200 #region Folder retrieval
201
202 IDbCommand command = dbConnection.CreateCommand();
203 command.CommandText = String.Format("SELECT folderName,type,version,agentID,folderID FROM inventoryfolders WHERE parentFolderID='{0}'",
204 folderID.ToString());
205 reader = command.ExecuteReader();
206
207 contents.Folders = new Dictionary<UUID, InventoryFolder>();
208
209 while (reader.Read())
210 {
211 InventoryFolder folder = new InventoryFolder();
212 folder.ParentID = folderID;
213 folder.Children = null; // This call doesn't do recursion
214 folder.Name = reader.GetString(0);
215 folder.Type = reader.GetInt16(1);
216 folder.Version = (ushort)reader.GetInt16(2);
217 folder.Owner = UUID.Parse(reader.GetString(3));
218 folder.ID = UUID.Parse(reader.GetString(4));
219
220 contents.Folders.Add(folder.ID, folder);
221 contents.UserID = folder.Owner;
222 }
223
224 reader.Close();
225
226 #endregion Folder retrieval
227
228 #region Item retrieval
229
230 command = dbConnection.CreateCommand();
231 command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
232 "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
233 "creationDate,groupID,groupOwned,flags,avatarID,inventoryID,inventoryGroupPermissions FROM inventoryitems WHERE parentFolderID='{0}'",
234 folderID.ToString());
235 reader = command.ExecuteReader();
236
237 contents.Items = new Dictionary<UUID, InventoryItem>();
238
239 while (reader.Read())
240 {
241 InventoryItem item = new InventoryItem();
242 item.Folder = folderID;
243 item.AssetID = UUID.Parse(reader.GetString(0));
244 item.AssetType = reader.GetInt32(1);
245 item.Name = reader.GetString(2);
246 item.Description = reader.GetString(3);
247 item.NextPermissions = (uint)reader.GetInt32(4);
248 item.CurrentPermissions = (uint)reader.GetInt32(5);
249 item.InvType = reader.GetInt32(6);
250 item.Creator = UUID.Parse(reader.GetString(7));
251 item.BasePermissions = (uint)reader.GetInt32(8);
252 item.EveryOnePermissions = (uint)reader.GetInt32(9);
253 item.SalePrice = reader.GetInt32(10);
254 item.SaleType = reader.GetByte(11);
255 item.CreationDate = reader.GetInt32(12);
256 item.GroupID = UUID.Parse(reader.GetString(13));
257 item.GroupOwned = reader.GetBoolean(14);
258 item.Flags = (uint)reader.GetInt32(15);
259 item.Owner = UUID.Parse(reader.GetString(16));
260 item.ID = UUID.Parse(reader.GetString(17));
261 item.GroupPermissions = (uint)reader.GetInt32(18);
262
263 contents.Items.Add(item.ID, item);
264 contents.UserID = item.Owner;
265 }
266
267 #endregion Item retrieval
268
269 ret = BackendResponse.Success;
270 }
271 catch (MySqlException ex)
272 {
273 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
274 ret = BackendResponse.Failure;
275 }
276 }
277
278 server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
279 return ret;
280 }
281
282 public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders)
283 {
284 folders = null;
285 BackendResponse ret;
286 UUID ownerID;
287
288 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
289 {
290 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
291 {
292 IDataReader reader;
293
294 try
295 {
296 dbConnection.Open();
297 folders = new List<InventoryFolder>();
298
299 IDbCommand command = dbConnection.CreateCommand();
300 command.CommandText = String.Format("SELECT folderName,type,version,folderID,parentFolderID FROM inventoryfolders WHERE agentID='{0}'",
301 ownerID.ToString());
302 reader = command.ExecuteReader();
303
304 while (reader.Read())
305 {
306 InventoryFolder folder = new InventoryFolder();
307 folder.Owner = ownerID;
308 folder.Children = null; // This call does not create a folder hierarchy
309 folder.Name = reader.GetString(0);
310 folder.Type = reader.GetInt16(1);
311 folder.Version = (ushort)reader.GetInt16(2);
312 folder.ID = UUID.Parse(reader.GetString(3));
313 folder.ParentID = UUID.Parse(reader.GetString(4));
314
315 folders.Add(folder);
316 }
317
318 ret = BackendResponse.Success;
319 }
320 catch (MySqlException ex)
321 {
322 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
323 ret = BackendResponse.Failure;
324 }
325 }
326 }
327 else
328 {
329 ret = BackendResponse.NotFound;
330 }
331
332 server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now);
333 return ret;
334 }
335
336 public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory)
337 {
338 inventory = null;
339 BackendResponse ret;
340 List<InventoryFolder> folders;
341 UUID ownerID;
342
343 ret = TryFetchFolderList(owner, out folders);
344
345 if (ret == BackendResponse.Success)
346 {
347 // Add the retrieved folders to the inventory collection
348 inventory = new InventoryCollection();
349 inventory.Folders = new Dictionary<UUID, InventoryFolder>(folders.Count);
350 foreach (InventoryFolder folder in folders)
351 inventory.Folders[folder.ID] = folder;
352
353 // Fetch inventory items
354 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
355 {
356 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
357 {
358 IDataReader reader;
359
360 try
361 {
362 dbConnection.Open();
363
364 IDbCommand command = dbConnection.CreateCommand();
365 command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
366 "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
367 "creationDate,groupID,groupOwned,flags,inventoryID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE " +
368 "avatarID='{0}'", ownerID.ToString());
369 reader = command.ExecuteReader();
370
371 inventory.UserID = ownerID;
372 inventory.Items = new Dictionary<UUID, InventoryItem>();
373
374 while (reader.Read())
375 {
376 InventoryItem item = new InventoryItem();
377 item.Owner = ownerID;
378 item.AssetID = UUID.Parse(reader.GetString(0));
379 item.AssetType = reader.GetInt32(1);
380 item.Name = reader.GetString(2);
381 item.Description = reader.GetString(3);
382 item.NextPermissions = (uint)reader.GetInt32(4);
383 item.CurrentPermissions = (uint)reader.GetInt32(5);
384 item.InvType = reader.GetInt32(6);
385 item.Creator = UUID.Parse(reader.GetString(7));
386 item.BasePermissions = (uint)reader.GetInt32(8);
387 item.EveryOnePermissions = (uint)reader.GetInt32(9);
388 item.SalePrice = reader.GetInt32(10);
389 item.SaleType = reader.GetByte(11);
390 item.CreationDate = reader.GetInt32(12);
391 item.GroupID = UUID.Parse(reader.GetString(13));
392 item.GroupOwned = reader.GetBoolean(14);
393 item.Flags = (uint)reader.GetInt32(15);
394 item.ID = UUID.Parse(reader.GetString(16));
395 item.Folder = UUID.Parse(reader.GetString(17));
396 item.GroupPermissions = (uint)reader.GetInt32(18);
397
398 inventory.Items.Add(item.ID, item);
399 }
400
401 ret = BackendResponse.Success;
402 }
403 catch (MySqlException ex)
404 {
405 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
406 ret = BackendResponse.Failure;
407 }
408 }
409 }
410 else
411 {
412 ret = BackendResponse.NotFound;
413 }
414 }
415
416 server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now);
417 return ret;
418 }
419
420 public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures)
421 {
422 gestures = null;
423 BackendResponse ret;
424 UUID ownerID;
425
426 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
427 {
428 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
429 {
430 IDataReader reader;
431
432 try
433 {
434 dbConnection.Open();
435
436 MySqlCommand command = new MySqlCommand("SELECT assetID,inventoryName,inventoryDescription,inventoryNextPermissions," +
437 "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
438 "creationDate,groupID,groupOwned,inventoryID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE " +
439 "avatarId=?uuid AND assetType=?type AND flags=1", dbConnection);
440 command.Parameters.AddWithValue("?uuid", ownerID.ToString());
441 command.Parameters.AddWithValue("?type", (int)AssetType.Gesture);
442 reader = command.ExecuteReader();
443
444 while (reader.Read())
445 {
446 InventoryItem item = new InventoryItem();
447 item.Owner = ownerID;
448 item.AssetType = (int)AssetType.Gesture;
449 item.Flags = (uint)1;
450 item.AssetID = UUID.Parse(reader.GetString(0));
451 item.Name = reader.GetString(1);
452 item.Description = reader.GetString(2);
453 item.NextPermissions = (uint)reader.GetInt32(3);
454 item.CurrentPermissions = (uint)reader.GetInt32(4);
455 item.InvType = reader.GetInt32(5);
456 item.Creator = UUID.Parse(reader.GetString(6));
457 item.BasePermissions = (uint)reader.GetInt32(7);
458 item.EveryOnePermissions = (uint)reader.GetInt32(8);
459 item.SalePrice = reader.GetInt32(9);
460 item.SaleType = reader.GetByte(10);
461 item.CreationDate = reader.GetInt32(11);
462 item.GroupID = UUID.Parse(reader.GetString(12));
463 item.GroupOwned = reader.GetBoolean(13);
464 item.ID = UUID.Parse(reader.GetString(14));
465 item.Folder = UUID.Parse(reader.GetString(15));
466 item.GroupPermissions = (uint)reader.GetInt32(16);
467
468 gestures.Add(item);
469 }
470
471 ret = BackendResponse.Success;
472 }
473 catch (MySqlException ex)
474 {
475 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
476 ret = BackendResponse.Failure;
477 }
478 }
479 }
480 else
481 {
482 ret = BackendResponse.NotFound;
483 }
484
485 server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now);
486 return ret;
487 }
488
489 public BackendResponse TryCreateItem(Uri owner, InventoryItem item)
490 {
491 BackendResponse ret;
492
493 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
494 {
495 try
496 {
497 dbConnection.Open();
498
499 MySqlCommand command = new MySqlCommand(
500 "REPLACE INTO inventoryitems (assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
501 "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
502 "creationDate,groupID,groupOwned,flags,inventoryID,avatarID,parentFolderID,inventoryGroupPermissions) VALUES " +
503
504 "(?assetID,?assetType,?inventoryName,?inventoryDescription,?inventoryNextPermissions,?inventoryCurrentPermissions,?invType," +
505 "?creatorID,?inventoryBasePermissions,?inventoryEveryOnePermissions,?salePrice,?saleType,?creationDate,?groupID,?groupOwned," +
506 "?flags,?inventoryID,?avatarID,?parentFolderID,?inventoryGroupPermissions)", dbConnection);
507
508 command.Parameters.AddWithValue("?assetID", item.AssetID.ToString());
509 command.Parameters.AddWithValue("?assetType", item.AssetType);
510 command.Parameters.AddWithValue("?inventoryName", item.Name);
511 command.Parameters.AddWithValue("?inventoryDescription", item.Description);
512 command.Parameters.AddWithValue("?inventoryNextPermissions", item.NextPermissions);
513 command.Parameters.AddWithValue("?inventoryCurrentPermissions", item.CurrentPermissions);
514 command.Parameters.AddWithValue("?invType", item.InvType);
515 command.Parameters.AddWithValue("?creatorID", item.Creator.ToString());
516 command.Parameters.AddWithValue("?inventoryBasePermissions", item.BasePermissions);
517 command.Parameters.AddWithValue("?inventoryEveryOnePermissions", item.EveryOnePermissions);
518 command.Parameters.AddWithValue("?salePrice", item.SalePrice);
519 command.Parameters.AddWithValue("?saleType", item.SaleType);
520 command.Parameters.AddWithValue("?creationDate", item.CreationDate);
521 command.Parameters.AddWithValue("?groupID", item.GroupID.ToString());
522 command.Parameters.AddWithValue("?groupOwned", item.GroupOwned);
523 command.Parameters.AddWithValue("?flags", item.Flags);
524 command.Parameters.AddWithValue("?inventoryID", item.ID);
525 command.Parameters.AddWithValue("?avatarID", item.Owner);
526 command.Parameters.AddWithValue("?parentFolderID", item.Folder);
527 command.Parameters.AddWithValue("?inventoryGroupPermissions", item.GroupPermissions);
528
529 int rowsAffected = command.ExecuteNonQuery();
530 if (rowsAffected == 1)
531 {
532 ret = BackendResponse.Success;
533 }
534 else if (rowsAffected == 2)
535 {
536 Logger.Log.Info("Replaced inventory item " + item.ID.ToString());
537 ret = BackendResponse.Success;
538 }
539 else
540 {
541 Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
542 ret = BackendResponse.Failure;
543 }
544 }
545 catch (MySqlException ex)
546 {
547 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
548 ret = BackendResponse.Failure;
549 }
550 }
551
552 server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now);
553 return ret;
554 }
555
556 public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder)
557 {
558 BackendResponse ret;
559
560 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
561 {
562 try
563 {
564 dbConnection.Open();
565
566 MySqlCommand command = new MySqlCommand(
567 "REPLACE INTO inventoryfolders (folderName,type,version,folderID,agentID,parentFolderID) VALUES " +
568 "(?folderName,?type,?version,?folderID,?agentID,?parentFolderID)", dbConnection);
569
570 command.Parameters.AddWithValue("?folderName", folder.Name);
571 command.Parameters.AddWithValue("?type", folder.Type);
572 command.Parameters.AddWithValue("?version", folder.Version);
573 command.Parameters.AddWithValue("?folderID", folder.ID);
574 command.Parameters.AddWithValue("?agentID", folder.Owner);
575 command.Parameters.AddWithValue("?parentFolderID", folder.ParentID);
576
577 int rowsAffected = command.ExecuteNonQuery();
578 if (rowsAffected == 1)
579 {
580 ret = BackendResponse.Success;
581 }
582 else if (rowsAffected == 2)
583 {
584 Logger.Log.Info("Replaced inventory folder " + folder.ID.ToString());
585 ret = BackendResponse.Success;
586 }
587 else
588 {
589 Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
590 ret = BackendResponse.Failure;
591 }
592 }
593 catch (MySqlException ex)
594 {
595 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
596 ret = BackendResponse.Failure;
597 }
598 }
599
600 server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now);
601 return ret;
602 }
603
604 public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder)
605 {
606 return TryCreateFolder(owner, rootFolder);
607 }
608
609 public BackendResponse TryDeleteItem(Uri owner, UUID itemID)
610 {
611 BackendResponse ret;
612 UUID ownerID;
613
614 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
615 {
616 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
617 {
618 try
619 {
620 dbConnection.Open();
621
622 MySqlCommand command = new MySqlCommand(
623 "DELETE FROM inventoryitems WHERE inventoryID=?inventoryID AND avatarID=?avatarID", dbConnection);
624
625 command.Parameters.AddWithValue("?inventoryID", itemID.ToString());
626 command.Parameters.AddWithValue("?avatarID", ownerID.ToString());
627
628 int rowsAffected = command.ExecuteNonQuery();
629 if (rowsAffected == 1)
630 {
631 ret = BackendResponse.Success;
632 }
633 else
634 {
635 Logger.Log.ErrorFormat("MySQL DELETE query affected {0} rows", rowsAffected);
636 ret = BackendResponse.NotFound;
637 }
638 }
639 catch (MySqlException ex)
640 {
641 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
642 ret = BackendResponse.Failure;
643 }
644 }
645 }
646 else
647 {
648 ret = BackendResponse.NotFound;
649 }
650
651 server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
652 return ret;
653 }
654
655 public BackendResponse TryDeleteFolder(Uri owner, UUID folderID)
656 {
657 BackendResponse ret;
658 UUID ownerID;
659
660 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
661 {
662 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
663 {
664 try
665 {
666 dbConnection.Open();
667
668 MySqlCommand command = new MySqlCommand(
669 "DELETE FROM inventoryfolders WHERE folderID=?folderID AND agentID=?agentID", dbConnection);
670
671 command.Parameters.AddWithValue("?folderID", folderID.ToString());
672 command.Parameters.AddWithValue("?agentID", ownerID.ToString());
673
674 int rowsAffected = command.ExecuteNonQuery();
675 if (rowsAffected == 1)
676 {
677 ret = BackendResponse.Success;
678 }
679 else
680 {
681 Logger.Log.ErrorFormat("MySQL DELETE query affected {0} rows", rowsAffected);
682 ret = BackendResponse.NotFound;
683 }
684 }
685 catch (MySqlException ex)
686 {
687 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
688 ret = BackendResponse.Failure;
689 }
690 }
691 }
692 else
693 {
694 ret = BackendResponse.NotFound;
695 }
696
697 server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
698 return ret;
699 }
700
701 public BackendResponse TryPurgeFolder(Uri owner, UUID folderID)
702 {
703 BackendResponse ret;
704 UUID ownerID;
705
706 if (Utils.TryGetOpenSimUUID(owner, out ownerID))
707 {
708 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
709 {
710 try
711 {
712 dbConnection.Open();
713
714 #region Delete items
715
716 MySqlCommand command = new MySqlCommand(
717 "DELETE FROM inventoryitems WHERE parentFolderID=?parentFolderID AND avatarID=?avatarID", dbConnection);
718
719 command.Parameters.AddWithValue("?parentFolderID", folderID.ToString());
720 command.Parameters.AddWithValue("?avatarID", ownerID.ToString());
721
722 int rowsAffected = command.ExecuteNonQuery();
723
724 #endregion Delete items
725
726 #region Delete folders
727
728 command = new MySqlCommand(
729 "DELETE FROM inventoryfolders WHERE parentFolderID=?parentFolderID AND agentID=?agentID", dbConnection);
730
731 command.Parameters.AddWithValue("?parentFolderID", folderID.ToString());
732 command.Parameters.AddWithValue("?agentID", ownerID.ToString());
733
734 rowsAffected += command.ExecuteNonQuery();
735
736 #endregion Delete folders
737
738 Logger.Log.DebugFormat("Deleted {0} inventory objects from MySQL in a folder purge", rowsAffected);
739
740 ret = BackendResponse.Success;
741 }
742 catch (MySqlException ex)
743 {
744 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
745 ret = BackendResponse.Failure;
746 }
747 }
748 }
749 else
750 {
751 ret = BackendResponse.NotFound;
752 }
753
754 server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
755 return ret;
756 }
757
758 public int ForEach(Action<Metadata> action, int start, int count)
759 {
760 int rowCount = 0;
761
762 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
763 {
764 MySqlDataReader reader;
765
766 try
767 {
768 dbConnection.Open();
769
770 MySqlCommand command = dbConnection.CreateCommand();
771 command.CommandText = String.Format("SELECT name,description,assetType,temporary,data,id FROM assets LIMIT {0}, {1}",
772 start, count);
773 reader = command.ExecuteReader();
774 }
775 catch (MySqlException ex)
776 {
777 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
778 return 0;
779 }
780
781 while (reader.Read())
782 {
783 Metadata metadata = new Metadata();
784 metadata.CreationDate = OpenMetaverse.Utils.Epoch;
785 metadata.Description = reader.GetString(1);
786 metadata.ID = UUID.Parse(reader.GetString(5));
787 metadata.Name = reader.GetString(0);
788 metadata.SHA1 = OpenMetaverse.Utils.SHA1((byte[])reader.GetValue(4));
789 metadata.Temporary = reader.GetBoolean(3);
790 metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
791
792 action(metadata);
793 ++rowCount;
794 }
795
796 reader.Close();
797 }
798
799 return rowCount;
800 }
801
802 #endregion Required Interfaces
803 }
804}
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs
deleted file mode 100644
index c140965..0000000
--- a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs
+++ /dev/null
@@ -1,602 +0,0 @@
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
30using System;
31using System.Collections.Generic;
32using System.Net;
33using System.IO;
34using System.Text;
35using ExtensionLoader;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38
39namespace OpenSim.Grid.AssetInventoryServer.Extensions
40{
41 public class SimpleInventory : IExtension<AssetInventoryServer>, IInventoryProvider
42 {
43 const string EXTENSION_NAME = "SimpleInventory"; // Used for metrics reporting
44 const string DEFAULT_INVENTORY_DIR = "SimpleInventory";
45
46 AssetInventoryServer server;
47 Dictionary<Uri, InventoryCollection> inventories = new Dictionary<Uri, InventoryCollection>();
48 Dictionary<Uri, List<InventoryItem>> activeGestures = new Dictionary<Uri, List<InventoryItem>>();
49 Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer();
50 Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer();
51
52 public SimpleInventory()
53 {
54 }
55
56 #region Required Interfaces
57
58 public void Start(AssetInventoryServer server)
59 {
60 this.server = server;
61
62 LoadFiles(DEFAULT_INVENTORY_DIR);
63
64 Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars",
65 inventories.Count);
66 }
67
68 public void Stop()
69 {
70 }
71
72 public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item)
73 {
74 item = null;
75 BackendResponse ret;
76
77 InventoryCollection collection;
78 if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item))
79 ret = BackendResponse.Success;
80 else
81 ret = BackendResponse.NotFound;
82
83 server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
84 return ret;
85 }
86
87 public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder)
88 {
89 folder = null;
90 BackendResponse ret;
91
92 InventoryCollection collection;
93 if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
94 ret = BackendResponse.Success;
95 else
96 ret = BackendResponse.NotFound;
97
98 server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
99 return ret;
100 }
101
102 public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents)
103 {
104 contents = null;
105 BackendResponse ret;
106
107 InventoryCollection collection;
108 InventoryFolder folder;
109
110 if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
111 {
112 contents = new InventoryCollection();
113 contents.UserID = collection.UserID;
114 contents.Folders = new Dictionary<UUID, InventoryFolder>();
115 contents.Items = new Dictionary<UUID, InventoryItem>();
116
117 foreach (InventoryBase invBase in folder.Children.Values)
118 {
119 if (invBase is InventoryItem)
120 {
121 InventoryItem invItem = invBase as InventoryItem;
122 contents.Items.Add(invItem.ID, invItem);
123 }
124 else
125 {
126 InventoryFolder invFolder = invBase as InventoryFolder;
127 contents.Folders.Add(invFolder.ID, invFolder);
128 }
129 }
130
131 ret = BackendResponse.Success;
132 }
133 else
134 {
135 ret = BackendResponse.NotFound;
136 }
137
138 server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
139 return ret;
140 }
141
142 public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders)
143 {
144 folders = null;
145 BackendResponse ret;
146
147 InventoryCollection collection;
148 if (inventories.TryGetValue(owner, out collection))
149 {
150 folders = new List<InventoryFolder>(collection.Folders.Values);
151 return BackendResponse.Success;
152 }
153 else
154 {
155 ret = BackendResponse.NotFound;
156 }
157
158 server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now);
159 return ret;
160 }
161
162 public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory)
163 {
164 inventory = null;
165 BackendResponse ret;
166
167 if (inventories.TryGetValue(owner, out inventory))
168 ret = BackendResponse.Success;
169 else
170 ret = BackendResponse.NotFound;
171
172 server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now);
173 return ret;
174 }
175
176 public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures)
177 {
178 gestures = null;
179 BackendResponse ret;
180
181 if (activeGestures.TryGetValue(owner, out gestures))
182 ret = BackendResponse.Success;
183 else
184 ret = BackendResponse.NotFound;
185
186 server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now);
187 return ret;
188 }
189
190 public BackendResponse TryCreateItem(Uri owner, InventoryItem item)
191 {
192 BackendResponse ret;
193
194 InventoryCollection collection;
195 if (inventories.TryGetValue(owner, out collection))
196 {
197 // Delete this item first if it already exists
198 InventoryItem oldItem;
199 if (collection.Items.TryGetValue(item.ID, out oldItem))
200 TryDeleteItem(owner, item.ID);
201
202 try
203 {
204 // Create the file
205 SaveItem(item);
206
207 // Add the item to the collection
208 lock (collection) collection.Items[item.ID] = item;
209
210 // Add the item to its parent folder
211 InventoryFolder parent;
212 if (collection.Folders.TryGetValue(item.Folder, out parent))
213 lock (parent.Children) parent.Children.Add(item.ID, item);
214
215 // Add active gestures to our list
216 if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1)
217 {
218 lock (activeGestures)
219 activeGestures[owner].Add(item);
220 }
221
222 ret = BackendResponse.Success;
223 }
224 catch (Exception ex)
225 {
226 Logger.Log.Error(ex.Message);
227 ret = BackendResponse.Failure;
228 }
229 }
230 else
231 {
232 return BackendResponse.NotFound;
233 }
234
235 server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now);
236 return ret;
237 }
238
239 public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder)
240 {
241 BackendResponse ret;
242
243 InventoryCollection collection;
244 if (inventories.TryGetValue(owner, out collection))
245 {
246 // Delete this folder first if it already exists
247 InventoryFolder oldFolder;
248 if (collection.Folders.TryGetValue(folder.ID, out oldFolder))
249 TryDeleteFolder(owner, folder.ID);
250
251 try
252 {
253 // Create the file
254 SaveFolder(folder);
255
256 // Add the folder to the collection
257 lock (collection) collection.Folders[folder.ID] = folder;
258
259 // Add the folder to its parent folder
260 InventoryFolder parent;
261 if (collection.Folders.TryGetValue(folder.ParentID, out parent))
262 lock (parent.Children) parent.Children.Add(folder.ID, folder);
263
264 ret = BackendResponse.Success;
265 }
266 catch (Exception ex)
267 {
268 Logger.Log.Error(ex.Message);
269 ret = BackendResponse.Failure;
270 }
271 }
272 else
273 {
274 ret = BackendResponse.NotFound;
275 }
276
277 server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now);
278 return ret;
279 }
280
281 public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder)
282 {
283 BackendResponse ret;
284
285 lock (inventories)
286 {
287 if (!inventories.ContainsKey(owner))
288 {
289 InventoryCollection collection = new InventoryCollection();
290 collection.UserID = rootFolder.Owner;
291 collection.Folders = new Dictionary<UUID, InventoryFolder>();
292 collection.Folders.Add(rootFolder.ID, rootFolder);
293 collection.Items = new Dictionary<UUID, InventoryItem>();
294
295 inventories.Add(owner, collection);
296
297 ret = BackendResponse.Success;
298 }
299 else
300 {
301 ret = BackendResponse.Failure;
302 }
303 }
304
305 if (ret == BackendResponse.Success)
306 {
307 string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString());
308 try
309 {
310 // Create the directory for this agent
311 Directory.CreateDirectory(path);
312
313 // Create an index.txt containing the UUID and URI for this agent
314 string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() };
315 File.WriteAllLines(Path.Combine(path, "index.txt"), index);
316
317 // Create the root folder file
318 SaveFolder(rootFolder);
319 }
320 catch (Exception ex)
321 {
322 Logger.Log.Error(ex.Message);
323 ret = BackendResponse.Failure;
324 }
325 }
326
327 server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now);
328 return ret;
329 }
330
331 public BackendResponse TryDeleteItem(Uri owner, UUID itemID)
332 {
333 BackendResponse ret;
334
335 InventoryCollection collection;
336 InventoryItem item;
337 if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item))
338 {
339 // Remove the item from its parent folder
340 InventoryFolder parent;
341 if (collection.Folders.TryGetValue(item.Folder, out parent))
342 lock (parent.Children) parent.Children.Remove(itemID);
343
344 // Remove the item from the collection
345 lock (collection) collection.Items.Remove(itemID);
346
347 // Remove from the active gestures list if applicable
348 if (item.InvType == (int)InventoryType.Gesture)
349 {
350 lock (activeGestures)
351 {
352 for (int i = 0; i < activeGestures[owner].Count; i++)
353 {
354 if (activeGestures[owner][i].ID == itemID)
355 {
356 activeGestures[owner].RemoveAt(i);
357 break;
358 }
359 }
360 }
361 }
362
363 // Delete the file. We don't know exactly what the file name is,
364 // so search for it
365 string path = PathFromURI(owner);
366 string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly);
367 foreach (string match in matches)
368 {
369 try { File.Delete(match); }
370 catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); }
371 }
372
373 ret = BackendResponse.Success;
374 }
375 else
376 {
377 ret = BackendResponse.NotFound;
378 }
379
380 server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
381 return ret;
382 }
383
384 public BackendResponse TryDeleteFolder(Uri owner, UUID folderID)
385 {
386 BackendResponse ret;
387
388 InventoryCollection collection;
389 InventoryFolder folder;
390 if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
391 {
392 // Remove the folder from its parent folder
393 InventoryFolder parent;
394 if (collection.Folders.TryGetValue(folder.ParentID, out parent))
395 lock (parent.Children) parent.Children.Remove(folderID);
396
397 // Remove the folder from the collection
398 lock (collection) collection.Items.Remove(folderID);
399
400 // Delete the folder file. We don't know exactly what the file name is,
401 // so search for it
402 string path = PathFromURI(owner);
403 string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly);
404 foreach (string match in matches)
405 {
406 try { File.Delete(match); }
407 catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); }
408 }
409
410 ret = BackendResponse.Success;
411 }
412 else
413 {
414 ret = BackendResponse.NotFound;
415 }
416
417 server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
418 return ret;
419 }
420
421 public BackendResponse TryPurgeFolder(Uri owner, UUID folderID)
422 {
423 BackendResponse ret;
424
425 InventoryCollection collection;
426 InventoryFolder folder;
427 if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
428 {
429 // Delete all of the folder children
430 foreach (InventoryBase obj in new List<InventoryBase>(folder.Children.Values))
431 {
432 if (obj is InventoryItem)
433 {
434 TryDeleteItem(owner, (obj as InventoryItem).ID);
435 }
436 else
437 {
438 InventoryFolder childFolder = obj as InventoryFolder;
439 TryPurgeFolder(owner, childFolder.ID);
440 TryDeleteFolder(owner, childFolder.ID);
441 }
442 }
443
444 ret = BackendResponse.Success;
445 }
446 else
447 {
448 ret = BackendResponse.NotFound;
449 }
450
451 server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
452 return ret;
453 }
454
455 #endregion Required Interfaces
456
457 void SaveItem(InventoryItem item)
458 {
459 string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID);
460
461 string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString());
462 path = Path.Combine(path, filename);
463
464 using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
465 {
466 itemSerializer.Serialize(stream, item);
467 stream.Flush();
468 }
469 }
470
471 void SaveFolder(InventoryFolder folder)
472 {
473 string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID);
474
475 string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString());
476 path = Path.Combine(path, filename);
477
478 using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
479 {
480 folderSerializer.Serialize(stream, folder);
481 stream.Flush();
482 }
483 }
484
485 string SanitizeFilename(string filename)
486 {
487 string output = filename;
488
489 if (output.Length > 64)
490 output = output.Substring(0, 64);
491
492 foreach (char i in Path.GetInvalidFileNameChars())
493 output = output.Replace(i, '_');
494
495 return output;
496 }
497
498 static string PathFromURI(Uri uri)
499 {
500 byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString()));
501 StringBuilder digest = new StringBuilder(40);
502
503 // Convert the hash to a hex string
504 foreach (byte b in hash)
505 digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b);
506
507 return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString());
508 }
509
510 void LoadFiles(string folder)
511 {
512 // Try to create the directory if it doesn't already exist
513 if (!Directory.Exists(folder))
514 {
515 try { Directory.CreateDirectory(folder); }
516 catch (Exception ex)
517 {
518 Logger.Log.Warn(ex.Message);
519 return;
520 }
521 }
522
523 try
524 {
525 string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR);
526
527 for (int i = 0; i < agentFolders.Length; i++)
528 {
529 string foldername = agentFolders[i];
530 string indexPath = Path.Combine(foldername, "index.txt");
531 UUID ownerID = UUID.Zero;
532 Uri owner = null;
533
534 try
535 {
536 string[] index = File.ReadAllLines(indexPath);
537 ownerID = UUID.Parse(index[0]);
538 owner = new Uri(index[1]);
539 }
540 catch (Exception ex)
541 {
542 Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message);
543 }
544
545 if (ownerID != UUID.Zero && owner != null)
546 {
547 // Initialize the active gestures list for this agent
548 activeGestures.Add(owner, new List<InventoryItem>());
549
550 InventoryCollection collection = new InventoryCollection();
551 collection.UserID = ownerID;
552
553 // Load all of the folders for this agent
554 string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly);
555 collection.Folders = new Dictionary<UUID,InventoryFolder>(folders.Length);
556
557 for (int j = 0; j < folders.Length; j++)
558 {
559 InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize(
560 new FileStream(folders[j], FileMode.Open, FileAccess.Read));
561 collection.Folders[invFolder.ID] = invFolder;
562 }
563
564 // Iterate over the folders collection, adding children to their parents
565 foreach (InventoryFolder invFolder in collection.Folders.Values)
566 {
567 InventoryFolder parent;
568 if (collection.Folders.TryGetValue(invFolder.ParentID, out parent))
569 parent.Children[invFolder.ID] = invFolder;
570 }
571
572 // Load all of the items for this agent
573 string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly);
574 collection.Items = new Dictionary<UUID, InventoryItem>(files.Length);
575
576 for (int j = 0; j < files.Length; j++)
577 {
578 InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize(
579 new FileStream(files[j], FileMode.Open, FileAccess.Read));
580 collection.Items[invItem.ID] = invItem;
581
582 // Add items to their parent folders
583 InventoryFolder parent;
584 if (collection.Folders.TryGetValue(invItem.Folder, out parent))
585 parent.Children[invItem.ID] = invItem;
586
587 // Add active gestures to our list
588 if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0)
589 activeGestures[owner].Add(invItem);
590 }
591
592 inventories.Add(owner, collection);
593 }
594 }
595 }
596 catch (Exception ex)
597 {
598 Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message);
599 }
600 }
601 }
602}