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