diff options
author | MW | 2007-08-19 13:35:20 +0000 |
---|---|---|
committer | MW | 2007-08-19 13:35:20 +0000 |
commit | c89db49f3cd3bbd60577eb5a1787ccf8dea930e3 (patch) | |
tree | 2b51b0d261724427933f543dd2f39ef8cd21127f /OpenSim/Region/Storage | |
parent | Code comments on recent changes in EventQueueManager (diff) | |
download | opensim-SC-c89db49f3cd3bbd60577eb5a1787ccf8dea930e3.zip opensim-SC-c89db49f3cd3bbd60577eb5a1787ccf8dea930e3.tar.gz opensim-SC-c89db49f3cd3bbd60577eb5a1787ccf8dea930e3.tar.bz2 opensim-SC-c89db49f3cd3bbd60577eb5a1787ccf8dea930e3.tar.xz |
Sqlite datastore should now save the textures and extraparams data (used by sculpties) correctly. [Really need to add a ExtraParams field to the sqlite database though, but for now I have combined their data so that we don't lose backward compatibility, know a couple of people have been using the datastore already].
Now have a rough day/night cycle (the movement of the sun needs to be made smoother but for now it is better than we had I think).
Added dalien's patch (issue 294) for saving and loading prims to a xml file (think he will be modifying these to be import/export functions and maybe writing a xml datastore for backups).
Some preliminary work on task inventory (ie object's/prim's inventory).
Added place holder data for AvatarProperties (ie a avatar's profile). Should we store this sort of data on the user server or have another server for it (a normal webserver should work).
Added a few more method to IClientAPI.
Sure there is something I'm forgeting.
Diffstat (limited to 'OpenSim/Region/Storage')
-rw-r--r-- | OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs | 138 |
1 files changed, 100 insertions, 38 deletions
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs index 6f12c47..391ac84 100644 --- a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs +++ b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs | |||
@@ -1,6 +1,9 @@ | |||
1 | using System; | 1 | using System; |
2 | using System.Collections.Generic; | 2 | using System.Collections.Generic; |
3 | using System.Text; | 3 | using System.Text; |
4 | using System.Xml; | ||
5 | using System.Xml.Serialization; | ||
6 | using System.IO; | ||
4 | 7 | ||
5 | using OpenSim.Region.Environment.Scenes; | 8 | using OpenSim.Region.Environment.Scenes; |
6 | using OpenSim.Region.Environment.LandManagement; | 9 | using OpenSim.Region.Environment.LandManagement; |
@@ -38,7 +41,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
38 | SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn); | 41 | SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn); |
39 | primDa = new SqliteDataAdapter(primSelectCmd); | 42 | primDa = new SqliteDataAdapter(primSelectCmd); |
40 | // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); | 43 | // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); |
41 | 44 | ||
42 | SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, conn); | 45 | SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, conn); |
43 | shapeDa = new SqliteDataAdapter(shapeSelectCmd); | 46 | shapeDa = new SqliteDataAdapter(shapeSelectCmd); |
44 | // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); | 47 | // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); |
@@ -55,12 +58,12 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
55 | DataTable prims = ds.Tables["prims"]; | 58 | DataTable prims = ds.Tables["prims"]; |
56 | prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; | 59 | prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; |
57 | setupPrimCommands(primDa, conn); | 60 | setupPrimCommands(primDa, conn); |
58 | 61 | ||
59 | // shapeDa.FillSchema(ds, SchemaType.Source, "ShapeSchema"); | 62 | // shapeDa.FillSchema(ds, SchemaType.Source, "ShapeSchema"); |
60 | DataTable shapes = ds.Tables["primshapes"]; | 63 | DataTable shapes = ds.Tables["primshapes"]; |
61 | shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] }; | 64 | shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] }; |
62 | setupShapeCommands(shapeDa, conn); | 65 | setupShapeCommands(shapeDa, conn); |
63 | 66 | ||
64 | return; | 67 | return; |
65 | } | 68 | } |
66 | 69 | ||
@@ -158,7 +161,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
158 | return data; | 161 | return data; |
159 | } | 162 | } |
160 | 163 | ||
161 | private SqliteCommand createInsertCommand(string table, Dictionary<string, DbType> defs) | 164 | private SqliteCommand createInsertCommand(string table, Dictionary<string, DbType> defs) |
162 | { | 165 | { |
163 | /** | 166 | /** |
164 | * This is subtle enough to deserve some commentary. | 167 | * This is subtle enough to deserve some commentary. |
@@ -171,7 +174,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
171 | */ | 174 | */ |
172 | string[] cols = new string[defs.Keys.Count]; | 175 | string[] cols = new string[defs.Keys.Count]; |
173 | defs.Keys.CopyTo(cols, 0); | 176 | defs.Keys.CopyTo(cols, 0); |
174 | 177 | ||
175 | string sql = "insert into " + table + "("; | 178 | string sql = "insert into " + table + "("; |
176 | sql += String.Join(", ", cols); | 179 | sql += String.Join(", ", cols); |
177 | // important, the first ':' needs to be here, the rest get added in the join | 180 | // important, the first ':' needs to be here, the rest get added in the join |
@@ -179,21 +182,24 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
179 | sql += String.Join(", :", cols); | 182 | sql += String.Join(", :", cols); |
180 | sql += ")"; | 183 | sql += ")"; |
181 | SqliteCommand cmd = new SqliteCommand(sql); | 184 | SqliteCommand cmd = new SqliteCommand(sql); |
182 | 185 | ||
183 | // this provides the binding for all our parameters, so | 186 | // this provides the binding for all our parameters, so |
184 | // much less code than it used to be | 187 | // much less code than it used to be |
185 | foreach (KeyValuePair<string, DbType> kvp in defs) { | 188 | foreach (KeyValuePair<string, DbType> kvp in defs) |
189 | { | ||
186 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); | 190 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); |
187 | } | 191 | } |
188 | return cmd; | 192 | return cmd; |
189 | } | 193 | } |
190 | 194 | ||
191 | private SqliteCommand createUpdateCommand(string table, string pk, Dictionary<string, DbType> defs) | 195 | private SqliteCommand createUpdateCommand(string table, string pk, Dictionary<string, DbType> defs) |
192 | { | 196 | { |
193 | string sql = "update " + table + " set "; | 197 | string sql = "update " + table + " set "; |
194 | string subsql = ""; | 198 | string subsql = ""; |
195 | foreach (string key in defs.Keys) { | 199 | foreach (string key in defs.Keys) |
196 | if (subsql.Length > 0) { // a map function would rock so much here | 200 | { |
201 | if (subsql.Length > 0) | ||
202 | { // a map function would rock so much here | ||
197 | subsql += ", "; | 203 | subsql += ", "; |
198 | } | 204 | } |
199 | subsql += key + "= :" + key; | 205 | subsql += key + "= :" + key; |
@@ -204,7 +210,8 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
204 | 210 | ||
205 | // this provides the binding for all our parameters, so | 211 | // this provides the binding for all our parameters, so |
206 | // much less code than it used to be | 212 | // much less code than it used to be |
207 | foreach (KeyValuePair<string, DbType> kvp in defs) { | 213 | foreach (KeyValuePair<string, DbType> kvp in defs) |
214 | { | ||
208 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); | 215 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); |
209 | } | 216 | } |
210 | return cmd; | 217 | return cmd; |
@@ -213,13 +220,13 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
213 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) | 220 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) |
214 | { | 221 | { |
215 | Dictionary<string, DbType> primDataDefs = createPrimDataDefs(); | 222 | Dictionary<string, DbType> primDataDefs = createPrimDataDefs(); |
216 | 223 | ||
217 | da.InsertCommand = createInsertCommand("prims", primDataDefs); | 224 | da.InsertCommand = createInsertCommand("prims", primDataDefs); |
218 | da.InsertCommand.Connection = conn; | 225 | da.InsertCommand.Connection = conn; |
219 | 226 | ||
220 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", primDataDefs); | 227 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", primDataDefs); |
221 | da.UpdateCommand.Connection = conn; | 228 | da.UpdateCommand.Connection = conn; |
222 | 229 | ||
223 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); | 230 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); |
224 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); | 231 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); |
225 | delete.Connection = conn; | 232 | delete.Connection = conn; |
@@ -229,13 +236,13 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
229 | private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) | 236 | private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) |
230 | { | 237 | { |
231 | Dictionary<string, DbType> shapeDataDefs = createShapeDataDefs(); | 238 | Dictionary<string, DbType> shapeDataDefs = createShapeDataDefs(); |
232 | 239 | ||
233 | da.InsertCommand = createInsertCommand("primshapes", shapeDataDefs); | 240 | da.InsertCommand = createInsertCommand("primshapes", shapeDataDefs); |
234 | da.InsertCommand.Connection = conn; | 241 | da.InsertCommand.Connection = conn; |
235 | 242 | ||
236 | da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", shapeDataDefs); | 243 | da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", shapeDataDefs); |
237 | da.UpdateCommand.Connection = conn; | 244 | da.UpdateCommand.Connection = conn; |
238 | 245 | ||
239 | SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); | 246 | SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); |
240 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); | 247 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); |
241 | delete.Connection = conn; | 248 | delete.Connection = conn; |
@@ -271,8 +278,8 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
271 | prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); | 278 | prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); |
272 | // vectors | 279 | // vectors |
273 | prim.OffsetPosition = new LLVector3( | 280 | prim.OffsetPosition = new LLVector3( |
274 | Convert.ToSingle(row["PositionX"]), | 281 | Convert.ToSingle(row["PositionX"]), |
275 | Convert.ToSingle(row["PositionY"]), | 282 | Convert.ToSingle(row["PositionY"]), |
276 | Convert.ToSingle(row["PositionZ"]) | 283 | Convert.ToSingle(row["PositionZ"]) |
277 | ); | 284 | ); |
278 | prim.GroupPosition = new LLVector3( | 285 | prim.GroupPosition = new LLVector3( |
@@ -306,7 +313,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
306 | return prim; | 313 | return prim; |
307 | } | 314 | } |
308 | 315 | ||
309 | private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID) | 316 | private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID) |
310 | { | 317 | { |
311 | row["UUID"] = prim.UUID; | 318 | row["UUID"] = prim.UUID; |
312 | row["ParentID"] = prim.ParentID; | 319 | row["ParentID"] = prim.ParentID; |
@@ -383,11 +390,22 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
383 | // text TODO: this isn't right] = but I'm not sure the right | 390 | // text TODO: this isn't right] = but I'm not sure the right |
384 | // way to specify this as a blob atm | 391 | // way to specify this as a blob atm |
385 | // s.TextureEntry = (byte[])row["Texture"]; | 392 | // s.TextureEntry = (byte[])row["Texture"]; |
386 | 393 | ||
387 | //following hack will only save the default face texture, any other textures on other faces | 394 | string texture = (string)row["Texture"]; |
388 | //won't be saved or restored. | 395 | if (!texture.StartsWith("<")) |
389 | LLObject.TextureEntry texture = new LLObject.TextureEntry( new LLUUID((string)row["Texture"])); | 396 | { |
390 | s.TextureEntry = texture.ToBytes(); | 397 | //here so that we can still work with old format database files (ie from before I added xml serialization) |
398 | LLObject.TextureEntry textureEntry = null; | ||
399 | textureEntry = new LLObject.TextureEntry(new LLUUID(texture)); | ||
400 | s.TextureEntry = textureEntry.ToBytes(); | ||
401 | } | ||
402 | else | ||
403 | { | ||
404 | TextureBlock textureEntry = TextureBlock.FromXmlString(texture); | ||
405 | s.TextureEntry = textureEntry.TextureData; | ||
406 | s.ExtraParams = textureEntry.ExtraParams; | ||
407 | } | ||
408 | |||
391 | return s; | 409 | return s; |
392 | } | 410 | } |
393 | 411 | ||
@@ -428,34 +446,41 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
428 | // And I couldn't work out how to save binary data either | 446 | // And I couldn't work out how to save binary data either |
429 | // seems that the texture colum is being treated as a string in the Datarow | 447 | // seems that the texture colum is being treated as a string in the Datarow |
430 | // if you do a .getType() on it, it returns string, while the other columns return correct type | 448 | // if you do a .getType() on it, it returns string, while the other columns return correct type |
431 | //following hack will only save the default face texture, any other textures on other faces | ||
432 | //won't be saved or restored. | ||
433 | // MW[10-08-07] | 449 | // MW[10-08-07] |
434 | LLObject.TextureEntry text = new LLObject.TextureEntry(s.TextureEntry, 0, s.TextureEntry.Length); | 450 | // Added following xml hack but not really ideal , also ExtraParams isn't currently part of the database |
435 | row["Texture"] = text.DefaultTexture.TextureID.ToStringHyphenated(); | 451 | // am a bit worried about adding it now as some people will have old format databases, so for now including that data in this xml data |
436 | 452 | // MW[17-08-07] | |
453 | TextureBlock textureBlock = new TextureBlock(s.TextureEntry); | ||
454 | textureBlock.ExtraParams = s.ExtraParams; | ||
455 | row["Texture"] = textureBlock.ToXMLString(); | ||
437 | } | 456 | } |
438 | 457 | ||
439 | private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID) | 458 | private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID) |
440 | { | 459 | { |
441 | DataTable prims = ds.Tables["prims"]; | 460 | DataTable prims = ds.Tables["prims"]; |
442 | DataTable shapes = ds.Tables["primshapes"]; | 461 | DataTable shapes = ds.Tables["primshapes"]; |
443 | 462 | ||
444 | DataRow primRow = prims.Rows.Find(prim.UUID); | 463 | DataRow primRow = prims.Rows.Find(prim.UUID); |
445 | if (primRow == null) { | 464 | if (primRow == null) |
465 | { | ||
446 | primRow = prims.NewRow(); | 466 | primRow = prims.NewRow(); |
447 | fillPrimRow(primRow, prim, sceneGroupID); | 467 | fillPrimRow(primRow, prim, sceneGroupID); |
448 | prims.Rows.Add(primRow); | 468 | prims.Rows.Add(primRow); |
449 | } else { | 469 | } |
470 | else | ||
471 | { | ||
450 | fillPrimRow(primRow, prim, sceneGroupID); | 472 | fillPrimRow(primRow, prim, sceneGroupID); |
451 | } | 473 | } |
452 | 474 | ||
453 | DataRow shapeRow = shapes.Rows.Find(prim.UUID); | 475 | DataRow shapeRow = shapes.Rows.Find(prim.UUID); |
454 | if (shapeRow == null) { | 476 | if (shapeRow == null) |
477 | { | ||
455 | shapeRow = shapes.NewRow(); | 478 | shapeRow = shapes.NewRow(); |
456 | fillShapeRow(shapeRow, prim); | 479 | fillShapeRow(shapeRow, prim); |
457 | shapes.Rows.Add(shapeRow); | 480 | shapes.Rows.Add(shapeRow); |
458 | } else { | 481 | } |
482 | else | ||
483 | { | ||
459 | fillShapeRow(shapeRow, prim); | 484 | fillShapeRow(shapeRow, prim); |
460 | } | 485 | } |
461 | } | 486 | } |
@@ -466,11 +491,11 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
466 | { | 491 | { |
467 | addPrim(prim, obj.UUID); | 492 | addPrim(prim, obj.UUID); |
468 | } | 493 | } |
469 | 494 | ||
470 | // MainLog.Instance.Verbose("Attempting to do database update...."); | 495 | // MainLog.Instance.Verbose("Attempting to do database update...."); |
471 | primDa.Update(ds, "prims"); | 496 | primDa.Update(ds, "prims"); |
472 | shapeDa.Update(ds, "primshapes"); | 497 | shapeDa.Update(ds, "primshapes"); |
473 | // MainLog.Instance.Verbose("Dump of prims:", ds.GetXml()); | 498 | // MainLog.Instance.Verbose("Dump of prims:", ds.GetXml()); |
474 | } | 499 | } |
475 | 500 | ||
476 | public void RemoveObject(LLUUID obj) | 501 | public void RemoveObject(LLUUID obj) |
@@ -502,7 +527,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
502 | 527 | ||
503 | DataTable prims = ds.Tables["prims"]; | 528 | DataTable prims = ds.Tables["prims"]; |
504 | DataTable shapes = ds.Tables["primshapes"]; | 529 | DataTable shapes = ds.Tables["primshapes"]; |
505 | 530 | ||
506 | foreach (DataRow primRow in prims.Rows) | 531 | foreach (DataRow primRow in prims.Rows) |
507 | { | 532 | { |
508 | string uuid = (string)primRow["UUID"]; | 533 | string uuid = (string)primRow["UUID"]; |
@@ -548,7 +573,7 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
548 | 573 | ||
549 | return retvals; | 574 | return retvals; |
550 | } | 575 | } |
551 | 576 | ||
552 | public void StoreTerrain(double[,] ter) | 577 | public void StoreTerrain(double[,] ter) |
553 | { | 578 | { |
554 | 579 | ||
@@ -578,5 +603,42 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
578 | { | 603 | { |
579 | // TODO: DataSet commit | 604 | // TODO: DataSet commit |
580 | } | 605 | } |
606 | |||
607 | public class TextureBlock | ||
608 | { | ||
609 | public byte[] TextureData; | ||
610 | public byte[] ExtraParams = new byte[1]; | ||
611 | |||
612 | public TextureBlock(byte[] data) | ||
613 | { | ||
614 | TextureData = data; | ||
615 | } | ||
616 | |||
617 | public TextureBlock() | ||
618 | { | ||
619 | |||
620 | } | ||
621 | |||
622 | public string ToXMLString() | ||
623 | { | ||
624 | StringWriter sw = new StringWriter(); | ||
625 | XmlTextWriter writer = new XmlTextWriter(sw); | ||
626 | XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock)); | ||
627 | serializer.Serialize(writer, this); | ||
628 | return sw.ToString(); | ||
629 | } | ||
630 | |||
631 | public static TextureBlock FromXmlString(string xmlData) | ||
632 | { | ||
633 | TextureBlock textureEntry = null; | ||
634 | StringReader sr = new StringReader(xmlData); | ||
635 | XmlTextReader reader = new XmlTextReader(sr); | ||
636 | XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock)); | ||
637 | textureEntry = (TextureBlock)serializer.Deserialize(reader); | ||
638 | reader.Close(); | ||
639 | sr.Close(); | ||
640 | return textureEntry; | ||
641 | } | ||
642 | } | ||
581 | } | 643 | } |
582 | } | 644 | } |