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/Extensions | |
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/Extensions')
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLInventory.cs | 804 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | 602 |
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 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.Data; | ||
34 | using MySql.Data.MySqlClient; | ||
35 | using ExtensionLoader; | ||
36 | using ExtensionLoader.Config; | ||
37 | using OpenMetaverse; | ||
38 | using OpenMetaverse.StructuredData; | ||
39 | |||
40 | namespace 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 | |||
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 | |||
39 | namespace 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 | } | ||