aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2010-04-30 17:45:00 +0100
committerJustin Clark-Casey (justincc)2010-04-30 17:45:00 +0100
commitcc67de5b86ebcebadbe2ea46872a0dc63d99cae7 (patch)
tree1607da4eee9e63fe45e0abcf05da37ae5e239d70 /OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs
parentMake SQLiteNG the default since it actually does work with Mono 2.4 on Linux. (diff)
downloadopensim-SC_OLD-cc67de5b86ebcebadbe2ea46872a0dc63d99cae7.zip
opensim-SC_OLD-cc67de5b86ebcebadbe2ea46872a0dc63d99cae7.tar.gz
opensim-SC_OLD-cc67de5b86ebcebadbe2ea46872a0dc63d99cae7.tar.bz2
opensim-SC_OLD-cc67de5b86ebcebadbe2ea46872a0dc63d99cae7.tar.xz
rename SQLiteNG to SQLite and SQLite to SQLiteLegacy
this seems the least evil way forward since mono 2.6 and later will see increasing usage, and this only works with what was SQLiteNG MAC USERS WILL NEED TO CHANGE REFERENCES TO "OpenSim.Data.SQLite.dll" to "OpenSim.Data.SQLiteLegacy.dll" in OpenSim.ini and config-include/StandaloneCommon.ini (if using standalone) See the OpenSim.ini.example and StandaloneCommon.ini.example files for more details This commit also temporarily changes unsigned ParentEstateID values in the OpenSim.Data.Tests to signed temporarily, since the new plugin enforces creation of signed fields in the database (which is what the SQL actually specifies). And change data columns in sqlite is a pita.
Diffstat (limited to 'OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs')
-rw-r--r--OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs2264
1 files changed, 2264 insertions, 0 deletions
diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs
new file mode 100644
index 0000000..eb78037
--- /dev/null
+++ b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs
@@ -0,0 +1,2264 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using Mono.Data.SqliteClient;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40
41namespace OpenSim.Data.SQLiteLegacy
42{
43 /// <summary>
44 /// A RegionData Interface to the SQLite database
45 /// </summary>
46 public class SQLiteRegionData : IRegionDataStore
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private const string primSelect = "select * from prims";
51 private const string shapeSelect = "select * from primshapes";
52 private const string itemsSelect = "select * from primitems";
53 private const string terrainSelect = "select * from terrain limit 1";
54 private const string landSelect = "select * from land";
55 private const string landAccessListSelect = "select distinct * from landaccesslist";
56 private const string regionbanListSelect = "select * from regionban";
57 private const string regionSettingsSelect = "select * from regionsettings";
58
59 private DataSet ds;
60 private SqliteDataAdapter primDa;
61 private SqliteDataAdapter shapeDa;
62 private SqliteDataAdapter itemsDa;
63 private SqliteDataAdapter terrainDa;
64 private SqliteDataAdapter landDa;
65 private SqliteDataAdapter landAccessListDa;
66 private SqliteDataAdapter regionSettingsDa;
67
68 private SqliteConnection m_conn;
69
70 private String m_connectionString;
71
72 // Temporary attribute while this is experimental
73
74 /***********************************************************************
75 *
76 * Public Interface Functions
77 *
78 **********************************************************************/
79
80 /// <summary>
81 /// See IRegionDataStore
82 /// <list type="bullet">
83 /// <item>Initialises RegionData Interface</item>
84 /// <item>Loads and initialises a new SQLite connection and maintains it.</item>
85 /// </list>
86 /// </summary>
87 /// <param name="connectionString">the connection string</param>
88 public void Initialise(string connectionString)
89 {
90 m_connectionString = connectionString;
91
92 ds = new DataSet();
93
94 m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString);
95 m_conn = new SqliteConnection(m_connectionString);
96 m_conn.Open();
97
98
99
100 SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn);
101 primDa = new SqliteDataAdapter(primSelectCmd);
102 // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa);
103
104 SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn);
105 shapeDa = new SqliteDataAdapter(shapeSelectCmd);
106 // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa);
107
108 SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn);
109 itemsDa = new SqliteDataAdapter(itemsSelectCmd);
110
111 SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn);
112 terrainDa = new SqliteDataAdapter(terrainSelectCmd);
113
114 SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn);
115 landDa = new SqliteDataAdapter(landSelectCmd);
116
117 SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn);
118 landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd);
119
120 SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn);
121 regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd);
122 // This actually does the roll forward assembly stuff
123 Assembly assem = GetType().Assembly;
124 Migration m = new Migration(m_conn, assem, "RegionStore");
125 m.Update();
126
127 lock (ds)
128 {
129 ds.Tables.Add(createPrimTable());
130 setupPrimCommands(primDa, m_conn);
131 primDa.Fill(ds.Tables["prims"]);
132
133 ds.Tables.Add(createShapeTable());
134 setupShapeCommands(shapeDa, m_conn);
135
136 ds.Tables.Add(createItemsTable());
137 setupItemsCommands(itemsDa, m_conn);
138 itemsDa.Fill(ds.Tables["primitems"]);
139
140 ds.Tables.Add(createTerrainTable());
141 setupTerrainCommands(terrainDa, m_conn);
142
143 ds.Tables.Add(createLandTable());
144 setupLandCommands(landDa, m_conn);
145
146 ds.Tables.Add(createLandAccessListTable());
147 setupLandAccessCommands(landAccessListDa, m_conn);
148
149 ds.Tables.Add(createRegionSettingsTable());
150
151 setupRegionSettingsCommands(regionSettingsDa, m_conn);
152
153 // WORKAROUND: This is a work around for sqlite on
154 // windows, which gets really unhappy with blob columns
155 // that have no sample data in them. At some point we
156 // need to actually find a proper way to handle this.
157 try
158 {
159 shapeDa.Fill(ds.Tables["primshapes"]);
160 }
161 catch (Exception)
162 {
163 m_log.Info("[REGION DB]: Caught fill error on primshapes table");
164 }
165
166 try
167 {
168 terrainDa.Fill(ds.Tables["terrain"]);
169 }
170 catch (Exception)
171 {
172 m_log.Info("[REGION DB]: Caught fill error on terrain table");
173 }
174
175 try
176 {
177 landDa.Fill(ds.Tables["land"]);
178 }
179 catch (Exception)
180 {
181 m_log.Info("[REGION DB]: Caught fill error on land table");
182 }
183
184 try
185 {
186 landAccessListDa.Fill(ds.Tables["landaccesslist"]);
187 }
188 catch (Exception)
189 {
190 m_log.Info("[REGION DB]: Caught fill error on landaccesslist table");
191 }
192
193 try
194 {
195 regionSettingsDa.Fill(ds.Tables["regionsettings"]);
196 }
197 catch (Exception)
198 {
199 m_log.Info("[REGION DB]: Caught fill error on regionsettings table");
200 }
201 return;
202 }
203 }
204
205 public void Dispose()
206 {
207 if (m_conn != null)
208 {
209 m_conn.Close();
210 m_conn = null;
211 }
212 if (ds != null)
213 {
214 ds.Dispose();
215 ds = null;
216 }
217 if (primDa != null)
218 {
219 primDa.Dispose();
220 primDa = null;
221 }
222 if (shapeDa != null)
223 {
224 shapeDa.Dispose();
225 shapeDa = null;
226 }
227 if (itemsDa != null)
228 {
229 itemsDa.Dispose();
230 itemsDa = null;
231 }
232 if (terrainDa != null)
233 {
234 terrainDa.Dispose();
235 terrainDa = null;
236 }
237 if (landDa != null)
238 {
239 landDa.Dispose();
240 landDa = null;
241 }
242 if (landAccessListDa != null)
243 {
244 landAccessListDa.Dispose();
245 landAccessListDa = null;
246 }
247 if (regionSettingsDa != null)
248 {
249 regionSettingsDa.Dispose();
250 regionSettingsDa = null;
251 }
252 }
253
254 public void StoreRegionSettings(RegionSettings rs)
255 {
256 lock (ds)
257 {
258 DataTable regionsettings = ds.Tables["regionsettings"];
259
260 DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString());
261 if (settingsRow == null)
262 {
263 settingsRow = regionsettings.NewRow();
264 fillRegionSettingsRow(settingsRow, rs);
265 regionsettings.Rows.Add(settingsRow);
266 }
267 else
268 {
269 fillRegionSettingsRow(settingsRow, rs);
270 }
271
272 Commit();
273 }
274 }
275 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
276 {
277 //This connector doesn't support the windlight module yet
278 //Return default LL windlight settings
279 return new RegionLightShareData();
280 }
281 public void StoreRegionWindlightSettings(RegionLightShareData wl)
282 {
283 //This connector doesn't support the windlight module yet
284 }
285 public RegionSettings LoadRegionSettings(UUID regionUUID)
286 {
287 lock (ds)
288 {
289 DataTable regionsettings = ds.Tables["regionsettings"];
290
291 string searchExp = "regionUUID = '" + regionUUID.ToString() + "'";
292 DataRow[] rawsettings = regionsettings.Select(searchExp);
293 if (rawsettings.Length == 0)
294 {
295 RegionSettings rs = new RegionSettings();
296 rs.RegionUUID = regionUUID;
297 rs.OnSave += StoreRegionSettings;
298
299 StoreRegionSettings(rs);
300
301 return rs;
302 }
303 DataRow row = rawsettings[0];
304
305 RegionSettings newSettings = buildRegionSettings(row);
306 newSettings.OnSave += StoreRegionSettings;
307
308 return newSettings;
309 }
310 }
311
312 /// <summary>
313 /// Adds an object into region storage
314 /// </summary>
315 /// <param name="obj">the object</param>
316 /// <param name="regionUUID">the region UUID</param>
317 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
318 {
319 uint flags = obj.RootPart.GetEffectiveObjectFlags();
320
321 // Eligibility check
322 //
323 if ((flags & (uint)PrimFlags.Temporary) != 0)
324 return;
325 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
326 return;
327
328 lock (ds)
329 {
330 foreach (SceneObjectPart prim in obj.Children.Values)
331 {
332// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
333 addPrim(prim, obj.UUID, regionUUID);
334 }
335 }
336
337 Commit();
338 // m_log.Info("[Dump of prims]: " + ds.GetXml());
339 }
340
341 /// <summary>
342 /// Removes an object from region storage
343 /// </summary>
344 /// <param name="obj">the object</param>
345 /// <param name="regionUUID">the region UUID</param>
346 public void RemoveObject(UUID obj, UUID regionUUID)
347 {
348 // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID);
349
350 DataTable prims = ds.Tables["prims"];
351 DataTable shapes = ds.Tables["primshapes"];
352
353 string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'";
354 lock (ds)
355 {
356 DataRow[] primRows = prims.Select(selectExp);
357 foreach (DataRow row in primRows)
358 {
359 // Remove shape rows
360 UUID uuid = new UUID((string) row["UUID"]);
361 DataRow shapeRow = shapes.Rows.Find(uuid.ToString());
362 if (shapeRow != null)
363 {
364 shapeRow.Delete();
365 }
366
367 RemoveItems(uuid);
368
369 // Remove prim row
370 row.Delete();
371 }
372 }
373
374 Commit();
375 }
376
377 /// <summary>
378 /// Remove all persisted items of the given prim.
379 /// The caller must acquire the necessrary synchronization locks and commit or rollback changes.
380 /// </summary>
381 /// <param name="uuid">The item UUID</param>
382 private void RemoveItems(UUID uuid)
383 {
384 DataTable items = ds.Tables["primitems"];
385
386 String sql = String.Format("primID = '{0}'", uuid);
387 DataRow[] itemRows = items.Select(sql);
388
389 foreach (DataRow itemRow in itemRows)
390 {
391 itemRow.Delete();
392 }
393 }
394
395 /// <summary>
396 /// Load persisted objects from region storage.
397 /// </summary>
398 /// <param name="regionUUID">The region UUID</param>
399 /// <returns>List of loaded groups</returns>
400 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
401 {
402 Dictionary<UUID, SceneObjectGroup> createdObjects = new Dictionary<UUID, SceneObjectGroup>();
403
404 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
405
406 DataTable prims = ds.Tables["prims"];
407 DataTable shapes = ds.Tables["primshapes"];
408
409 string byRegion = "RegionUUID = '" + regionUUID + "'";
410
411 lock (ds)
412 {
413 DataRow[] primsForRegion = prims.Select(byRegion);
414 m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID);
415
416 // First, create all groups
417 foreach (DataRow primRow in primsForRegion)
418 {
419 try
420 {
421 SceneObjectPart prim = null;
422
423 string uuid = (string) primRow["UUID"];
424 string objID = (string) primRow["SceneGroupID"];
425
426 if (uuid == objID) //is new SceneObjectGroup ?
427 {
428 prim = buildPrim(primRow);
429 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
430 if (shapeRow != null)
431 {
432 prim.Shape = buildShape(shapeRow);
433 }
434 else
435 {
436 m_log.Info(
437 "[REGION DB]: No shape found for prim in storage, so setting default box shape");
438 prim.Shape = PrimitiveBaseShape.Default;
439 }
440
441 SceneObjectGroup group = new SceneObjectGroup(prim);
442 createdObjects.Add(group.UUID, group);
443 retvals.Add(group);
444 LoadItems(prim);
445 }
446 }
447 catch (Exception e)
448 {
449 m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows");
450 m_log.Info("[REGION DB]: " + e.ToString());
451 foreach (DataColumn col in prims.Columns)
452 {
453 m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
454 }
455 }
456 }
457
458 // Now fill the groups with part data
459 foreach (DataRow primRow in primsForRegion)
460 {
461 try
462 {
463 SceneObjectPart prim = null;
464
465 string uuid = (string) primRow["UUID"];
466 string objID = (string) primRow["SceneGroupID"];
467 if (uuid != objID) //is new SceneObjectGroup ?
468 {
469 prim = buildPrim(primRow);
470 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
471 if (shapeRow != null)
472 {
473 prim.Shape = buildShape(shapeRow);
474 }
475 else
476 {
477 m_log.Warn(
478 "[REGION DB]: No shape found for prim in storage, so setting default box shape");
479 prim.Shape = PrimitiveBaseShape.Default;
480 }
481
482 createdObjects[new UUID(objID)].AddPart(prim);
483 LoadItems(prim);
484 }
485 }
486 catch (Exception e)
487 {
488 m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows");
489 m_log.Info("[REGION DB]: " + e.ToString());
490 foreach (DataColumn col in prims.Columns)
491 {
492 m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
493 }
494 }
495 }
496 }
497 return retvals;
498 }
499
500 /// <summary>
501 /// Load in a prim's persisted inventory.
502 /// </summary>
503 /// <param name="prim">the prim</param>
504 private void LoadItems(SceneObjectPart prim)
505 {
506 //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID);
507
508 DataTable dbItems = ds.Tables["primitems"];
509 String sql = String.Format("primID = '{0}'", prim.UUID.ToString());
510 DataRow[] dbItemRows = dbItems.Select(sql);
511 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
512
513 foreach (DataRow row in dbItemRows)
514 {
515 TaskInventoryItem item = buildItem(row);
516 inventory.Add(item);
517
518 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID);
519 }
520
521 prim.Inventory.RestoreInventoryItems(inventory);
522 }
523
524 /// <summary>
525 /// Store a terrain revision in region storage
526 /// </summary>
527 /// <param name="ter">terrain heightfield</param>
528 /// <param name="regionID">region UUID</param>
529 public void StoreTerrain(double[,] ter, UUID regionID)
530 {
531 lock (ds)
532 {
533 int revision = Util.UnixTimeSinceEpoch();
534
535 // This is added to get rid of the infinitely growing
536 // terrain databases which negatively impact on SQLite
537 // over time. Before reenabling this feature there
538 // needs to be a limitter put on the number of
539 // revisions in the database, as this old
540 // implementation is a DOS attack waiting to happen.
541
542 using (
543 SqliteCommand cmd =
544 new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision",
545 m_conn))
546 {
547 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
548 cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
549 cmd.ExecuteNonQuery();
550 }
551
552 // the following is an work around for .NET. The perf
553 // issues associated with it aren't as bad as you think.
554 m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString());
555 String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
556 " values(:RegionUUID, :Revision, :Heightfield)";
557
558 using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
559 {
560 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
561 cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
562 cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter)));
563 cmd.ExecuteNonQuery();
564 }
565 }
566 }
567
568 /// <summary>
569 /// Load the latest terrain revision from region storage
570 /// </summary>
571 /// <param name="regionID">the region UUID</param>
572 /// <returns>Heightfield data</returns>
573 public double[,] LoadTerrain(UUID regionID)
574 {
575 lock (ds)
576 {
577 double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
578 terret.Initialize();
579
580 String sql = "select RegionUUID, Revision, Heightfield from terrain" +
581 " where RegionUUID=:RegionUUID order by Revision desc";
582
583 using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
584 {
585 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
586
587 using (IDataReader row = cmd.ExecuteReader())
588 {
589 int rev = 0;
590 if (row.Read())
591 {
592 // TODO: put this into a function
593 using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"]))
594 {
595 using (BinaryReader br = new BinaryReader(str))
596 {
597 for (int x = 0; x < (int)Constants.RegionSize; x++)
598 {
599 for (int y = 0; y < (int)Constants.RegionSize; y++)
600 {
601 terret[x, y] = br.ReadDouble();
602 }
603 }
604 }
605 }
606 rev = (int) row["Revision"];
607 }
608 else
609 {
610 m_log.Info("[REGION DB]: No terrain found for region");
611 return null;
612 }
613
614 m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString());
615 }
616 }
617 return terret;
618 }
619 }
620
621 /// <summary>
622 ///
623 /// </summary>
624 /// <param name="globalID"></param>
625 public void RemoveLandObject(UUID globalID)
626 {
627 lock (ds)
628 {
629 // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter
630 // after you're done.
631 // replaced below code with the SqliteAdapter version.
632 //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn))
633 //{
634 // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString()));
635 // cmd.ExecuteNonQuery();
636 //}
637
638 //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn))
639 //{
640 // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString()));
641 // cmd.ExecuteNonQuery();
642 //}
643
644 DataTable land = ds.Tables["land"];
645 DataTable landaccesslist = ds.Tables["landaccesslist"];
646 DataRow landRow = land.Rows.Find(globalID.ToString());
647 if (landRow != null)
648 {
649 land.Rows.Remove(landRow);
650 }
651 List<DataRow> rowsToDelete = new List<DataRow>();
652 foreach (DataRow rowToCheck in landaccesslist.Rows)
653 {
654 if (rowToCheck["LandUUID"].ToString() == globalID.ToString())
655 rowsToDelete.Add(rowToCheck);
656 }
657 for (int iter = 0; iter < rowsToDelete.Count; iter++)
658 {
659 landaccesslist.Rows.Remove(rowsToDelete[iter]);
660 }
661
662
663 }
664 Commit();
665 }
666
667 /// <summary>
668 ///
669 /// </summary>
670 /// <param name="parcel"></param>
671 public void StoreLandObject(ILandObject parcel)
672 {
673 lock (ds)
674 {
675 DataTable land = ds.Tables["land"];
676 DataTable landaccesslist = ds.Tables["landaccesslist"];
677
678 DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString());
679 if (landRow == null)
680 {
681 landRow = land.NewRow();
682 fillLandRow(landRow, parcel.LandData, parcel.RegionUUID);
683 land.Rows.Add(landRow);
684 }
685 else
686 {
687 fillLandRow(landRow, parcel.LandData, parcel.RegionUUID);
688 }
689
690 // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around
691 //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn))
692 //{
693 // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString()));
694 // cmd.ExecuteNonQuery();
695
696// }
697
698 // This is the slower.. but more appropriate thing to do
699
700 // We can't modify the table with direct queries before calling Commit() and re-filling them.
701 List<DataRow> rowsToDelete = new List<DataRow>();
702 foreach (DataRow rowToCheck in landaccesslist.Rows)
703 {
704 if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString())
705 rowsToDelete.Add(rowToCheck);
706 }
707 for (int iter = 0; iter < rowsToDelete.Count; iter++)
708 {
709 landaccesslist.Rows.Remove(rowsToDelete[iter]);
710 }
711 rowsToDelete.Clear();
712 foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList)
713 {
714 DataRow newAccessRow = landaccesslist.NewRow();
715 fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID);
716 landaccesslist.Rows.Add(newAccessRow);
717 }
718 }
719
720 Commit();
721 }
722
723 /// <summary>
724 ///
725 /// </summary>
726 /// <param name="regionUUID"></param>
727 /// <returns></returns>
728 public List<LandData> LoadLandObjects(UUID regionUUID)
729 {
730 List<LandData> landDataForRegion = new List<LandData>();
731 lock (ds)
732 {
733 DataTable land = ds.Tables["land"];
734 DataTable landaccesslist = ds.Tables["landaccesslist"];
735 string searchExp = "RegionUUID = '" + regionUUID + "'";
736 DataRow[] rawDataForRegion = land.Select(searchExp);
737 foreach (DataRow rawDataLand in rawDataForRegion)
738 {
739 LandData newLand = buildLandData(rawDataLand);
740 string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'";
741 DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp);
742 foreach (DataRow rawDataLandAccess in rawDataForLandAccessList)
743 {
744 newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess));
745 }
746
747 landDataForRegion.Add(newLand);
748 }
749 }
750 return landDataForRegion;
751 }
752
753 /// <summary>
754 ///
755 /// </summary>
756 public void Commit()
757 {
758 lock (ds)
759 {
760 primDa.Update(ds, "prims");
761 shapeDa.Update(ds, "primshapes");
762
763 itemsDa.Update(ds, "primitems");
764
765 terrainDa.Update(ds, "terrain");
766 landDa.Update(ds, "land");
767 landAccessListDa.Update(ds, "landaccesslist");
768 try
769 {
770 regionSettingsDa.Update(ds, "regionsettings");
771 }
772 catch (SqliteExecutionException SqlEx)
773 {
774 if (SqlEx.Message.Contains("logic error"))
775 {
776 throw new Exception(
777 "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!",
778 SqlEx);
779 }
780 else
781 {
782 throw SqlEx;
783 }
784 }
785 ds.AcceptChanges();
786 }
787 }
788
789 /// <summary>
790 /// See <see cref="Commit"/>
791 /// </summary>
792 public void Shutdown()
793 {
794 Commit();
795 }
796
797 /***********************************************************************
798 *
799 * Database Definition Functions
800 *
801 * This should be db agnostic as we define them in ADO.NET terms
802 *
803 **********************************************************************/
804
805 /// <summary>
806 ///
807 /// </summary>
808 /// <param name="dt"></param>
809 /// <param name="name"></param>
810 /// <param name="type"></param>
811 private static void createCol(DataTable dt, string name, Type type)
812 {
813 DataColumn col = new DataColumn(name, type);
814 dt.Columns.Add(col);
815 }
816
817 /// <summary>
818 /// Creates the "terrain" table
819 /// </summary>
820 /// <returns>terrain table DataTable</returns>
821 private static DataTable createTerrainTable()
822 {
823 DataTable terrain = new DataTable("terrain");
824
825 createCol(terrain, "RegionUUID", typeof (String));
826 createCol(terrain, "Revision", typeof (Int32));
827 createCol(terrain, "Heightfield", typeof (Byte[]));
828
829 return terrain;
830 }
831
832 /// <summary>
833 /// Creates the "prims" table
834 /// </summary>
835 /// <returns>prim table DataTable</returns>
836 private static DataTable createPrimTable()
837 {
838 DataTable prims = new DataTable("prims");
839
840 createCol(prims, "UUID", typeof (String));
841 createCol(prims, "RegionUUID", typeof (String));
842 createCol(prims, "CreationDate", typeof (Int32));
843 createCol(prims, "Name", typeof (String));
844 createCol(prims, "SceneGroupID", typeof (String));
845 // various text fields
846 createCol(prims, "Text", typeof (String));
847 createCol(prims, "ColorR", typeof (Int32));
848 createCol(prims, "ColorG", typeof (Int32));
849 createCol(prims, "ColorB", typeof (Int32));
850 createCol(prims, "ColorA", typeof (Int32));
851 createCol(prims, "Description", typeof (String));
852 createCol(prims, "SitName", typeof (String));
853 createCol(prims, "TouchName", typeof (String));
854 // permissions
855 createCol(prims, "ObjectFlags", typeof (Int32));
856 createCol(prims, "CreatorID", typeof (String));
857 createCol(prims, "OwnerID", typeof (String));
858 createCol(prims, "GroupID", typeof (String));
859 createCol(prims, "LastOwnerID", typeof (String));
860 createCol(prims, "OwnerMask", typeof (Int32));
861 createCol(prims, "NextOwnerMask", typeof (Int32));
862 createCol(prims, "GroupMask", typeof (Int32));
863 createCol(prims, "EveryoneMask", typeof (Int32));
864 createCol(prims, "BaseMask", typeof (Int32));
865 // vectors
866 createCol(prims, "PositionX", typeof (Double));
867 createCol(prims, "PositionY", typeof (Double));
868 createCol(prims, "PositionZ", typeof (Double));
869 createCol(prims, "GroupPositionX", typeof (Double));
870 createCol(prims, "GroupPositionY", typeof (Double));
871 createCol(prims, "GroupPositionZ", typeof (Double));
872 createCol(prims, "VelocityX", typeof (Double));
873 createCol(prims, "VelocityY", typeof (Double));
874 createCol(prims, "VelocityZ", typeof (Double));
875 createCol(prims, "AngularVelocityX", typeof (Double));
876 createCol(prims, "AngularVelocityY", typeof (Double));
877 createCol(prims, "AngularVelocityZ", typeof (Double));
878 createCol(prims, "AccelerationX", typeof (Double));
879 createCol(prims, "AccelerationY", typeof (Double));
880 createCol(prims, "AccelerationZ", typeof (Double));
881 // quaternions
882 createCol(prims, "RotationX", typeof (Double));
883 createCol(prims, "RotationY", typeof (Double));
884 createCol(prims, "RotationZ", typeof (Double));
885 createCol(prims, "RotationW", typeof (Double));
886
887 // sit target
888 createCol(prims, "SitTargetOffsetX", typeof (Double));
889 createCol(prims, "SitTargetOffsetY", typeof (Double));
890 createCol(prims, "SitTargetOffsetZ", typeof (Double));
891
892 createCol(prims, "SitTargetOrientW", typeof (Double));
893 createCol(prims, "SitTargetOrientX", typeof (Double));
894 createCol(prims, "SitTargetOrientY", typeof (Double));
895 createCol(prims, "SitTargetOrientZ", typeof (Double));
896
897 createCol(prims, "PayPrice", typeof(Int32));
898 createCol(prims, "PayButton1", typeof(Int32));
899 createCol(prims, "PayButton2", typeof(Int32));
900 createCol(prims, "PayButton3", typeof(Int32));
901 createCol(prims, "PayButton4", typeof(Int32));
902
903 createCol(prims, "LoopedSound", typeof(String));
904 createCol(prims, "LoopedSoundGain", typeof(Double));
905 createCol(prims, "TextureAnimation", typeof(String));
906 createCol(prims, "ParticleSystem", typeof(String));
907
908 createCol(prims, "OmegaX", typeof(Double));
909 createCol(prims, "OmegaY", typeof(Double));
910 createCol(prims, "OmegaZ", typeof(Double));
911
912 createCol(prims, "CameraEyeOffsetX", typeof(Double));
913 createCol(prims, "CameraEyeOffsetY", typeof(Double));
914 createCol(prims, "CameraEyeOffsetZ", typeof(Double));
915
916 createCol(prims, "CameraAtOffsetX", typeof(Double));
917 createCol(prims, "CameraAtOffsetY", typeof(Double));
918 createCol(prims, "CameraAtOffsetZ", typeof(Double));
919
920 createCol(prims, "ForceMouselook", typeof(Int16));
921
922 createCol(prims, "ScriptAccessPin", typeof(Int32));
923
924 createCol(prims, "AllowedDrop", typeof(Int16));
925 createCol(prims, "DieAtEdge", typeof(Int16));
926
927 createCol(prims, "SalePrice", typeof(Int32));
928 createCol(prims, "SaleType", typeof(Int16));
929
930 // click action
931 createCol(prims, "ClickAction", typeof (Byte));
932
933 createCol(prims, "Material", typeof(Byte));
934
935 createCol(prims, "CollisionSound", typeof(String));
936 createCol(prims, "CollisionSoundVolume", typeof(Double));
937
938 createCol(prims, "VolumeDetect", typeof(Int16));
939
940 // Add in contraints
941 prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]};
942
943 return prims;
944 }
945
946 /// <summary>
947 /// Creates "primshapes" table
948 /// </summary>
949 /// <returns>shape table DataTable</returns>
950 private static DataTable createShapeTable()
951 {
952 DataTable shapes = new DataTable("primshapes");
953 createCol(shapes, "UUID", typeof (String));
954 // shape is an enum
955 createCol(shapes, "Shape", typeof (Int32));
956 // vectors
957 createCol(shapes, "ScaleX", typeof (Double));
958 createCol(shapes, "ScaleY", typeof (Double));
959 createCol(shapes, "ScaleZ", typeof (Double));
960 // paths
961 createCol(shapes, "PCode", typeof (Int32));
962 createCol(shapes, "PathBegin", typeof (Int32));
963 createCol(shapes, "PathEnd", typeof (Int32));
964 createCol(shapes, "PathScaleX", typeof (Int32));
965 createCol(shapes, "PathScaleY", typeof (Int32));
966 createCol(shapes, "PathShearX", typeof (Int32));
967 createCol(shapes, "PathShearY", typeof (Int32));
968 createCol(shapes, "PathSkew", typeof (Int32));
969 createCol(shapes, "PathCurve", typeof (Int32));
970 createCol(shapes, "PathRadiusOffset", typeof (Int32));
971 createCol(shapes, "PathRevolutions", typeof (Int32));
972 createCol(shapes, "PathTaperX", typeof (Int32));
973 createCol(shapes, "PathTaperY", typeof (Int32));
974 createCol(shapes, "PathTwist", typeof (Int32));
975 createCol(shapes, "PathTwistBegin", typeof (Int32));
976 // profile
977 createCol(shapes, "ProfileBegin", typeof (Int32));
978 createCol(shapes, "ProfileEnd", typeof (Int32));
979 createCol(shapes, "ProfileCurve", typeof (Int32));
980 createCol(shapes, "ProfileHollow", typeof (Int32));
981 createCol(shapes, "State", typeof(Int32));
982 // text TODO: this isn't right, but I'm not sure the right
983 // way to specify this as a blob atm
984 createCol(shapes, "Texture", typeof (Byte[]));
985 createCol(shapes, "ExtraParams", typeof (Byte[]));
986
987 shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]};
988
989 return shapes;
990 }
991
992 /// <summary>
993 /// creates "primitems" table
994 /// </summary>
995 /// <returns>item table DataTable</returns>
996 private static DataTable createItemsTable()
997 {
998 DataTable items = new DataTable("primitems");
999
1000 createCol(items, "itemID", typeof (String));
1001 createCol(items, "primID", typeof (String));
1002 createCol(items, "assetID", typeof (String));
1003 createCol(items, "parentFolderID", typeof (String));
1004
1005 createCol(items, "invType", typeof (Int32));
1006 createCol(items, "assetType", typeof (Int32));
1007
1008 createCol(items, "name", typeof (String));
1009 createCol(items, "description", typeof (String));
1010
1011 createCol(items, "creationDate", typeof (Int64));
1012 createCol(items, "creatorID", typeof (String));
1013 createCol(items, "ownerID", typeof (String));
1014 createCol(items, "lastOwnerID", typeof (String));
1015 createCol(items, "groupID", typeof (String));
1016
1017 createCol(items, "nextPermissions", typeof (UInt32));
1018 createCol(items, "currentPermissions", typeof (UInt32));
1019 createCol(items, "basePermissions", typeof (UInt32));
1020 createCol(items, "everyonePermissions", typeof (UInt32));
1021 createCol(items, "groupPermissions", typeof (UInt32));
1022 createCol(items, "flags", typeof (UInt32));
1023
1024 items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] };
1025
1026 return items;
1027 }
1028
1029 /// <summary>
1030 /// Creates "land" table
1031 /// </summary>
1032 /// <returns>land table DataTable</returns>
1033 private static DataTable createLandTable()
1034 {
1035 DataTable land = new DataTable("land");
1036 createCol(land, "UUID", typeof (String));
1037 createCol(land, "RegionUUID", typeof (String));
1038 createCol(land, "LocalLandID", typeof (UInt32));
1039
1040 // Bitmap is a byte[512]
1041 createCol(land, "Bitmap", typeof (Byte[]));
1042
1043 createCol(land, "Name", typeof (String));
1044 createCol(land, "Desc", typeof (String));
1045 createCol(land, "OwnerUUID", typeof (String));
1046 createCol(land, "IsGroupOwned", typeof (Boolean));
1047 createCol(land, "Area", typeof (Int32));
1048 createCol(land, "AuctionID", typeof (Int32)); //Unemplemented
1049 createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory
1050 createCol(land, "ClaimDate", typeof (Int32));
1051 createCol(land, "ClaimPrice", typeof (Int32));
1052 createCol(land, "GroupUUID", typeof (string));
1053 createCol(land, "SalePrice", typeof (Int32));
1054 createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus
1055 createCol(land, "LandFlags", typeof (UInt32));
1056 createCol(land, "LandingType", typeof (Byte));
1057 createCol(land, "MediaAutoScale", typeof (Byte));
1058 createCol(land, "MediaTextureUUID", typeof (String));
1059 createCol(land, "MediaURL", typeof (String));
1060 createCol(land, "MusicURL", typeof (String));
1061 createCol(land, "PassHours", typeof (Double));
1062 createCol(land, "PassPrice", typeof (UInt32));
1063 createCol(land, "SnapshotUUID", typeof (String));
1064 createCol(land, "UserLocationX", typeof (Double));
1065 createCol(land, "UserLocationY", typeof (Double));
1066 createCol(land, "UserLocationZ", typeof (Double));
1067 createCol(land, "UserLookAtX", typeof (Double));
1068 createCol(land, "UserLookAtY", typeof (Double));
1069 createCol(land, "UserLookAtZ", typeof (Double));
1070 createCol(land, "AuthbuyerID", typeof(String));
1071 createCol(land, "OtherCleanTime", typeof(Int32));
1072 createCol(land, "Dwell", typeof(Int32));
1073
1074 land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]};
1075
1076 return land;
1077 }
1078
1079 /// <summary>
1080 /// create "landaccesslist" table
1081 /// </summary>
1082 /// <returns>Landacceslist DataTable</returns>
1083 private static DataTable createLandAccessListTable()
1084 {
1085 DataTable landaccess = new DataTable("landaccesslist");
1086 createCol(landaccess, "LandUUID", typeof (String));
1087 createCol(landaccess, "AccessUUID", typeof (String));
1088 createCol(landaccess, "Flags", typeof (UInt32));
1089
1090 return landaccess;
1091 }
1092
1093 private static DataTable createRegionSettingsTable()
1094 {
1095 DataTable regionsettings = new DataTable("regionsettings");
1096 createCol(regionsettings, "regionUUID", typeof(String));
1097 createCol(regionsettings, "block_terraform", typeof (Int32));
1098 createCol(regionsettings, "block_fly", typeof (Int32));
1099 createCol(regionsettings, "allow_damage", typeof (Int32));
1100 createCol(regionsettings, "restrict_pushing", typeof (Int32));
1101 createCol(regionsettings, "allow_land_resell", typeof (Int32));
1102 createCol(regionsettings, "allow_land_join_divide", typeof (Int32));
1103 createCol(regionsettings, "block_show_in_search", typeof (Int32));
1104 createCol(regionsettings, "agent_limit", typeof (Int32));
1105 createCol(regionsettings, "object_bonus", typeof (Double));
1106 createCol(regionsettings, "maturity", typeof (Int32));
1107 createCol(regionsettings, "disable_scripts", typeof (Int32));
1108 createCol(regionsettings, "disable_collisions", typeof (Int32));
1109 createCol(regionsettings, "disable_physics", typeof (Int32));
1110 createCol(regionsettings, "terrain_texture_1", typeof(String));
1111 createCol(regionsettings, "terrain_texture_2", typeof(String));
1112 createCol(regionsettings, "terrain_texture_3", typeof(String));
1113 createCol(regionsettings, "terrain_texture_4", typeof(String));
1114 createCol(regionsettings, "elevation_1_nw", typeof (Double));
1115 createCol(regionsettings, "elevation_2_nw", typeof (Double));
1116 createCol(regionsettings, "elevation_1_ne", typeof (Double));
1117 createCol(regionsettings, "elevation_2_ne", typeof (Double));
1118 createCol(regionsettings, "elevation_1_se", typeof (Double));
1119 createCol(regionsettings, "elevation_2_se", typeof (Double));
1120 createCol(regionsettings, "elevation_1_sw", typeof (Double));
1121 createCol(regionsettings, "elevation_2_sw", typeof (Double));
1122 createCol(regionsettings, "water_height", typeof (Double));
1123 createCol(regionsettings, "terrain_raise_limit", typeof (Double));
1124 createCol(regionsettings, "terrain_lower_limit", typeof (Double));
1125 createCol(regionsettings, "use_estate_sun", typeof (Int32));
1126 createCol(regionsettings, "sandbox", typeof (Int32));
1127 createCol(regionsettings, "sunvectorx",typeof (Double));
1128 createCol(regionsettings, "sunvectory",typeof (Double));
1129 createCol(regionsettings, "sunvectorz",typeof (Double));
1130 createCol(regionsettings, "fixed_sun", typeof (Int32));
1131 createCol(regionsettings, "sun_position", typeof (Double));
1132 createCol(regionsettings, "covenant", typeof(String));
1133 regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] };
1134 return regionsettings;
1135 }
1136
1137 /***********************************************************************
1138 *
1139 * Convert between ADO.NET <=> OpenSim Objects
1140 *
1141 * These should be database independant
1142 *
1143 **********************************************************************/
1144
1145 /// <summary>
1146 ///
1147 /// </summary>
1148 /// <param name="row"></param>
1149 /// <returns></returns>
1150 private SceneObjectPart buildPrim(DataRow row)
1151 {
1152 // Code commented. Uncomment to test the unit test inline.
1153
1154 // The unit test mentions this commented code for the purposes
1155 // of debugging a unit test failure
1156
1157 // SceneObjectGroup sog = new SceneObjectGroup();
1158 // SceneObjectPart sop = new SceneObjectPart();
1159 // sop.LocalId = 1;
1160 // sop.Name = "object1";
1161 // sop.Description = "object1";
1162 // sop.Text = "";
1163 // sop.SitName = "";
1164 // sop.TouchName = "";
1165 // sop.UUID = UUID.Random();
1166 // sop.Shape = PrimitiveBaseShape.Default;
1167 // sog.SetRootPart(sop);
1168 // Add breakpoint in above line. Check sop fields.
1169
1170 // TODO: this doesn't work yet because something more
1171 // interesting has to be done to actually get these values
1172 // back out. Not enough time to figure it out yet.
1173
1174 SceneObjectPart prim = new SceneObjectPart();
1175 prim.UUID = new UUID((String) row["UUID"]);
1176 // explicit conversion of integers is required, which sort
1177 // of sucks. No idea if there is a shortcut here or not.
1178 prim.CreationDate = Convert.ToInt32(row["CreationDate"]);
1179 prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"];
1180 // various text fields
1181 prim.Text = (String) row["Text"];
1182 prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]),
1183 Convert.ToInt32(row["ColorR"]),
1184 Convert.ToInt32(row["ColorG"]),
1185 Convert.ToInt32(row["ColorB"]));
1186 prim.Description = (String) row["Description"];
1187 prim.SitName = (String) row["SitName"];
1188 prim.TouchName = (String) row["TouchName"];
1189 // permissions
1190 prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]);
1191 prim.CreatorID = new UUID((String) row["CreatorID"]);
1192 prim.OwnerID = new UUID((String) row["OwnerID"]);
1193 prim.GroupID = new UUID((String) row["GroupID"]);
1194 prim.LastOwnerID = new UUID((String) row["LastOwnerID"]);
1195 prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]);
1196 prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]);
1197 prim.GroupMask = Convert.ToUInt32(row["GroupMask"]);
1198 prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]);
1199 prim.BaseMask = Convert.ToUInt32(row["BaseMask"]);
1200 // vectors
1201 prim.OffsetPosition = new Vector3(
1202 Convert.ToSingle(row["PositionX"]),
1203 Convert.ToSingle(row["PositionY"]),
1204 Convert.ToSingle(row["PositionZ"])
1205 );
1206 prim.GroupPosition = new Vector3(
1207 Convert.ToSingle(row["GroupPositionX"]),
1208 Convert.ToSingle(row["GroupPositionY"]),
1209 Convert.ToSingle(row["GroupPositionZ"])
1210 );
1211 prim.Velocity = new Vector3(
1212 Convert.ToSingle(row["VelocityX"]),
1213 Convert.ToSingle(row["VelocityY"]),
1214 Convert.ToSingle(row["VelocityZ"])
1215 );
1216 prim.AngularVelocity = new Vector3(
1217 Convert.ToSingle(row["AngularVelocityX"]),
1218 Convert.ToSingle(row["AngularVelocityY"]),
1219 Convert.ToSingle(row["AngularVelocityZ"])
1220 );
1221 prim.Acceleration = new Vector3(
1222 Convert.ToSingle(row["AccelerationX"]),
1223 Convert.ToSingle(row["AccelerationY"]),
1224 Convert.ToSingle(row["AccelerationZ"])
1225 );
1226 // quaternions
1227 prim.RotationOffset = new Quaternion(
1228 Convert.ToSingle(row["RotationX"]),
1229 Convert.ToSingle(row["RotationY"]),
1230 Convert.ToSingle(row["RotationZ"]),
1231 Convert.ToSingle(row["RotationW"])
1232 );
1233
1234 prim.SitTargetPositionLL = new Vector3(
1235 Convert.ToSingle(row["SitTargetOffsetX"]),
1236 Convert.ToSingle(row["SitTargetOffsetY"]),
1237 Convert.ToSingle(row["SitTargetOffsetZ"]));
1238 prim.SitTargetOrientationLL = new Quaternion(
1239 Convert.ToSingle(
1240 row["SitTargetOrientX"]),
1241 Convert.ToSingle(
1242 row["SitTargetOrientY"]),
1243 Convert.ToSingle(
1244 row["SitTargetOrientZ"]),
1245 Convert.ToSingle(
1246 row["SitTargetOrientW"]));
1247
1248 prim.ClickAction = Convert.ToByte(row["ClickAction"]);
1249 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]);
1250 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]);
1251 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]);
1252 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]);
1253 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]);
1254
1255 prim.Sound = new UUID(row["LoopedSound"].ToString());
1256 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1257 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1258
1259 if (!row.IsNull("TextureAnimation"))
1260 prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString());
1261 if (!row.IsNull("ParticleSystem"))
1262 prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString());
1263
1264 prim.AngularVelocity = new Vector3(
1265 Convert.ToSingle(row["OmegaX"]),
1266 Convert.ToSingle(row["OmegaY"]),
1267 Convert.ToSingle(row["OmegaZ"])
1268 );
1269
1270 prim.SetCameraEyeOffset(new Vector3(
1271 Convert.ToSingle(row["CameraEyeOffsetX"]),
1272 Convert.ToSingle(row["CameraEyeOffsetY"]),
1273 Convert.ToSingle(row["CameraEyeOffsetZ"])
1274 ));
1275
1276 prim.SetCameraAtOffset(new Vector3(
1277 Convert.ToSingle(row["CameraAtOffsetX"]),
1278 Convert.ToSingle(row["CameraAtOffsetY"]),
1279 Convert.ToSingle(row["CameraAtOffsetZ"])
1280 ));
1281
1282 if (Convert.ToInt16(row["ForceMouselook"]) != 0)
1283 prim.SetForceMouselook(true);
1284
1285 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]);
1286
1287 if (Convert.ToInt16(row["AllowedDrop"]) != 0)
1288 prim.AllowedDrop = true;
1289
1290 if (Convert.ToInt16(row["DieAtEdge"]) != 0)
1291 prim.DIE_AT_EDGE = true;
1292
1293 prim.SalePrice = Convert.ToInt32(row["SalePrice"]);
1294 prim.ObjectSaleType = Convert.ToByte(row["SaleType"]);
1295
1296 prim.Material = Convert.ToByte(row["Material"]);
1297
1298 prim.CollisionSound = new UUID(row["CollisionSound"].ToString());
1299 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]);
1300
1301 if (Convert.ToInt16(row["VolumeDetect"]) != 0)
1302 prim.VolumeDetectActive = true;
1303
1304 return prim;
1305 }
1306
1307 /// <summary>
1308 /// Build a prim inventory item from the persisted data.
1309 /// </summary>
1310 /// <param name="row"></param>
1311 /// <returns></returns>
1312 private static TaskInventoryItem buildItem(DataRow row)
1313 {
1314 TaskInventoryItem taskItem = new TaskInventoryItem();
1315
1316 taskItem.ItemID = new UUID((String)row["itemID"]);
1317 taskItem.ParentPartID = new UUID((String)row["primID"]);
1318 taskItem.AssetID = new UUID((String)row["assetID"]);
1319 taskItem.ParentID = new UUID((String)row["parentFolderID"]);
1320
1321 taskItem.InvType = Convert.ToInt32(row["invType"]);
1322 taskItem.Type = Convert.ToInt32(row["assetType"]);
1323
1324 taskItem.Name = (String)row["name"];
1325 taskItem.Description = (String)row["description"];
1326 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
1327 taskItem.CreatorID = new UUID((String)row["creatorID"]);
1328 taskItem.OwnerID = new UUID((String)row["ownerID"]);
1329 taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]);
1330 taskItem.GroupID = new UUID((String)row["groupID"]);
1331
1332 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
1333 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
1334 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
1335 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
1336 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
1337 taskItem.Flags = Convert.ToUInt32(row["flags"]);
1338
1339 return taskItem;
1340 }
1341
1342 /// <summary>
1343 /// Build a Land Data from the persisted data.
1344 /// </summary>
1345 /// <param name="row"></param>
1346 /// <returns></returns>
1347 private LandData buildLandData(DataRow row)
1348 {
1349 LandData newData = new LandData();
1350
1351 newData.GlobalID = new UUID((String) row["UUID"]);
1352 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
1353
1354 // Bitmap is a byte[512]
1355 newData.Bitmap = (Byte[]) row["Bitmap"];
1356
1357 newData.Name = (String) row["Name"];
1358 newData.Description = (String) row["Desc"];
1359 newData.OwnerID = (UUID)(String) row["OwnerUUID"];
1360 newData.IsGroupOwned = (Boolean) row["IsGroupOwned"];
1361 newData.Area = Convert.ToInt32(row["Area"]);
1362 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1363 newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]);
1364 //Enum OpenMetaverse.Parcel.ParcelCategory
1365 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1366 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1367 newData.GroupID = new UUID((String) row["GroupUUID"]);
1368 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1369 newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]);
1370 //Enum. OpenMetaverse.Parcel.ParcelStatus
1371 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1372 newData.LandingType = (Byte) row["LandingType"];
1373 newData.MediaAutoScale = (Byte) row["MediaAutoScale"];
1374 newData.MediaID = new UUID((String) row["MediaTextureUUID"]);
1375 newData.MediaURL = (String) row["MediaURL"];
1376 newData.MusicURL = (String) row["MusicURL"];
1377 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1378 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1379 newData.SnapshotID = (UUID)(String) row["SnapshotUUID"];
1380 try
1381 {
1382
1383 newData.UserLocation =
1384 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1385 Convert.ToSingle(row["UserLocationZ"]));
1386 newData.UserLookAt =
1387 new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1388 Convert.ToSingle(row["UserLookAtZ"]));
1389
1390 }
1391 catch (InvalidCastException)
1392 {
1393 m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name);
1394 newData.UserLocation = Vector3.Zero;
1395 newData.UserLookAt = Vector3.Zero;
1396 }
1397 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
1398 UUID authBuyerID = UUID.Zero;
1399
1400 UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID);
1401
1402 newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]);
1403 newData.Dwell = Convert.ToInt32(row["Dwell"]);
1404
1405 return newData;
1406 }
1407
1408 private RegionSettings buildRegionSettings(DataRow row)
1409 {
1410 RegionSettings newSettings = new RegionSettings();
1411
1412 newSettings.RegionUUID = new UUID((string) row["regionUUID"]);
1413 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
1414 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
1415 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
1416 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
1417 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
1418 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
1419 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
1420 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
1421 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
1422 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
1423 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
1424 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
1425 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
1426 newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]);
1427 newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]);
1428 newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]);
1429 newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]);
1430 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
1431 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
1432 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
1433 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
1434 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
1435 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
1436 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
1437 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
1438 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
1439 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
1440 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
1441 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
1442 newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
1443 newSettings.SunVector = new Vector3 (
1444 Convert.ToSingle(row["sunvectorx"]),
1445 Convert.ToSingle(row["sunvectory"]),
1446 Convert.ToSingle(row["sunvectorz"])
1447 );
1448 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
1449 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
1450 newSettings.Covenant = new UUID((String) row["covenant"]);
1451
1452 return newSettings;
1453 }
1454
1455 /// <summary>
1456 /// Build a land access entry from the persisted data.
1457 /// </summary>
1458 /// <param name="row"></param>
1459 /// <returns></returns>
1460 private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row)
1461 {
1462 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1463 entry.AgentID = new UUID((string) row["AccessUUID"]);
1464 entry.Flags = (AccessList) row["Flags"];
1465 entry.Time = new DateTime();
1466 return entry;
1467 }
1468
1469 /// <summary>
1470 ///
1471 /// </summary>
1472 /// <param name="val"></param>
1473 /// <returns></returns>
1474 private static Array serializeTerrain(double[,] val)
1475 {
1476 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double));
1477 BinaryWriter bw = new BinaryWriter(str);
1478
1479 // TODO: COMPATIBILITY - Add byte-order conversions
1480 for (int x = 0; x < (int)Constants.RegionSize; x++)
1481 for (int y = 0; y < (int)Constants.RegionSize; y++)
1482 bw.Write(val[x, y]);
1483
1484 return str.ToArray();
1485 }
1486
1487// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val)
1488// {
1489// row["RegionUUID"] = regionUUID;
1490// row["Revision"] = rev;
1491
1492 // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double));
1493// BinaryWriter bw = new BinaryWriter(str);
1494
1495// // TODO: COMPATIBILITY - Add byte-order conversions
1496 // for (int x = 0; x < (int)Constants.RegionSize; x++)
1497 // for (int y = 0; y < (int)Constants.RegionSize; y++)
1498// bw.Write(val[x, y]);
1499
1500// row["Heightfield"] = str.ToArray();
1501// }
1502
1503 /// <summary>
1504 ///
1505 /// </summary>
1506 /// <param name="row"></param>
1507 /// <param name="prim"></param>
1508 /// <param name="sceneGroupID"></param>
1509 /// <param name="regionUUID"></param>
1510 private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1511 {
1512 row["UUID"] = prim.UUID.ToString();
1513 row["RegionUUID"] = regionUUID.ToString();
1514 row["CreationDate"] = prim.CreationDate;
1515 row["Name"] = prim.Name;
1516 row["SceneGroupID"] = sceneGroupID.ToString();
1517 // the UUID of the root part for this SceneObjectGroup
1518 // various text fields
1519 row["Text"] = prim.Text;
1520 row["Description"] = prim.Description;
1521 row["SitName"] = prim.SitName;
1522 row["TouchName"] = prim.TouchName;
1523 // permissions
1524 row["ObjectFlags"] = prim.ObjectFlags;
1525 row["CreatorID"] = prim.CreatorID.ToString();
1526 row["OwnerID"] = prim.OwnerID.ToString();
1527 row["GroupID"] = prim.GroupID.ToString();
1528 row["LastOwnerID"] = prim.LastOwnerID.ToString();
1529 row["OwnerMask"] = prim.OwnerMask;
1530 row["NextOwnerMask"] = prim.NextOwnerMask;
1531 row["GroupMask"] = prim.GroupMask;
1532 row["EveryoneMask"] = prim.EveryoneMask;
1533 row["BaseMask"] = prim.BaseMask;
1534 // vectors
1535 row["PositionX"] = prim.OffsetPosition.X;
1536 row["PositionY"] = prim.OffsetPosition.Y;
1537 row["PositionZ"] = prim.OffsetPosition.Z;
1538 row["GroupPositionX"] = prim.GroupPosition.X;
1539 row["GroupPositionY"] = prim.GroupPosition.Y;
1540 row["GroupPositionZ"] = prim.GroupPosition.Z;
1541 row["VelocityX"] = prim.Velocity.X;
1542 row["VelocityY"] = prim.Velocity.Y;
1543 row["VelocityZ"] = prim.Velocity.Z;
1544 row["AngularVelocityX"] = prim.AngularVelocity.X;
1545 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1546 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1547 row["AccelerationX"] = prim.Acceleration.X;
1548 row["AccelerationY"] = prim.Acceleration.Y;
1549 row["AccelerationZ"] = prim.Acceleration.Z;
1550 // quaternions
1551 row["RotationX"] = prim.RotationOffset.X;
1552 row["RotationY"] = prim.RotationOffset.Y;
1553 row["RotationZ"] = prim.RotationOffset.Z;
1554 row["RotationW"] = prim.RotationOffset.W;
1555
1556 // Sit target
1557 Vector3 sitTargetPos = prim.SitTargetPositionLL;
1558 row["SitTargetOffsetX"] = sitTargetPos.X;
1559 row["SitTargetOffsetY"] = sitTargetPos.Y;
1560 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1561
1562 Quaternion sitTargetOrient = prim.SitTargetOrientationLL;
1563 row["SitTargetOrientW"] = sitTargetOrient.W;
1564 row["SitTargetOrientX"] = sitTargetOrient.X;
1565 row["SitTargetOrientY"] = sitTargetOrient.Y;
1566 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1567 row["ColorR"] = Convert.ToInt32(prim.Color.R);
1568 row["ColorG"] = Convert.ToInt32(prim.Color.G);
1569 row["ColorB"] = Convert.ToInt32(prim.Color.B);
1570 row["ColorA"] = Convert.ToInt32(prim.Color.A);
1571 row["PayPrice"] = prim.PayPrice[0];
1572 row["PayButton1"] = prim.PayPrice[1];
1573 row["PayButton2"] = prim.PayPrice[2];
1574 row["PayButton3"] = prim.PayPrice[3];
1575 row["PayButton4"] = prim.PayPrice[4];
1576
1577
1578 row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation);
1579 row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem);
1580
1581 row["OmegaX"] = prim.AngularVelocity.X;
1582 row["OmegaY"] = prim.AngularVelocity.Y;
1583 row["OmegaZ"] = prim.AngularVelocity.Z;
1584
1585 row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X;
1586 row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y;
1587 row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z;
1588
1589 row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X;
1590 row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y;
1591 row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z;
1592
1593
1594 if ((prim.SoundFlags & 1) != 0) // Looped
1595 {
1596 row["LoopedSound"] = prim.Sound.ToString();
1597 row["LoopedSoundGain"] = prim.SoundGain;
1598 }
1599 else
1600 {
1601 row["LoopedSound"] = UUID.Zero.ToString();
1602 row["LoopedSoundGain"] = 0.0f;
1603 }
1604
1605 if (prim.GetForceMouselook())
1606 row["ForceMouselook"] = 1;
1607 else
1608 row["ForceMouselook"] = 0;
1609
1610 row["ScriptAccessPin"] = prim.ScriptAccessPin;
1611
1612 if (prim.AllowedDrop)
1613 row["AllowedDrop"] = 1;
1614 else
1615 row["AllowedDrop"] = 0;
1616
1617 if (prim.DIE_AT_EDGE)
1618 row["DieAtEdge"] = 1;
1619 else
1620 row["DieAtEdge"] = 0;
1621
1622 row["SalePrice"] = prim.SalePrice;
1623 row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType);
1624
1625 // click action
1626 row["ClickAction"] = prim.ClickAction;
1627
1628 row["SalePrice"] = prim.SalePrice;
1629 row["Material"] = prim.Material;
1630
1631 row["CollisionSound"] = prim.CollisionSound.ToString();
1632 row["CollisionSoundVolume"] = prim.CollisionSoundVolume;
1633 if (prim.VolumeDetectActive)
1634 row["VolumeDetect"] = 1;
1635 else
1636 row["VolumeDetect"] = 0;
1637
1638 }
1639
1640 /// <summary>
1641 ///
1642 /// </summary>
1643 /// <param name="row"></param>
1644 /// <param name="taskItem"></param>
1645 private static void fillItemRow(DataRow row, TaskInventoryItem taskItem)
1646 {
1647 row["itemID"] = taskItem.ItemID.ToString();
1648 row["primID"] = taskItem.ParentPartID.ToString();
1649 row["assetID"] = taskItem.AssetID.ToString();
1650 row["parentFolderID"] = taskItem.ParentID.ToString();
1651
1652 row["invType"] = taskItem.InvType;
1653 row["assetType"] = taskItem.Type;
1654
1655 row["name"] = taskItem.Name;
1656 row["description"] = taskItem.Description;
1657 row["creationDate"] = taskItem.CreationDate;
1658 row["creatorID"] = taskItem.CreatorID.ToString();
1659 row["ownerID"] = taskItem.OwnerID.ToString();
1660 row["lastOwnerID"] = taskItem.LastOwnerID.ToString();
1661 row["groupID"] = taskItem.GroupID.ToString();
1662 row["nextPermissions"] = taskItem.NextPermissions;
1663 row["currentPermissions"] = taskItem.CurrentPermissions;
1664 row["basePermissions"] = taskItem.BasePermissions;
1665 row["everyonePermissions"] = taskItem.EveryonePermissions;
1666 row["groupPermissions"] = taskItem.GroupPermissions;
1667 row["flags"] = taskItem.Flags;
1668 }
1669
1670 /// <summary>
1671 ///
1672 /// </summary>
1673 /// <param name="row"></param>
1674 /// <param name="land"></param>
1675 /// <param name="regionUUID"></param>
1676 private static void fillLandRow(DataRow row, LandData land, UUID regionUUID)
1677 {
1678 row["UUID"] = land.GlobalID.ToString();
1679 row["RegionUUID"] = regionUUID.ToString();
1680 row["LocalLandID"] = land.LocalID;
1681
1682 // Bitmap is a byte[512]
1683 row["Bitmap"] = land.Bitmap;
1684
1685 row["Name"] = land.Name;
1686 row["Desc"] = land.Description;
1687 row["OwnerUUID"] = land.OwnerID.ToString();
1688 row["IsGroupOwned"] = land.IsGroupOwned;
1689 row["Area"] = land.Area;
1690 row["AuctionID"] = land.AuctionID; //Unemplemented
1691 row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory
1692 row["ClaimDate"] = land.ClaimDate;
1693 row["ClaimPrice"] = land.ClaimPrice;
1694 row["GroupUUID"] = land.GroupID.ToString();
1695 row["SalePrice"] = land.SalePrice;
1696 row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus
1697 row["LandFlags"] = land.Flags;
1698 row["LandingType"] = land.LandingType;
1699 row["MediaAutoScale"] = land.MediaAutoScale;
1700 row["MediaTextureUUID"] = land.MediaID.ToString();
1701 row["MediaURL"] = land.MediaURL;
1702 row["MusicURL"] = land.MusicURL;
1703 row["PassHours"] = land.PassHours;
1704 row["PassPrice"] = land.PassPrice;
1705 row["SnapshotUUID"] = land.SnapshotID.ToString();
1706 row["UserLocationX"] = land.UserLocation.X;
1707 row["UserLocationY"] = land.UserLocation.Y;
1708 row["UserLocationZ"] = land.UserLocation.Z;
1709 row["UserLookAtX"] = land.UserLookAt.X;
1710 row["UserLookAtY"] = land.UserLookAt.Y;
1711 row["UserLookAtZ"] = land.UserLookAt.Z;
1712 row["AuthbuyerID"] = land.AuthBuyerID.ToString();
1713 row["OtherCleanTime"] = land.OtherCleanTime;
1714 row["Dwell"] = land.Dwell;
1715 }
1716
1717 /// <summary>
1718 ///
1719 /// </summary>
1720 /// <param name="row"></param>
1721 /// <param name="entry"></param>
1722 /// <param name="parcelID"></param>
1723 private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID)
1724 {
1725 row["LandUUID"] = parcelID.ToString();
1726 row["AccessUUID"] = entry.AgentID.ToString();
1727 row["Flags"] = entry.Flags;
1728 }
1729
1730 private static void fillRegionSettingsRow(DataRow row, RegionSettings settings)
1731 {
1732 row["regionUUID"] = settings.RegionUUID.ToString();
1733 row["block_terraform"] = settings.BlockTerraform;
1734 row["block_fly"] = settings.BlockFly;
1735 row["allow_damage"] = settings.AllowDamage;
1736 row["restrict_pushing"] = settings.RestrictPushing;
1737 row["allow_land_resell"] = settings.AllowLandResell;
1738 row["allow_land_join_divide"] = settings.AllowLandJoinDivide;
1739 row["block_show_in_search"] = settings.BlockShowInSearch;
1740 row["agent_limit"] = settings.AgentLimit;
1741 row["object_bonus"] = settings.ObjectBonus;
1742 row["maturity"] = settings.Maturity;
1743 row["disable_scripts"] = settings.DisableScripts;
1744 row["disable_collisions"] = settings.DisableCollisions;
1745 row["disable_physics"] = settings.DisablePhysics;
1746 row["terrain_texture_1"] = settings.TerrainTexture1.ToString();
1747 row["terrain_texture_2"] = settings.TerrainTexture2.ToString();
1748 row["terrain_texture_3"] = settings.TerrainTexture3.ToString();
1749 row["terrain_texture_4"] = settings.TerrainTexture4.ToString();
1750 row["elevation_1_nw"] = settings.Elevation1NW;
1751 row["elevation_2_nw"] = settings.Elevation2NW;
1752 row["elevation_1_ne"] = settings.Elevation1NE;
1753 row["elevation_2_ne"] = settings.Elevation2NE;
1754 row["elevation_1_se"] = settings.Elevation1SE;
1755 row["elevation_2_se"] = settings.Elevation2SE;
1756 row["elevation_1_sw"] = settings.Elevation1SW;
1757 row["elevation_2_sw"] = settings.Elevation2SW;
1758 row["water_height"] = settings.WaterHeight;
1759 row["terrain_raise_limit"] = settings.TerrainRaiseLimit;
1760 row["terrain_lower_limit"] = settings.TerrainLowerLimit;
1761 row["use_estate_sun"] = settings.UseEstateSun;
1762 row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox
1763 row["sunvectorx"] = settings.SunVector.X;
1764 row["sunvectory"] = settings.SunVector.Y;
1765 row["sunvectorz"] = settings.SunVector.Z;
1766 row["fixed_sun"] = settings.FixedSun;
1767 row["sun_position"] = settings.SunPosition;
1768 row["covenant"] = settings.Covenant.ToString();
1769 }
1770
1771 /// <summary>
1772 ///
1773 /// </summary>
1774 /// <param name="row"></param>
1775 /// <returns></returns>
1776 private PrimitiveBaseShape buildShape(DataRow row)
1777 {
1778 PrimitiveBaseShape s = new PrimitiveBaseShape();
1779 s.Scale = new Vector3(
1780 Convert.ToSingle(row["ScaleX"]),
1781 Convert.ToSingle(row["ScaleY"]),
1782 Convert.ToSingle(row["ScaleZ"])
1783 );
1784 // paths
1785 s.PCode = Convert.ToByte(row["PCode"]);
1786 s.PathBegin = Convert.ToUInt16(row["PathBegin"]);
1787 s.PathEnd = Convert.ToUInt16(row["PathEnd"]);
1788 s.PathScaleX = Convert.ToByte(row["PathScaleX"]);
1789 s.PathScaleY = Convert.ToByte(row["PathScaleY"]);
1790 s.PathShearX = Convert.ToByte(row["PathShearX"]);
1791 s.PathShearY = Convert.ToByte(row["PathShearY"]);
1792 s.PathSkew = Convert.ToSByte(row["PathSkew"]);
1793 s.PathCurve = Convert.ToByte(row["PathCurve"]);
1794 s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]);
1795 s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]);
1796 s.PathTaperX = Convert.ToSByte(row["PathTaperX"]);
1797 s.PathTaperY = Convert.ToSByte(row["PathTaperY"]);
1798 s.PathTwist = Convert.ToSByte(row["PathTwist"]);
1799 s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]);
1800 // profile
1801 s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]);
1802 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
1803 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
1804 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
1805 s.State = Convert.ToByte(row["State"]);
1806
1807 byte[] textureEntry = (byte[])row["Texture"];
1808 s.TextureEntry = textureEntry;
1809
1810 s.ExtraParams = (byte[]) row["ExtraParams"];
1811 return s;
1812 }
1813
1814 /// <summary>
1815 ///
1816 /// </summary>
1817 /// <param name="row"></param>
1818 /// <param name="prim"></param>
1819 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1820 {
1821 PrimitiveBaseShape s = prim.Shape;
1822 row["UUID"] = prim.UUID.ToString();
1823 // shape is an enum
1824 row["Shape"] = 0;
1825 // vectors
1826 row["ScaleX"] = s.Scale.X;
1827 row["ScaleY"] = s.Scale.Y;
1828 row["ScaleZ"] = s.Scale.Z;
1829 // paths
1830 row["PCode"] = s.PCode;
1831 row["PathBegin"] = s.PathBegin;
1832 row["PathEnd"] = s.PathEnd;
1833 row["PathScaleX"] = s.PathScaleX;
1834 row["PathScaleY"] = s.PathScaleY;
1835 row["PathShearX"] = s.PathShearX;
1836 row["PathShearY"] = s.PathShearY;
1837 row["PathSkew"] = s.PathSkew;
1838 row["PathCurve"] = s.PathCurve;
1839 row["PathRadiusOffset"] = s.PathRadiusOffset;
1840 row["PathRevolutions"] = s.PathRevolutions;
1841 row["PathTaperX"] = s.PathTaperX;
1842 row["PathTaperY"] = s.PathTaperY;
1843 row["PathTwist"] = s.PathTwist;
1844 row["PathTwistBegin"] = s.PathTwistBegin;
1845 // profile
1846 row["ProfileBegin"] = s.ProfileBegin;
1847 row["ProfileEnd"] = s.ProfileEnd;
1848 row["ProfileCurve"] = s.ProfileCurve;
1849 row["ProfileHollow"] = s.ProfileHollow;
1850 row["State"] = s.State;
1851
1852 row["Texture"] = s.TextureEntry;
1853 row["ExtraParams"] = s.ExtraParams;
1854 }
1855
1856 /// <summary>
1857 ///
1858 /// </summary>
1859 /// <param name="prim"></param>
1860 /// <param name="sceneGroupID"></param>
1861 /// <param name="regionUUID"></param>
1862 private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1863 {
1864
1865 DataTable prims = ds.Tables["prims"];
1866 DataTable shapes = ds.Tables["primshapes"];
1867
1868 DataRow primRow = prims.Rows.Find(prim.UUID.ToString());
1869 if (primRow == null)
1870 {
1871 primRow = prims.NewRow();
1872 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1873 prims.Rows.Add(primRow);
1874 }
1875 else
1876 {
1877 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1878 }
1879
1880 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
1881 if (shapeRow == null)
1882 {
1883 shapeRow = shapes.NewRow();
1884 fillShapeRow(shapeRow, prim);
1885 shapes.Rows.Add(shapeRow);
1886 }
1887 else
1888 {
1889 fillShapeRow(shapeRow, prim);
1890 }
1891 }
1892
1893 /// <summary>
1894 /// see IRegionDatastore
1895 /// </summary>
1896 /// <param name="primID"></param>
1897 /// <param name="items"></param>
1898 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1899 {
1900 m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID);
1901
1902 DataTable dbItems = ds.Tables["primitems"];
1903
1904 // For now, we're just going to crudely remove all the previous inventory items
1905 // no matter whether they have changed or not, and replace them with the current set.
1906 lock (ds)
1907 {
1908 RemoveItems(primID);
1909
1910 // repalce with current inventory details
1911 foreach (TaskInventoryItem newItem in items)
1912 {
1913// m_log.InfoFormat(
1914// "[DATASTORE]: ",
1915// "Adding item {0}, {1} to prim ID {2}",
1916// newItem.Name, newItem.ItemID, newItem.ParentPartID);
1917
1918 DataRow newItemRow = dbItems.NewRow();
1919 fillItemRow(newItemRow, newItem);
1920 dbItems.Rows.Add(newItemRow);
1921 }
1922 }
1923
1924 Commit();
1925 }
1926
1927 /***********************************************************************
1928 *
1929 * SQL Statement Creation Functions
1930 *
1931 * These functions create SQL statements for update, insert, and create.
1932 * They can probably be factored later to have a db independant
1933 * portion and a db specific portion
1934 *
1935 **********************************************************************/
1936
1937 /// <summary>
1938 /// Create an insert command
1939 /// </summary>
1940 /// <param name="table">table name</param>
1941 /// <param name="dt">data table</param>
1942 /// <returns>the created command</returns>
1943 /// <remarks>
1944 /// This is subtle enough to deserve some commentary.
1945 /// Instead of doing *lots* and *lots of hardcoded strings
1946 /// for database definitions we'll use the fact that
1947 /// realistically all insert statements look like "insert
1948 /// into A(b, c) values(:b, :c) on the parameterized query
1949 /// front. If we just have a list of b, c, etc... we can
1950 /// generate these strings instead of typing them out.
1951 /// </remarks>
1952 private static SqliteCommand createInsertCommand(string table, DataTable dt)
1953 {
1954 string[] cols = new string[dt.Columns.Count];
1955 for (int i = 0; i < dt.Columns.Count; i++)
1956 {
1957 DataColumn col = dt.Columns[i];
1958 cols[i] = col.ColumnName;
1959 }
1960
1961 string sql = "insert into " + table + "(";
1962 sql += String.Join(", ", cols);
1963 // important, the first ':' needs to be here, the rest get added in the join
1964 sql += ") values (:";
1965 sql += String.Join(", :", cols);
1966 sql += ")";
1967 SqliteCommand cmd = new SqliteCommand(sql);
1968
1969 // this provides the binding for all our parameters, so
1970 // much less code than it used to be
1971 foreach (DataColumn col in dt.Columns)
1972 {
1973 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
1974 }
1975 return cmd;
1976 }
1977
1978
1979 /// <summary>
1980 /// create an update command
1981 /// </summary>
1982 /// <param name="table">table name</param>
1983 /// <param name="pk"></param>
1984 /// <param name="dt"></param>
1985 /// <returns>the created command</returns>
1986 private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt)
1987 {
1988 string sql = "update " + table + " set ";
1989 string subsql = String.Empty;
1990 foreach (DataColumn col in dt.Columns)
1991 {
1992 if (subsql.Length > 0)
1993 {
1994 // a map function would rock so much here
1995 subsql += ", ";
1996 }
1997 subsql += col.ColumnName + "= :" + col.ColumnName;
1998 }
1999 sql += subsql;
2000 sql += " where " + pk;
2001 SqliteCommand cmd = new SqliteCommand(sql);
2002
2003 // this provides the binding for all our parameters, so
2004 // much less code than it used to be
2005
2006 foreach (DataColumn col in dt.Columns)
2007 {
2008 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
2009 }
2010 return cmd;
2011 }
2012
2013 /// <summary>
2014 /// create an update command
2015 /// </summary>
2016 /// <param name="table">table name</param>
2017 /// <param name="pk"></param>
2018 /// <param name="dt"></param>
2019 /// <returns>the created command</returns>
2020 private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt)
2021 {
2022 string sql = "update " + table + " set ";
2023 string subsql = String.Empty;
2024 foreach (DataColumn col in dt.Columns)
2025 {
2026 if (subsql.Length > 0)
2027 {
2028 // a map function would rock so much here
2029 subsql += ", ";
2030 }
2031 subsql += col.ColumnName + "= :" + col.ColumnName;
2032 }
2033 sql += subsql;
2034 sql += " where " + pk1 + " and " + pk2;
2035 SqliteCommand cmd = new SqliteCommand(sql);
2036
2037 // this provides the binding for all our parameters, so
2038 // much less code than it used to be
2039
2040 foreach (DataColumn col in dt.Columns)
2041 {
2042 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
2043 }
2044 return cmd;
2045 }
2046
2047 /// <summary>
2048 ///
2049 /// </summary>
2050 /// <param name="dt">Data Table</param>
2051 /// <returns></returns>
2052 // private static string defineTable(DataTable dt)
2053 // {
2054 // string sql = "create table " + dt.TableName + "(";
2055 // string subsql = String.Empty;
2056 // foreach (DataColumn col in dt.Columns)
2057 // {
2058 // if (subsql.Length > 0)
2059 // {
2060 // // a map function would rock so much here
2061 // subsql += ",\n";
2062 // }
2063 // subsql += col.ColumnName + " " + sqliteType(col.DataType);
2064 // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0])
2065 // {
2066 // subsql += " primary key";
2067 // }
2068 // }
2069 // sql += subsql;
2070 // sql += ")";
2071 // return sql;
2072 // }
2073
2074 /***********************************************************************
2075 *
2076 * Database Binding functions
2077 *
2078 * These will be db specific due to typing, and minor differences
2079 * in databases.
2080 *
2081 **********************************************************************/
2082
2083 ///<summary>
2084 /// This is a convenience function that collapses 5 repetitive
2085 /// lines for defining SqliteParameters to 2 parameters:
2086 /// column name and database type.
2087 ///
2088 /// It assumes certain conventions like :param as the param
2089 /// name to replace in parametrized queries, and that source
2090 /// version is always current version, both of which are fine
2091 /// for us.
2092 ///</summary>
2093 ///<returns>a built sqlite parameter</returns>
2094 private static SqliteParameter createSqliteParameter(string name, Type type)
2095 {
2096 SqliteParameter param = new SqliteParameter();
2097 param.ParameterName = ":" + name;
2098 param.DbType = dbtypeFromType(type);
2099 param.SourceColumn = name;
2100 param.SourceVersion = DataRowVersion.Current;
2101 return param;
2102 }
2103
2104 /// <summary>
2105 ///
2106 /// </summary>
2107 /// <param name="da"></param>
2108 /// <param name="conn"></param>
2109 private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn)
2110 {
2111 da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]);
2112 da.InsertCommand.Connection = conn;
2113
2114 da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]);
2115 da.UpdateCommand.Connection = conn;
2116
2117 SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID");
2118 delete.Parameters.Add(createSqliteParameter("UUID", typeof (String)));
2119 delete.Connection = conn;
2120 da.DeleteCommand = delete;
2121 }
2122
2123 /// <summary>
2124 ///
2125 /// </summary>
2126 /// <param name="da"></param>
2127 /// <param name="conn"></param>
2128 private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn)
2129 {
2130 da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]);
2131 da.InsertCommand.Connection = conn;
2132
2133 da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]);
2134 da.UpdateCommand.Connection = conn;
2135
2136 SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID");
2137 delete.Parameters.Add(createSqliteParameter("itemID", typeof (String)));
2138 delete.Connection = conn;
2139 da.DeleteCommand = delete;
2140 }
2141
2142 /// <summary>
2143 ///
2144 /// </summary>
2145 /// <param name="da"></param>
2146 /// <param name="conn"></param>
2147 private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn)
2148 {
2149 da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]);
2150 da.InsertCommand.Connection = conn;
2151 }
2152
2153 /// <summary>
2154 ///
2155 /// </summary>
2156 /// <param name="da"></param>
2157 /// <param name="conn"></param>
2158 private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn)
2159 {
2160 da.InsertCommand = createInsertCommand("land", ds.Tables["land"]);
2161 da.InsertCommand.Connection = conn;
2162
2163 da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]);
2164 da.UpdateCommand.Connection = conn;
2165
2166 SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID");
2167 delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
2168 da.DeleteCommand = delete;
2169 da.DeleteCommand.Connection = conn;
2170 }
2171
2172 /// <summary>
2173 ///
2174 /// </summary>
2175 /// <param name="da"></param>
2176 /// <param name="conn"></param>
2177 private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn)
2178 {
2179 da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]);
2180 da.InsertCommand.Connection = conn;
2181
2182 da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]);
2183 da.UpdateCommand.Connection = conn;
2184
2185 SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID");
2186 delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String)));
2187 delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String)));
2188 da.DeleteCommand = delete;
2189 da.DeleteCommand.Connection = conn;
2190
2191 }
2192
2193 private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn)
2194 {
2195 da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]);
2196 da.InsertCommand.Connection = conn;
2197 da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]);
2198 da.UpdateCommand.Connection = conn;
2199 }
2200
2201 /// <summary>
2202 ///
2203 /// </summary>
2204 /// <param name="da"></param>
2205 /// <param name="conn"></param>
2206 private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn)
2207 {
2208 da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]);
2209 da.InsertCommand.Connection = conn;
2210
2211 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]);
2212 da.UpdateCommand.Connection = conn;
2213
2214 SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID");
2215 delete.Parameters.Add(createSqliteParameter("UUID", typeof (String)));
2216 delete.Connection = conn;
2217 da.DeleteCommand = delete;
2218 }
2219
2220 /***********************************************************************
2221 *
2222 * Type conversion functions
2223 *
2224 **********************************************************************/
2225
2226 /// <summary>
2227 /// Type conversion function
2228 /// </summary>
2229 /// <param name="type"></param>
2230 /// <returns></returns>
2231 private static DbType dbtypeFromType(Type type)
2232 {
2233 if (type == typeof (String))
2234 {
2235 return DbType.String;
2236 }
2237 else if (type == typeof (Int32))
2238 {
2239 return DbType.Int32;
2240 }
2241 else if (type == typeof (Double))
2242 {
2243 return DbType.Double;
2244 }
2245 else if (type == typeof (Byte))
2246 {
2247 return DbType.Byte;
2248 }
2249 else if (type == typeof (Double))
2250 {
2251 return DbType.Double;
2252 }
2253 else if (type == typeof (Byte[]))
2254 {
2255 return DbType.Binary;
2256 }
2257 else
2258 {
2259 return DbType.String;
2260 }
2261 }
2262
2263 }
2264}