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