diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a0af1ca941..ef00c19b04 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -117,6 +117,7 @@ what it is today. * SachaMagne * Salahzar Stenvaag * sempuki +* SignpostMarv * Snoopy * Strawberry Fride * tglion diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index f37c399050..e26c1d23b4 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -68,7 +68,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions public void Initialise() { - m_log.Error("[LOADREGIONS]: " + Name + " cannot be default-initialized!"); + m_log.Error("[LOAD REGIONS PLUGIN]: " + Name + " cannot be default-initialized!"); throw new PluginNotInitialisedException(Name); } @@ -85,41 +85,39 @@ namespace OpenSim.ApplicationPlugins.LoadRegions IRegionLoader regionLoader; if (m_openSim.ConfigSource.Source.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem") { - m_log.Info("[LOADREGIONS]: Loading region configurations from filesystem"); + m_log.Info("[LOAD REGIONS PLUGIN]: Loading region configurations from filesystem"); regionLoader = new RegionLoaderFileSystem(); } else { - m_log.Info("[LOADREGIONSPLUGIN]: Loading region configurations from web"); + m_log.Info("[LOAD REGIONS PLUGIN]: Loading region configurations from web"); regionLoader = new RegionLoaderWebServer(); } - m_log.Info("[LOADREGIONSPLUGIN]: Loading region configurations..."); - regionLoader.SetIniConfigSource(m_openSim.ConfigSource.Source); RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); - m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules..."); - m_log.Info("[LOADREGIONSPLUGIN]: DynamicTextureModule..."); + m_log.Info("[LOAD REGIONS PLUGIN]: Loading specific shared modules..."); + m_log.Info("[LOAD REGIONS PLUGIN]: DynamicTextureModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule()); - m_log.Info("[LOADREGIONSPLUGIN]: LoadImageURLModule..."); + m_log.Info("[LOAD REGIONS PLUGIN]: LoadImageURLModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule()); - m_log.Info("[LOADREGIONSPLUGIN]: XMLRPCModule..."); + m_log.Info("[LOAD REGIONS PLUGIN]: XMLRPCModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule()); // m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule..."); // m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule()); - m_log.Info("[LOADREGIONSPLUGIN]: Done."); + m_log.Info("[LOAD REGIONS PLUGIN]: Done."); if (!CheckRegionsForSanity(regionsToLoad)) { - m_log.Error("[LOADREGIONS]: Halting startup due to conflicts in region configurations"); + m_log.Error("[LOAD REGIONS PLUGIN]: Halting startup due to conflicts in region configurations"); Environment.Exit(1); } for (int i = 0; i < regionsToLoad.Length; i++) { IScene scene; - m_log.Debug("[LOADREGIONS]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + + m_log.Debug("[LOAD REGIONS PLUGIN]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + Thread.CurrentThread.ManagedThreadId.ToString() + ")"); @@ -164,7 +162,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions if (regions[i].RegionID == regions[j].RegionID) { m_log.ErrorFormat( - "[LOADREGIONS]: Regions {0} and {1} have the same UUID {2}", + "[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same UUID {2}", regions[i].RegionName, regions[j].RegionName, regions[i].RegionID); return false; } @@ -172,14 +170,14 @@ namespace OpenSim.ApplicationPlugins.LoadRegions regions[i].RegionLocX == regions[j].RegionLocX && regions[i].RegionLocY == regions[j].RegionLocY) { m_log.ErrorFormat( - "[LOADREGIONS]: Regions {0} and {1} have the same grid location ({2}, {3})", + "[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same grid location ({2}, {3})", regions[i].RegionName, regions[j].RegionName, regions[i].RegionLocX, regions[i].RegionLocY); return false; } else if (regions[i].InternalEndPoint.Port == regions[j].InternalEndPoint.Port) { m_log.ErrorFormat( - "[LOADREGIONS]: Regions {0} and {1} have the same internal IP port {2}", + "[LOAD REGIONS PLUGIN]: Regions {0} and {1} have the same internal IP port {2}", regions[i].RegionName, regions[j].RegionName, regions[i].InternalEndPoint.Port); return false; } diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs index e9a0935048..92a8d80b9a 100644 --- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs +++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs @@ -350,26 +350,43 @@ namespace OpenSim.Data.MSSQL public EstateSettings LoadEstateSettings(int estateID) { + // TODO: Implementation! return new EstateSettings(); } + + public List LoadEstateSettingsAll() + { + // TODO: Implementation! + return new List(); + } public List GetEstates(string search) { + // TODO: Implementation! + return new List(); + } + + public List GetEstatesAll() + { + // TODO: Implementation! return new List(); } public bool LinkRegion(UUID regionID, int estateID) { + // TODO: Implementation! return false; } public List GetRegions(int estateID) { + // TODO: Implementation! return new List(); } public bool DeleteEstate(int estateID) { + // TODO: Implementation! return false; } #endregion diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs index de72a6a931..6d72e82e2b 100644 --- a/OpenSim/Data/MySQL/MySQLEstateData.cs +++ b/OpenSim/Data/MySQL/MySQLEstateData.cs @@ -413,6 +413,46 @@ namespace OpenSim.Data.MySQL return DoLoad(cmd, UUID.Zero, false); } } + + public List LoadEstateSettingsAll() + { + List allEstateSettings = new List(); + + List allEstateIds = GetEstatesAll(); + + foreach (int estateId in allEstateIds) + allEstateSettings.Add(LoadEstateSettings(estateId)); + + return allEstateSettings; + } + + public List GetEstatesAll() + { + List result = new List(); + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select estateID from estate_settings"; + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + + dbcon.Close(); + } + + return result; + } public List GetEstates(string search) { diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs index 63252aa3d3..6afc5401d8 100644 --- a/OpenSim/Data/SQLite/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs @@ -357,6 +357,17 @@ namespace OpenSim.Data.SQLite return DoLoad(cmd, UUID.Zero, false); } + + public List LoadEstateSettingsAll() + { + List estateSettings = new List(); + + List estateIds = GetEstatesAll(); + foreach (int estateId in estateIds) + estateSettings.Add(LoadEstateSettings(estateId)); + + return estateSettings; + } public List GetEstates(string search) { @@ -379,6 +390,27 @@ namespace OpenSim.Data.SQLite return result; } + + public List GetEstatesAll() + { + List result = new List(); + + string sql = "select EstateID from estate_settings"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + result.Add(Convert.ToInt32(r["EstateID"])); + } + r.Close(); + + return result; + } public bool LinkRegion(UUID regionID, int estateID) { diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs index 547ea6b07d..ad28c000c6 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs @@ -100,6 +100,17 @@ namespace OpenSim.Data.SQLiteLegacy return DoLoad(cmd, regionID, create); } + + public List LoadEstateSettingsAll() + { + List estateSettings = new List(); + + List estateIds = GetEstatesAll(); + foreach (int estateId in estateIds) + estateSettings.Add(LoadEstateSettings(estateId)); + + return estateSettings; + } private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) { @@ -369,6 +380,28 @@ namespace OpenSim.Data.SQLiteLegacy return result; } + + public List GetEstatesAll() + { + List result = new List(); + + string sql = "select EstateID from estate_settings"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + result.Add(Convert.ToInt32(r["EstateID"])); + } + r.Close(); + + return result; + } + public bool LinkRegion(UUID regionID, int estateID) { SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); diff --git a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs index 63e09ae401..0aae4ff353 100644 --- a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs +++ b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs @@ -25,15 +25,19 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using log4net; using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using Nini.Config; namespace OpenSim.Framework.RegionLoader.Filesystem { public class RegionLoaderFileSystem : IRegionLoader { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IConfigSource m_configSource; public void SetIniConfigSource(IConfigSource configSource) @@ -63,36 +67,48 @@ namespace OpenSim.Framework.RegionLoader.Filesystem string[] configFiles = Directory.GetFiles(regionConfigPath, "*.xml"); string[] iniFiles = Directory.GetFiles(regionConfigPath, "*.ini"); + // Create an empty Regions.ini if there are no existing config files. if (configFiles.Length == 0 && iniFiles.Length == 0) - { + { new RegionInfo("DEFAULT REGION CONFIG", Path.Combine(regionConfigPath, "Regions.ini"), false, m_configSource); iniFiles = Directory.GetFiles(regionConfigPath, "*.ini"); } + + m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config files from {0}", regionConfigPath); List regionInfos = new List(); int i = 0; foreach (string file in iniFiles) { + m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config file {0}", file); + IConfigSource source = new IniConfigSource(file); foreach (IConfig config in source.Configs) - { - //m_log.Info("[REGIONLOADERFILESYSTEM]: Creating RegionInfo for " + config.Name); + { RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), file, false, m_configSource, config.Name); regionInfos.Add(regionInfo); + + m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loaded config for region {0}", regionInfo.RegionName); + i++; } } foreach (string file in configFiles) { + m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loading config file {0}", file); + RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), file, false, m_configSource); regionInfos.Add(regionInfo); + + m_log.InfoFormat("[REGION LOADER FILE SYSTEM]: Loaded config for region {0}", regionInfo.RegionName); + i++; } return regionInfos.ToArray(); } } -} +} \ No newline at end of file diff --git a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs index 0ec4af5c17..de4898a0d7 100644 --- a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs +++ b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs @@ -66,9 +66,9 @@ namespace OpenSim.Framework.RegionLoader.Web { HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url); webRequest.Timeout = 30000; //30 Second Timeout - m_log.Debug("[WEBLOADER]: Sending Download Request..."); + m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url); HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse(); - m_log.Debug("[WEBLOADER]: Downloading Region Information From Remote Server..."); + m_log.Debug("[WEBLOADER]: Downloading region information..."); StreamReader reader = new StreamReader(webResponse.GetResponseStream()); string xmlSource = String.Empty; string tempStr = reader.ReadLine(); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index e950613e6b..640581181c 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -792,67 +792,116 @@ namespace OpenSim regionnum = m_sceneManager.Scenes.Count; } + /// + /// Create an estate with an initial region. + /// + /// + /// This method doesn't allow an estate to be created with the same name as existing estates. + /// + /// + /// A list of estate names that already exist. + /// true if the estate was created, false otherwise + public bool CreateEstate(RegionInfo regInfo, List existingNames) + { + // Create a new estate + regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true); + string newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName); + + if (existingNames.Contains(newName)) + { + MainConsole.Instance.OutputFormat("An estate named {0} already exists. Please try again.", newName); + return false; + } + + regInfo.EstateSettings.EstateName = newName; + + // FIXME: Later on, the scene constructor will reload the estate settings no matter what. + // Therefore, we need to do an initial save here otherwise the new estate name will be reset + // back to the default. The reloading of estate settings by scene could be eliminated if it + // knows that the passed in settings in RegionInfo are already valid. Also, it might be + // possible to eliminate some additional later saves made by callers of this method. + regInfo.EstateSettings.Save(); + + return true; + } + /// /// Load the estate information for the provided RegionInfo object. /// /// public void PopulateRegionEstateInfo(RegionInfo regInfo) { - IEstateDataService estateDataService = EstateDataService; - - if (estateDataService != null) - { - regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, false); - } + if (EstateDataService != null) + regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false); if (regInfo.EstateSettings.EstateID == 0) // No record at all { - MainConsole.Instance.Output("Your region is not part of an estate."); + MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName); + + List estates = EstateDataService.LoadEstateSettingsAll(); + List estateNames = new List(); + foreach (EstateSettings estate in estates) + estateNames.Add(estate.EstateName); + while (true) { - string response = MainConsole.Instance.CmdPrompt("Do you wish to join an existing estate?", "no", new List() { "yes", "no" }); - if (response == "no") - { - // Create a new estate - regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, true); - - regInfo.EstateSettings.EstateName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName); + if (estates.Count == 0) + { + MainConsole.Instance.Output("No existing estates found. You must create a new one."); - // FIXME: Later on, the scene constructor will reload the estate settings no matter what. - // Therefore, we need to do an initial save here otherwise the new estate name will be reset - // back to the default. The reloading of estate settings by scene could be eliminated if it - // knows that the passed in settings in RegionInfo are already valid. Also, it might be - // possible to eliminate some additional later saves made by callers of this method. - regInfo.EstateSettings.Save(); - break; + if (CreateEstate(regInfo, estateNames)) + break; + else + continue; } else { - response = MainConsole.Instance.CmdPrompt("Estate name to join", "None"); - if (response == "None") - continue; - - List estateIDs = estateDataService.GetEstates(response); - if (estateIDs.Count < 1) + string response + = MainConsole.Instance.CmdPrompt( + string.Format( + "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName), + "no", + new List() { "yes", "no" }); + + if (response == "no") { - MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again"); - continue; + if (CreateEstate(regInfo, estateNames)) + break; + else + continue; + } + else + { + response + = MainConsole.Instance.CmdPrompt( + string.Format( + "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())), + "None"); + + if (response == "None") + continue; + + List estateIDs = EstateDataService.GetEstates(response); + if (estateIDs.Count < 1) + { + MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again."); + continue; + } + + int estateID = estateIDs[0]; + + regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID); + + if (EstateDataService.LinkRegion(regInfo.RegionID, estateID)) + break; + + MainConsole.Instance.Output("Joining the estate failed. Please try again."); } - - int estateID = estateIDs[0]; - - regInfo.EstateSettings = estateDataService.LoadEstateSettings(estateID); - - if (estateDataService.LinkRegion(regInfo.RegionID, estateID)) - break; - - MainConsole.Instance.Output("Joining the estate failed. Please try again."); } } } } } - public class OpenSimConfigSource { diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 98ba8c3c8c..d0727d958c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -72,6 +72,7 @@ namespace OpenSim.Region.CoreModules.World.Land protected Commander m_commander = new Commander("land"); protected IUserManagement m_userManager; + protected IPrimCountModule m_primCountModule; // Minimum for parcels to work is 64m even if we don't actually use them. #pragma warning disable 0429 @@ -147,6 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void RegionLoaded(Scene scene) { m_userManager = m_scene.RequestModuleInterface(); + m_primCountModule = m_scene.RequestModuleInterface(); } public void RemoveRegion(Scene scene) @@ -306,10 +308,14 @@ namespace OpenSim.Region.CoreModules.World.Land /// The parcel created. protected ILandObject CreateDefaultParcel() { - ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); +// m_log.DebugFormat( +// "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); + + ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); + return AddLandObject(fullSimParcel); } @@ -579,7 +585,7 @@ namespace OpenSim.Region.CoreModules.World.Land } else { - m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID); + m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid local land ID {0}", landLocalID); } } @@ -590,6 +596,11 @@ namespace OpenSim.Region.CoreModules.World.Land public ILandObject AddLandObject(ILandObject land) { ILandObject new_land = land.Copy(); + + // Only now can we add the prim counts to the land object - we rely on the global ID which is generated + // as a random UUID inside LandData initialization + if (m_primCountModule != null) + new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); lock (m_landList) { @@ -630,7 +641,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (m_landIDList[x, y] == local_id) { - m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}", + m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Not removing land object {0}; still being used at {1}, {2}", local_id, x, y); return; //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); @@ -851,6 +862,10 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnParcelPrimCountUpdate() { +// m_log.DebugFormat( +// "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}", +// m_scene.RegionInfo.RegionName); + ResetAllLandPrimCounts(); EntityBase[] entities = m_scene.Entities.GetEntities(); foreach (EntityBase obj in entities) @@ -1198,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.World.Land } else { - m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id); + m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid land object {0} passed for parcel object owner request", local_id); } } @@ -1361,7 +1376,7 @@ namespace OpenSim.Region.CoreModules.World.Land { ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); new_land.LandData = data.Copy(); - new_land.SetLandBitmapFromByteArray(); + new_land.SetLandBitmapFromByteArray(); AddLandObject(new_land); } @@ -1426,7 +1441,7 @@ namespace OpenSim.Region.CoreModules.World.Land { IClientAPI client; if (! m_scene.TryGetClient(agentID, out client)) { - m_log.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString()); + m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID); return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); } @@ -1475,7 +1490,7 @@ namespace OpenSim.Region.CoreModules.World.Land } else { - m_log.WarnFormat("[LAND] unable to find parcelID {0}", parcelID); + m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); } return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); } @@ -1533,17 +1548,17 @@ namespace OpenSim.Region.CoreModules.World.Land } catch (LLSD.LLSDParseException e) { - m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message); - m_log.ErrorFormat("[LAND] ... in request {0}", request); + m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Fetch error: {0}", e.Message); + m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: ... in request {0}", request); } - catch(InvalidCastException) + catch (InvalidCastException) { - m_log.ErrorFormat("[LAND] Wrong type in request {0}", request); + m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Wrong type in request {0}", request); } LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); response.parcel_id = parcelID; - m_log.DebugFormat("[LAND] got parcelID {0}", parcelID); + m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); return LLSDHelpers.SerialiseLLSDReply(response); } @@ -1564,7 +1579,7 @@ namespace OpenSim.Region.CoreModules.World.Land ExtendedLandData extLandData = new ExtendedLandData(); Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, out extLandData.X, out extLandData.Y); - m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", + m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", extLandData.RegionHandle, extLandData.X, extLandData.Y); // for this region or for somewhere else? @@ -1605,7 +1620,7 @@ namespace OpenSim.Region.CoreModules.World.Land info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); } // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. - m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...", + m_log.DebugFormat("[LAND MANAGEMENT MODULE]: got parcelinfo for parcel {0} in region {1}; sending...", data.LandData.Name, data.RegionHandle); // HACK for now RegionInfo r = new RegionInfo(); @@ -1616,7 +1631,7 @@ namespace OpenSim.Region.CoreModules.World.Land remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y); } else - m_log.Debug("[LAND] got no parcelinfo; not sending"); + m_log.Debug("[LAND MANAGEMENT MODULE]: got no parcelinfo; not sending"); } public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 46c15ed2c3..749bb3d8cd 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.World.Land private int m_lastSeqId = 0; - protected LandData m_landData = new LandData(); + protected LandData m_landData = new LandData(); protected Scene m_scene; protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); @@ -79,6 +79,8 @@ namespace OpenSim.Region.CoreModules.World.Land set { m_landData = value; } } + + public IPrimCounts PrimCounts { get; set; } public UUID RegionUUID { diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index 34ef67f10b..9fd347e371 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -51,8 +51,8 @@ namespace OpenSim.Region.CoreModules.World.Land public class PrimCountModule : IPrimCountModule, INonSharedRegionModule { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_Scene; private Dictionary m_PrimCounts = @@ -64,10 +64,16 @@ namespace OpenSim.Region.CoreModules.World.Land private Dictionary m_ParcelCounts = new Dictionary(); - // For now, a simple simwide taint to get this up. Later parcel based - // taint to allow recounting a parcel if only ownership has changed - // without recounting the whole sim. + + /// + /// For now, a simple simwide taint to get this up. Later parcel based + /// taint to allow recounting a parcel if only ownership has changed + /// without recounting the whole sim. + /// + /// We start out tainted so that the first get call resets the various prim counts. + /// private bool m_Tainted = true; + private Object m_TaintLock = new Object(); public Type ReplaceableInterface @@ -82,9 +88,10 @@ namespace OpenSim.Region.CoreModules.World.Land public void AddRegion(Scene scene) { m_Scene = scene; + + m_Scene.RegisterModuleInterface(this); - m_Scene.EventManager.OnParcelPrimCountAdd += - OnParcelPrimCountAdd; + m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd; m_Scene.EventManager.OnObjectBeingRemovedFromScene += OnObjectBeingRemovedFromScene; m_Scene.EventManager.OnParcelPrimCountTainted += @@ -156,6 +163,8 @@ namespace OpenSim.Region.CoreModules.World.Land // NOTE: Call under Taint Lock private void AddObject(SceneObjectGroup obj) { +// m_log.DebugFormat("[PRIM COUNT MODULE]: Adding object {0} to prim count", obj.Name); + if (obj.IsAttachment) return; if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) @@ -164,6 +173,10 @@ namespace OpenSim.Region.CoreModules.World.Land Vector3 pos = obj.AbsolutePosition; ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); LandData landData = landObject.LandData; + +// m_log.DebugFormat( +// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}", +// obj.Name, obj.OwnerID, landData.OwnerID); ParcelCounts parcelCounts; if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) @@ -218,8 +231,16 @@ namespace OpenSim.Region.CoreModules.World.Land return primCounts; } + + /// + /// Get the number of prims on the parcel that are owned by the parcel owner. + /// + /// + /// public int GetOwnerCount(UUID parcelID) { +// m_log.DebugFormat("[PRIM COUNT MODULE]: GetOwnerCount for {0}", parcelID); + lock (m_TaintLock) { if (m_Tainted) @@ -232,6 +253,11 @@ namespace OpenSim.Region.CoreModules.World.Land return 0; } + /// + /// Get the number of prims on the parcel that have been set to the group that owns the parcel. + /// + /// + /// public int GetGroupCount(UUID parcelID) { lock (m_TaintLock) @@ -246,6 +272,11 @@ namespace OpenSim.Region.CoreModules.World.Land return 0; } + /// + /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group. + /// + /// + /// public int GetOthersCount(UUID parcelID) { lock (m_TaintLock) @@ -260,6 +291,11 @@ namespace OpenSim.Region.CoreModules.World.Land return 0; } + /// + /// Get the number of prims that are in the entire simulator for the owner of this parcel. + /// + /// + /// public int GetSimulatorCount(UUID parcelID) { lock (m_TaintLock) @@ -278,6 +314,12 @@ namespace OpenSim.Region.CoreModules.World.Land return 0; } + /// + /// Get the number of prims that a particular user owns on this parcel. + /// + /// + /// + /// public int GetUserCount(UUID parcelID, UUID userID) { lock (m_TaintLock) @@ -299,18 +341,21 @@ namespace OpenSim.Region.CoreModules.World.Land // NOTE: This method MUST be called while holding the taint lock! private void Recount() { +// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName); + m_OwnerMap.Clear(); m_SimwideCounts.Clear(); m_ParcelCounts.Clear(); List land = m_Scene.LandChannel.AllParcels(); - + foreach (ILandObject l in land) { LandData landData = l.LandData; m_OwnerMap[landData.GlobalID] = landData.OwnerID; m_SimwideCounts[landData.OwnerID] = 0; +// m_log.DebugFormat("[PRIM COUNT MODULE]: Adding parcel count for {0}", landData.GlobalID); m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); } diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs new file mode 100644 index 0000000000..c9d393f4d6 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs @@ -0,0 +1,131 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * 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 OpenSimulator Project 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 DEVELOPERS ``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 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.Reflection; +using log4net.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.World.Land.Tests +{ + [TestFixture] + public class PrimCountModuleTests + { + protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); + protected UUID m_dummyUserId = new UUID("99999999-9999-9999-9999-999999999999"); + protected TestScene m_scene; + protected PrimCountModule m_pcm; + protected ILandObject m_lo; + + [SetUp] + public void SetUp() + { + m_pcm = new PrimCountModule(); + LandManagementModule lmm = new LandManagementModule(); + m_scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(m_scene, lmm, m_pcm); + + ILandObject lo = new LandObject(m_userId, false, m_scene); + lo.SetLandBitmap(lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); + m_lo = lmm.AddLandObject(lo); + //scene.loadAllLandObjectsFromStorage(scene.RegionInfo.originRegionID); + } + + /// + /// Test count after a parcel owner owned object is added. + /// + [Test] + public void TestAddOwnerObject() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + IPrimCounts pc = m_lo.PrimCounts; + + Assert.That(pc.Owner, Is.EqualTo(0)); + Assert.That(pc.Group, Is.EqualTo(0)); + Assert.That(pc.Others, Is.EqualTo(0)); + Assert.That(pc.Users[m_userId], Is.EqualTo(0)); + Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0)); + Assert.That(pc.Simulator, Is.EqualTo(0)); + + SceneObjectGroup sog = SceneSetupHelpers.CreateSceneObject(3, m_userId, 0x01); + m_scene.AddNewSceneObject(sog, false); + + Assert.That(pc.Owner, Is.EqualTo(3)); + Assert.That(pc.Group, Is.EqualTo(0)); + Assert.That(pc.Others, Is.EqualTo(0)); + Assert.That(pc.Users[m_userId], Is.EqualTo(3)); + Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0)); + Assert.That(pc.Simulator, Is.EqualTo(3)); + + // Add a second object and retest + SceneObjectGroup sog2 = SceneSetupHelpers.CreateSceneObject(2, m_userId, 0x10); + m_scene.AddNewSceneObject(sog2, false); + + Assert.That(pc.Owner, Is.EqualTo(5)); + Assert.That(pc.Group, Is.EqualTo(0)); + Assert.That(pc.Others, Is.EqualTo(0)); + Assert.That(pc.Users[m_userId], Is.EqualTo(5)); + Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0)); + Assert.That(pc.Simulator, Is.EqualTo(5)); + } + + /// + /// Test count after a parcel owner owned object is removed. + /// + [Test] + public void TestRemoveOwnerObject() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + IPrimCounts pc = m_lo.PrimCounts; + + m_scene.AddNewSceneObject(SceneSetupHelpers.CreateSceneObject(1, m_userId, 0x1), false); + SceneObjectGroup sogToDelete = SceneSetupHelpers.CreateSceneObject(3, m_userId, 0x10); + m_scene.AddNewSceneObject(sogToDelete, false); + m_scene.DeleteSceneObject(sogToDelete, false); + + Assert.That(pc.Owner, Is.EqualTo(1)); + Assert.That(pc.Group, Is.EqualTo(0)); + Assert.That(pc.Others, Is.EqualTo(0)); + Assert.That(pc.Users[m_userId], Is.EqualTo(1)); + Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0)); + Assert.That(pc.Simulator, Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs index 95c9659bc1..38c10a6d1b 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs @@ -34,12 +34,68 @@ namespace OpenSim.Region.Framework.Interfaces { public interface IEstateDataService { + /// + /// Load estate settings for a region. + /// + /// + /// If true, then an estate is created if one is not found. + /// EstateSettings LoadEstateSettings(UUID regionID, bool create); + + /// + /// Load estate settings for an estate ID. + /// + /// + /// EstateSettings LoadEstateSettings(int estateID); + + /// + /// Load/Get all estate settings. + /// + /// An empty list if no estates were found. + List LoadEstateSettingsAll(); + + /// + /// Store estate settings. + /// + /// + /// This is also called by EstateSettings.Save() + /// void StoreEstateSettings(EstateSettings es); + + /// + /// Get estate IDs. + /// + /// Name of estate to search for. This is the exact name, no parttern matching is done. + /// List GetEstates(string search); + + /// + /// Get the IDs of all estates. + /// + /// An empty list if no estates were found. + List GetEstatesAll(); + + /// + /// Link a region to an estate. + /// + /// + /// + /// true if the link succeeded, false otherwise bool LinkRegion(UUID regionID, int estateID); + + /// + /// Get the UUIDs of all the regions in an estate. + /// + /// + /// List GetRegions(int estateID); + + /// + /// Delete an estate + /// + /// + /// true if the delete succeeded, false otherwise bool DeleteEstate(int estateID); } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs index 87c7a05f6d..c82661db74 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs @@ -33,14 +33,74 @@ namespace OpenSim.Region.Framework.Interfaces { public interface IEstateDataStore { + /// + /// Initialise the data store. + /// + /// void Initialise(string connectstring); + /// + /// Load estate settings for a region. + /// + /// + /// If true, then an estate is created if one is not found. + /// EstateSettings LoadEstateSettings(UUID regionID, bool create); + + /// + /// Load estate settings for an estate ID. + /// + /// + /// EstateSettings LoadEstateSettings(int estateID); + + /// + /// Load/Get all estate settings. + /// + /// An empty list if no estates were found. + List LoadEstateSettingsAll(); + + /// + /// Store estate settings. + /// + /// + /// This is also called by EstateSettings.Save() + /// void StoreEstateSettings(EstateSettings es); + + /// + /// Get estate IDs. + /// + /// Name of estate to search for. This is the exact name, no parttern matching is done. + /// List GetEstates(string search); + + /// + /// Get the IDs of all estates. + /// + /// An empty list if no estates were found. + List GetEstatesAll(); + + /// + /// Link a region to an estate. + /// + /// + /// + /// true if the link succeeded, false otherwise bool LinkRegion(UUID regionID, int estateID); + + /// + /// Get the UUIDs of all the regions in an estate. + /// + /// + /// List GetRegions(int estateID); + + /// + /// Delete an estate + /// + /// + /// true if the delete succeeded, false otherwise bool DeleteEstate(int estateID); } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/ILandObject.cs b/OpenSim/Region/Framework/Interfaces/ILandObject.cs index eeb9d3ad1d..9c0abdeedc 100644 --- a/OpenSim/Region/Framework/Interfaces/ILandObject.cs +++ b/OpenSim/Region/Framework/Interfaces/ILandObject.cs @@ -45,6 +45,11 @@ namespace OpenSim.Region.Framework.Interfaces bool[,] LandBitmap { get; set; } UUID RegionUUID { get; } + /// + /// Prim counts for this land object. + /// + IPrimCounts PrimCounts { get; set; } + /// /// The start point for the land object. This is the western-most point as one scans land working from /// north to south. diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index c321a15866..fd6253533a 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -242,7 +242,15 @@ namespace OpenSim.Region.Framework.Scenes public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); public event EstateToolsSunUpdate OnEstateToolsSunUpdate; + + /// + /// Triggered when an object is added to the scene. + /// + public event Action OnObjectAddedToScene; + /// + /// Triggered when an object is removed from the scene. + /// public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; @@ -345,6 +353,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void Attach(uint localID, UUID itemID, UUID avatarID); public event Attach OnAttach; + /// /// Called immediately after an object is loaded from storage. /// @@ -800,6 +809,27 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerObjectAddedToScene(SceneObjectGroup obj) + { + Action handler = OnObjectAddedToScene; + if (handler != null) + { + foreach (Action d in handler.GetInvocationList()) + { + try + { + d(obj); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerObjectAddedToScene failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } + public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj) { ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1a6a70bfbe..d407a6f033 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1109,7 +1109,7 @@ namespace OpenSim.Region.Framework.Scenes // while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) { - MainConsole.Instance.Output("The current estate has no owner set."); + MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", m_regInfo.EstateSettings.EstateName); List excluded = new List(new char[1]{' '}); string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded); string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded); @@ -1956,8 +1956,14 @@ namespace OpenSim.Region.Framework.Scenes /// If false, it is left to the caller to schedule the update /// public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) - { - return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); + { + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; } /// @@ -1974,7 +1980,13 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) { - return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel); + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 734ba22e9c..60855b2c36 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -88,9 +88,21 @@ namespace OpenSim.Region.Framework.Scenes protected internal object m_syncRoot = new object(); protected internal PhysicsScene _PhyScene; - - protected internal Dictionary SceneObjectGroupsByLocalID = new Dictionary(); + + /// + /// Index the SceneObjectGroup for each part by the root part's UUID. + /// protected internal Dictionary SceneObjectGroupsByFullID = new Dictionary(); + + /// + /// Index the SceneObjectGroup for each part by that part's UUID. + /// + protected internal Dictionary SceneObjectGroupsByFullPartID = new Dictionary(); + + /// + /// Index the SceneObjectGroup for each part by that part's local ID. + /// + protected internal Dictionary SceneObjectGroupsByLocalPartID = new Dictionary(); private Object m_updateLock = new Object(); @@ -133,8 +145,10 @@ namespace OpenSim.Region.Framework.Scenes lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Clear(); - lock (SceneObjectGroupsByLocalID) - SceneObjectGroupsByLocalID.Clear(); + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID.Clear(); + lock (SceneObjectGroupsByLocalPartID) + SceneObjectGroupsByLocalPartID.Clear(); Entities.Clear(); } @@ -349,6 +363,10 @@ namespace OpenSim.Region.Framework.Scenes if (Entities.ContainsKey(sceneObject.UUID)) return false; + +// m_log.DebugFormat( +// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", +// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); SceneObjectPart[] children = sceneObject.Parts; @@ -385,17 +403,20 @@ namespace OpenSim.Region.Framework.Scenes OnObjectCreate(sceneObject); lock (SceneObjectGroupsByFullID) - { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + + lock (SceneObjectGroupsByFullPartID) + { + SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject; foreach (SceneObjectPart part in children) - SceneObjectGroupsByFullID[part.UUID] = sceneObject; + SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; } - lock (SceneObjectGroupsByLocalID) + lock (SceneObjectGroupsByLocalPartID) { - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in children) - SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; + SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } return true; @@ -426,21 +447,24 @@ namespace OpenSim.Region.Framework.Scenes if (OnObjectRemove != null) OnObjectRemove(Entities[uuid]); - + lock (SceneObjectGroupsByFullID) + SceneObjectGroupsByFullID.Remove(grp.UUID); + + lock (SceneObjectGroupsByFullPartID) { SceneObjectPart[] parts = grp.Parts; for (int i = 0; i < parts.Length; i++) - SceneObjectGroupsByFullID.Remove(parts[i].UUID); - SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); + SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); + SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID); } - lock (SceneObjectGroupsByLocalID) + lock (SceneObjectGroupsByLocalPartID) { SceneObjectPart[] parts = grp.Parts; for (int i = 0; i < parts.Length; i++) - SceneObjectGroupsByLocalID.Remove(parts[i].LocalId); - SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); + SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); + SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId); } return Entities.Remove(uuid); @@ -627,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes if (!Entities.Remove(agentID)) { m_log.WarnFormat( - "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", + "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", agentID); } @@ -650,7 +674,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); + m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); } } } @@ -854,14 +878,14 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); SceneObjectGroup sog; - lock (SceneObjectGroupsByLocalID) - SceneObjectGroupsByLocalID.TryGetValue(localID, out sog); + lock (SceneObjectGroupsByLocalPartID) + SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog); if (sog != null) { if (sog.HasChildPrim(localID)) return sog; - SceneObjectGroupsByLocalID.Remove(localID); + SceneObjectGroupsByLocalPartID.Remove(localID); } EntityBase[] entityList = GetEntities(); @@ -873,8 +897,8 @@ namespace OpenSim.Region.Framework.Scenes sog = (SceneObjectGroup)ent; if (sog.HasChildPrim(localID)) { - lock (SceneObjectGroupsByLocalID) - SceneObjectGroupsByLocalID[localID] = sog; + lock (SceneObjectGroupsByLocalPartID) + SceneObjectGroupsByLocalPartID[localID] = sog; return sog; } } @@ -891,16 +915,16 @@ namespace OpenSim.Region.Framework.Scenes private SceneObjectGroup GetGroupByPrim(UUID fullID) { SceneObjectGroup sog; - lock (SceneObjectGroupsByFullID) - SceneObjectGroupsByFullID.TryGetValue(fullID, out sog); + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID.TryGetValue(fullID, out sog); if (sog != null) { if (sog.ContainsPart(fullID)) return sog; - lock (SceneObjectGroupsByFullID) - SceneObjectGroupsByFullID.Remove(fullID); + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID.Remove(fullID); } EntityBase[] entityList = GetEntities(); @@ -911,8 +935,8 @@ namespace OpenSim.Region.Framework.Scenes sog = (SceneObjectGroup)ent; if (sog.HasChildPrim(fullID)) { - lock (SceneObjectGroupsByFullID) - SceneObjectGroupsByFullID[fullID] = sog; + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID[fullID] = sog; return sog; } } @@ -1064,11 +1088,12 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Performs action on all scene object groups. + /// Performs action once on all scene object groups. /// /// protected internal void ForEachSOG(Action action) { + // FIXME: Need to lock here, really. List objlist = new List(SceneObjectGroupsByFullID.Values); foreach (SceneObjectGroup obj in objlist) { @@ -1079,11 +1104,11 @@ namespace OpenSim.Region.Framework.Scenes catch (Exception e) { // Catch it and move on. This includes situations where splist has inconsistent info - m_log.WarnFormat("[SCENE]: Problem processing action in ForEachSOG: ", e.ToString()); + m_log.WarnFormat( + "[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}", e.Message, e.StackTrace); } } } - /// /// Performs action on all scene presences. This can ultimately run the actions in parallel but @@ -1103,8 +1128,8 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); - m_log.Info("[BUG] Stack Trace: " + e.StackTrace); + m_log.Info("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); + m_log.Info("[SCENEGRAPH]: Stack Trace: " + e.StackTrace); } }); Parallel.ForEach(GetScenePresences(), protectedAction); @@ -1119,7 +1144,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); + m_log.Error("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); } } } @@ -1777,7 +1802,10 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) { - //m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID); +// m_log.DebugFormat( +// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", +// originalPrimID, offset, AgentID); + SceneObjectGroup original = GetGroupByPrim(originalPrimID); if (original != null) { @@ -1808,7 +1836,28 @@ namespace OpenSim.Region.Framework.Scenes copy.RootPart.SalePrice = 10; } + // FIXME: This section needs to be refactored so that it just calls AddSceneObject() Entities.Add(copy); + + lock (SceneObjectGroupsByFullID) + SceneObjectGroupsByFullID[copy.UUID] = copy; + + SceneObjectPart[] children = copy.Parts; + + lock (SceneObjectGroupsByFullPartID) + { + SceneObjectGroupsByFullPartID[copy.UUID] = copy; + foreach (SceneObjectPart part in children) + SceneObjectGroupsByFullPartID[part.UUID] = copy; + } + + lock (SceneObjectGroupsByLocalPartID) + { + SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; + foreach (SceneObjectPart part in children) + SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; + } + // PROBABLE END OF FIXME // Since we copy from a source group that is in selected // state, but the copy is shown deselected in the viewer, diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index 48f5f99ed3..8048f861de 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -74,12 +74,23 @@ namespace OpenSim.Server.Handlers.Login if (requestData != null) { if (requestData.ContainsKey("first") && requestData["first"] != null && - requestData.ContainsKey("last") && requestData["last"] != null && - requestData.ContainsKey("passwd") && requestData["passwd"] != null) + requestData.ContainsKey("last") && requestData["last"] != null && ( + (requestData.ContainsKey("passwd") && requestData["passwd"] != null) || + (!requestData.ContainsKey("passwd") && requestData.ContainsKey("web_login_key") && requestData["web_login_key"] != null && requestData["web_login_key"].ToString() != UUID.Zero.ToString()) + )) { string first = requestData["first"].ToString(); string last = requestData["last"].ToString(); - string passwd = requestData["passwd"].ToString(); + string passwd = null; + if (requestData.ContainsKey("passwd")) + { + passwd = requestData["passwd"].ToString(); + } + else if (requestData.ContainsKey("web_login_key")) + { + passwd = "$1$" + requestData["web_login_key"].ToString(); + m_log.InfoFormat("[LOGIN]: XMLRPC Login Req key {0}", passwd); + } string startLocation = string.Empty; UUID scopeID = UUID.Zero; if (requestData["scope_id"] != null) @@ -103,7 +114,7 @@ namespace OpenSim.Server.Handlers.Login string id0 = "Unknown"; if (requestData.Contains("id0") && requestData["id0"] != null) id0 = requestData["id0"].ToString(); - + //m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion); LoginResponse reply = null; diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs index d1a5b0f041..2344c0ed4e 100644 --- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs @@ -31,6 +31,9 @@ using OpenSim.Services.Interfaces; using log4net; using Nini.Config; using System.Reflection; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Console; namespace OpenSim.Services.AuthenticationService { @@ -43,17 +46,45 @@ namespace OpenSim.Services.AuthenticationService public class WebkeyAuthenticationService : AuthenticationServiceBase, IAuthenticationService { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + public WebkeyAuthenticationService(IConfigSource config) : - base(config) + base(config) { } public string Authenticate(UUID principalID, string password, int lifetime) { + if (new UUID(password) == UUID.Zero) + { + m_log.DebugFormat("[AUTH SERVICE]: UUID.Zero is not a valid web_login_key on PrincipalID {0}", principalID); + } + else + { + AuthenticationData data = m_Database.Get(principalID); + if (data != null && data.Data != null) + { + if (data.Data.ContainsKey("webLoginKey")) + { + string key = data.Data["webLoginKey"].ToString(); + if (key == password) + { + data.Data["webLoginKey"] = UUID.Zero.ToString(); + m_Database.Store(data); + return GetToken(principalID, lifetime); + } + else + { + m_log.DebugFormat("[AUTH SERVICE]: web login auth failed, got PrincipalID {0} gave {1} instead of {2}", principalID, password, key); + } + }else{ + m_log.DebugFormat("[AUTH SERVICE]: no col webLoginKey in passwd.db"); + } + } + m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); + } return String.Empty; } } diff --git a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs new file mode 100644 index 0000000000..3590e128b1 --- /dev/null +++ b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs @@ -0,0 +1,94 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * 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 OpenSimulator Project 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 DEVELOPERS ``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 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 OpenMetaverse; +using OpenSim.Services.Interfaces; +using log4net; +using Nini.Config; +using System.Reflection; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Server.Base; + +namespace OpenSim.Services.AuthenticationService +{ + public class WebkeyOrPasswordAuthenticationService : AuthenticationServiceBase, IAuthenticationService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IConfigSource m_config; + private Dictionary m_svcChecks + = new Dictionary(); + + public WebkeyOrPasswordAuthenticationService(IConfigSource config) + : base(config) + { + this.m_config = config; + m_svcChecks["web_login_key"] = new WebkeyAuthenticationService(config); + m_svcChecks["password"] = new PasswordAuthenticationService(config); + } + + public string Authenticate(UUID principalID, string password, int lifetime) + { + AuthenticationData data = m_Database.Get(principalID); + string result = String.Empty; + if (data != null && data.Data != null) + { + if (data.Data.ContainsKey("webLoginKey")) + { + m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID); + result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime); + if (result == String.Empty) + { + m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID); + } + } + if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt")) + { + m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID); + result = m_svcChecks["password"].Authenticate(principalID, password, lifetime); + if (result == String.Empty) + { + m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID); + } + } + if (result == string.Empty) + { + m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID); + } + } + else + { + m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); + } + return result; + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs index b6df5a2595..d0588bff09 100644 --- a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs +++ b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs @@ -90,6 +90,11 @@ namespace OpenSim.Services.Connectors { return m_database.LoadEstateSettings(estateID); } + + public List LoadEstateSettingsAll() + { + return m_database.LoadEstateSettingsAll(); + } public void StoreEstateSettings(EstateSettings es) { @@ -100,6 +105,11 @@ namespace OpenSim.Services.Connectors { return m_database.GetEstates(search); } + + public List GetEstatesAll() + { + return m_database.GetEstatesAll(); + } public bool LinkRegion(UUID regionID, int estateID) { diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index aa4b285981..57850c1cc7 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -454,9 +454,7 @@ namespace OpenSim.Tests.Common.Setup /// public static SceneObjectPart AddSceneObject(Scene scene, string name) { - SceneObjectPart part - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); - part.Name = name; + SceneObjectPart part = CreateSceneObjectPart(name, UUID.Random(), UUID.Zero); //part.UpdatePrimFlags(false, false, true); //part.ObjectFlags |= (uint)PrimFlags.Phantom; @@ -465,5 +463,62 @@ namespace OpenSim.Tests.Common.Setup return part; } + + /// + /// Create a scene object part. + /// + /// + /// + /// + /// + public static SceneObjectPart CreateSceneObjectPart(string name, UUID id, UUID ownerId) + { + return new SceneObjectPart( + ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) + { Name = name, UUID = id }; + } + + /// + /// Create a scene object but do not add it to the scene. + /// + /// + /// UUID always starts at 00000000-0000-0000-0000-000000000001 + /// + /// The number of parts that should be in the scene object + /// + /// + public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId) + { + return CreateSceneObject(parts, ownerId, 0x1); + } + + /// + /// Create a scene object but do not add it to the scene. + /// + /// The number of parts that should be in the scene object + /// + /// + /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be given to the root part, and incremented for each part thereafter. + /// + /// + public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail) + { + string rawSogId = string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail); + + SceneObjectGroup sog + = new SceneObjectGroup( + CreateSceneObjectPart("part0", new UUID(rawSogId), ownerId)); + + if (parts > 1) + for (int i = 1; i < parts; i++) + sog.AddPart( + CreateSceneObjectPart( + string.Format("obj{0}", i), + new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail + i)), + ownerId)); + + return sog; + } } -} +} \ No newline at end of file diff --git a/README.txt b/README.txt index 391a6599d1..8d925b5df6 100644 --- a/README.txt +++ b/README.txt @@ -44,7 +44,7 @@ for more information. To run OpenSim, from the unpacked distribution type: * cd bin - * mono OpenSim.exe + * LD_LIBRARY_PATH=. mono OpenSim.exe Now see the "Configuring OpenSim" section diff --git a/bin/Mono.Data.Sqlite.dll.config b/bin/Mono.Data.Sqlite.dll.config new file mode 100644 index 0000000000..0c5e9412f2 --- /dev/null +++ b/bin/Mono.Data.Sqlite.dll.config @@ -0,0 +1,4 @@ + + + + diff --git a/bin/libsqlite3_32.so b/bin/libsqlite3_32.so new file mode 100755 index 0000000000..171ffcd1cc Binary files /dev/null and b/bin/libsqlite3_32.so differ diff --git a/bin/libsqlite3.so.0 b/bin/libsqlite3_64.so similarity index 89% rename from bin/libsqlite3.so.0 rename to bin/libsqlite3_64.so index 0512d8a3c0..2646a9c41e 100755 Binary files a/bin/libsqlite3.so.0 and b/bin/libsqlite3_64.so differ diff --git a/prebuild.xml b/prebuild.xml index b31812dc17..c818908d80 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -402,6 +402,7 @@ + @@ -1058,6 +1059,7 @@ + @@ -2156,8 +2158,8 @@ - - + + @@ -2927,6 +2929,7 @@ +