From bedafb8fae9898ef0c5fc6470236ee7244e616a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 27 Mar 2015 19:32:50 -0700 Subject: varregion: refactor use of 'double heightmap[,]' into references to new class TerrainData and push the implementation from Scene into the database readers and writers. --- OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 83 +++++++++++++++++------------ OpenSim/Data/MySQL/MySQLSimulationData.cs | 66 +++++++++++++---------- OpenSim/Data/Null/NullSimulationData.cs | 22 +++++++- OpenSim/Data/PGSQL/PGSQLSimulationData.cs | 72 +++++++++++++++---------- OpenSim/Data/SQLite/SQLiteSimulationData.cs | 54 +++++++++++-------- 5 files changed, 184 insertions(+), 113 deletions(-) (limited to 'OpenSim/Data') diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 0d09be6..145b9c0 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -530,43 +530,52 @@ ELSE /// public double[,] LoadTerrain(UUID regionID) { - double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terrain.Initialize(); + double[,] ret = null; + TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight); + if (terrData != null) + ret = terrData.GetDoubles(); + return ret; + } + + // Returns 'null' if region not found + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + TerrainData terrData = null; string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc"; using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) { - // MySqlParameter param = new MySqlParameter(); - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - conn.Open(); - using (SqlDataReader reader = cmd.ExecuteReader()) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - int rev; - if (reader.Read()) + // MySqlParameter param = new MySqlParameter(); + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { - MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]); - BinaryReader br = new BinaryReader(str); - for (int x = 0; x < (int)Constants.RegionSize; x++) + if (reader.Read()) { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terrain[x, y] = br.ReadDouble(); - } + int rev = (int)reader["Revision"]; + byte[] blob = (byte[])reader["Heightfield"]; + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); } - rev = (int)reader["Revision"]; - } - else - { - _Log.Info("[REGION DB]: No terrain found for region"); - return null; + else + { + _Log.Info("[REGION DB]: No terrain found for region"); + return null; + } + _Log.Info("[REGION DB]: Loaded terrain"); } - _Log.Info("[REGION DB]: Loaded terrain revision r" + rev); } } - return terrain; + return terrData; + } + + // Legacy entry point for when terrain was always a 256x256 hieghtmap + public void StoreTerrain(double[,] ter, UUID regionID) + { + StoreTerrain(new HeightmapTerrainData(ter), regionID); } /// @@ -574,10 +583,8 @@ ELSE /// /// terrain map data. /// regionID. - public void StoreTerrain(double[,] terrain, UUID regionID) + public void StoreTerrain(TerrainData terrData, UUID regionID) { - int revision = Util.UnixTimeSinceEpoch(); - //Delete old terrain map string sql = "delete from terrain where RegionUUID=@RegionUUID"; using (SqlConnection conn = new SqlConnection(m_connectionString)) @@ -590,17 +597,23 @@ ELSE sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)"; + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); + using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) { - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision)); - cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain))); - conn.Open(); - cmd.ExecuteNonQuery(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + cmd.Parameters.Add(_Database.CreateParameter("@Revision", terrainDBRevision)); + cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", terrainDBblob)); + conn.Open(); + cmd.ExecuteNonQuery(); + } } - _Log.Info("[REGION DB]: Stored terrain revision r " + revision); + _Log.Info("[REGION DB]: Stored terrain"); } /// @@ -1344,6 +1357,7 @@ VALUES #region Private Methods + /* /// /// Serializes the terrain data for storage in DB. /// @@ -1367,6 +1381,7 @@ VALUES return str.ToArray(); } + */ /// /// Stores new regionsettings. diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index cc844ae..f910e44 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -48,8 +48,18 @@ namespace OpenSim.Data.MySQL public class MySQLSimulationData : ISimulationDataStore { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static string LogHeader = "[REGION DB MYSQL]"; private string m_connectionString; + + /// + /// This lock was being used to serialize database operations when the connection was shared, but this has + /// been unnecessary for a long time after we switched to using MySQL's underlying connection pooling instead. + /// FIXME: However, the locks remain in many places since they are effectively providing a level of + /// transactionality. This should be replaced by more efficient database transactions which would not require + /// unrelated operations to block each other or unrelated operations on the same tables from blocking each + /// other. + /// private object m_dbLock = new object(); protected virtual Assembly Assembly @@ -91,7 +101,7 @@ namespace OpenSim.Data.MySQL } catch (Exception e) { - m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message); + m_log.ErrorFormat("{0} MySQL error in ExecuteReader: {1}", LogHeader, e); throw; } @@ -574,12 +584,16 @@ namespace OpenSim.Data.MySQL } } - public virtual void StoreTerrain(double[,] ter, UUID regionID) + // Legacy entry point for when terrain was always a 256x256 hieghtmap + public void StoreTerrain(double[,] ter, UUID regionID) + { + StoreTerrain(new HeightmapTerrainData(ter), regionID); + } + + public void StoreTerrain(TerrainData terrData, UUID regionID) { Util.FireAndForget(delegate(object x) { - double[,] oldTerrain = LoadTerrain(regionID); - m_log.Info("[REGION DB]: Storing terrain"); lock (m_dbLock) @@ -601,8 +615,12 @@ namespace OpenSim.Data.MySQL "Revision, Heightfield) values (?RegionUUID, " + "1, ?Heightfield)"; - cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString()); - cmd2.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter, oldTerrain)); + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); + + cmd2.Parameters.AddWithValue("Revision", terrainDBRevision); + cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob); ExecuteNonQuery(cmd); ExecuteNonQuery(cmd2); @@ -618,9 +636,20 @@ namespace OpenSim.Data.MySQL }); } + // Legacy region loading public virtual double[,] LoadTerrain(UUID regionID) { - double[,] terrain = null; + double[,] ret = null; + TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight); + if (terrData != null) + ret = terrData.GetDoubles(); + return ret; + } + + // Returns 'null' if region not found + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + TerrainData terrData = null; lock (m_dbLock) { @@ -640,32 +669,15 @@ namespace OpenSim.Data.MySQL while (reader.Read()) { int rev = Convert.ToInt32(reader["Revision"]); - - terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terrain.Initialize(); - - using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(mstr)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terrain[x, y] = br.ReadDouble(); - } - } - } - - m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev); - } + byte[] blob = (byte[])reader["Heightfield"]; + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); } } } } } - return terrain; + return terrData; } public virtual void RemoveLandObject(UUID globalID) diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs index 15824a9..339e7f4 100644 --- a/OpenSim/Data/Null/NullSimulationData.cs +++ b/OpenSim/Data/Null/NullSimulationData.cs @@ -132,18 +132,36 @@ namespace OpenSim.Data.Null return new List(); } - Dictionary m_terrains = new Dictionary(); - public void StoreTerrain(double[,] ter, UUID regionID) + Dictionary m_terrains = new Dictionary(); + public void StoreTerrain(TerrainData ter, UUID regionID) { if (m_terrains.ContainsKey(regionID)) m_terrains.Remove(regionID); m_terrains.Add(regionID, ter); } + // Legacy. Just don't do this. + public void StoreTerrain(double[,] ter, UUID regionID) + { + TerrainData terrData = new HeightmapTerrainData(ter); + StoreTerrain(terrData, regionID); + } + + // Legacy. Just don't do this. + // Returns 'null' if region not found public double[,] LoadTerrain(UUID regionID) { if (m_terrains.ContainsKey(regionID)) { + return m_terrains[regionID].GetDoubles(); + } + return null; + } + + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + if (m_terrains.ContainsKey(regionID)) + { return m_terrains[regionID]; } return null; diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs index 3243635..cd02e05 100644 --- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs +++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs @@ -46,6 +46,7 @@ namespace OpenSim.Data.PGSQL public class PGSQLSimulationData : ISimulationDataStore { private const string _migrationStore = "RegionStore"; + private const string LogHeader = "[REGION DB PGSQL]"; // private static FileSystemDataStore Instance = new FileSystemDataStore(); private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -523,8 +524,17 @@ namespace OpenSim.Data.PGSQL /// public double[,] LoadTerrain(UUID regionID) { - double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terrain.Initialize(); + double[,] ret = null; + TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight); + if (terrData != null) + ret = terrData.GetDoubles(); + return ret; + } + + // Returns 'null' if region not found + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + TerrainData terrData = null; string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; "; @@ -540,16 +550,9 @@ namespace OpenSim.Data.PGSQL int rev; if (reader.Read()) { - MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]); - BinaryReader br = new BinaryReader(str); - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terrain[x, y] = br.ReadDouble(); - } - } - rev = (int)reader["Revision"]; + rev = Convert.ToInt32(reader["Revision"]); + byte[] blob = (byte[])reader["Heightfield"]; + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); } else { @@ -560,7 +563,13 @@ namespace OpenSim.Data.PGSQL } } - return terrain; + return terrData; + } + + // Legacy entry point for when terrain was always a 256x256 heightmap + public void StoreTerrain(double[,] terrain, UUID regionID) + { + StoreTerrain(new HeightmapTerrainData(terrain), regionID); } /// @@ -568,35 +577,38 @@ namespace OpenSim.Data.PGSQL /// /// terrain map data. /// regionID. - public void StoreTerrain(double[,] terrain, UUID regionID) + public void StoreTerrain(TerrainData terrData, UUID regionID) { - int revision = Util.UnixTimeSinceEpoch(); - //Delete old terrain map string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID"; using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) - using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) { - cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID)); - conn.Open(); - cmd.ExecuteNonQuery(); + using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } } - - _Log.Info("[REGION DB]: Deleted terrain revision r " + revision); + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)"; using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString)) - using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) { - cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID)); - cmd.Parameters.Add(_Database.CreateParameter("Revision", revision)); - cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain))); - conn.Open(); - cmd.ExecuteNonQuery(); + using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID)); + cmd.Parameters.Add(_Database.CreateParameter("Revision", terrainDBRevision)); + cmd.Parameters.Add(_Database.CreateParameter("Heightfield", terrainDBblob)); + conn.Open(); + cmd.ExecuteNonQuery(); + } } - _Log.Info("[REGION DB]: Stored terrain revision r " + revision); + _Log.Info("[REGION DB]: Stored terrain revision r " + terrainDBRevision); } /// @@ -1349,6 +1361,7 @@ namespace OpenSim.Data.PGSQL #region Private Methods + /* /// /// Serializes the terrain data for storage in DB. /// @@ -1372,6 +1385,7 @@ namespace OpenSim.Data.PGSQL return str.ToArray(); } + */ /// /// Stores new regionsettings. diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index 4d6a80a..d28c227 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -51,6 +51,7 @@ namespace OpenSim.Data.SQLite public class SQLiteSimulationData : ISimulationDataStore { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly string LogHeader = "[REGION DB SQLLITE]"; private const string primSelect = "select * from prims"; private const string shapeSelect = "select * from primshapes"; @@ -819,12 +820,18 @@ namespace OpenSim.Data.SQLite prim.Inventory.RestoreInventoryItems(inventory); } + // Legacy entry point for when terrain was always a 256x256 hieghtmap + public void StoreTerrain(double[,] ter, UUID regionID) + { + StoreTerrain(new HeightmapTerrainData(ter), regionID); + } + /// /// Store a terrain revision in region storage /// /// terrain heightfield /// region UUID - public void StoreTerrain(double[,] ter, UUID regionID) + public void StoreTerrain(TerrainData terrData, UUID regionID) { lock (ds) { @@ -853,11 +860,17 @@ namespace OpenSim.Data.SQLite String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + " values(:RegionUUID, :Revision, :Heightfield)"; + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); + + m_log.DebugFormat("{0} Storing terrain revision r {1}", LogHeader, terrainDBRevision); + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) { cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.Parameters.Add(new SqliteParameter(":Revision", terrainDBRevision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", terrainDBblob)); cmd.ExecuteNonQuery(); } } @@ -870,11 +883,20 @@ namespace OpenSim.Data.SQLite /// Heightfield data public double[,] LoadTerrain(UUID regionID) { + double[,] ret = null; + TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight); + if (terrData != null) + ret = terrData.GetDoubles(); + return ret; + } + + // Returns 'null' if region not found + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + TerrainData terrData = null; + lock (ds) { - double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terret.Initialize(); - String sql = "select RegionUUID, Revision, Heightfield from terrain" + " where RegionUUID=:RegionUUID order by Revision desc"; @@ -887,21 +909,9 @@ namespace OpenSim.Data.SQLite int rev = 0; if (row.Read()) { - // TODO: put this into a function - using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(str)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terret[x, y] = br.ReadDouble(); - } - } - } - } rev = Convert.ToInt32(row["Revision"]); + byte[] blob = (byte[])row["Heightfield"]; + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); } else { @@ -912,8 +922,8 @@ namespace OpenSim.Data.SQLite m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString()); } } - return terret; } + return terrData; } public void RemoveLandObject(UUID globalID) @@ -2016,6 +2026,7 @@ namespace OpenSim.Data.SQLite return entry; } + /* /// /// /// @@ -2033,6 +2044,7 @@ namespace OpenSim.Data.SQLite return str.ToArray(); } + */ // private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) // { -- cgit v1.1 From 08c72a8dc1e54114559521a6c2952905ecf6f105 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 28 Mar 2015 07:50:04 -0700 Subject: varregion: remove use of Constants.RegionSize is various places. More use of the Util routines for conversion of region handles into addresses. --- OpenSim/Data/IRegionData.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Data') diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs index 463c621..ca9b327 100644 --- a/OpenSim/Data/IRegionData.cs +++ b/OpenSim/Data/IRegionData.cs @@ -52,14 +52,14 @@ namespace OpenSim.Data public int sizeY; /// - /// Return the x-coordinate of this region. + /// Return the x-coordinate of this region in region units. /// - public int coordX { get { return posX / (int)Constants.RegionSize; } } + public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } } /// - /// Return the y-coordinate of this region. + /// Return the y-coordinate of this region in region units. /// - public int coordY { get { return posY / (int)Constants.RegionSize; } } + public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } } public Dictionary Data; } -- cgit v1.1