Step one on the long march towards grid based inventory. Introduction of an InevntoryServer

This commit is contained in:
Tleiades Hax
2007-10-30 22:42:34 +00:00
parent a8c42a5829
commit 6a8d8f54e8
15 changed files with 533 additions and 73 deletions

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenSim.Framework
{
/// <summary>
/// UserConfig -- For User Server Configuration
/// </summary>
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;
}
}
}

View File

@@ -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
/// <param name="folder">The id of the folder</param>
void deleteInventoryFolder(LLUUID folder);
}
}
/*
* .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;
}
}

View File

@@ -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());
}
}
}
}

View File

@@ -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<string, IInventoryData> _plugins = new Dictionary<string, IInventoryData>();
IInventoryData _databasePlugin;
/// <summary>
/// Adds a new inventory server plugin - user servers will be requested in the order they were loaded.
/// </summary>
/// <param name="FileName">The filename to the inventory server plugin DLL</param>
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<InventoryFolderBase> getRootFolders(LLUUID user)
protected static SerializableInventory loadInventoryFromXmlFile(string fileName)
{
foreach (KeyValuePair<string, IInventoryData> 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<byte>(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;
}
}
}
}

View File

@@ -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);

View File

@@ -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
}
}
}

View File

@@ -770,4 +770,4 @@ namespace OpenSim.Region.ClientStack
OutPacket(logReply);
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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
}
}
}

View File

@@ -431,4 +431,4 @@ namespace OpenSim.Region.Environment.Modules
m_tcp.Close();
}
}
}
}

View File

@@ -490,4 +490,4 @@ namespace OpenSim.Region.Environment.Modules
return m_id;
}
}
}
}

View File

@@ -1059,4 +1059,4 @@ namespace OpenSim.Region.Environment.Scenes
SendOurAppearance(m_controllingClient);
}
}
}
}