From 74a2bd237aed26b49d88045fe6afa526ed19c00d Mon Sep 17 00:00:00 2001
From: Mike Mazur
Date: Mon, 16 Feb 2009 02:26:27 +0000
Subject: Add OpenSim & Simple inventory storage plugins and Null metrics
plugin.
---
.../AssetInventoryServer/Plugins/NullMetrics.cs | 150 ----
.../Plugins/NullMetricsPlugin.cs | 150 ++++
.../OpenSim/OpenSimInventoryStoragePlugin.cs | 835 +++++++++++++++++++++
.../AssetInventoryServerOpenSimPlugins.addin.xml | 3 +
.../AssetInventoryServerPlugins.addin.xml | 2 +-
.../AssetInventoryServerSimplePlugins.addin.xml | 3 +
.../Plugins/Simple/SimpleInventoryStoragePlugin.cs | 627 ++++++++++++++++
7 files changed, 1619 insertions(+), 151 deletions(-)
delete mode 100644 OpenSim/Grid/AssetInventoryServer/Plugins/NullMetrics.cs
create mode 100644 OpenSim/Grid/AssetInventoryServer/Plugins/NullMetricsPlugin.cs
create mode 100644 OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimInventoryStoragePlugin.cs
create mode 100644 OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs
(limited to 'OpenSim/Grid/AssetInventoryServer/Plugins')
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetrics.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetrics.cs
deleted file mode 100644
index 86ae5cd..0000000
--- a/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetrics.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2008 Intel Corporation
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * -- Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * -- Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * -- Neither the name of the Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using OpenMetaverse;
-
-namespace OpenSim.Grid.AssetInventoryServer.Plugins
-{
- public class NullMetrics : IMetricsProvider
- {
- AssetInventoryServer server;
-
- public NullMetrics()
- {
- }
-
- #region IMetricsProvider implementation
-
- public void LogAssetMetadataFetch(string extension, BackendResponse response, UUID assetID, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] AssetMetadataFetch(): AssetID: {1}, Response: {2}", extension, assetID, response);
- }
-
- public void LogAssetDataFetch(string extension, BackendResponse response, UUID assetID, int dataSize, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] AssetDataFetch(): AssetID: {1}, DataSize: {2}, Response: {3}", extension, assetID,
- dataSize, response);
- }
-
- public void LogAssetCreate(string extension, BackendResponse response, UUID assetID, int dataSize, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] AssetCreate(): AssetID: {1}, DataSize: {2}, Response: {3}", extension, assetID,
- dataSize, response);
- }
-
- public void LogInventoryFetch(string extension, BackendResponse response, Uri owner, UUID objID, bool folder, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryFetch(): ObjID: {1}, Folder: {2}, OwnerID: {3}, Response: {4}", extension,
- objID, folder, owner, response);
- }
-
- public void LogInventoryFetchFolderContents(string extension, BackendResponse response, Uri owner, UUID folderID, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryFetchFolderContents(): FolderID: {1}, OwnerID: {2}, Response: {3}", extension,
- folderID, owner, response);
- }
-
- public void LogInventoryFetchFolderList(string extension, BackendResponse response, Uri owner, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryFetchFolderList(): OwnerID: {1}, Response: {2}", extension,
- owner, response);
- }
-
- public void LogInventoryFetchInventory(string extension, BackendResponse response, Uri owner, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryFetchInventory(): OwnerID: {1}, Response: {2}", extension,
- owner, response);
- }
-
- public void LogInventoryFetchActiveGestures(string extension, BackendResponse response, Uri owner, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryFetchActiveGestures(): OwnerID: {1}, Response: {2}", extension,
- owner, response);
- }
-
- public void LogInventoryCreate(string extension, BackendResponse response, Uri owner, bool folder, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryCreate(): OwnerID: {1}, Response: {2}", extension,
- owner, response);
- }
-
- public void LogInventoryCreateInventory(string extension, BackendResponse response, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryCreateInventory(): Response: {1}", extension,
- response);
- }
-
- public void LogInventoryDelete(string extension, BackendResponse response, Uri owner, UUID objID, bool folder, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryDelete(): OwnerID: {1}, Folder: {2}, Response: {3}", extension,
- owner, folder, response);
- }
-
- public void LogInventoryPurgeFolder(string extension, BackendResponse response, Uri owner, UUID folderID, DateTime time)
- {
- Logger.Log.DebugFormat("[{0}] InventoryPurgeFolder(): OwnerID: {1}, FolderID: {2}, Response: {3}", extension,
- owner, response);
- }
-
- #endregion IMetricsProvider implementation
-
- #region IPlugin implementation
-
- public void Initialise(AssetInventoryServer server)
- {
- this.server = server;
- }
-
- ///
- /// Initialises metrics interface
- ///
- public void Initialise()
- {
- this.server = null;
- }
-
- public void Dispose()
- {
- }
-
- public string Version
- {
- // TODO: this should be something meaningful and not hardcoded?
- get { return "0.1"; }
- }
-
- public string Name
- {
- get { return "AssetInventoryServer Null Metrics"; }
- }
-
- #endregion IPlugin implementation
- }
-}
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetricsPlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetricsPlugin.cs
new file mode 100644
index 0000000..caa4efd
--- /dev/null
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/NullMetricsPlugin.cs
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2008 Intel Corporation
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * -- Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * -- Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * -- Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using OpenMetaverse;
+
+namespace OpenSim.Grid.AssetInventoryServer.Plugins
+{
+ public class NullMetricsPlugin : IMetricsProvider
+ {
+ AssetInventoryServer server;
+
+ public NullMetricsPlugin()
+ {
+ }
+
+ #region IMetricsProvider implementation
+
+ public void LogAssetMetadataFetch(string extension, BackendResponse response, UUID assetID, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] AssetMetadataFetch(): AssetID: {1}, Response: {2}", extension, assetID, response);
+ }
+
+ public void LogAssetDataFetch(string extension, BackendResponse response, UUID assetID, int dataSize, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] AssetDataFetch(): AssetID: {1}, DataSize: {2}, Response: {3}", extension, assetID,
+ dataSize, response);
+ }
+
+ public void LogAssetCreate(string extension, BackendResponse response, UUID assetID, int dataSize, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] AssetCreate(): AssetID: {1}, DataSize: {2}, Response: {3}", extension, assetID,
+ dataSize, response);
+ }
+
+ public void LogInventoryFetch(string extension, BackendResponse response, Uri owner, UUID objID, bool folder, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryFetch(): ObjID: {1}, Folder: {2}, OwnerID: {3}, Response: {4}", extension,
+ objID, folder, owner, response);
+ }
+
+ public void LogInventoryFetchFolderContents(string extension, BackendResponse response, Uri owner, UUID folderID, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryFetchFolderContents(): FolderID: {1}, OwnerID: {2}, Response: {3}", extension,
+ folderID, owner, response);
+ }
+
+ public void LogInventoryFetchFolderList(string extension, BackendResponse response, Uri owner, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryFetchFolderList(): OwnerID: {1}, Response: {2}", extension,
+ owner, response);
+ }
+
+ public void LogInventoryFetchInventory(string extension, BackendResponse response, Uri owner, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryFetchInventory(): OwnerID: {1}, Response: {2}", extension,
+ owner, response);
+ }
+
+ public void LogInventoryFetchActiveGestures(string extension, BackendResponse response, Uri owner, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryFetchActiveGestures(): OwnerID: {1}, Response: {2}", extension,
+ owner, response);
+ }
+
+ public void LogInventoryCreate(string extension, BackendResponse response, Uri owner, bool folder, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryCreate(): OwnerID: {1}, Response: {2}", extension,
+ owner, response);
+ }
+
+ public void LogInventoryCreateInventory(string extension, BackendResponse response, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryCreateInventory(): Response: {1}", extension,
+ response);
+ }
+
+ public void LogInventoryDelete(string extension, BackendResponse response, Uri owner, UUID objID, bool folder, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryDelete(): OwnerID: {1}, Folder: {2}, Response: {3}", extension,
+ owner, folder, response);
+ }
+
+ public void LogInventoryPurgeFolder(string extension, BackendResponse response, Uri owner, UUID folderID, DateTime time)
+ {
+ Logger.Log.DebugFormat("[{0}] InventoryPurgeFolder(): OwnerID: {1}, FolderID: {2}, Response: {3}", extension,
+ owner, response);
+ }
+
+ #endregion IMetricsProvider implementation
+
+ #region IPlugin implementation
+
+ public void Initialise(AssetInventoryServer server)
+ {
+ this.server = server;
+ }
+
+ ///
+ /// Initialises metrics interface
+ ///
+ public void Initialise()
+ {
+ this.server = null;
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public string Version
+ {
+ // TODO: this should be something meaningful and not hardcoded?
+ get { return "0.1"; }
+ }
+
+ public string Name
+ {
+ get { return "AssetInventoryServer Null Metrics"; }
+ }
+
+ #endregion IPlugin implementation
+ }
+}
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimInventoryStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimInventoryStoragePlugin.cs
new file mode 100644
index 0000000..3fd06c0
--- /dev/null
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimInventoryStoragePlugin.cs
@@ -0,0 +1,835 @@
+/*
+ * Copyright (c) 2008 Intel Corporation
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * -- Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * -- Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * -- Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Data;
+using MySql.Data.MySqlClient;
+using ExtensionLoader;
+using ExtensionLoader.Config;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+using OpenSim.Grid.AssetInventoryServer.Extensions;
+using OpenSim.Data;
+
+namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim
+{
+ public class OpenSimInventoryStoragePlugin : IInventoryStorageProvider
+ {
+ const string EXTENSION_NAME = "OpenSimInventoryStorage"; // Used in metrics reporting
+
+ private AssetInventoryServer server;
+ private IInventoryDataPlugin m_inventoryProvider;
+
+ public OpenSimInventoryStoragePlugin()
+ {
+ }
+
+ #region Required Interfaces
+
+ public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item)
+ {
+ item = null;
+ BackendResponse ret;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ IDbCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
+ "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
+ "creationDate,groupID,groupOwned,flags,avatarID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE inventoryID='{0}'",
+ itemID.ToString());
+ reader = command.ExecuteReader();
+
+ if (reader.Read())
+ {
+ item = new InventoryItem();
+ item.ID = itemID;
+ item.AssetID = UUID.Parse(reader.GetString(0));
+ item.AssetType = reader.GetInt32(1);
+ item.Name = reader.GetString(2);
+ item.Description = reader.GetString(3);
+ item.NextPermissions = (uint)reader.GetInt32(4);
+ item.CurrentPermissions = (uint)reader.GetInt32(5);
+ item.InvType = reader.GetInt32(6);
+ item.Creator = UUID.Parse(reader.GetString(7));
+ item.BasePermissions = (uint)reader.GetInt32(8);
+ item.EveryOnePermissions = (uint)reader.GetInt32(9);
+ item.SalePrice = reader.GetInt32(10);
+ item.SaleType = reader.GetByte(11);
+ item.CreationDate = reader.GetInt32(12);
+ item.GroupID = UUID.Parse(reader.GetString(13));
+ item.GroupOwned = reader.GetBoolean(14);
+ item.Flags = (uint)reader.GetInt32(15);
+ item.Owner = UUID.Parse(reader.GetString(16));
+ item.Folder = UUID.Parse(reader.GetString(17));
+ item.GroupPermissions = (uint)reader.GetInt32(18);
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder)
+ {
+ folder = null;
+ BackendResponse ret;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ IDbCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT folderName,type,version,agentID,parentFolderID FROM inventoryfolders WHERE folderID='{0}'",
+ folderID.ToString());
+ reader = command.ExecuteReader();
+
+ if (reader.Read())
+ {
+ folder = new InventoryFolder();
+ folder.Children = null; // This call only returns data for the folder itself, no children data
+ folder.ID = folderID;
+ folder.Name = reader.GetString(0);
+ folder.Type = reader.GetInt16(1);
+ folder.Version = (ushort)reader.GetInt16(2);
+ folder.Owner = UUID.Parse(reader.GetString(3));
+ folder.ParentID = UUID.Parse(reader.GetString(4));
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents)
+ {
+ contents = null;
+ BackendResponse ret;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ contents = new InventoryCollection();
+
+ #region Folder retrieval
+
+ IDbCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT folderName,type,version,agentID,folderID FROM inventoryfolders WHERE parentFolderID='{0}'",
+ folderID.ToString());
+ reader = command.ExecuteReader();
+
+ contents.Folders = new Dictionary();
+
+ while (reader.Read())
+ {
+ InventoryFolder folder = new InventoryFolder();
+ folder.ParentID = folderID;
+ folder.Children = null; // This call doesn't do recursion
+ folder.Name = reader.GetString(0);
+ folder.Type = reader.GetInt16(1);
+ folder.Version = (ushort)reader.GetInt16(2);
+ folder.Owner = UUID.Parse(reader.GetString(3));
+ folder.ID = UUID.Parse(reader.GetString(4));
+
+ contents.Folders.Add(folder.ID, folder);
+ contents.UserID = folder.Owner;
+ }
+
+ reader.Close();
+
+ #endregion Folder retrieval
+
+ #region Item retrieval
+
+ command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
+ "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
+ "creationDate,groupID,groupOwned,flags,avatarID,inventoryID,inventoryGroupPermissions FROM inventoryitems WHERE parentFolderID='{0}'",
+ folderID.ToString());
+ reader = command.ExecuteReader();
+
+ contents.Items = new Dictionary();
+
+ while (reader.Read())
+ {
+ InventoryItem item = new InventoryItem();
+ item.Folder = folderID;
+ item.AssetID = UUID.Parse(reader.GetString(0));
+ item.AssetType = reader.GetInt32(1);
+ item.Name = reader.GetString(2);
+ item.Description = reader.GetString(3);
+ item.NextPermissions = (uint)reader.GetInt32(4);
+ item.CurrentPermissions = (uint)reader.GetInt32(5);
+ item.InvType = reader.GetInt32(6);
+ item.Creator = UUID.Parse(reader.GetString(7));
+ item.BasePermissions = (uint)reader.GetInt32(8);
+ item.EveryOnePermissions = (uint)reader.GetInt32(9);
+ item.SalePrice = reader.GetInt32(10);
+ item.SaleType = reader.GetByte(11);
+ item.CreationDate = reader.GetInt32(12);
+ item.GroupID = UUID.Parse(reader.GetString(13));
+ item.GroupOwned = reader.GetBoolean(14);
+ item.Flags = (uint)reader.GetInt32(15);
+ item.Owner = UUID.Parse(reader.GetString(16));
+ item.ID = UUID.Parse(reader.GetString(17));
+ item.GroupPermissions = (uint)reader.GetInt32(18);
+
+ contents.Items.Add(item.ID, item);
+ contents.UserID = item.Owner;
+ }
+
+ #endregion Item retrieval
+
+ ret = BackendResponse.Success;
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolderList(Uri owner, out List folders)
+ {
+ folders = null;
+ BackendResponse ret;
+ UUID ownerID;
+
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+ folders = new List();
+
+ IDbCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT folderName,type,version,folderID,parentFolderID FROM inventoryfolders WHERE agentID='{0}'",
+ ownerID.ToString());
+ reader = command.ExecuteReader();
+
+ while (reader.Read())
+ {
+ InventoryFolder folder = new InventoryFolder();
+ folder.Owner = ownerID;
+ folder.Children = null; // This call does not create a folder hierarchy
+ folder.Name = reader.GetString(0);
+ folder.Type = reader.GetInt16(1);
+ folder.Version = (ushort)reader.GetInt16(2);
+ folder.ID = UUID.Parse(reader.GetString(3));
+ folder.ParentID = UUID.Parse(reader.GetString(4));
+
+ folders.Add(folder);
+ }
+
+ ret = BackendResponse.Success;
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory)
+ {
+ inventory = null;
+ BackendResponse ret;
+ List folders;
+ UUID ownerID;
+
+ ret = TryFetchFolderList(owner, out folders);
+
+ if (ret == BackendResponse.Success)
+ {
+ // Add the retrieved folders to the inventory collection
+ inventory = new InventoryCollection();
+ inventory.Folders = new Dictionary(folders.Count);
+ foreach (InventoryFolder folder in folders)
+ inventory.Folders[folder.ID] = folder;
+
+ // Fetch inventory items
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ IDbCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
+ "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
+ "creationDate,groupID,groupOwned,flags,inventoryID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE " +
+ "avatarID='{0}'", ownerID.ToString());
+ reader = command.ExecuteReader();
+
+ inventory.UserID = ownerID;
+ inventory.Items = new Dictionary();
+
+ while (reader.Read())
+ {
+ InventoryItem item = new InventoryItem();
+ item.Owner = ownerID;
+ item.AssetID = UUID.Parse(reader.GetString(0));
+ item.AssetType = reader.GetInt32(1);
+ item.Name = reader.GetString(2);
+ item.Description = reader.GetString(3);
+ item.NextPermissions = (uint)reader.GetInt32(4);
+ item.CurrentPermissions = (uint)reader.GetInt32(5);
+ item.InvType = reader.GetInt32(6);
+ item.Creator = UUID.Parse(reader.GetString(7));
+ item.BasePermissions = (uint)reader.GetInt32(8);
+ item.EveryOnePermissions = (uint)reader.GetInt32(9);
+ item.SalePrice = reader.GetInt32(10);
+ item.SaleType = reader.GetByte(11);
+ item.CreationDate = reader.GetInt32(12);
+ item.GroupID = UUID.Parse(reader.GetString(13));
+ item.GroupOwned = reader.GetBoolean(14);
+ item.Flags = (uint)reader.GetInt32(15);
+ item.ID = UUID.Parse(reader.GetString(16));
+ item.Folder = UUID.Parse(reader.GetString(17));
+ item.GroupPermissions = (uint)reader.GetInt32(18);
+
+ inventory.Items.Add(item.ID, item);
+ }
+
+ ret = BackendResponse.Success;
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchActiveGestures(Uri owner, out List gestures)
+ {
+ gestures = null;
+ BackendResponse ret;
+ UUID ownerID;
+
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ IDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = new MySqlCommand("SELECT assetID,inventoryName,inventoryDescription,inventoryNextPermissions," +
+ "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
+ "creationDate,groupID,groupOwned,inventoryID,parentFolderID,inventoryGroupPermissions FROM inventoryitems WHERE " +
+ "avatarId=?uuid AND assetType=?type AND flags=1", dbConnection);
+ command.Parameters.AddWithValue("?uuid", ownerID.ToString());
+ command.Parameters.AddWithValue("?type", (int)AssetType.Gesture);
+ reader = command.ExecuteReader();
+
+ while (reader.Read())
+ {
+ InventoryItem item = new InventoryItem();
+ item.Owner = ownerID;
+ item.AssetType = (int)AssetType.Gesture;
+ item.Flags = (uint)1;
+ item.AssetID = UUID.Parse(reader.GetString(0));
+ item.Name = reader.GetString(1);
+ item.Description = reader.GetString(2);
+ item.NextPermissions = (uint)reader.GetInt32(3);
+ item.CurrentPermissions = (uint)reader.GetInt32(4);
+ item.InvType = reader.GetInt32(5);
+ item.Creator = UUID.Parse(reader.GetString(6));
+ item.BasePermissions = (uint)reader.GetInt32(7);
+ item.EveryOnePermissions = (uint)reader.GetInt32(8);
+ item.SalePrice = reader.GetInt32(9);
+ item.SaleType = reader.GetByte(10);
+ item.CreationDate = reader.GetInt32(11);
+ item.GroupID = UUID.Parse(reader.GetString(12));
+ item.GroupOwned = reader.GetBoolean(13);
+ item.ID = UUID.Parse(reader.GetString(14));
+ item.Folder = UUID.Parse(reader.GetString(15));
+ item.GroupPermissions = (uint)reader.GetInt32(16);
+
+ gestures.Add(item);
+ }
+
+ ret = BackendResponse.Success;
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateItem(Uri owner, InventoryItem item)
+ {
+ BackendResponse ret;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = new MySqlCommand(
+ "REPLACE INTO inventoryitems (assetID,assetType,inventoryName,inventoryDescription,inventoryNextPermissions," +
+ "inventoryCurrentPermissions,invType,creatorID,inventoryBasePermissions,inventoryEveryOnePermissions,salePrice,saleType," +
+ "creationDate,groupID,groupOwned,flags,inventoryID,avatarID,parentFolderID,inventoryGroupPermissions) VALUES " +
+
+ "(?assetID,?assetType,?inventoryName,?inventoryDescription,?inventoryNextPermissions,?inventoryCurrentPermissions,?invType," +
+ "?creatorID,?inventoryBasePermissions,?inventoryEveryOnePermissions,?salePrice,?saleType,?creationDate,?groupID,?groupOwned," +
+ "?flags,?inventoryID,?avatarID,?parentFolderID,?inventoryGroupPermissions)", dbConnection);
+
+ command.Parameters.AddWithValue("?assetID", item.AssetID.ToString());
+ command.Parameters.AddWithValue("?assetType", item.AssetType);
+ command.Parameters.AddWithValue("?inventoryName", item.Name);
+ command.Parameters.AddWithValue("?inventoryDescription", item.Description);
+ command.Parameters.AddWithValue("?inventoryNextPermissions", item.NextPermissions);
+ command.Parameters.AddWithValue("?inventoryCurrentPermissions", item.CurrentPermissions);
+ command.Parameters.AddWithValue("?invType", item.InvType);
+ command.Parameters.AddWithValue("?creatorID", item.Creator.ToString());
+ command.Parameters.AddWithValue("?inventoryBasePermissions", item.BasePermissions);
+ command.Parameters.AddWithValue("?inventoryEveryOnePermissions", item.EveryOnePermissions);
+ command.Parameters.AddWithValue("?salePrice", item.SalePrice);
+ command.Parameters.AddWithValue("?saleType", item.SaleType);
+ command.Parameters.AddWithValue("?creationDate", item.CreationDate);
+ command.Parameters.AddWithValue("?groupID", item.GroupID.ToString());
+ command.Parameters.AddWithValue("?groupOwned", item.GroupOwned);
+ command.Parameters.AddWithValue("?flags", item.Flags);
+ command.Parameters.AddWithValue("?inventoryID", item.ID);
+ command.Parameters.AddWithValue("?avatarID", item.Owner);
+ command.Parameters.AddWithValue("?parentFolderID", item.Folder);
+ command.Parameters.AddWithValue("?inventoryGroupPermissions", item.GroupPermissions);
+
+ int rowsAffected = command.ExecuteNonQuery();
+ if (rowsAffected == 1)
+ {
+ ret = BackendResponse.Success;
+ }
+ else if (rowsAffected == 2)
+ {
+ Logger.Log.Info("Replaced inventory item " + item.ID.ToString());
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
+ ret = BackendResponse.Failure;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder)
+ {
+ BackendResponse ret;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = new MySqlCommand(
+ "REPLACE INTO inventoryfolders (folderName,type,version,folderID,agentID,parentFolderID) VALUES " +
+ "(?folderName,?type,?version,?folderID,?agentID,?parentFolderID)", dbConnection);
+
+ command.Parameters.AddWithValue("?folderName", folder.Name);
+ command.Parameters.AddWithValue("?type", folder.Type);
+ command.Parameters.AddWithValue("?version", folder.Version);
+ command.Parameters.AddWithValue("?folderID", folder.ID);
+ command.Parameters.AddWithValue("?agentID", folder.Owner);
+ command.Parameters.AddWithValue("?parentFolderID", folder.ParentID);
+
+ int rowsAffected = command.ExecuteNonQuery();
+ if (rowsAffected == 1)
+ {
+ ret = BackendResponse.Success;
+ }
+ else if (rowsAffected == 2)
+ {
+ Logger.Log.Info("Replaced inventory folder " + folder.ID.ToString());
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
+ ret = BackendResponse.Failure;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder)
+ {
+ return TryCreateFolder(owner, rootFolder);
+ }
+
+ public BackendResponse TryDeleteItem(Uri owner, UUID itemID)
+ {
+ BackendResponse ret;
+ UUID ownerID;
+
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = new MySqlCommand(
+ "DELETE FROM inventoryitems WHERE inventoryID=?inventoryID AND avatarID=?avatarID", dbConnection);
+
+ command.Parameters.AddWithValue("?inventoryID", itemID.ToString());
+ command.Parameters.AddWithValue("?avatarID", ownerID.ToString());
+
+ int rowsAffected = command.ExecuteNonQuery();
+ if (rowsAffected == 1)
+ {
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ Logger.Log.ErrorFormat("MySQL DELETE query affected {0} rows", rowsAffected);
+ ret = BackendResponse.NotFound;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryDeleteFolder(Uri owner, UUID folderID)
+ {
+ BackendResponse ret;
+ UUID ownerID;
+
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = new MySqlCommand(
+ "DELETE FROM inventoryfolders WHERE folderID=?folderID AND agentID=?agentID", dbConnection);
+
+ command.Parameters.AddWithValue("?folderID", folderID.ToString());
+ command.Parameters.AddWithValue("?agentID", ownerID.ToString());
+
+ int rowsAffected = command.ExecuteNonQuery();
+ if (rowsAffected == 1)
+ {
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ Logger.Log.ErrorFormat("MySQL DELETE query affected {0} rows", rowsAffected);
+ ret = BackendResponse.NotFound;
+ }
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryPurgeFolder(Uri owner, UUID folderID)
+ {
+ BackendResponse ret;
+ UUID ownerID;
+
+ if (Utils.TryGetOpenSimUUID(owner, out ownerID))
+ {
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ try
+ {
+ dbConnection.Open();
+
+ #region Delete items
+
+ MySqlCommand command = new MySqlCommand(
+ "DELETE FROM inventoryitems WHERE parentFolderID=?parentFolderID AND avatarID=?avatarID", dbConnection);
+
+ command.Parameters.AddWithValue("?parentFolderID", folderID.ToString());
+ command.Parameters.AddWithValue("?avatarID", ownerID.ToString());
+
+ int rowsAffected = command.ExecuteNonQuery();
+
+ #endregion Delete items
+
+ #region Delete folders
+
+ command = new MySqlCommand(
+ "DELETE FROM inventoryfolders WHERE parentFolderID=?parentFolderID AND agentID=?agentID", dbConnection);
+
+ command.Parameters.AddWithValue("?parentFolderID", folderID.ToString());
+ command.Parameters.AddWithValue("?agentID", ownerID.ToString());
+
+ rowsAffected += command.ExecuteNonQuery();
+
+ #endregion Delete folders
+
+ Logger.Log.DebugFormat("Deleted {0} inventory objects from MySQL in a folder purge", rowsAffected);
+
+ ret = BackendResponse.Success;
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
+ return ret;
+ }
+
+ public int ForEach(Action action, int start, int count)
+ {
+ int rowCount = 0;
+
+ using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
+ {
+ MySqlDataReader reader;
+
+ try
+ {
+ dbConnection.Open();
+
+ MySqlCommand command = dbConnection.CreateCommand();
+ command.CommandText = String.Format("SELECT name,description,assetType,temporary,data,id FROM assets LIMIT {0}, {1}",
+ start, count);
+ reader = command.ExecuteReader();
+ }
+ catch (MySqlException ex)
+ {
+ Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
+ return 0;
+ }
+
+ while (reader.Read())
+ {
+ Metadata metadata = new Metadata();
+ metadata.CreationDate = OpenMetaverse.Utils.Epoch;
+ metadata.Description = reader.GetString(1);
+ metadata.ID = UUID.Parse(reader.GetString(5));
+ metadata.Name = reader.GetString(0);
+ metadata.SHA1 = OpenMetaverse.Utils.SHA1((byte[])reader.GetValue(4));
+ metadata.Temporary = reader.GetBoolean(3);
+ metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
+
+ action(metadata);
+ ++rowCount;
+ }
+
+ reader.Close();
+ }
+
+ return rowCount;
+ }
+
+ #endregion Required Interfaces
+
+ #region IPlugin implementation
+
+ public void Initialise(AssetInventoryServer server)
+ {
+ this.server = server;
+
+ try
+ {
+ m_inventoryProvider = DataPluginFactory.LoadInventoryDataPlugin("OpenSim.Data.MySQL.dll", server.ConfigFile.Configs["MySQL"].GetString("database_connect", null));
+ if (m_inventoryProvider == null)
+ {
+ Logger.Log.Error("[INVENTORY]: Failed to load a database plugin, server halting.");
+ Environment.Exit(-1);
+ }
+ else
+ Logger.Log.InfoFormat("[INVENTORY]: Loaded storage backend: {0}", Version);
+ }
+ catch (Exception e)
+ {
+ Logger.Log.WarnFormat("[INVENTORY]: Failure loading data plugin: {0}", e.ToString());
+ }
+ }
+
+ public void Stop()
+ {
+ }
+
+ public void Initialise()
+ {
+ Logger.Log.InfoFormat("[INVENTORY]: {0} cannot be default-initialized!", Name);
+ throw new PluginNotInitialisedException(Name);
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public string Version
+ {
+ get { return m_inventoryProvider.Version; }
+ }
+
+ public string Name
+ {
+ get { return "AssetInventoryServer OpenSim inventory storage provider"; }
+ }
+
+ #endregion IPlugin implementation
+ }
+}
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml
index f458909..6d21327 100644
--- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml
@@ -15,6 +15,9 @@
+
+
+
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Resources/AssetInventoryServerPlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/Resources/AssetInventoryServerPlugins.addin.xml
index bca7ee1..089c6a2 100644
--- a/OpenSim/Grid/AssetInventoryServer/Plugins/Resources/AssetInventoryServerPlugins.addin.xml
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Resources/AssetInventoryServerPlugins.addin.xml
@@ -8,6 +8,6 @@
-
+
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml
index 53534c4..f898145 100644
--- a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml
@@ -10,4 +10,7 @@
+
+
+
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs
new file mode 100644
index 0000000..78dae35
--- /dev/null
+++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleInventoryStoragePlugin.cs
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2008 Intel Corporation
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * -- Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * -- Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * -- Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.IO;
+using System.Text;
+using ExtensionLoader;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+
+namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple
+{
+ public class SimpleInventoryStoragePlugin : IInventoryStorageProvider
+ {
+ const string EXTENSION_NAME = "SimpleInventoryStorage"; // Used for metrics reporting
+ const string DEFAULT_INVENTORY_DIR = "SimpleInventory";
+
+ AssetInventoryServer server;
+ Dictionary inventories = new Dictionary();
+ Dictionary> activeGestures = new Dictionary>();
+ Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer();
+ Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer();
+
+ public SimpleInventoryStoragePlugin()
+ {
+ }
+
+ #region Required Interfaces
+
+ public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item)
+ {
+ item = null;
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item))
+ ret = BackendResponse.Success;
+ else
+ ret = BackendResponse.NotFound;
+
+ server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder)
+ {
+ folder = null;
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
+ ret = BackendResponse.Success;
+ else
+ ret = BackendResponse.NotFound;
+
+ server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents)
+ {
+ contents = null;
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ InventoryFolder folder;
+
+ if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
+ {
+ contents = new InventoryCollection();
+ contents.UserID = collection.UserID;
+ contents.Folders = new Dictionary();
+ contents.Items = new Dictionary();
+
+ foreach (InventoryBase invBase in folder.Children.Values)
+ {
+ if (invBase is InventoryItem)
+ {
+ InventoryItem invItem = invBase as InventoryItem;
+ contents.Items.Add(invItem.ID, invItem);
+ }
+ else
+ {
+ InventoryFolder invFolder = invBase as InventoryFolder;
+ contents.Folders.Add(invFolder.ID, invFolder);
+ }
+ }
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchFolderList(Uri owner, out List folders)
+ {
+ folders = null;
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ if (inventories.TryGetValue(owner, out collection))
+ {
+ folders = new List(collection.Folders.Values);
+ return BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory)
+ {
+ inventory = null;
+ BackendResponse ret;
+
+ if (inventories.TryGetValue(owner, out inventory))
+ ret = BackendResponse.Success;
+ else
+ ret = BackendResponse.NotFound;
+
+ server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryFetchActiveGestures(Uri owner, out List gestures)
+ {
+ gestures = null;
+ BackendResponse ret;
+
+ if (activeGestures.TryGetValue(owner, out gestures))
+ ret = BackendResponse.Success;
+ else
+ ret = BackendResponse.NotFound;
+
+ server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateItem(Uri owner, InventoryItem item)
+ {
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ if (inventories.TryGetValue(owner, out collection))
+ {
+ // Delete this item first if it already exists
+ InventoryItem oldItem;
+ if (collection.Items.TryGetValue(item.ID, out oldItem))
+ TryDeleteItem(owner, item.ID);
+
+ try
+ {
+ // Create the file
+ SaveItem(item);
+
+ // Add the item to the collection
+ lock (collection) collection.Items[item.ID] = item;
+
+ // Add the item to its parent folder
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(item.Folder, out parent))
+ lock (parent.Children) parent.Children.Add(item.ID, item);
+
+ // Add active gestures to our list
+ if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1)
+ {
+ lock (activeGestures)
+ activeGestures[owner].Add(item);
+ }
+
+ ret = BackendResponse.Success;
+ }
+ catch (Exception ex)
+ {
+ Logger.Log.Error(ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ else
+ {
+ return BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder)
+ {
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ if (inventories.TryGetValue(owner, out collection))
+ {
+ // Delete this folder first if it already exists
+ InventoryFolder oldFolder;
+ if (collection.Folders.TryGetValue(folder.ID, out oldFolder))
+ TryDeleteFolder(owner, folder.ID);
+
+ try
+ {
+ // Create the file
+ SaveFolder(folder);
+
+ // Add the folder to the collection
+ lock (collection) collection.Folders[folder.ID] = folder;
+
+ // Add the folder to its parent folder
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(folder.ParentID, out parent))
+ lock (parent.Children) parent.Children.Add(folder.ID, folder);
+
+ ret = BackendResponse.Success;
+ }
+ catch (Exception ex)
+ {
+ Logger.Log.Error(ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder)
+ {
+ BackendResponse ret;
+
+ lock (inventories)
+ {
+ if (!inventories.ContainsKey(owner))
+ {
+ InventoryCollection collection = new InventoryCollection();
+ collection.UserID = rootFolder.Owner;
+ collection.Folders = new Dictionary();
+ collection.Folders.Add(rootFolder.ID, rootFolder);
+ collection.Items = new Dictionary();
+
+ inventories.Add(owner, collection);
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ if (ret == BackendResponse.Success)
+ {
+ string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString());
+ try
+ {
+ // Create the directory for this agent
+ Directory.CreateDirectory(path);
+
+ // Create an index.txt containing the UUID and URI for this agent
+ string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() };
+ File.WriteAllLines(Path.Combine(path, "index.txt"), index);
+
+ // Create the root folder file
+ SaveFolder(rootFolder);
+ }
+ catch (Exception ex)
+ {
+ Logger.Log.Error(ex.Message);
+ ret = BackendResponse.Failure;
+ }
+ }
+
+ server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryDeleteItem(Uri owner, UUID itemID)
+ {
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ InventoryItem item;
+ if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item))
+ {
+ // Remove the item from its parent folder
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(item.Folder, out parent))
+ lock (parent.Children) parent.Children.Remove(itemID);
+
+ // Remove the item from the collection
+ lock (collection) collection.Items.Remove(itemID);
+
+ // Remove from the active gestures list if applicable
+ if (item.InvType == (int)InventoryType.Gesture)
+ {
+ lock (activeGestures)
+ {
+ for (int i = 0; i < activeGestures[owner].Count; i++)
+ {
+ if (activeGestures[owner][i].ID == itemID)
+ {
+ activeGestures[owner].RemoveAt(i);
+ break;
+ }
+ }
+ }
+ }
+
+ // Delete the file. We don't know exactly what the file name is,
+ // so search for it
+ string path = PathFromURI(owner);
+ string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly);
+ foreach (string match in matches)
+ {
+ try { File.Delete(match); }
+ catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); }
+ }
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryDeleteFolder(Uri owner, UUID folderID)
+ {
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ InventoryFolder folder;
+ if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
+ {
+ // Remove the folder from its parent folder
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(folder.ParentID, out parent))
+ lock (parent.Children) parent.Children.Remove(folderID);
+
+ // Remove the folder from the collection
+ lock (collection) collection.Items.Remove(folderID);
+
+ // Delete the folder file. We don't know exactly what the file name is,
+ // so search for it
+ string path = PathFromURI(owner);
+ string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly);
+ foreach (string match in matches)
+ {
+ try { File.Delete(match); }
+ catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); }
+ }
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now);
+ return ret;
+ }
+
+ public BackendResponse TryPurgeFolder(Uri owner, UUID folderID)
+ {
+ BackendResponse ret;
+
+ InventoryCollection collection;
+ InventoryFolder folder;
+ if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder))
+ {
+ // Delete all of the folder children
+ foreach (InventoryBase obj in new List(folder.Children.Values))
+ {
+ if (obj is InventoryItem)
+ {
+ TryDeleteItem(owner, (obj as InventoryItem).ID);
+ }
+ else
+ {
+ InventoryFolder childFolder = obj as InventoryFolder;
+ TryPurgeFolder(owner, childFolder.ID);
+ TryDeleteFolder(owner, childFolder.ID);
+ }
+ }
+
+ ret = BackendResponse.Success;
+ }
+ else
+ {
+ ret = BackendResponse.NotFound;
+ }
+
+ server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now);
+ return ret;
+ }
+
+ #endregion Required Interfaces
+
+ void SaveItem(InventoryItem item)
+ {
+ string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID);
+
+ string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString());
+ path = Path.Combine(path, filename);
+
+ using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
+ {
+ itemSerializer.Serialize(stream, item);
+ stream.Flush();
+ }
+ }
+
+ void SaveFolder(InventoryFolder folder)
+ {
+ string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID);
+
+ string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString());
+ path = Path.Combine(path, filename);
+
+ using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
+ {
+ folderSerializer.Serialize(stream, folder);
+ stream.Flush();
+ }
+ }
+
+ string SanitizeFilename(string filename)
+ {
+ string output = filename;
+
+ if (output.Length > 64)
+ output = output.Substring(0, 64);
+
+ foreach (char i in Path.GetInvalidFileNameChars())
+ output = output.Replace(i, '_');
+
+ return output;
+ }
+
+ static string PathFromURI(Uri uri)
+ {
+ byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString()));
+ StringBuilder digest = new StringBuilder(40);
+
+ // Convert the hash to a hex string
+ foreach (byte b in hash)
+ digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b);
+
+ return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString());
+ }
+
+ void LoadFiles(string folder)
+ {
+ // Try to create the directory if it doesn't already exist
+ if (!Directory.Exists(folder))
+ {
+ try { Directory.CreateDirectory(folder); }
+ catch (Exception ex)
+ {
+ Logger.Log.Warn(ex.Message);
+ return;
+ }
+ }
+
+ try
+ {
+ string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR);
+
+ for (int i = 0; i < agentFolders.Length; i++)
+ {
+ string foldername = agentFolders[i];
+ string indexPath = Path.Combine(foldername, "index.txt");
+ UUID ownerID = UUID.Zero;
+ Uri owner = null;
+
+ try
+ {
+ string[] index = File.ReadAllLines(indexPath);
+ ownerID = UUID.Parse(index[0]);
+ owner = new Uri(index[1]);
+ }
+ catch (Exception ex)
+ {
+ Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message);
+ }
+
+ if (ownerID != UUID.Zero && owner != null)
+ {
+ // Initialize the active gestures list for this agent
+ activeGestures.Add(owner, new List());
+
+ InventoryCollection collection = new InventoryCollection();
+ collection.UserID = ownerID;
+
+ // Load all of the folders for this agent
+ string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly);
+ collection.Folders = new Dictionary(folders.Length);
+
+ for (int j = 0; j < folders.Length; j++)
+ {
+ InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize(
+ new FileStream(folders[j], FileMode.Open, FileAccess.Read));
+ collection.Folders[invFolder.ID] = invFolder;
+ }
+
+ // Iterate over the folders collection, adding children to their parents
+ foreach (InventoryFolder invFolder in collection.Folders.Values)
+ {
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(invFolder.ParentID, out parent))
+ parent.Children[invFolder.ID] = invFolder;
+ }
+
+ // Load all of the items for this agent
+ string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly);
+ collection.Items = new Dictionary(files.Length);
+
+ for (int j = 0; j < files.Length; j++)
+ {
+ InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize(
+ new FileStream(files[j], FileMode.Open, FileAccess.Read));
+ collection.Items[invItem.ID] = invItem;
+
+ // Add items to their parent folders
+ InventoryFolder parent;
+ if (collection.Folders.TryGetValue(invItem.Folder, out parent))
+ parent.Children[invItem.ID] = invItem;
+
+ // Add active gestures to our list
+ if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0)
+ activeGestures[owner].Add(invItem);
+ }
+
+ inventories.Add(owner, collection);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message);
+ }
+ }
+
+ #region IPlugin implementation
+
+ public void Initialise(AssetInventoryServer server)
+ {
+ this.server = server;
+
+ LoadFiles(DEFAULT_INVENTORY_DIR);
+
+ Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars",
+ inventories.Count);
+ }
+
+ ///
+ /// Initialises asset interface
+ ///
+ public void Initialise()
+ {
+ Logger.Log.InfoFormat("[ASSET]: {0} cannot be default-initialized!", Name);
+ throw new PluginNotInitialisedException(Name);
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public string Version
+ {
+ // TODO: this should be something meaningful and not hardcoded?
+ get { return "0.1"; }
+ }
+
+ public string Name
+ {
+ get { return "AssetInventoryServer Simple inventory storage provider"; }
+ }
+
+ #endregion IPlugin implementation
+ }
+}
--
cgit v1.1