diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index e0a96e76ad..31aeda3ab8 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -86,8 +86,10 @@ what it is today.
* Grumly57
* GuduleLapointe
* Ewe Loon
+* Fernando Oliveira
* Fly-Man
* Flyte Xevious
+* Garmin Kawaguichi
* Imaze Rhiano
* Intimidated
* Jeremy Bongio (IBM)
@@ -106,6 +108,7 @@ what it is today.
* M.Igarashi
* maimedleech
* Mana Janus
+* MarcelEdward
* Mic Bowman
* Michelle Argus
* Michael Cortez (The Flotsam Project, http://osflotsam.org/)
@@ -135,6 +138,7 @@ what it is today.
* Ruud Lathorp
* SachaMagne
* Salahzar Stenvaag
+* satguru p srivastava
* sempuki
* SignpostMarv
* SpotOn3D
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs b/OpenSim/Data/IXAssetDataPlugin.cs
similarity index 57%
rename from OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs
rename to OpenSim/Data/IXAssetDataPlugin.cs
index 659c3a5c54..74ad6f497d 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs
+++ b/OpenSim/Data/IXAssetDataPlugin.cs
@@ -26,38 +26,22 @@
*/
using System.Collections.Generic;
-using System.Xml;
using OpenMetaverse;
+using OpenSim.Framework;
-namespace OpenSim.Region.Framework.Scenes.Animation
+namespace OpenSim.Data
{
- public class AvatarAnimations
+ ///
+ /// This interface exists to distinguish between the normal IAssetDataPlugin and the one used by XAssetService
+ /// for now.
+ ///
+ public interface IXAssetDataPlugin : IPlugin
{
- public Dictionary AnimsUUID = new Dictionary();
- public Dictionary AnimsNames = new Dictionary();
- public Dictionary AnimStateNames = new Dictionary();
-
- public AvatarAnimations()
- {
- using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml"))
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(reader);
- foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
- {
- if (nod.Attributes["name"] != null)
- {
- string name = (string)nod.Attributes["name"].Value;
- UUID id = (UUID)nod.InnerText;
- string animState = (string)nod.Attributes["state"].Value;
-
- AnimsUUID.Add(name, id);
- AnimsNames.Add(id, name);
- if (animState != "")
- AnimStateNames.Add(id, animState);
- }
- }
- }
- }
+ AssetBase GetAsset(UUID uuid);
+ void StoreAsset(AssetBase asset);
+ bool ExistsAsset(UUID uuid);
+ List FetchAssetMetadataSet(int start, int count);
+ void Initialise(string connect);
+ bool Delete(string id);
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
index 09dde5e182..fef6978f33 100644
--- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
@@ -89,5 +89,11 @@ namespace OpenSim.Data.MSSQL
return DoQuery(cmd);
}
}
+
+ public FriendsData[] GetFriends(Guid principalID)
+ {
+ return GetFriends(principalID.ToString());
+ }
+
}
}
diff --git a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs
index 4d06377452..961593fc6f 100644
--- a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs
@@ -813,7 +813,7 @@ namespace OpenSim.Data.MSSQL
{
try
{
- using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID", connection))
+ using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID and type=-1", connection))
{
command.Parameters.Add(database.CreateParameter("folderID", folderID));
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index d6b1561055..d9dfe864ec 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -675,7 +675,7 @@ VALUES
cmd.ExecuteNonQuery();
}
- sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)";
+ sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags],[Expires]) VALUES (@LandUUID,@AccessUUID,@Flags,@Expires)";
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
@@ -1215,6 +1215,8 @@ VALUES
//Store new values
StoreNewRegionSettings(regionSettings);
+ LoadSpawnPoints(regionSettings);
+
return regionSettings;
}
@@ -1252,7 +1254,7 @@ VALUES
,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se
,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit
,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position
-,[covenant] = @covenant ,[covenant_datetime] = @covenant_datetime, [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id
+,[covenant] = @covenant ,[covenant_datetime] = @covenant_datetime, [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id, [map_tile_id] = @TerrainImageID, [telehubobject] = @telehubobject, [parcel_tile_id] = @ParcelImageID
WHERE [regionUUID] = @regionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
@@ -1263,6 +1265,7 @@ VALUES
cmd.ExecuteNonQuery();
}
}
+ SaveSpawnPoints(regionSettings);
}
public void Shutdown()
@@ -1383,6 +1386,11 @@ VALUES
newSettings.LoadedCreationID = "";
else
newSettings.LoadedCreationID = (String)row["loaded_creation_id"];
+
+ newSettings.TerrainImageID = new UUID((string)row["map_tile_ID"]);
+ newSettings.ParcelImageID = new UUID((Guid)row["parcel_tile_ID"]);
+ newSettings.TelehubObject = new UUID((Guid)row["TelehubObject"]);
+
return newSettings;
}
@@ -1454,6 +1462,13 @@ VALUES
}
newData.ParcelAccessList = new List();
+ newData.MediaDescription = (string)row["MediaDescription"];
+ newData.MediaType = (string)row["MediaType"];
+ newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
+ newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
+ newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
+ newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
+ newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
return newData;
}
@@ -1468,7 +1483,7 @@ VALUES
LandAccessEntry entry = new LandAccessEntry();
entry.AgentID = new UUID((Guid)row["AccessUUID"]);
entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]);
- entry.Expires = 0;
+ entry.Expires = Convert.ToInt32(row["Expires"]);
return entry;
}
@@ -1497,7 +1512,8 @@ VALUES
prim.TouchName = (string)primRow["TouchName"];
// permissions
prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]);
- prim.CreatorID = new UUID((Guid)primRow["CreatorID"]);
+ //prim.CreatorID = new UUID((Guid)primRow["CreatorID"]);
+ prim.CreatorIdentification = (string)primRow["CreatorID"];
prim.OwnerID = new UUID((Guid)primRow["OwnerID"]);
prim.GroupID = new UUID((Guid)primRow["GroupID"]);
prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]);
@@ -1691,7 +1707,8 @@ VALUES
taskItem.Name = (string)inventoryRow["name"];
taskItem.Description = (string)inventoryRow["description"];
taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]);
- taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]);
+ //taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]);
+ taskItem.CreatorIdentification = (string)inventoryRow["creatorID"];
taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]);
taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]);
taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]);
@@ -1792,6 +1809,9 @@ VALUES
parameters.Add(_Database.CreateParameter("covenant_datetime", settings.CovenantChangedDateTime));
parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime));
parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID));
+ parameters.Add(_Database.CreateParameter("TerrainImageID", settings.TerrainImageID));
+ parameters.Add(_Database.CreateParameter("ParcelImageID", settings.ParcelImageID));
+ parameters.Add(_Database.CreateParameter("TelehubObject", settings.TelehubObject));
return parameters.ToArray();
}
@@ -1859,6 +1879,7 @@ VALUES
parameters.Add(_Database.CreateParameter("LandUUID", parcelID));
parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID));
parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags));
+ parameters.Add(_Database.CreateParameter("Expires", parcelAccessEntry.Expires));
return parameters.ToArray();
}
@@ -2063,5 +2084,57 @@ VALUES
#endregion
#endregion
+
+ private void LoadSpawnPoints(RegionSettings rs)
+ {
+ rs.ClearSpawnPoints();
+
+ string sql = "SELECT Yaw, Pitch, Distance FROM spawn_points WHERE RegionUUID = @RegionUUID";
+ using (SqlConnection conn = new SqlConnection(m_connectionString))
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID.ToString()));
+ conn.Open();
+ using (SqlDataReader reader = cmd.ExecuteReader())
+ {
+ if (reader.Read())
+ {
+ SpawnPoint sp = new SpawnPoint();
+
+ sp.Yaw = (float)reader["Yaw"];
+ sp.Pitch = (float)reader["Pitch"];
+ sp.Distance = (float)reader["Distance"];
+
+ rs.AddSpawnPoint(sp);
+ }
+ }
+ }
+ }
+
+ private void SaveSpawnPoints(RegionSettings rs)
+ {
+ string sql = "DELETE FROM spawn_points WHERE RegionUUID = @RegionUUID";
+ using (SqlConnection conn = new SqlConnection(m_connectionString))
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
+ foreach (SpawnPoint p in rs.SpawnPoints())
+ {
+ sql = "INSERT INTO spawn_points (RegionUUID, Yaw, Pitch, Distance) VALUES (@RegionUUID, @Yaw, @Pitch, @Distance)";
+ using (SqlConnection conn = new SqlConnection(m_connectionString))
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", rs.RegionUUID));
+ cmd.Parameters.Add(_Database.CreateParameter("@Yaw", p.Yaw));
+ cmd.Parameters.Add(_Database.CreateParameter("@Pitch", p.Pitch));
+ cmd.Parameters.Add(_Database.CreateParameter("@Distance", p.Distance));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
+ }
+ }
}
}
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
index a98690affb..d6a3be9282 100644
--- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
@@ -1044,10 +1044,93 @@ ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL
COMMIT
-:VERSION 29 #---------------------
+:VERSION 29 #----------------- Region Covenant changed time
BEGIN TRANSACTION
ALTER TABLE regionsettings ADD covenant_datetime int NOT NULL default 0
COMMIT
+
+:VERSION 30 #------------------Migrate creatorID storage to varchars instead of UUIDs for HG support
+
+BEGIN TRANSACTION
+
+EXECUTE sp_rename N'dbo.prims.creatorid', N'creatoridold', 'COLUMN'
+EXECUTE sp_rename N'dbo.primitems.creatorid', N'creatoridold', 'COLUMN'
+
+COMMIT
+
+:VERSION 31 #---------------------
+
+BEGIN TRANSACTION
+
+ALTER TABLE prims ADD CreatorID varchar(255)
+ALTER TABLE primitems ADD CreatorID varchar(255)
+
+COMMIT
+
+:VERSION 32 #---------------------
+
+BEGIN TRANSACTION
+
+UPDATE prims SET prims.CreatorID = CONVERT(varchar(255), creatoridold)
+UPDATE primitems SET primitems.CreatorID = CONVERT(varchar(255), creatoridold)
+
+COMMIT
+
+:VERSION 33 #---------------------
+
+BEGIN TRANSACTION
+
+ALTER TABLE prims
+ADD CONSTRAINT DF_prims_CreatorIDNew
+DEFAULT '00000000-0000-0000-0000-000000000000'
+FOR CreatorID
+
+ALTER TABLE prims ALTER COLUMN CreatorID varchar(255) NOT NULL
+
+ALTER TABLE primitems
+ADD CONSTRAINT DF_primitems_CreatorIDNew
+DEFAULT '00000000-0000-0000-0000-000000000000'
+FOR CreatorID
+
+ALTER TABLE primitems ALTER COLUMN CreatorID varchar(255) NOT NULL
+
+COMMIT
+
+:VERSION 34 #--------------- Telehub support
+
+BEGIN TRANSACTION
+
+CREATE TABLE [dbo].[Spawn_Points](
+ [RegionUUID] [uniqueidentifier] NOT NULL,
+ [Yaw] [float] NOT NULL,
+ [Pitch] [float] NOT NULL,
+ [Distance] [float] NOT NULL,
+ PRIMARY KEY CLUSTERED
+ (
+ [RegionUUID] ASC
+ )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
+) ON [PRIMARY]
+
+ALTER TABLE regionsettings ADD TelehubObject uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
+
+COMMIT
+
+:VERSION 35 #---------------- Parcels for sale
+
+BEGIN TRANSACTION
+
+ALTER TABLE regionsettings ADD parcel_tile_ID uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
+
+COMMIT
+
+:VERSION 36 #---------------- Timed bans/access
+
+BEGIN TRANSACTION
+
+ALTER TABLE landaccesslist ADD Expires integer NOT NULL DEFAULT 0;
+
+COMMIT
+
diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs
new file mode 100644
index 0000000000..e6ac22e09c
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLXAssetData.cs
@@ -0,0 +1,500 @@
+/*
+ * 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.Data;
+using System.IO;
+using System.IO.Compression;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+using log4net;
+using MySql.Data.MySqlClient;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Data;
+
+namespace OpenSim.Data.MySQL
+{
+ public class MySQLXAssetData : IXAssetDataPlugin
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected virtual Assembly Assembly
+ {
+ get { return GetType().Assembly; }
+ }
+
+ private bool m_enableCompression = false;
+ private string m_connectionString;
+ private object m_dbLock = new object();
+
+ ///
+ /// We can reuse this for all hashing since all methods are single-threaded through m_dbBLock
+ ///
+ private HashAlgorithm hasher = new SHA256CryptoServiceProvider();
+
+ #region IPlugin Members
+
+ public string Version { get { return "1.0.0.0"; } }
+
+ ///
+ /// Initialises Asset interface
+ ///
+ ///
+ /// - Loads and initialises the MySQL storage plugin.
+ /// - Warns and uses the obsolete mysql_connection.ini if connect string is empty.
+ /// - Check for migration
+ ///
+ ///
+ ///
+ /// connect string
+ public void Initialise(string connect)
+ {
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: THIS PLUGIN IS STRICTLY EXPERIMENTAL.");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: DO NOT USE FOR ANY DATA THAT YOU DO NOT MIND LOSING.");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: DATABASE TABLES CAN CHANGE AT ANY TIME, CAUSING EXISTING DATA TO BE LOST.");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+ m_log.ErrorFormat("[MYSQL XASSETDATA]: ***********************************************************");
+
+ m_connectionString = connect;
+
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+ Migration m = new Migration(dbcon, Assembly, "XAssetStore");
+ m.Update();
+ }
+ }
+
+ public void Initialise()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Dispose() { }
+
+ ///
+ /// The name of this DB provider
+ ///
+ public string Name
+ {
+ get { return "MySQL XAsset storage engine"; }
+ }
+
+ #endregion
+
+ #region IAssetDataPlugin Members
+
+ ///
+ /// Fetch Asset from database
+ ///
+ /// Asset UUID to fetch
+ /// Return the asset
+ /// On failure : throw an exception and attempt to reconnect to database
+ public AssetBase GetAsset(UUID assetID)
+ {
+// m_log.DebugFormat("[MYSQL XASSET DATA]: Looking for asset {0}", assetID);
+
+ AssetBase asset = null;
+ lock (m_dbLock)
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand(
+ "SELECT name, description, asset_type, local, temporary, asset_flags, creator_id, data FROM xassetsmeta JOIN xassetsdata ON xassetsmeta.hash = xassetsdata.hash WHERE id=?id",
+ dbcon))
+ {
+ cmd.Parameters.AddWithValue("?id", assetID.ToString());
+
+ try
+ {
+ using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if (dbReader.Read())
+ {
+ asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["asset_type"], dbReader["creator_id"].ToString());
+ asset.Data = (byte[])dbReader["data"];
+ asset.Description = (string)dbReader["description"];
+
+ string local = dbReader["local"].ToString();
+ if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
+ asset.Local = true;
+ else
+ asset.Local = false;
+
+ asset.Temporary = Convert.ToBoolean(dbReader["temporary"]);
+ asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
+
+ if (m_enableCompression)
+ {
+ using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress))
+ {
+ MemoryStream outputStream = new MemoryStream();
+ WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue);
+ // int compressedLength = asset.Data.Length;
+ asset.Data = outputStream.ToArray();
+
+ // m_log.DebugFormat(
+ // "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
+ // asset.ID, asset.Name, asset.Data.Length, compressedLength);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[MYSQL XASSET DATA]: MySql failure fetching asset " + assetID + ": " + e.Message);
+ }
+ }
+ }
+ }
+
+ return asset;
+ }
+
+ ///
+ /// Create an asset in database, or update it if existing.
+ ///
+ /// Asset UUID to create
+ /// On failure : Throw an exception and attempt to reconnect to database
+ public void StoreAsset(AssetBase asset)
+ {
+ lock (m_dbLock)
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlTransaction transaction = dbcon.BeginTransaction())
+ {
+ string assetName = asset.Name;
+ if (asset.Name.Length > 64)
+ {
+ assetName = asset.Name.Substring(0, 64);
+ m_log.Warn("[XASSET DB]: Name field truncated from " + asset.Name.Length + " to " + assetName.Length + " characters on add");
+ }
+
+ string assetDescription = asset.Description;
+ if (asset.Description.Length > 64)
+ {
+ assetDescription = asset.Description.Substring(0, 64);
+ m_log.Warn("[XASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add");
+ }
+
+ if (m_enableCompression)
+ {
+ MemoryStream outputStream = new MemoryStream();
+
+ using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress, false))
+ {
+ // Console.WriteLine(WebUtil.CopyTo(new MemoryStream(asset.Data), compressionStream, int.MaxValue));
+ // We have to close the compression stream in order to make sure it writes everything out to the underlying memory output stream.
+ compressionStream.Close();
+ byte[] compressedData = outputStream.ToArray();
+ asset.Data = compressedData;
+ }
+ }
+
+ byte[] hash = hasher.ComputeHash(asset.Data);
+
+// m_log.DebugFormat(
+// "[XASSET DB]: Compressed data size for {0} {1}, hash {2} is {3}",
+// asset.ID, asset.Name, hash, compressedData.Length);
+
+ try
+ {
+ using (MySqlCommand cmd =
+ new MySqlCommand(
+ "replace INTO xassetsmeta(id, hash, name, description, asset_type, local, temporary, create_time, access_time, asset_flags, creator_id)" +
+ "VALUES(?id, ?hash, ?name, ?description, ?asset_type, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?creator_id)",
+ dbcon))
+ {
+ // create unix epoch time
+ int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
+ cmd.Parameters.AddWithValue("?id", asset.ID);
+ cmd.Parameters.AddWithValue("?hash", hash);
+ cmd.Parameters.AddWithValue("?name", assetName);
+ cmd.Parameters.AddWithValue("?description", assetDescription);
+ cmd.Parameters.AddWithValue("?asset_type", asset.Type);
+ cmd.Parameters.AddWithValue("?local", asset.Local);
+ cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
+ cmd.Parameters.AddWithValue("?create_time", now);
+ cmd.Parameters.AddWithValue("?access_time", now);
+ cmd.Parameters.AddWithValue("?creator_id", asset.Metadata.CreatorID);
+ cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags);
+ cmd.ExecuteNonQuery();
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset metadata {0} with name \"{1}\". Error: {2}",
+ asset.FullID, asset.Name, e.Message);
+
+ transaction.Rollback();
+
+ return;
+ }
+
+ if (!ExistsData(dbcon, transaction, hash))
+ {
+ try
+ {
+ using (MySqlCommand cmd =
+ new MySqlCommand(
+ "INSERT INTO xassetsdata(hash, data) VALUES(?hash, ?data)",
+ dbcon))
+ {
+ cmd.Parameters.AddWithValue("?hash", hash);
+ cmd.Parameters.AddWithValue("?data", asset.Data);
+ cmd.ExecuteNonQuery();
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[XASSET DB]: MySQL failure creating asset data {0} with name \"{1}\". Error: {2}",
+ asset.FullID, asset.Name, e.Message);
+
+ transaction.Rollback();
+
+ return;
+ }
+ }
+
+ transaction.Commit();
+ }
+ }
+ }
+ }
+
+// private void UpdateAccessTime(AssetBase asset)
+// {
+// lock (m_dbLock)
+// {
+// using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+// {
+// dbcon.Open();
+// MySqlCommand cmd =
+// new MySqlCommand("update assets set access_time=?access_time where id=?id",
+// dbcon);
+//
+// // need to ensure we dispose
+// try
+// {
+// using (cmd)
+// {
+// // create unix epoch time
+// int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
+// cmd.Parameters.AddWithValue("?id", asset.ID);
+// cmd.Parameters.AddWithValue("?access_time", now);
+// cmd.ExecuteNonQuery();
+// cmd.Dispose();
+// }
+// }
+// catch (Exception e)
+// {
+// m_log.ErrorFormat(
+// "[ASSETS DB]: " +
+// "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
+// + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
+// }
+// }
+// }
+//
+// }
+
+ ///
+ /// We assume we already have the m_dbLock.
+ ///
+ /// TODO: need to actually use the transaction.
+ ///
+ ///
+ ///
+ ///
+ private bool ExistsData(MySqlConnection dbcon, MySqlTransaction transaction, byte[] hash)
+ {
+// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
+
+ bool exists = false;
+
+ using (MySqlCommand cmd = new MySqlCommand("SELECT hash FROM xassetsdata WHERE hash=?hash", dbcon))
+ {
+ cmd.Parameters.AddWithValue("?hash", hash);
+
+ try
+ {
+ using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if (dbReader.Read())
+ {
+// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
+ exists = true;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat(
+ "[XASSETS DB]: MySql failure in ExistsData fetching hash {0}. Exception {1}{2}",
+ hash, e.Message, e.StackTrace);
+ }
+ }
+
+ return exists;
+ }
+
+ ///
+ /// Check if the asset exists in the database
+ ///
+ /// The asset UUID
+ /// true if it exists, false otherwise.
+ public bool ExistsAsset(UUID uuid)
+ {
+// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
+
+ bool assetExists = false;
+
+ lock (m_dbLock)
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+ using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM xassetsmeta WHERE id=?id", dbcon))
+ {
+ cmd.Parameters.AddWithValue("?id", uuid.ToString());
+
+ try
+ {
+ using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
+ {
+ if (dbReader.Read())
+ {
+// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
+ assetExists = true;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat(
+ "[XASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
+ }
+ }
+ }
+ }
+
+ return assetExists;
+ }
+
+ ///
+ /// Returns a list of AssetMetadata objects. The list is a subset of
+ /// the entire data set offset by containing
+ /// elements.
+ ///
+ /// The number of results to discard from the total data set.
+ /// The number of rows the returned list should contain.
+ /// A list of AssetMetadata objects.
+ public List FetchAssetMetadataSet(int start, int count)
+ {
+ List retList = new List(count);
+
+ lock (m_dbLock)
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+ MySqlCommand cmd = new MySqlCommand("SELECT name,description,asset_type,temporary,id,asset_flags,creator_id FROM xassetsmeta LIMIT ?start, ?count", dbcon);
+ cmd.Parameters.AddWithValue("?start", start);
+ cmd.Parameters.AddWithValue("?count", count);
+
+ try
+ {
+ using (MySqlDataReader dbReader = cmd.ExecuteReader())
+ {
+ while (dbReader.Read())
+ {
+ AssetMetadata metadata = new AssetMetadata();
+ metadata.Name = (string)dbReader["name"];
+ metadata.Description = (string)dbReader["description"];
+ metadata.Type = (sbyte)dbReader["asset_type"];
+ metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct.
+ metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
+ metadata.FullID = DBGuid.FromDB(dbReader["id"]);
+ metadata.CreatorID = dbReader["creator_id"].ToString();
+
+ // We'll ignore this for now - it appears unused!
+// metadata.SHA1 = dbReader["hash"]);
+
+ retList.Add(metadata);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[XASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
+ }
+ }
+ }
+
+ return retList;
+ }
+
+ public bool Delete(string id)
+ {
+// m_log.DebugFormat("[XASSETS DB]: Deleting asset {0}", id);
+
+ lock (m_dbLock)
+ {
+ using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+ {
+ dbcon.Open();
+
+ using (MySqlCommand cmd = new MySqlCommand("delete from xassetsmeta where id=?id", dbcon))
+ {
+ cmd.Parameters.AddWithValue("?id", id);
+ cmd.ExecuteNonQuery();
+ }
+
+ // TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we
+ // keep a reference count (?)
+ }
+ }
+
+ return true;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Data/MySQL/Resources/XAssetStore.migrations b/OpenSim/Data/MySQL/Resources/XAssetStore.migrations
new file mode 100644
index 0000000000..d3cca5e884
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/XAssetStore.migrations
@@ -0,0 +1,27 @@
+# -----------------
+:VERSION 1
+
+BEGIN;
+
+CREATE TABLE `xassetsmeta` (
+ `id` char(36) NOT NULL,
+ `hash` binary(32) NOT NULL,
+ `name` varchar(64) NOT NULL,
+ `description` varchar(64) NOT NULL,
+ `asset_type` tinyint(4) NOT NULL,
+ `local` tinyint(1) NOT NULL,
+ `temporary` tinyint(1) NOT NULL,
+ `create_time` int(11) NOT NULL,
+ `access_time` int(11) NOT NULL,
+ `asset_flags` int(11) NOT NULL,
+ `creator_id` varchar(128) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Version 1';
+
+CREATE TABLE `xassetsdata` (
+ `hash` binary(32) NOT NULL,
+ `data` longblob NOT NULL,
+ PRIMARY KEY (`hash`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Version 1';
+
+COMMIT;
\ No newline at end of file
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 0d6288b5a3..c5d6b78686 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -29,6 +29,7 @@ using System;
using System.Xml;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
@@ -40,6 +41,8 @@ namespace OpenSim.Framework.Console
{
public class Commands : ICommands
{
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
///
/// Encapsulates a command that can be invoked from the console
///
@@ -76,12 +79,19 @@ namespace OpenSim.Framework.Console
public List fn;
}
+ public const string GeneralHelpText = "For more information, type 'help - ' where
- is one of the following categories:";
+
///
/// Commands organized by keyword in a tree
///
private Dictionary tree =
new Dictionary();
+ ///
+ /// Commands organized by module
+ ///
+ private Dictionary> m_modulesCommands = new Dictionary>();
+
///
/// Get help for the given help string
///
@@ -98,8 +108,8 @@ namespace OpenSim.Framework.Console
// General help
if (helpParts.Count == 0)
{
- help.AddRange(CollectHelp(tree));
- help.Sort();
+ help.Add(GeneralHelpText);
+ help.AddRange(CollectModulesHelp(tree));
}
else
{
@@ -118,6 +128,13 @@ namespace OpenSim.Framework.Console
{
string originalHelpRequest = string.Join(" ", helpParts.ToArray());
List help = new List();
+
+ // Check modules first to see if we just need to display a list of those commands
+ if (TryCollectModuleHelp(originalHelpRequest, help))
+ {
+ help.Insert(0, GeneralHelpText);
+ return help;
+ }
Dictionary dict = tree;
while (helpParts.Count > 0)
@@ -161,25 +178,63 @@ namespace OpenSim.Framework.Console
return help;
}
- private List CollectHelp(Dictionary dict)
+ ///
+ /// Try to collect help for the given module if that module exists.
+ ///
+ ///
+ /// /param>
+ /// true if there was the module existed, false otherwise.
+ private bool TryCollectModuleHelp(string moduleName, List helpText)
{
- List result = new List();
-
- foreach (KeyValuePair kvp in dict)
+ lock (m_modulesCommands)
{
- if (kvp.Value is Dictionary)
+ foreach (string key in m_modulesCommands.Keys)
{
- result.AddRange(CollectHelp((Dictionary)kvp.Value));
- }
- else
- {
- if (((CommandInfo)kvp.Value).long_help != String.Empty)
- result.Add(((CommandInfo)kvp.Value).help_text+" - "+
- ((CommandInfo)kvp.Value).long_help);
+ // Allow topic help requests to succeed whether they are upper or lowercase.
+ if (moduleName.ToLower() == key.ToLower())
+ {
+ List commands = m_modulesCommands[key];
+ var ourHelpText = commands.ConvertAll(c => string.Format("{0} - {1}", c.help_text, c.long_help));
+ ourHelpText.Sort();
+ helpText.AddRange(ourHelpText);
+
+ return true;
+ }
}
+
+ return false;
}
- return result;
}
+
+ private List CollectModulesHelp(Dictionary dict)
+ {
+ lock (m_modulesCommands)
+ {
+ List helpText = new List(m_modulesCommands.Keys);
+ helpText.Sort();
+ return helpText;
+ }
+ }
+
+// private List CollectHelp(Dictionary dict)
+// {
+// List result = new List();
+//
+// foreach (KeyValuePair kvp in dict)
+// {
+// if (kvp.Value is Dictionary)
+// {
+// result.AddRange(CollectHelp((Dictionary)kvp.Value));
+// }
+// else
+// {
+// if (((CommandInfo)kvp.Value).long_help != String.Empty)
+// result.Add(((CommandInfo)kvp.Value).help_text+" - "+
+// ((CommandInfo)kvp.Value).long_help);
+// }
+// }
+// return result;
+// }
///
/// Add a command to those which can be invoked from the console.
@@ -212,21 +267,19 @@ namespace OpenSim.Framework.Console
Dictionary current = tree;
- foreach (string s in parts)
+ foreach (string part in parts)
{
- if (current.ContainsKey(s))
+ if (current.ContainsKey(part))
{
- if (current[s] is Dictionary)
- {
- current = (Dictionary)current[s];
- }
+ if (current[part] is Dictionary)
+ current = (Dictionary)current[part];
else
return;
}
else
{
- current[s] = new Dictionary();
- current = (Dictionary)current[s];
+ current[part] = new Dictionary();
+ current = (Dictionary)current[part];
}
}
@@ -250,6 +303,24 @@ namespace OpenSim.Framework.Console
info.fn = new List();
info.fn.Add(fn);
current[String.Empty] = info;
+
+ // Now add command to modules dictionary
+ lock (m_modulesCommands)
+ {
+ List commands;
+ if (m_modulesCommands.ContainsKey(module))
+ {
+ commands = m_modulesCommands[module];
+ }
+ else
+ {
+ commands = new List();
+ m_modulesCommands[module] = commands;
+ }
+
+// m_log.DebugFormat("[COMMAND CONSOLE]: Adding to category {0} command {1}", module, command);
+ commands.Add(info);
+ }
}
public string[] FindNextOption(string[] cmd, bool term)
@@ -607,8 +678,9 @@ namespace OpenSim.Framework.Console
{
Commands = new Commands();
- Commands.AddCommand("console", false, "help", "help []",
- "Get general command list or more detailed help on a specific command", Help);
+ Commands.AddCommand(
+ "Help", false, "help", "help [
- ]",
+ "Display help on a particular command or on a list of commands in a category", Help);
}
private void Help(string module, string[] cmd)
diff --git a/OpenSim/Framework/GcNotify.cs b/OpenSim/Framework/GcNotify.cs
new file mode 100644
index 0000000000..14a22a6104
--- /dev/null
+++ b/OpenSim/Framework/GcNotify.cs
@@ -0,0 +1,62 @@
+/*
+ * 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.Reflection;
+using log4net;
+
+public class GcNotify
+{
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ public static bool Enabled
+ {
+ get { return s_initialized; }
+ set
+ {
+ if (!s_initialized && value)
+ new GcNotify();
+
+ s_initialized = value;
+ }
+ }
+
+ private static bool s_initialized = false;
+
+ private GcNotify() {}
+
+ ~GcNotify()
+ {
+ if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload())
+ {
+ m_log.DebugFormat("[GC NOTIFY]: Garbage collection triggered.");
+
+ if (Enabled)
+ new GcNotify();
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index c85e599e26..3f560d0ec4 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1215,10 +1215,9 @@ namespace OpenSim.Framework
/// The orbital position is given in radians, and must be "adjusted" for the linden client, see LLClientView
void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear,
float OrbitalPosition);
-
+
void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks);
void SendViewerTime(int phase);
- UUID GetDefaultAnimation(string name);
void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, string flAbout,
uint flags, UUID flImageID, UUID imageID, string profileURL, UUID partnerID);
diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs
index d33b9b5772..ca0ff936ca 100644
--- a/OpenSim/Framework/ICommandConsole.cs
+++ b/OpenSim/Framework/ICommandConsole.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Framework
///
/// Get help for the given help string
///
- /// Parsed parts of the help string. If empty then general help is returned.
+ /// Parsed parts of the help string. If empty then general help is returned.
///
List GetHelp(string[] cmd);
diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs
index dd73b3fe01..4f98d7bb30 100644
--- a/OpenSim/Framework/ILandObject.cs
+++ b/OpenSim/Framework/ILandObject.cs
@@ -71,6 +71,7 @@ namespace OpenSim.Framework
bool IsEitherBannedOrRestricted(UUID avatar);
bool IsBannedFromLand(UUID avatar);
bool IsRestrictedFromLand(UUID avatar);
+ bool IsInLandAccessList(UUID avatar);
void SendLandUpdateToClient(IClientAPI remote_client);
void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client);
List CreateAccessListArrayByFlag(AccessList flag);
diff --git a/OpenSim/Framework/MultipartForm.cs b/OpenSim/Framework/MultipartForm.cs
index 90c4007ddc..7a13e8b21c 100644
--- a/OpenSim/Framework/MultipartForm.cs
+++ b/OpenSim/Framework/MultipartForm.cs
@@ -119,7 +119,7 @@ namespace OpenSim.Framework
// Copy the temporary stream to the network stream
formDataStream.Seek(0, SeekOrigin.Begin);
using (Stream requestStream = request.GetRequestStream())
- formDataStream.CopyTo(requestStream, (int)formDataStream.Length);
+ formDataStream.CopyStream(requestStream, (int)formDataStream.Length);
}
#endregion Stream Writing
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 5ba3863529..a5055247c7 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -421,12 +421,18 @@ namespace OpenSim.Framework
set { m_internalEndPoint = value; }
}
+ ///
+ /// The x co-ordinate of this region in map tiles (e.g. 1000).
+ ///
public uint RegionLocX
{
get { return m_regionLocX.Value; }
set { m_regionLocX = value; }
}
+ ///
+ /// The y co-ordinate of this region in map tiles (e.g. 1000).
+ ///
public uint RegionLocY
{
get { return m_regionLocY.Value; }
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index b337e034fa..db4541ef1a 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -27,7 +27,9 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Reflection;
+using System.Xml;
using log4net;
using OpenMetaverse;
@@ -375,4 +377,4 @@ namespace OpenSim.Framework
return output;
}
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6a3135eb7d..06a8021b5f 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -161,43 +161,43 @@ namespace OpenSim.Framework.Servers
Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
}
- m_console.Commands.AddCommand("base", false, "quit",
+ m_console.Commands.AddCommand("General", false, "quit",
"quit",
"Quit the application", HandleQuit);
- m_console.Commands.AddCommand("base", false, "shutdown",
+ m_console.Commands.AddCommand("General", false, "shutdown",
"shutdown",
"Quit the application", HandleQuit);
- m_console.Commands.AddCommand("base", false, "set log level",
+ m_console.Commands.AddCommand("General", false, "set log level",
"set log level ",
"Set the console logging level", HandleLogLevel);
- m_console.Commands.AddCommand("base", false, "show info",
+ m_console.Commands.AddCommand("General", false, "show info",
"show info",
"Show general information about the server", HandleShow);
- m_console.Commands.AddCommand("base", false, "show stats",
+ m_console.Commands.AddCommand("General", false, "show stats",
"show stats",
"Show statistics", HandleShow);
- m_console.Commands.AddCommand("base", false, "show threads",
+ m_console.Commands.AddCommand("General", false, "show threads",
"show threads",
"Show thread status", HandleShow);
- m_console.Commands.AddCommand("base", false, "show uptime",
+ m_console.Commands.AddCommand("General", false, "show uptime",
"show uptime",
"Show server uptime", HandleShow);
- m_console.Commands.AddCommand("base", false, "show version",
+ m_console.Commands.AddCommand("General", false, "show version",
"show version",
"Show server version", HandleShow);
- m_console.Commands.AddCommand("base", false, "threads abort",
+ m_console.Commands.AddCommand("General", false, "threads abort",
"threads abort ",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
- m_console.Commands.AddCommand("base", false, "threads show",
+ m_console.Commands.AddCommand("General", false, "threads show",
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
@@ -269,15 +269,19 @@ namespace OpenSim.Framework.Servers
t.Priority,
t.ThreadState);
- sb.Append(Environment.NewLine);
+ sb.Append("\n");
}
- int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0;
- ThreadPool.GetAvailableThreads(out workers, out ports);
- ThreadPool.GetMaxThreads(out maxWorkers, out maxPorts);
+ sb.Append("\n");
- sb.Append(Environment.NewLine + "*** ThreadPool threads ***" + Environment.NewLine);
- sb.Append("workers: " + (maxWorkers - workers) + " (" + maxWorkers + "); ports: " + (maxPorts - ports) + " (" + maxPorts + ")" + Environment.NewLine);
+ // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
+ // zero active threads.
+ int totalThreads = Process.GetCurrentProcess().Threads.Count;
+ if (totalThreads > 0)
+ sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
+
+ sb.Append("Main threadpool (excluding script engine pools)\n");
+ sb.Append(Util.GetThreadPoolReport());
return sb.ToString();
}
diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs
index a1841c568a..c9e57ce7b3 100644
--- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs
@@ -26,8 +26,8 @@
*/
using System;
+using System.Diagnostics;
using System.Text;
-
using OpenMetaverse;
using OpenMetaverse.StructuredData;
@@ -46,8 +46,12 @@ namespace OpenSim.Framework.Statistics
sb.Append(Environment.NewLine);
sb.Append(
string.Format(
- "Allocated to OpenSim : {0} MB" + Environment.NewLine,
+ "Allocated to OpenSim objects: {0} MB\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
+ sb.Append(
+ string.Format(
+ "Process memory : {0} MB\n",
+ Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)));
return sb.ToString();
}
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index efa4a7ba87..e03bb7491c 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -35,7 +35,7 @@ using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
-using System.Reflection;
+using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
@@ -81,12 +81,15 @@ namespace OpenSim.Framework
private static uint nextXferID = 5000;
private static Random randomClass = new Random();
+
// Get a list of invalid file characters (OS dependent)
private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
private static object XferLock = new object();
- /// Thread pool used for Util.FireAndForget if
- /// FireAndForgetMethod.SmartThreadPool is used
+
+ ///
+ /// Thread pool used for Util.FireAndForget if FireAndForgetMethod.SmartThreadPool is used
+ ///
private static SmartThreadPool m_ThreadPool;
// Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
@@ -144,7 +147,6 @@ namespace OpenSim.Framework
return lerp(y, lerp(x, a, b), lerp(x, c, d));
}
-
public static Encoding UTF8 = Encoding.UTF8;
///
@@ -376,20 +378,20 @@ namespace OpenSim.Framework
}
return sb.ToString();
- }
-
- ///
- /// Is the platform Windows?
- ///
- /// true if so, false otherwise
- public static bool IsWindows()
- {
- PlatformID platformId = Environment.OSVersion.Platform;
-
- return (platformId == PlatformID.Win32NT
- || platformId == PlatformID.Win32S
- || platformId == PlatformID.Win32Windows
- || platformId == PlatformID.WinCE);
+ }
+
+ ///
+ /// Is the platform Windows?
+ ///
+ /// true if so, false otherwise
+ public static bool IsWindows()
+ {
+ PlatformID platformId = Environment.OSVersion.Platform;
+
+ return (platformId == PlatformID.Win32NT
+ || platformId == PlatformID.Win32S
+ || platformId == PlatformID.Win32Windows
+ || platformId == PlatformID.WinCE);
}
public static bool LoadArchSpecificWindowsDll(string libraryName)
@@ -1502,27 +1504,27 @@ namespace OpenSim.Framework
}
return data;
- }
-
- ///
- /// Used to trigger an early library load on Windows systems.
- ///
- ///
- /// Required to get 32-bit and 64-bit processes to automatically use the
- /// appropriate native library.
- ///
- ///
- ///
- [DllImport("kernel32.dll")]
- public static extern IntPtr LoadLibrary(string dllToLoad);
-
- ///
- /// Determine whether the current process is 64 bit
- ///
- /// true if so, false if not
- public static bool Is64BitProcess()
- {
- return IntPtr.Size == 8;
+ }
+
+ ///
+ /// Used to trigger an early library load on Windows systems.
+ ///
+ ///
+ /// Required to get 32-bit and 64-bit processes to automatically use the
+ /// appropriate native library.
+ ///
+ ///
+ ///
+ [DllImport("kernel32.dll")]
+ public static extern IntPtr LoadLibrary(string dllToLoad);
+
+ ///
+ /// Determine whether the current process is 64 bit
+ ///
+ /// true if so, false if not
+ public static bool Is64BitProcess()
+ {
+ return IntPtr.Size == 8;
}
#region FireAndForget Threading Pattern
@@ -1671,6 +1673,61 @@ namespace OpenSim.Framework
}
}
+ ///
+ /// Get a thread pool report.
+ ///
+ ///
+ public static string GetThreadPoolReport()
+ {
+ string threadPoolUsed = null;
+ int maxThreads = 0;
+ int minThreads = 0;
+ int allocatedThreads = 0;
+ int inUseThreads = 0;
+ int waitingCallbacks = 0;
+ int completionPortThreads = 0;
+
+ StringBuilder sb = new StringBuilder();
+ if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
+ {
+ threadPoolUsed = "SmartThreadPool";
+ maxThreads = m_ThreadPool.MaxThreads;
+ minThreads = m_ThreadPool.MinThreads;
+ inUseThreads = m_ThreadPool.InUseThreads;
+ allocatedThreads = m_ThreadPool.ActiveThreads;
+ waitingCallbacks = m_ThreadPool.WaitingCallbacks;
+ }
+ else if (
+ FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
+ || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
+ {
+ threadPoolUsed = "BuiltInThreadPool";
+ ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
+ ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
+ int availableThreads;
+ ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
+ inUseThreads = maxThreads - availableThreads;
+ allocatedThreads = -1;
+ waitingCallbacks = -1;
+ }
+
+ if (threadPoolUsed != null)
+ {
+ sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
+ sb.AppendFormat("Max threads : {0}\n", maxThreads);
+ sb.AppendFormat("Min threads : {0}\n", minThreads);
+ sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
+ sb.AppendFormat("In use threads : {0}\n", inUseThreads);
+ sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
+ }
+ else
+ {
+ sb.AppendFormat("Thread pool not used\n");
+ }
+
+ return sb.ToString();
+ }
+
private static object SmartThreadPoolCallback(object o)
{
object[] array = (object[])o;
@@ -1696,6 +1753,20 @@ namespace OpenSim.Framework
}
const Int32 EnvironmentTickCountMask = 0x3fffffff;
+ ///
+ /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
+ /// and negative every 24.9 days. Subtracts the passed value (previously fetched by
+ /// 'EnvironmentTickCount()') and accounts for any wrapping.
+ ///
+ ///
+ ///
+ /// subtraction of passed prevValue from current Environment.TickCount
+ public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue)
+ {
+ Int32 diff = newValue - prevValue;
+ return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
+ }
+
///
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
@@ -1704,8 +1775,7 @@ namespace OpenSim.Framework
/// subtraction of passed prevValue from current Environment.TickCount
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
{
- Int32 diff = EnvironmentTickCount() - prevValue;
- return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
+ return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
}
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
@@ -1870,11 +1940,12 @@ namespace OpenSim.Framework
#region Universal User Identifiers
///
///
- /// uuid[;endpoint[;name]]
- ///
- ///
- ///
- ///
+ /// uuid[;endpoint[;first last[;secret]]]
+ /// the uuid part
+ /// the endpoint part (e.g. http://foo.com)
+ /// the first name part (e.g. Test)
+ /// the last name part (e.g User)
+ /// the secret part
public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
{
uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty;
@@ -1903,31 +1974,64 @@ namespace OpenSim.Framework
}
///
- ///
+ /// Produces a universal (HG) system-facing identifier given the information
///
///
- /// uuid[;endpoint[;name]]
+ /// uuid[;homeURI[;first last]]
public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit)
{
if (acircuit.ServiceURLs.ContainsKey("HomeURI"))
- {
- string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString();
- if (!agentsURI.EndsWith("/"))
- agentsURI += "/";
-
- // This is ugly, but there's no other way, given that the name is changed
- // in the agent circuit data for foreigners
- if (acircuit.lastname.Contains("@"))
- {
- string[] parts = acircuit.firstname.Split(new char[] { '.' });
- if (parts.Length == 2)
- return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
- }
- return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname;
- }
+ return UniversalIdentifier(acircuit.AgentID, acircuit.firstname, acircuit.lastname, acircuit.ServiceURLs["HomeURI"].ToString());
else
return acircuit.AgentID.ToString();
- }
+ }
+
+ ///
+ /// Produces a universal (HG) system-facing identifier given the information
+ ///
+ /// UUID of the user
+ /// first name (e.g Test)
+ /// last name (e.g. User)
+ /// homeURI (e.g. http://foo.com)
+ /// a string of the form uuid[;homeURI[;first last]]
+ public static string UniversalIdentifier(UUID id, String firstName, String lastName, String homeURI)
+ {
+ string agentsURI = homeURI;
+ if (!agentsURI.EndsWith("/"))
+ agentsURI += "/";
+
+ // This is ugly, but there's no other way, given that the name is changed
+ // in the agent circuit data for foreigners
+ if (lastName.Contains("@"))
+ {
+ string[] parts = firstName.Split(new char[] { '.' });
+ if (parts.Length == 2)
+ return id.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
+ }
+ return id.ToString() + ";" + agentsURI + ";" + firstName + " " + lastName;
+
+ }
+
+ ///
+ /// Produces a universal (HG) user-facing name given the information
+ ///
+ ///
+ ///
+ ///
+ /// string of the form first.last @foo.com or first last
+ public static string UniversalName(String firstName, String lastName, String homeURI)
+ {
+ Uri uri = null;
+ try
+ {
+ uri = new Uri(homeURI);
+ }
+ catch (UriFormatException)
+ {
+ return firstName + " " + lastName;
+ }
+ return firstName + "." + lastName + " " + "@" + uri.Authority;
+ }
#endregion
}
}
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index af25da9b04..ead8f463f7 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -63,6 +63,31 @@ namespace OpenSim.Framework
// a "long" call for warning & debugging purposes
public const int LongCallTime = 500;
+ // dictionary of end points
+ private static Dictionary m_endpointSerializer = new Dictionary();
+
+
+ private static object EndPointLock(string url)
+ {
+ System.Uri uri = new System.Uri(url);
+ string endpoint = string.Format("{0}:{1}",uri.Host,uri.Port);
+
+ lock (m_endpointSerializer)
+ {
+ object eplock = null;
+
+ if (! m_endpointSerializer.TryGetValue(endpoint,out eplock))
+ {
+ eplock = new object();
+ m_endpointSerializer.Add(endpoint,eplock);
+ // m_log.WarnFormat("[WEB UTIL] add a new host to end point serializer {0}",endpoint);
+ }
+
+ return eplock;
+ }
+ }
+
+
#region JSONRequest
///
@@ -95,6 +120,14 @@ namespace OpenSim.Framework
}
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
+ {
+ lock (EndPointLock(url))
+ {
+ return ServiceOSDRequestWorker(url,data,method,timeout,compressed);
+ }
+ }
+
+ private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
{
int reqnum = m_requestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
@@ -247,6 +280,14 @@ namespace OpenSim.Framework
}
public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout)
+ {
+ lock (EndPointLock(url))
+ {
+ return ServiceFormRequestWorker(url,data,timeout);
+ }
+ }
+
+ private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
{
int reqnum = m_requestNumber++;
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
@@ -469,8 +510,13 @@ namespace OpenSim.Framework
///
/// Copying begins at the streams' current positions. The positions are
/// NOT reset after copying is complete.
+ /// NOTE!! .NET 4.0 adds the method 'Stream.CopyTo(stream, bufferSize)'.
+ /// This function could be replaced with that method once we move
+ /// totally to .NET 4.0. For versions before, this routine exists.
+ /// This routine used to be named 'CopyTo' but the int parameter has
+ /// a different meaning so this method was renamed to avoid any confusion.
///
- public static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy)
+ public static int CopyStream(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy)
{
byte[] buffer = new byte[4096];
int readBytes;
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 145875b601..59b6b2197e 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -225,12 +225,12 @@ namespace OpenSim
///
private void RegisterConsoleCommands()
{
- m_console.Commands.AddCommand("region", false, "force update",
+ m_console.Commands.AddCommand("Regions", false, "force update",
"force update",
"Force the update of all objects on clients",
HandleForceUpdate);
- m_console.Commands.AddCommand("region", false, "debug packet",
+ m_console.Commands.AddCommand("Comms", false, "debug packet",
"debug packet [ ]",
"Turn on packet debugging",
"If level > 255 then all incoming and outgoing packets are logged.\n"
@@ -242,7 +242,7 @@ namespace OpenSim
+ "If an avatar name is given then only packets from that avatar are logged",
Debug);
- m_console.Commands.AddCommand("region", false, "debug http",
+ m_console.Commands.AddCommand("Comms", false, "debug http",
"debug http ",
"Turn on inbound http request debugging for everything except the event queue (see debug eq).",
"If level >= 2 then the handler used to service the request is logged.\n"
@@ -250,37 +250,37 @@ namespace OpenSim
+ "If level <= 0 then no extra http logging is done.\n",
Debug);
- m_console.Commands.AddCommand("region", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
+ m_console.Commands.AddCommand("Comms", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
- m_console.Commands.AddCommand("region", false, "debug scene",
+ m_console.Commands.AddCommand("Regions", false, "debug scene",
"debug scene ",
"Turn on scene debugging", Debug);
- m_console.Commands.AddCommand("region", false, "change region",
+ m_console.Commands.AddCommand("General", false, "change region",
"change region ",
"Change current console region", ChangeSelectedRegion);
- m_console.Commands.AddCommand("region", false, "save xml",
+ m_console.Commands.AddCommand("Archiving", false, "save xml",
"save xml",
"Save a region's data in XML format", SaveXml);
- m_console.Commands.AddCommand("region", false, "save xml2",
+ m_console.Commands.AddCommand("Archiving", false, "save xml2",
"save xml2",
"Save a region's data in XML2 format", SaveXml2);
- m_console.Commands.AddCommand("region", false, "load xml",
+ m_console.Commands.AddCommand("Archiving", false, "load xml",
"load xml [-newIDs [ ]]",
"Load a region's data from XML format", LoadXml);
- m_console.Commands.AddCommand("region", false, "load xml2",
+ m_console.Commands.AddCommand("Archiving", false, "load xml2",
"load xml2",
"Load a region's data from XML2 format", LoadXml2);
- m_console.Commands.AddCommand("region", false, "save prims xml2",
+ m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
"save prims xml2 [ ]",
"Save named prim to XML2", SavePrimsXml2);
- m_console.Commands.AddCommand("region", false, "load oar",
+ m_console.Commands.AddCommand("Archiving", false, "load oar",
"load oar [--merge] [--skip-assets] []",
"Load a region's data from an OAR archive.",
"--merge will merge the OAR with the existing scene." + Environment.NewLine
@@ -289,7 +289,7 @@ namespace OpenSim
+ " If this is not given then the command looks for an OAR named region.oar in the current directory.",
LoadOar);
- m_console.Commands.AddCommand("region", false, "save oar",
+ m_console.Commands.AddCommand("Archiving", false, "save oar",
//"save oar [-v|--version=] [-p|--profile=] []",
"save oar [-h|--home=] [--noassets] [--publish] [--perm=] []",
"Save a region's data to an OAR archive.",
@@ -306,54 +306,54 @@ namespace OpenSim
+ " If this is not given then the oar is saved to region.oar in the current directory.",
SaveOar);
- m_console.Commands.AddCommand("region", false, "edit scale",
+ m_console.Commands.AddCommand("Regions", false, "edit scale",
"edit scale ",
"Change the scale of a named prim", HandleEditScale);
- m_console.Commands.AddCommand("region", false, "kick user",
+ m_console.Commands.AddCommand("Users", false, "kick user",
"kick user [message]",
"Kick a user off the simulator", KickUserCommand);
- m_console.Commands.AddCommand("region", false, "show users",
+ m_console.Commands.AddCommand("Users", false, "show users",
"show users [full]",
"Show user data for users currently on the region",
"Without the 'full' option, only users actually on the region are shown."
+ " With the 'full' option child agents of users in neighbouring regions are also shown.",
HandleShow);
- m_console.Commands.AddCommand("region", false, "show connections",
+ m_console.Commands.AddCommand("Comms", false, "show connections",
"show connections",
"Show connection data", HandleShow);
- m_console.Commands.AddCommand("region", false, "show circuits",
+ m_console.Commands.AddCommand("Comms", false, "show circuits",
"show circuits",
"Show agent circuit data", HandleShow);
- m_console.Commands.AddCommand("region", false, "show http-handlers",
+ m_console.Commands.AddCommand("Comms", false, "show http-handlers",
"show http-handlers",
"Show all registered http handlers", HandleShow);
- m_console.Commands.AddCommand("region", false, "show pending-objects",
+ m_console.Commands.AddCommand("Comms", false, "show pending-objects",
"show pending-objects",
"Show # of objects on the pending queues of all scene viewers", HandleShow);
- m_console.Commands.AddCommand("region", false, "show modules",
+ m_console.Commands.AddCommand("General", false, "show modules",
"show modules",
"Show module data", HandleShow);
- m_console.Commands.AddCommand("region", false, "show regions",
+ m_console.Commands.AddCommand("Regions", false, "show regions",
"show regions",
"Show region data", HandleShow);
- m_console.Commands.AddCommand("region", false, "show ratings",
+ m_console.Commands.AddCommand("Regions", false, "show ratings",
"show ratings",
"Show rating data", HandleShow);
- m_console.Commands.AddCommand("region", false, "backup",
+ m_console.Commands.AddCommand("Regions", false, "backup",
"backup",
"Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand);
- m_console.Commands.AddCommand("region", false, "create region",
+ m_console.Commands.AddCommand("Regions", false, "create region",
"create region [\"region name\"] ",
"Create a new region.",
"The settings for \"region name\" are read from . Paths specified with are relative to your Regions directory, unless an absolute path is given."
@@ -362,62 +362,57 @@ namespace OpenSim
+ "If does not exist, it will be created.",
HandleCreateRegion);
- m_console.Commands.AddCommand("region", false, "restart",
+ m_console.Commands.AddCommand("Regions", false, "restart",
"restart",
"Restart all sims in this instance", RunCommand);
- m_console.Commands.AddCommand("region", false, "config set",
+ m_console.Commands.AddCommand("General", false, "config set",
"config set ",
"Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
- m_console.Commands.AddCommand("region", false, "config get",
+ m_console.Commands.AddCommand("General", false, "config get",
"config get [] []",
"Synonym for config show",
HandleConfig);
- m_console.Commands.AddCommand("region", false, "config show",
+ m_console.Commands.AddCommand("General", false, "config show",
"config show [] []",
"Show config information",
"If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
+ "If a section is given but not a field, then all fields in that section are printed.",
HandleConfig);
- m_console.Commands.AddCommand("region", false, "config save",
+ m_console.Commands.AddCommand("General", false, "config save",
"config save ",
"Save current configuration to a file at the given path", HandleConfig);
- m_console.Commands.AddCommand("region", false, "command-script",
+ m_console.Commands.AddCommand("General", false, "command-script",
"command-script