From c4707a284ffecf81e8ca60a1019e234339222631 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Mon, 22 Oct 2007 15:23:48 +0000 Subject: * Major ass commit. * Sqlite Storage Engine now supports terrain -- however be aware that every terrain revision stored will at 512KB to your database file. At the moment it is storing every revision from the first. * Fixed an issue where by noverbose mode would display lots of useless junk. Noverbose mode is now quite usable. * Fixed a whole bunch of console message issues such as naming and categorisation --- .../MonoSqliteDataStore.cs | 121 ++++++++++++++++++++- 1 file changed, 117 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs') diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs index 733e4c4..cc0ff7a 100644 --- a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs +++ b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs @@ -43,10 +43,12 @@ namespace OpenSim.DataStore.MonoSqlite { private const string primSelect = "select * from prims"; private const string shapeSelect = "select * from primshapes"; + private const string terrainSelect = "select * from terrain"; private DataSet ds; private SqliteDataAdapter primDa; private SqliteDataAdapter shapeDa; + private SqliteDataAdapter terrainDa; /*********************************************************************** * @@ -70,6 +72,8 @@ namespace OpenSim.DataStore.MonoSqlite shapeDa = new SqliteDataAdapter(shapeSelectCmd); // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); // We fill the data set, now we've got copies in memory for the information // TODO: see if the linkage actually holds. @@ -83,6 +87,10 @@ namespace OpenSim.DataStore.MonoSqlite ds.Tables.Add(createShapeTable()); setupShapeCommands(shapeDa, conn); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, conn); + terrainDa.Fill(ds.Tables["terrain"]); // WORKAROUND: This is a work around for sqlite on // windows, which gets really unhappy with blob columns @@ -210,14 +218,57 @@ namespace OpenSim.DataStore.MonoSqlite } - public void StoreTerrain(double[,] ter) + public void StoreTerrain(double[,] ter, LLUUID regionID) { + int revision = OpenSim.Framework.Utilities.Util.UnixTimeSinceEpoch(); + + MainLog.Instance.Verbose("DATASTORE", "Storing terrain revision r" + revision.ToString()); + + DataTable terrain = ds.Tables["terrain"]; + + DataRow newrow = terrain.NewRow(); + fillTerrainRow(newrow, regionID, revision, ter); + terrain.Rows.Add(newrow); + Commit(); } - public double[,] LoadTerrain() + public double[,] LoadTerrain(LLUUID regionID) { - return null; + double[,] terret = new double[256, 256]; + terret.Initialize(); + + DataTable terrain = ds.Tables["terrain"]; + + DataRow[] rows = terrain.Select("RegionUUID = '" + regionID.ToString() + "'","Revision DESC"); + + int rev = 0; + + if (rows.Length > 0) + { + DataRow row = rows[0]; + + byte[] heightmap = (byte[])row["Heightfield"]; + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + terret[x, y] = BitConverter.ToDouble(heightmap, ((x * 256) + y) * 8); + } + } + + rev = (int)row["Revision"]; + } + else + { + MainLog.Instance.Verbose("DATASTORE", "No terrain found for region"); + return null; + } + + + MainLog.Instance.Verbose("DATASTORE", "Loaded terrain revision r" + rev.ToString()); + + return terret; } public void RemoveLandObject(uint id) @@ -240,6 +291,7 @@ namespace OpenSim.DataStore.MonoSqlite lock (ds) { primDa.Update(ds, "prims"); shapeDa.Update(ds, "primshapes"); + terrainDa.Update(ds, "terrain"); ds.AcceptChanges(); } } @@ -263,6 +315,22 @@ namespace OpenSim.DataStore.MonoSqlite dt.Columns.Add(col); } + private DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof(System.String)); + createCol(terrain, "Revision", typeof(System.Int32)); + createCol(terrain, "Heightfield", typeof(System.Byte[])); + + /* // Attempting to work out requirements to get SQLite to actually *save* the data. + createCol(terrain, "PrIndex", typeof(System.String)); + terrain.PrimaryKey = new DataColumn[] { terrain.Columns["PrIndex"] }; + */ + + return terrain; + } + private DataTable createPrimTable() { DataTable prims = new DataTable("prims"); @@ -431,6 +499,22 @@ namespace OpenSim.DataStore.MonoSqlite return prim; } + private void fillTerrainRow(DataRow row, LLUUID regionUUID, int rev, double[,] val) + { + row["RegionUUID"] = regionUUID; + row["Revision"] = rev; + + System.IO.MemoryStream str = new System.IO.MemoryStream(65536 * sizeof(double)); + System.IO.BinaryWriter bw = new System.IO.BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < 256; x++) + for (int y = 0; y < 256; y++) + bw.Write(val[x, y]); + + row["Heightfield"] = str.ToArray(); + } + private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) { row["UUID"] = prim.UUID; @@ -692,7 +776,7 @@ namespace OpenSim.DataStore.MonoSqlite subsql += ",\n"; } subsql += col.ColumnName + " " + sqliteType(col.DataType); - if (col == dt.PrimaryKey[0]) + if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) { subsql += " primary key"; } @@ -746,6 +830,12 @@ namespace OpenSim.DataStore.MonoSqlite da.DeleteCommand = delete; } + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) { da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); @@ -764,12 +854,15 @@ namespace OpenSim.DataStore.MonoSqlite { string createPrims = defineTable(createPrimTable()); string createShapes = defineTable(createShapeTable()); + string createTerrain = defineTable(createTerrainTable()); SqliteCommand pcmd = new SqliteCommand(createPrims, conn); SqliteCommand scmd = new SqliteCommand(createShapes, conn); + SqliteCommand tcmd = new SqliteCommand(createTerrain, conn); conn.Open(); pcmd.ExecuteNonQuery(); scmd.ExecuteNonQuery(); + tcmd.ExecuteNonQuery(); conn.Close(); } @@ -779,12 +872,15 @@ namespace OpenSim.DataStore.MonoSqlite SqliteDataAdapter pDa = new SqliteDataAdapter(primSelectCmd); SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, conn); SqliteDataAdapter sDa = new SqliteDataAdapter(shapeSelectCmd); + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, conn); + SqliteDataAdapter tDa = new SqliteDataAdapter(terrainSelectCmd); DataSet tmpDS = new DataSet(); try { pDa.Fill(tmpDS, "prims"); sDa.Fill(tmpDS, "primshapes"); + tDa.Fill(tmpDS, "terrain"); } catch (Mono.Data.SqliteClient.SqliteSyntaxException) { @@ -794,6 +890,7 @@ namespace OpenSim.DataStore.MonoSqlite pDa.Fill(tmpDS, "prims"); sDa.Fill(tmpDS, "primshapes"); + tDa.Fill(tmpDS, "terrain"); foreach (DataColumn col in createPrimTable().Columns) { @@ -811,6 +908,14 @@ namespace OpenSim.DataStore.MonoSqlite return false; } } + foreach (DataColumn col in createTerrainTable().Columns) + { + if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) + { + MainLog.Instance.Verbose("DATASTORE", "Missing require column:" + col.ColumnName); + return false; + } + } return true; } @@ -834,6 +939,14 @@ namespace OpenSim.DataStore.MonoSqlite { return DbType.Double; } + else if (type == typeof(System.Byte)) + { + return DbType.Byte; + } + else if (type == typeof(System.Double)) + { + return DbType.Double; + } else if (type == typeof(System.Byte[])) { return DbType.Binary; -- cgit v1.1