diff --git a/.nant/local.include b/.nant/local.include
index 4fa3e4df4b..6d3e97228f 100644
--- a/.nant/local.include
+++ b/.nant/local.include
@@ -2,13 +2,37 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index e0a96e76ad..de5a6fc04b 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -86,6 +86,7 @@ what it is today.
* Grumly57
* GuduleLapointe
* Ewe Loon
+* Fernando Oliveira
* Fly-Man
* Flyte Xevious
* Imaze Rhiano
@@ -135,6 +136,7 @@ what it is today.
* Ruud Lathorp
* SachaMagne
* Salahzar Stenvaag
+* satguru p srivastava
* sempuki
* SignpostMarv
* SpotOn3D
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 e58620a7a0..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()
@@ -1367,7 +1370,7 @@ VALUES
newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
- newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
+ newSettings.Sandbox = Convert.ToBoolean(row["Sandbox"]);
newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
newSettings.SunVector = new Vector3(
@@ -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"]);
@@ -1782,7 +1799,7 @@ VALUES
parameters.Add(_Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit));
parameters.Add(_Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit));
parameters.Add(_Database.CreateParameter("use_estate_sun", settings.UseEstateSun));
- parameters.Add(_Database.CreateParameter("sandbox", settings.Sandbox));
+ parameters.Add(_Database.CreateParameter("Sandbox", settings.Sandbox));
parameters.Add(_Database.CreateParameter("fixed_sun", settings.FixedSun));
parameters.Add(_Database.CreateParameter("sun_position", settings.SunPosition));
parameters.Add(_Database.CreateParameter("sunvectorx", settings.SunVector.X));
@@ -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/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 7c995ad4c4..381a514bea 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -1283,7 +1283,7 @@ namespace OpenSim.Data.MySQL
newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
- newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
+ newSettings.Sandbox = Convert.ToBoolean(row["Sandbox"]);
newSettings.SunVector = new Vector3 (
Convert.ToSingle(row["sunvectorx"]),
Convert.ToSingle(row["sunvectory"]),
diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs
new file mode 100644
index 0000000000..06fe55a9b3
--- /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 : AssetDataBase
+ {
+ 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 override 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 override 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 override void Initialise()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Dispose() { }
+
+ ///
+ /// The name of this DB provider
+ ///
+ override 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
+ override 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
+ override 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.
+ override 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 override 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 override 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/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
index 0f40cdc04d..1ceddf98a1 100644
--- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
@@ -541,4 +541,26 @@ CREATE TABLE regionwindlight (
cloud_scroll_y_lock INTEGER NOT NULL DEFAULT '0',
draw_classic_clouds INTEGER NOT NULL DEFAULT '1');
-COMMIT;
\ No newline at end of file
+COMMIT;
+
+
+:VERSION 24
+
+BEGIN;
+
+CREATE TABLE IF NOT EXISTS `spawn_points` (
+ `RegionID` varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000',
+ `Yaw` float NOT NULL,
+ `Pitch` float NOT NULL,
+ `Distance` float NOT NULL
+);
+
+ALTER TABLE `regionsettings` ADD COLUMN `TelehubObject` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
+
+COMMIT;
+
+:VERSION 25
+
+BEGIN;
+ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
+COMMIT;
diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs
index bb23fc1b56..d0e24c325c 100644
--- a/OpenSim/Data/SQLite/SQLiteAssetData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs
@@ -81,6 +81,9 @@ namespace OpenSim.Data.SQLite
/// connect string
override public void Initialise(string dbconnect)
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
if (dbconnect == string.Empty)
{
dbconnect = "URI=file:Asset.db,version=3";
diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
index f51aa288d4..5120453d1b 100644
--- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
@@ -65,6 +65,9 @@ namespace OpenSim.Data.SQLite
if (!m_initialized)
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
m_Connection = new SqliteConnection(connectionString);
m_Connection.Open();
diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs
index 8db9262e18..c042ba2bd3 100644
--- a/OpenSim/Data/SQLite/SQLiteEstateData.cs
+++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs
@@ -69,6 +69,9 @@ namespace OpenSim.Data.SQLite
public void Initialise(string connectionString)
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
m_connectionString = connectionString;
m_log.Info("[ESTATE DB]: Sqlite - connecting: "+m_connectionString);
diff --git a/OpenSim/Data/SQLite/SQLiteFramework.cs b/OpenSim/Data/SQLite/SQLiteFramework.cs
index 4992bcc7de..159471723e 100644
--- a/OpenSim/Data/SQLite/SQLiteFramework.cs
+++ b/OpenSim/Data/SQLite/SQLiteFramework.cs
@@ -48,6 +48,8 @@ namespace OpenSim.Data.SQLite
protected SQLiteFramework(string connectionString)
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
}
//////////////////////////////////////////////////////////////
diff --git a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs
index 7dc07ec1ac..ccbd154b80 100644
--- a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs
+++ b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs
@@ -77,6 +77,9 @@ namespace OpenSim.Data.SQLite
{
m_Initialized = true;
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
if (dbconnect == string.Empty)
{
dbconnect = "URI=file:inventoryStore.db,version=3";
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index ce1b7b4887..7e7c08a74f 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -61,6 +61,7 @@ namespace OpenSim.Data.SQLite
private const string regionbanListSelect = "select * from regionban";
private const string regionSettingsSelect = "select * from regionsettings";
private const string regionWindlightSelect = "select * from regionwindlight";
+ private const string regionSpawnPointsSelect = "select * from spawn_points";
private DataSet ds;
private SqliteDataAdapter primDa;
@@ -71,6 +72,7 @@ namespace OpenSim.Data.SQLite
private SqliteDataAdapter landAccessListDa;
private SqliteDataAdapter regionSettingsDa;
private SqliteDataAdapter regionWindlightDa;
+ private SqliteDataAdapter regionSpawnPointsDa;
private SqliteConnection m_conn;
private String m_connectionString;
@@ -108,6 +110,9 @@ namespace OpenSim.Data.SQLite
{
try
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
m_connectionString = connectionString;
ds = new DataSet("Region");
@@ -140,6 +145,10 @@ namespace OpenSim.Data.SQLite
SqliteCommand regionWindlightSelectCmd = new SqliteCommand(regionWindlightSelect, m_conn);
regionWindlightDa = new SqliteDataAdapter(regionWindlightSelectCmd);
+
+ SqliteCommand regionSpawnPointsSelectCmd = new SqliteCommand(regionSpawnPointsSelect, m_conn);
+ regionSpawnPointsDa = new SqliteDataAdapter(regionSpawnPointsSelectCmd);
+
// This actually does the roll forward assembly stuff
Migration m = new Migration(m_conn, Assembly, "RegionStore");
m.Update();
@@ -170,6 +179,9 @@ namespace OpenSim.Data.SQLite
ds.Tables.Add(createRegionWindlightTable());
setupRegionWindlightCommands(regionWindlightDa, m_conn);
+ ds.Tables.Add(createRegionSpawnPointsTable());
+ setupRegionSpawnPointsCommands(regionSpawnPointsDa, m_conn);
+
// WORKAROUND: This is a work around for sqlite on
// windows, which gets really unhappy with blob columns
// that have no sample data in them. At some point we
@@ -246,6 +258,15 @@ namespace OpenSim.Data.SQLite
m_log.ErrorFormat("[SQLITE REGION DB]: Caught fill error on regionwindlight table :{0}", e.Message);
}
+ try
+ {
+ regionSpawnPointsDa.Fill(ds.Tables["spawn_points"]);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[SQLITE REGION DB]: Caught fill error on spawn_points table :{0}", e.Message);
+ }
+
// We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values!
// Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409
// Possibly because we manually set up our own DataTables before connecting to the database
@@ -257,6 +278,7 @@ namespace OpenSim.Data.SQLite
CreateDataSetMapping(landAccessListDa, "landaccesslist");
CreateDataSetMapping(regionSettingsDa, "regionsettings");
CreateDataSetMapping(regionWindlightDa, "regionwindlight");
+ CreateDataSetMapping(regionSpawnPointsDa, "spawn_points");
}
}
catch (Exception e)
@@ -319,6 +341,11 @@ namespace OpenSim.Data.SQLite
regionWindlightDa.Dispose();
regionWindlightDa = null;
}
+ if (regionSpawnPointsDa != null)
+ {
+ regionSpawnPointsDa.Dispose();
+ regionWindlightDa = null;
+ }
}
public void StoreRegionSettings(RegionSettings rs)
@@ -339,8 +366,43 @@ namespace OpenSim.Data.SQLite
fillRegionSettingsRow(settingsRow, rs);
}
+ StoreSpawnPoints(rs);
+
Commit();
}
+
+ }
+
+ public void StoreSpawnPoints(RegionSettings rs)
+ {
+ lock (ds)
+ {
+ // DataTable spawnpoints = ds.Tables["spawn_points"];
+
+ // remove region's spawnpoints
+ using (
+ SqliteCommand cmd =
+ new SqliteCommand("delete from spawn_points where RegionID=:RegionID",
+ m_conn))
+ {
+
+ cmd.Parameters.Add(new SqliteParameter(":RegionID", rs.RegionUUID.ToString()));
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ foreach (SpawnPoint sp in rs.SpawnPoints())
+ {
+ using (SqliteCommand cmd = new SqliteCommand("insert into spawn_points(RegionID, Yaw, Pitch, Distance)" +
+ "values ( :RegionID, :Yaw, :Pitch, :Distance)", m_conn))
+ {
+ cmd.Parameters.Add(new SqliteParameter(":RegionID", rs.RegionUUID.ToString()));
+ cmd.Parameters.Add(new SqliteParameter(":Yaw", sp.Yaw));
+ cmd.Parameters.Add(new SqliteParameter(":Pitch", sp.Pitch));
+ cmd.Parameters.Add(new SqliteParameter(":Distance", sp.Distance));
+ cmd.ExecuteNonQuery();
+ }
+ }
}
///
@@ -435,10 +497,31 @@ namespace OpenSim.Data.SQLite
RegionSettings newSettings = buildRegionSettings(row);
newSettings.OnSave += StoreRegionSettings;
+ LoadSpawnPoints(newSettings);
+
return newSettings;
}
}
+ private void LoadSpawnPoints(RegionSettings rs)
+ {
+ rs.ClearSpawnPoints();
+
+ DataTable spawnpoints = ds.Tables["spawn_points"];
+ string byRegion = "RegionID = '" + rs.RegionUUID + "'";
+ DataRow[] spForRegion = spawnpoints.Select(byRegion);
+
+ foreach (DataRow spRow in spForRegion)
+ {
+ SpawnPoint sp = new SpawnPoint();
+ sp.Pitch = (float)spRow["Pitch"];
+ sp.Yaw = (float)spRow["Yaw"];
+ sp.Distance = (float)spRow["Distance"];
+
+ rs.AddSpawnPoint(sp);
+ }
+ }
+
///
/// Adds an object into region storage
///
@@ -1265,6 +1348,8 @@ namespace OpenSim.Data.SQLite
createCol(regionsettings, "covenant", typeof(String));
createCol(regionsettings, "covenant_datetime", typeof(Int32));
createCol(regionsettings, "map_tile_ID", typeof(String));
+ createCol(regionsettings, "TelehubObject", typeof(String));
+ createCol(regionsettings, "parcel_tile_ID", typeof(String));
regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] };
return regionsettings;
}
@@ -1345,6 +1430,17 @@ namespace OpenSim.Data.SQLite
return regionwindlight;
}
+ private static DataTable createRegionSpawnPointsTable()
+ {
+ DataTable spawn_points = new DataTable("spawn_points");
+ createCol(spawn_points, "regionID", typeof(String));
+ createCol(spawn_points, "Yaw", typeof(float));
+ createCol(spawn_points, "Pitch", typeof(float));
+ createCol(spawn_points, "Distance", typeof(float));
+
+ return spawn_points;
+ }
+
/***********************************************************************
*
* Convert between ADO.NET <=> OpenSim Objects
@@ -1666,6 +1762,8 @@ namespace OpenSim.Data.SQLite
newSettings.Covenant = new UUID((String)row["covenant"]);
newSettings.CovenantChangedDateTime = Convert.ToInt32(row["covenant_datetime"]);
newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]);
+ newSettings.TelehubObject = new UUID((String)row["TelehubObject"]);
+ newSettings.ParcelImageID = new UUID((String)row["parcel_tile_ID"]);
return newSettings;
}
@@ -2059,7 +2157,7 @@ namespace OpenSim.Data.SQLite
row["terrain_raise_limit"] = settings.TerrainRaiseLimit;
row["terrain_lower_limit"] = settings.TerrainLowerLimit;
row["use_estate_sun"] = settings.UseEstateSun;
- row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox
+ row["sandbox"] = settings.Sandbox; // unlike other database modules, sqlite uses a lower case s for sandbox!
row["sunvectorx"] = settings.SunVector.X;
row["sunvectory"] = settings.SunVector.Y;
row["sunvectorz"] = settings.SunVector.Z;
@@ -2068,6 +2166,8 @@ namespace OpenSim.Data.SQLite
row["covenant"] = settings.Covenant.ToString();
row["covenant_datetime"] = settings.CovenantChangedDateTime;
row["map_tile_ID"] = settings.TerrainImageID.ToString();
+ row["TelehubObject"] = settings.TelehubObject.ToString();
+ row["parcel_tile_ID"] = settings.ParcelImageID.ToString();
}
///
@@ -2591,6 +2691,14 @@ namespace OpenSim.Data.SQLite
da.UpdateCommand.Connection = conn;
}
+ private void setupRegionSpawnPointsCommands(SqliteDataAdapter da, SqliteConnection conn)
+ {
+ da.InsertCommand = createInsertCommand("spawn_points", ds.Tables["spawn_points"]);
+ da.InsertCommand.Connection = conn;
+ da.UpdateCommand = createUpdateCommand("spawn_points", "RegionID=:RegionID", ds.Tables["spawn_points"]);
+ da.UpdateCommand.Connection = conn;
+ }
+
///
///
///
diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
index 16f9046186..1f369867ce 100644
--- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
+++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
@@ -52,6 +52,9 @@ namespace OpenSim.Data.SQLite
public SQLiteXInventoryData(string conn, string realm)
{
+ if (Util.IsWindows())
+ Util.LoadArchSpecificWindowsDll("sqlite3.dll");
+
m_Folders = new SQLiteGenericTableHandler(
conn, "inventoryfolders", "XInventoryStore");
m_Items = new SqliteItemHandler(
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 0d6288b5a3..2bb7de1cae 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,61 @@ 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)
+ if (m_modulesCommands.ContainsKey(moduleName))
{
- result.AddRange(CollectHelp((Dictionary)kvp.Value));
+ List commands = m_modulesCommands[moduleName];
+ var ourHelpText = commands.ConvertAll(c => string.Format("{0} - {1}", c.help_text, c.long_help));
+ ourHelpText.Sort();
+ helpText.AddRange(ourHelpText);
+
+ return true;
}
else
{
- if (((CommandInfo)kvp.Value).long_help != String.Empty)
- result.Add(((CommandInfo)kvp.Value).help_text+" - "+
- ((CommandInfo)kvp.Value).long_help);
+ 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 +265,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 +301,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 +676,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/Console/MockConsole.cs b/OpenSim/Framework/Console/MockConsole.cs
index a29b370857..4d8751f5f6 100644
--- a/OpenSim/Framework/Console/MockConsole.cs
+++ b/OpenSim/Framework/Console/MockConsole.cs
@@ -29,6 +29,7 @@ using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;
+using System.Xml;
namespace OpenSim.Framework.Console
{
@@ -37,28 +38,42 @@ namespace OpenSim.Framework.Console
/// Don't use this except for Unit Testing or you're in for a world of hurt when the
/// sim gets to ReadLine
///
- public class MockConsole : CommandConsole
+ public class MockConsole : ICommandConsole
{
- public MockConsole(string defaultPrompt) : base(defaultPrompt)
- {
- }
- public override void Output(string text)
- {
- }
- public override void Output(string text, string level)
- {
- }
+ private MockCommands m_commands = new MockCommands();
- public override string ReadLine(string p, bool isCommand, bool e)
- {
- //Thread.CurrentThread.Join(1000);
- return string.Empty;
- }
- public override void UnlockOutput()
- {
- }
- public override void LockOutput()
- {
- }
+ public ICommands Commands { get { return m_commands; } }
+
+ public void Prompt() {}
+
+ public void RunCommand(string cmd) {}
+
+ public string ReadLine(string p, bool isCommand, bool e) { return ""; }
+
+ public object ConsoleScene { get { return null; } }
+
+ public void Output(string text, string level) {}
+ public void Output(string text) {}
+ public void OutputFormat(string format, params object[] components) {}
+
+ public string CmdPrompt(string p) { return ""; }
+ public string CmdPrompt(string p, string def) { return ""; }
+ public string CmdPrompt(string p, List excludedCharacters) { return ""; }
+ public string CmdPrompt(string p, string def, List excludedCharacters) { return ""; }
+
+ public string CmdPrompt(string prompt, string defaultresponse, List options) { return ""; }
+
+ public string PasswdPrompt(string p) { return ""; }
}
-}
+
+ public class MockCommands : ICommands
+ {
+ public void FromXml(XmlElement root, CommandDelegate fn) {}
+ public List GetHelp(string[] cmd) { return null; }
+ public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) {}
+ public void AddCommand(string module, bool shared, string command, string help, string longhelp, string descriptivehelp, CommandDelegate fn) {}
+ public string[] FindNextOption(string[] cmd, bool term) { return null; }
+ public string[] Resolve(string[] cmd) { return null; }
+ public XmlElement GetXml(XmlDocument doc) { return null; }
+ }
+}
\ No newline at end of file
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/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/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index b337e034fa..f9cb851a9e 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
+using System.Xml;
using log4net;
using OpenMetaverse;
@@ -39,6 +40,13 @@ namespace OpenSim.Framework
#region SL / file extension / content-type conversions
+ public static Dictionary DefaultAvatarAnimations = new Dictionary();
+
+ static SLUtil()
+ {
+ DefaultAvatarAnimations = LoadDefaultAvatarAnimations("data/avataranimations.xml");
+ }
+
public static string SLAssetTypeToContentType(int assetType)
{
switch ((AssetType)assetType)
@@ -374,5 +382,47 @@ namespace OpenSim.Framework
return output;
}
+
+ ///
+ /// Load the default SL avatar animations.
+ ///
+ ///
+ public static Dictionary LoadDefaultAvatarAnimations(string path)
+ {
+ Dictionary animations = new Dictionary();
+
+ using (XmlTextReader reader = new XmlTextReader(path))
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.Load(reader);
+ if (doc.DocumentElement != null)
+ {
+ foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
+ {
+ if (nod.Attributes["name"] != null)
+ {
+ string name = nod.Attributes["name"].Value.ToLower();
+ string id = nod.InnerText;
+ animations.Add(name, (UUID)id);
+ }
+ }
+ }
+ }
+
+ return animations;
+ }
+
+ ///
+ /// Get the default SL avatar animation with the given name.
+ ///
+ ///
+ ///
+ public static UUID GetDefaultAvatarAnimation(string name)
+ {
+ if (DefaultAvatarAnimations.ContainsKey(name))
+ return DefaultAvatarAnimations[name];
+
+ return UUID.Zero;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 545e76c85c..d5c2515124 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()));
@@ -247,7 +247,7 @@ namespace OpenSim.Framework.Servers
string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
StringBuilder sb = new StringBuilder();
- Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreads();
+ Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
@@ -308,7 +308,9 @@ namespace OpenSim.Framework.Servers
// clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
// the clr version number doesn't match the project version number under Mono.
//m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
- m_log.Info("[STARTUP]: Operating system version: " + Environment.OSVersion + Environment.NewLine);
+ m_log.InfoFormat(
+ "[STARTUP]: Operating system version: {0}, .NET platform {1}, {2}-bit\n",
+ Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32");
StartupSpecific();
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 2206febdb1..0062d4ef15 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -65,6 +65,7 @@ namespace OpenSim.Framework.Servers.HttpServer
String.Format("PollServiceWorkerThread{0}", i),
ThreadPriority.Normal,
false,
+ true,
int.MaxValue);
}
@@ -73,6 +74,7 @@ namespace OpenSim.Framework.Servers.HttpServer
"PollServiceWatcherThread",
ThreadPriority.Normal,
false,
+ true,
1000 * 60 * 10);
}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index f30cb7a4c0..7a5d7158d6 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
{
public class VersionInfo
{
- private const string VERSION_NUMBER = "0.7.3";
+ private const string VERSION_NUMBER = "0.7.4";
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
public enum Flavour
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 4b0b13c3f4..efa4a7ba87 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -35,7 +35,8 @@ 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;
using System.Security.Cryptography;
@@ -375,6 +376,50 @@ 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);
+ }
+
+ public static bool LoadArchSpecificWindowsDll(string libraryName)
+ {
+ // We do this so that OpenSimulator on Windows loads the correct native library depending on whether
+ // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
+ // will find it already loaded later on.
+ //
+ // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be
+ // controlled in config files.
+ string nativeLibraryPath;
+
+ if (Util.Is64BitProcess())
+ nativeLibraryPath = "lib64/" + libraryName;
+ else
+ nativeLibraryPath = "lib32/" + libraryName;
+
+ m_log.DebugFormat("[UTIL]: Loading native Windows library at {0}", nativeLibraryPath);
+
+ if (Util.LoadLibrary(nativeLibraryPath) == IntPtr.Zero)
+ {
+ m_log.ErrorFormat(
+ "[UTIL]: Couldn't find native Windows library at {0}", nativeLibraryPath);
+
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
public static bool IsEnvironmentSupported(ref string reason)
@@ -1457,6 +1502,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;
}
#region FireAndForget Threading Pattern
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs
index 2dd6ebe49a..e93e50e2ca 100644
--- a/OpenSim/Framework/Watchdog.cs
+++ b/OpenSim/Framework/Watchdog.cs
@@ -72,6 +72,11 @@ namespace OpenSim.Framework
///
public bool IsTimedOut { get; set; }
+ ///
+ /// Will this thread trigger the alarm function if it has timed out?
+ ///
+ public bool AlarmIfTimeout { get; set; }
+
public ThreadWatchdogInfo(Thread thread, int timeout)
{
Thread = thread;
@@ -112,12 +117,13 @@ namespace OpenSim.Framework
/// The method that will be executed in a new thread
/// A name to give to the new thread
/// Priority to run the thread at
- /// True to run this thread as a background
- /// thread, otherwise false
+ /// True to run this thread as a background thread, otherwise false
+ /// Trigger an alarm function is we have timed out
/// The newly created Thread object
- public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground)
+ public static Thread StartThread(
+ ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
{
- return StartThread(start, name, priority, isBackground, WATCHDOG_TIMEOUT_MS);
+ return StartThread(start, name, priority, isBackground, alarmIfTimeout, WATCHDOG_TIMEOUT_MS);
}
///
@@ -128,21 +134,21 @@ namespace OpenSim.Framework
/// Priority to run the thread at
/// True to run this thread as a background
/// thread, otherwise false
- ///
- /// Number of milliseconds to wait until we issue a warning about timeout.
- ///
+ /// Trigger an alarm function is we have timed out
+ /// Number of milliseconds to wait until we issue a warning about timeout.
/// The newly created Thread object
public static Thread StartThread(
- ThreadStart start, string name, ThreadPriority priority, bool isBackground, int timeout)
+ ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, int timeout)
{
Thread thread = new Thread(start);
thread.Name = name;
thread.Priority = priority;
thread.IsBackground = isBackground;
- ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout);
+ ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout) { AlarmIfTimeout = alarmIfTimeout };
- m_log.Debug("[WATCHDOG]: Started tracking thread \"" + twi.Thread.Name + "\" (ID " + twi.Thread.ManagedThreadId + ")");
+ m_log.DebugFormat(
+ "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
lock (m_threads)
m_threads.Add(twi.Thread.ManagedThreadId, twi);
@@ -224,19 +230,39 @@ namespace OpenSim.Framework
/// Get currently watched threads for diagnostic purposes
///
///
- public static ThreadWatchdogInfo[] GetThreads()
+ public static ThreadWatchdogInfo[] GetThreadsInfo()
{
lock (m_threads)
return m_threads.Values.ToArray();
}
+ ///
+ /// Return the current thread's watchdog info.
+ ///
+ /// The watchdog info. null if the thread isn't being monitored.
+ public static ThreadWatchdogInfo GetCurrentThreadInfo()
+ {
+ lock (m_threads)
+ {
+ if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
+ return m_threads[Thread.CurrentThread.ManagedThreadId];
+ }
+
+ return null;
+ }
+
+ ///
+ /// Check watched threads. Fire alarm if appropriate.
+ ///
+ ///
+ ///
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
WatchdogTimeout callback = OnWatchdogTimeout;
if (callback != null)
{
- ThreadWatchdogInfo timedOut = null;
+ List callbackInfos = null;
lock (m_threads)
{
@@ -246,21 +272,31 @@ namespace OpenSim.Framework
{
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
{
- timedOut = threadInfo;
RemoveThread(threadInfo.Thread.ManagedThreadId);
- break;
+
+ if (callbackInfos == null)
+ callbackInfos = new List();
+
+ callbackInfos.Add(threadInfo);
}
else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout)
{
threadInfo.IsTimedOut = true;
- timedOut = threadInfo;
- break;
+
+ if (threadInfo.AlarmIfTimeout)
+ {
+ if (callbackInfos == null)
+ callbackInfos = new List();
+
+ callbackInfos.Add(threadInfo);
+ }
}
}
}
- if (timedOut != null)
- callback(timedOut.Thread, timedOut.LastTick);
+ if (callbackInfos != null)
+ foreach (ThreadWatchdogInfo callbackInfo in callbackInfos)
+ callback(callbackInfo.Thread, callbackInfo.LastTick);
}
m_watchdogTimer.Start();
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index b761dfe2a8..ead8f463f7 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -63,77 +63,32 @@ namespace OpenSim.Framework
// a "long" call for warning & debugging purposes
public const int LongCallTime = 500;
-// ///
-// /// Send LLSD to an HTTP client in application/llsd+json form
-// ///
-// /// HTTP response to send the data in
-// /// LLSD to send to the client
-// public static void SendJSONResponse(OSHttpResponse response, OSDMap body)
-// {
-// byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body));
-//
-// response.ContentEncoding = Encoding.UTF8;
-// response.ContentLength = responseData.Length;
-// response.ContentType = "application/llsd+json";
-// response.Body.Write(responseData, 0, responseData.Length);
-// }
-//
-// ///
-// /// Send LLSD to an HTTP client in application/llsd+xml form
-// ///
-// /// HTTP response to send the data in
-// /// LLSD to send to the client
-// public static void SendXMLResponse(OSHttpResponse response, OSDMap body)
-// {
-// byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body);
-//
-// response.ContentEncoding = Encoding.UTF8;
-// response.ContentLength = responseData.Length;
-// response.ContentType = "application/llsd+xml";
-// response.Body.Write(responseData, 0, responseData.Length);
-// }
+ // dictionary of end points
+ private static Dictionary m_endpointSerializer = new Dictionary();
+
- ///
- /// Make a GET or GET-like request to a web service that returns LLSD
- /// or JSON data
- ///
- public static OSDMap ServiceRequest(string url, string httpVerb)
+ private static object EndPointLock(string url)
{
- string errorMessage;
+ System.Uri uri = new System.Uri(url);
+ string endpoint = string.Format("{0}:{1}",uri.Host,uri.Port);
- try
+ lock (m_endpointSerializer)
{
- HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
- request.Method = httpVerb;
+ object eplock = null;
- using (WebResponse response = request.GetResponse())
+ if (! m_endpointSerializer.TryGetValue(endpoint,out eplock))
{
- using (Stream responseStream = response.GetResponseStream())
- {
- try
- {
- string responseStr = responseStream.GetStreamString();
- OSD responseOSD = OSDParser.Deserialize(responseStr);
- if (responseOSD.Type == OSDType.Map)
- return (OSDMap)responseOSD;
- else
- errorMessage = "Response format was invalid.";
- }
- catch
- {
- errorMessage = "Failed to parse the response.";
- }
- }
+ eplock = new object();
+ m_endpointSerializer.Add(endpoint,eplock);
+ // m_log.WarnFormat("[WEB UTIL] add a new host to end point serializer {0}",endpoint);
}
- }
- catch (Exception ex)
- {
- m_log.Warn(httpVerb + " on URL " + url + " failed: " + ex.Message);
- errorMessage = ex.Message;
- }
- return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } };
+ return eplock;
+ }
}
+
+
+ #region JSONRequest
///
/// PUT JSON-encoded data to a web service that returns LLSD or
@@ -165,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);
@@ -303,6 +266,10 @@ namespace OpenSim.Framework
return result;
}
+ #endregion JSONRequest
+
+ #region FormRequest
+
///
/// POST URL-encoded form data to a web service that returns LLSD or
/// JSON data
@@ -313,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";
@@ -397,6 +372,8 @@ namespace OpenSim.Framework
result["Message"] = OSD.FromString("Service request failed: " + msg);
return result;
}
+
+ #endregion FormRequest
#region Uri
@@ -533,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..6fba2493d4 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