From 6a8d8f54e88a21e6cfd78dc7981cdeec2f18094d Mon Sep 17 00:00:00 2001 From: Tleiades Hax Date: Tue, 30 Oct 2007 22:42:34 +0000 Subject: [PATCH] Step one on the long march towards grid based inventory. Introduction of an InevntoryServer --- OpenSim/Framework/General/InventoryConfig.cs | 67 +++++++ .../Framework/General/InventoryItemBase.cs | 30 ++- .../Framework/General/NetworkServersInfo.cs | 6 +- .../Grid/InventoryServer/InventoryManager.cs | 174 +++++++++++++----- OpenSim/Grid/InventoryServer/Main.cs | 55 ++++-- OpenSim/Region/Application/OpenSimMain.cs | 3 +- .../ClientStack/ClientView.ProcessPackets.cs | 2 +- .../Communications/OGS1/CommunicationsOGS1.cs | 4 +- .../OGS1/OGS1InventoryService.cs | 24 ++- .../Region/Environment/Modules/ChatModule.cs | 2 +- .../Environment/Modules/WorldCommModule.cs | 2 +- .../Environment/Scenes/ScenePresence.cs | 2 +- bin/Inventory_Default.xml | 62 +++++++ bin/Inventory_Library.xml | 144 +++++++++++++++ prebuild.xml | 29 +++ 15 files changed, 533 insertions(+), 73 deletions(-) create mode 100644 OpenSim/Framework/General/InventoryConfig.cs create mode 100644 bin/Inventory_Default.xml create mode 100644 bin/Inventory_Library.xml diff --git a/OpenSim/Framework/General/InventoryConfig.cs b/OpenSim/Framework/General/InventoryConfig.cs new file mode 100644 index 0000000000..9ba3e07ee0 --- /dev/null +++ b/OpenSim/Framework/General/InventoryConfig.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Framework +{ + /// + /// UserConfig -- For User Server Configuration + /// + public class InventoryConfig + { + public string DefaultStartupMsg = ""; + public string UserServerURL = ""; + public string UserSendKey = ""; + public string UserRecvKey = ""; + + public string DatabaseProvider = ""; + public static uint DefaultHttpPort = 8004; + + public int HttpPort = 8004; + + private ConfigurationMember configMember; + + public InventoryConfig(string description, string filename) + { + configMember = new ConfigurationMember(filename, description, this.loadConfigurationOptions, this.handleIncomingConfiguration); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("default_startup_message", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Default Startup Message", "Welcome to OGS", false); + configMember.addConfigurationOption("default_user_server", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Default User Server URI", "http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString(), false); + configMember.addConfigurationOption("user_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, "Key to send to user server", "null", false); + configMember.addConfigurationOption("user_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, "Key to expect from user server", "null", false); + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, "DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false); + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Http Listener port", DefaultHttpPort.ToString(), false); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "default_startup_message": + this.DefaultStartupMsg = (string)configuration_result; + break; + case "default_user_server": + this.UserServerURL = (string)configuration_result; + break; + case "user_send_key": + this.UserSendKey = (string)configuration_result; + break; + case "user_recv_key": + this.UserRecvKey = (string)configuration_result; + break; + case "database_provider": + this.DatabaseProvider = (string)configuration_result; + break; + case "http_port": + HttpPort = (int)configuration_result; + break; + } + + return true; + } + } +} diff --git a/OpenSim/Framework/General/InventoryItemBase.cs b/OpenSim/Framework/General/InventoryItemBase.cs index 45700ae644..f782913746 100644 --- a/OpenSim/Framework/General/InventoryItemBase.cs +++ b/OpenSim/Framework/General/InventoryItemBase.cs @@ -25,6 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +using System; +using System.Xml.Serialization; +using System.Collections; using System.Collections.Generic; using libsecondlife; @@ -242,4 +245,29 @@ namespace OpenSim.Framework /// The id of the folder void deleteInventoryFolder(LLUUID folder); } -} \ No newline at end of file + + /* + * .Net has some issues, serializing a dictionary, so we cannot reuse the InventoryFolder + * class defined in Communications.Framework.Communications.Caches. So we serialize/deserialize + * into this simpler class, and then use that. + */ + [XmlRoot(ElementName = "inventory", IsNullable = true)] + public class SerializableInventory + { + [XmlRoot(ElementName = "folder", IsNullable = true)] + public class SerializableFolder : InventoryFolderBase + { + [XmlArray(ElementName = "folders", IsNullable = true)] + [XmlArrayItem(ElementName = "folder", IsNullable = true, Type = typeof(SerializableFolder))] + public ArrayList SubFolders; + + [XmlArray(ElementName = "items", IsNullable = true)] + [XmlArrayItem(ElementName = "item", IsNullable = true, Type = typeof(InventoryItemBase))] + public ArrayList Items; + } + + [XmlElement(ElementName = "folder", IsNullable = true)] + public SerializableFolder root; + } + +} diff --git a/OpenSim/Framework/General/NetworkServersInfo.cs b/OpenSim/Framework/General/NetworkServersInfo.cs index 98d489ec6e..aa8aa2b900 100644 --- a/OpenSim/Framework/General/NetworkServersInfo.cs +++ b/OpenSim/Framework/General/NetworkServersInfo.cs @@ -43,6 +43,8 @@ namespace OpenSim.Framework public string UserRecvKey = ""; public bool isSandbox; + public string InventoryURL = ""; + public static int DefaultHttpListenerPort = 9000; public int HttpListenerPort = DefaultHttpListenerPort; @@ -91,6 +93,8 @@ namespace OpenSim.Framework UserSendKey = config.Configs["Network"].GetString("user_send_key", "null"); UserRecvKey = config.Configs["Network"].GetString("user_recv_key", "null"); AssetURL = config.Configs["Network"].GetString("asset_server_url", AssetURL); + InventoryURL = config.Configs["Network"].GetString("inventory_server_url", + "http://127.0.0.1:" + InventoryConfig.DefaultHttpPort.ToString()); } } -} \ No newline at end of file +} diff --git a/OpenSim/Grid/InventoryServer/InventoryManager.cs b/OpenSim/Grid/InventoryServer/InventoryManager.cs index 016b8bb30c..ca9ebf4f15 100644 --- a/OpenSim/Grid/InventoryServer/InventoryManager.cs +++ b/OpenSim/Grid/InventoryServer/InventoryManager.cs @@ -26,37 +26,36 @@ * */ using System; +using System.IO; +using System.Text; +using System.Reflection; using System.Collections; using System.Collections.Generic; -using System.Text; -using OpenGrid.Framework.Data; -using libsecondlife; -using System.Reflection; - using System.Xml; -using Nwc.XmlRpc; -using OpenSim.Framework.Sims; -using OpenSim.Framework.Inventory; -using OpenSim.Framework.Utilities; +using System.Xml.Serialization; +using libsecondlife; -using System.Security.Cryptography; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; -namespace OpenGridServices.InventoryServer +namespace OpenSim.Grid.InventoryServer { - class InventoryManager + + public class InventoryManager { - Dictionary _plugins = new Dictionary(); + IInventoryData _databasePlugin; /// /// Adds a new inventory server plugin - user servers will be requested in the order they were loaded. /// /// The filename to the inventory server plugin DLL - public void AddPlugin(string FileName) + public void AddDatabasePlugin(string FileName) { - OpenSim.Framework.Console.MainConsole.Instance.Verbose( "Invenstorage: Attempting to load " + FileName); + MainLog.Instance.Verbose(OpenInventory_Main.LogName, "Invenstorage: Attempting to load " + FileName); Assembly pluginAssembly = Assembly.LoadFrom(FileName); - OpenSim.Framework.Console.MainConsole.Instance.Verbose( "Invenstorage: Found " + pluginAssembly.GetTypes().Length + " interfaces."); + MainLog.Instance.Verbose(OpenInventory_Main.LogName, "Invenstorage: Found " + pluginAssembly.GetTypes().Length + " interfaces."); foreach (Type pluginType in pluginAssembly.GetTypes()) { if (!pluginType.IsAbstract) @@ -67,8 +66,9 @@ namespace OpenGridServices.InventoryServer { IInventoryData plug = (IInventoryData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); plug.Initialise(); - this._plugins.Add(plug.getName(), plug); - OpenSim.Framework.Console.MainConsole.Instance.Verbose( "Invenstorage: Added IUserData Interface"); + _databasePlugin = plug; + MainLog.Instance.Verbose(OpenInventory_Main.LogName, "Invenstorage: Added IInventoryData Interface"); + break; } typeInterface = null; @@ -78,48 +78,132 @@ namespace OpenGridServices.InventoryServer pluginAssembly = null; } - public List getRootFolders(LLUUID user) + protected static SerializableInventory loadInventoryFromXmlFile(string fileName) { - foreach (KeyValuePair kvp in _plugins) - { - try - { - return kvp.Value.getUserRootFolders(user); - } - catch (Exception e) - { - OpenSim.Framework.Console.MainConsole.Instance.Notice("Unable to get root folders via " + kvp.Key + " (" + e.ToString() + ")"); - } - } - return null; + FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); + XmlReader reader = new XmlTextReader(fs); + XmlSerializer x = new XmlSerializer(typeof(SerializableInventory)); + SerializableInventory inventory = (SerializableInventory)x.Deserialize(reader); + fs.Close(); + fs.Dispose(); + return inventory; } - public XmlRpcResponse XmlRpcInventoryRequest(XmlRpcRequest request) + protected static void saveInventoryToStream(SerializableInventory inventory, Stream s) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable requestData = (Hashtable)request.Params[0]; + XmlTextWriter writer = new XmlTextWriter(s, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + XmlSerializer x = new XmlSerializer(typeof(SerializableInventory)); + x.Serialize(writer, inventory); + } - Hashtable responseData = new Hashtable(); + protected static bool fixupFolder(SerializableInventory.SerializableFolder f, SerializableInventory.SerializableFolder parent) + { + bool modified = false; - // Stuff happens here - - if (requestData.ContainsKey("Access-type")) + // ensure we have a valid folder id + if (f.folderID == LLUUID.Zero) { - if (requestData["access-type"] == "rootfolders") + f.folderID = LLUUID.Random(); + modified = true; + } + + // ensure we have valid agent id + if (f.agentID == LLUUID.Zero) + { + if (parent != null) + f.agentID = parent.agentID; + else + f.agentID = f.folderID; + modified = true; + } + + if (f.parentID == LLUUID.Zero && parent != null) + { + f.parentID = parent.folderID; + modified = true; + } + + + foreach (SerializableInventory.SerializableFolder child in f.SubFolders) + { + modified |= fixupFolder(child, f); + } + + return modified; + } + + protected static bool fixupInventory(SerializableInventory inventory) + { + return fixupFolder(inventory.root, null); + } + + public class GetInventory : BaseStreamHandler + { + private SerializableInventory _inventory; + private InventoryManager _manager; + public GetInventory(InventoryManager manager) + : base("GET", "/inventory") + { + _manager = manager; + + _inventory = loadInventoryFromXmlFile("Inventory_Library.xml"); + if (fixupInventory(_inventory)) { -// responseData["rootfolders"] = + FileStream fs = new FileStream("Inventory_Library.xml", FileMode.Truncate, FileAccess.Write); + saveInventoryToStream(_inventory, fs); + fs.Flush(); + fs.Close(); + MainLog.Instance.Debug(OpenInventory_Main.LogName, "Modified"); } } - else + + private void CreateDefaultInventory(LLUUID userID) { - responseData["error"] = "No access-type specified."; } + private byte[] GetUserInventory(LLUUID userID) + { + MainLog.Instance.Notice(OpenInventory_Main.LogName, "Getting Inventory for user {0}", userID.ToStringHyphenated()); + byte[] result = new byte[] { }; - // Stuff stops happening here + InventoryFolderBase fb = _manager._databasePlugin.getUserRootFolder(userID); + if (fb == null) + { + MainLog.Instance.Notice(OpenInventory_Main.LogName, "Inventory not found for user {0}, creating new", userID.ToStringHyphenated()); + CreateDefaultInventory(userID); + } - response.Value = responseData; - return response; + return result; + } + + override public byte[] Handle(string path, Stream request) + { + byte[] result = new byte[] { }; + + string[] parms = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (parms.Length >= 1) + { + if (string.Compare(parms[1], "library", true) == 0) + { + + MemoryStream ms = new MemoryStream(); + saveInventoryToStream(_inventory, ms); + + result = ms.GetBuffer(); + Array.Resize(ref result, (int)ms.Length); + } + else if (string.Compare(parms[1], "user", true) == 0) + { + if (parms.Length >= 2) + { + result = GetUserInventory(new LLUUID(parms[2])); + } + } + } + return result; + } } + } } diff --git a/OpenSim/Grid/InventoryServer/Main.cs b/OpenSim/Grid/InventoryServer/Main.cs index 97addb0acd..1bc396b8c4 100644 --- a/OpenSim/Grid/InventoryServer/Main.cs +++ b/OpenSim/Grid/InventoryServer/Main.cs @@ -31,48 +31,71 @@ using System.Collections.Generic; using System.Reflection; using System.IO; using System.Text; + using libsecondlife; -using OpenSim.Framework.User; -using OpenSim.Framework.Sims; -using OpenSim.Framework.Inventory; -using OpenSim.Framework.Interfaces; + +using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Servers; -using OpenSim.Framework.Utilities; +using OpenSim.Framework.Servers; -namespace OpenGridServices.InventoryServer +using InventoryManager = OpenSim.Grid.InventoryServer.InventoryManager; + +namespace OpenSim.Grid.InventoryServer { - public class OpenInventory_Main : BaseServer, conscmd_callback + public class OpenInventory_Main : conscmd_callback { - ConsoleBase m_console; + LogBase m_console; InventoryManager m_inventoryManager; + InventoryConfig m_config; + public const string LogName = "INVENTORY"; + + [STAThread] public static void Main(string[] args) { + OpenInventory_Main theServer = new OpenInventory_Main(); + theServer.Startup(); + + theServer.Work(); } public OpenInventory_Main() { - m_console = new ConsoleBase("opengrid-inventory-console.log", "OpenInventory", this, false); - MainConsole.Instance = m_console; + m_console = new LogBase("opengrid-inventory-console.log", LogName, this, true); + MainLog.Instance = m_console; } public void Startup() { - MainConsole.Instance.Notice("Initialising inventory manager..."); + MainLog.Instance.Notice("Initialising inventory manager..."); + m_config = new InventoryConfig(LogName, (Path.Combine(Util.configDir(), "InventoryServer_Config.xml"))); + m_inventoryManager = new InventoryManager(); + m_inventoryManager.AddDatabasePlugin(m_config.DatabaseProvider); + MainLog.Instance.Notice(LogName, "Starting HTTP server ..."); + BaseHttpServer httpServer = new BaseHttpServer(m_config.HttpPort); - MainConsole.Instance.Notice("Starting HTTP server"); - BaseHttpServer httpServer = new BaseHttpServer(8004); + httpServer.AddStreamHandler(new InventoryManager.GetInventory(m_inventoryManager)); - httpServer.AddXmlRPCHandler("rootfolders", m_inventoryManager.XmlRpcInventoryRequest); - //httpServer.AddRestHandler("GET","/rootfolders/",Rest + httpServer.Start(); + MainLog.Instance.Notice(LogName, "Started HTTP server"); + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.MainLogPrompt(); + } } public void RunCmd(string cmd, string[] cmdparams) { switch (cmd) { + case "quit": case "shutdown": m_console.Close(); Environment.Exit(0); diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index 7245482c88..6be067f97f 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -175,6 +175,7 @@ namespace OpenSim config.Set("user_send_key", "null"); config.Set("user_recv_key", "null"); config.Set("asset_server_url", "http://127.0.0.1:" + AssetConfig.DefaultHttpPort.ToString()); + config.Set("inventory_server_url", "http://127.0.0.1:" + InventoryConfig.DefaultHttpPort.ToString()); } } @@ -774,4 +775,4 @@ namespace OpenSim #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs index 7d1780c99f..89e5465420 100644 --- a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs +++ b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs @@ -770,4 +770,4 @@ namespace OpenSim.Region.ClientStack OutPacket(logReply); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs b/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs index 941cc30e2a..1281a4474b 100644 --- a/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs +++ b/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs @@ -42,8 +42,8 @@ namespace OpenSim.Region.Communications.OGS1 m_gridService = gridInterComms; m_interRegion = gridInterComms; - m_inventoryService = new OGS1InventoryService(); + m_inventoryService = new OGS1InventoryService(serversInfo.InventoryURL); m_userService = new OGS1UserServices(this); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs index 49fdee9405..85df353210 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs @@ -25,7 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ - +using System; +using System.IO; +using System.Xml.Serialization; using System.Collections.Generic; using libsecondlife; using OpenSim.Framework; @@ -36,8 +38,11 @@ namespace OpenSim.Region.Communications.OGS1 { public class OGS1InventoryService : IInventoryServices { - public OGS1InventoryService() + string _inventoryServerUrl; + + public OGS1InventoryService(string inventoryServerUrl) { + _inventoryServerUrl = inventoryServerUrl; } #region IInventoryServices Members @@ -45,6 +50,19 @@ namespace OpenSim.Region.Communications.OGS1 public void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack) { + //TODO! Uncomment when all is done + //SerializableInventory userInventory = null; + + //RestClient inventoryServer = new RestClient(_inventoryServerUrl); + //inventoryServer.AddResourcePath("inventory"); + //inventoryServer.AddResourcePath("user"); + //inventoryServer.AddResourcePath(userID.ToStringHyphenated()); + + //using (Stream userInventoryStream = inventoryServer.Request()) + //{ + // XmlSerializer x = new XmlSerializer(typeof(SerializableInventory)); + // userInventory = (SerializableInventory)x.Deserialize(userInventoryStream); + //} } public void AddNewInventoryFolder(LLUUID userID, InventoryFolderImpl folder) @@ -70,4 +88,4 @@ namespace OpenSim.Region.Communications.OGS1 #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Modules/ChatModule.cs b/OpenSim/Region/Environment/Modules/ChatModule.cs index 9d4187a41c..99b69e1d10 100644 --- a/OpenSim/Region/Environment/Modules/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/ChatModule.cs @@ -431,4 +431,4 @@ namespace OpenSim.Region.Environment.Modules m_tcp.Close(); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs index 7a631d7366..5af2ce386f 100644 --- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs @@ -490,4 +490,4 @@ namespace OpenSim.Region.Environment.Modules return m_id; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 5155b41e57..3b73893b6b 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -1059,4 +1059,4 @@ namespace OpenSim.Region.Environment.Scenes SendOurAppearance(m_controllingClient); } } -} \ No newline at end of file +} diff --git a/bin/Inventory_Default.xml b/bin/Inventory_Default.xml new file mode 100644 index 0000000000..898e241ed5 --- /dev/null +++ b/bin/Inventory_Default.xml @@ -0,0 +1,62 @@ + + + + My Inventory + + 9 + + + Animations + 20 + + + Body Parts + 13 + + + Clothing + 5 + + + Gestures + 21 + + + Landmarks + 3 + + + Lost And Found + 16 + + + Notecards + 7 + + + Objects + 6 + + + Photo Album + 15 + + + Scripts + 10 + + + Sounds + 1 + + + Textures + 0 + + + Trash + 14 + + + + diff --git a/bin/Inventory_Library.xml b/bin/Inventory_Library.xml new file mode 100644 index 0000000000..327b8da100 --- /dev/null +++ b/bin/Inventory_Library.xml @@ -0,0 +1,144 @@ + + + + Library + + + + 9 + 0 + + + Animations + + + + 20 + 0 + + + + + Body Parts + + + + 13 + 0 + + + + + Clothing + + + + 5 + 0 + + + + + Gestures + + + + 21 + 0 + + + + + Landmarks + + + + 3 + 0 + + + + + Lost And Found + + + + 3 + 0 + + + + + Notecards + + + + 7 + 0 + + + + + Objects + + + + 6 + 0 + + + + + Photo Album + + + + 15 + 0 + + + + + Scripts + + + + 10 + 0 + + + + + Sounds + + + + 1 + 0 + + + + + Textures + + + + 0 + 0 + + + + + Accessories + + + + 8 + 0 + + + + + + + \ No newline at end of file diff --git a/prebuild.xml b/prebuild.xml index bc1cc78137..79f8d3a943 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -846,6 +846,34 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + @@ -1054,3 +1082,4 @@ +