aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MSSQL/MSSQLRegionData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Data/MSSQL/MSSQLRegionData.cs')
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs2410
1 files changed, 1048 insertions, 1362 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 3f85fef..7af3e7e 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -42,225 +42,155 @@ namespace OpenSim.Data.MSSQL
42 /// <summary> 42 /// <summary>
43 /// A MSSQL Interface for the Region Server. 43 /// A MSSQL Interface for the Region Server.
44 /// </summary> 44 /// </summary>
45 public class MSSQLDataStore : IRegionDataStore 45 public class MSSQLRegionDataStore : IRegionDataStore
46 { 46 {
47 // private static FileSystemDataStore Instance = new FileSystemDataStore(); 47 // private static FileSystemDataStore Instance = new FileSystemDataStore();
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private const string m_primSelect = "select * from prims"; 50 private MSSQLManager _Database;
51 private const string m_shapeSelect = "select * from primshapes"; 51
52 private const string m_itemsSelect = "select * from primitems"; 52// private const string _PrimSelect = "SELECT * FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID)";
53 private const string m_terrainSelect = "select top 1 * from terrain"; 53// private const string _ShapeSelect = "SELECT * FROM PRIMSHAPES WHERE UUID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID))";
54 private const string m_landSelect = "select * from land"; 54// private const string _ItemsSelect = "SELECT * FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID))";
55 private const string m_landAccessListSelect = "select * from landaccesslist"; 55 private const string _PrimSelect = "SELECT * FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID))";
56 56 private const string _ShapeSelect = "SELECT * FROM PRIMSHAPES WHERE UUID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID)))";
57 private DataSet m_dataSet; 57 private const string _ItemsSelect = "SELECT * FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID)))";
58 private SqlDataAdapter m_primDataAdapter; 58
59 private SqlDataAdapter m_shapeDataAdapter; 59 private DataSet _PrimsDataSet;
60 private SqlDataAdapter m_itemsDataAdapter; 60 private SqlDataAdapter _PrimDataAdapter;
61 private SqlConnection m_connection; 61 private SqlDataAdapter _ShapeDataAdapter;
62 private SqlDataAdapter m_terrainDataAdapter; 62 private SqlDataAdapter _ItemsDataAdapter;
63 private SqlDataAdapter m_landDataAdapter;
64 private SqlDataAdapter m_landAccessListDataAdapter;
65
66 private DataTable m_primTable;
67 private DataTable m_shapeTable;
68 private DataTable m_itemsTable;
69 private DataTable m_terrainTable;
70 private DataTable m_landTable;
71 private DataTable m_landAccessListTable;
72
73 /// <summary>Temporary attribute while this is experimental</summary>
74
75 /***********************************************************************
76 *
77 * Public Interface Functions
78 *
79 **********************************************************************/
80 63
81 /// <summary> 64 /// <summary>
82 /// see IRegionDataStore 65 /// Initialises the region datastore
83 /// </summary> 66 /// </summary>
84 /// <param name="connectionString"></param> 67 /// <param name="connectionString">The connection string.</param>
85 public void Initialise(string connectionString) 68 public void Initialise(string connectionString)
86 { 69 {
87 // Instance.Initialise("", true); 70 if (string.IsNullOrEmpty(connectionString))
88 71 {
89 m_dataSet = new DataSet(); 72 //Add MSSQLManager (dont know if we need it)
90 73 _Database = new MSSQLManager(connectionString);
91 m_log.Info("[REGION DB]: MSSql - connecting: " + connectionString); 74 }
92 m_connection = new SqlConnection(connectionString); 75 else
93 76 {
94 SqlCommand primSelectCmd = new SqlCommand(m_primSelect, m_connection); 77 IniFile iniFile = new IniFile("mssql_connection.ini");
95 m_primDataAdapter = new SqlDataAdapter(primSelectCmd); 78 string settingDataSource = iniFile.ParseFileReadValue("data_source");
96 79 string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog");
97 SqlCommand shapeSelectCmd = new SqlCommand(m_shapeSelect, m_connection); 80 string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info");
98 m_shapeDataAdapter = new SqlDataAdapter(shapeSelectCmd); 81 string settingUserId = iniFile.ParseFileReadValue("user_id");
82 string settingPassword = iniFile.ParseFileReadValue("password");
83
84 _Database =
85 new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
86 settingPassword);
87
88
89 SqlConnectionStringBuilder conBuilder = new SqlConnectionStringBuilder();
90 conBuilder.DataSource = settingDataSource;
91 conBuilder.InitialCatalog = settingInitialCatalog;
92 conBuilder.PersistSecurityInfo = Convert.ToBoolean(settingPersistSecurityInfo);
93 conBuilder.UserID = settingUserId;
94 conBuilder.Password = settingPassword;
95 conBuilder.ApplicationName = Assembly.GetEntryAssembly().Location;
96
97 connectionString = conBuilder.ToString();
98 }
99 99
100 SqlCommand itemsSelectCmd = new SqlCommand(m_itemsSelect, m_connection); 100 //Migration settings
101 m_itemsDataAdapter = new SqlDataAdapter(itemsSelectCmd); 101 Assembly assem = GetType().Assembly;
102 102
103 SqlCommand terrainSelectCmd = new SqlCommand(m_terrainSelect, m_connection); 103 using (SqlConnection connection = _Database.DatabaseConnection())
104 m_terrainDataAdapter = new SqlDataAdapter(terrainSelectCmd); 104 {
105 MSSQLMigration m = new MSSQLMigration(connection, assem, "RegionStore");
105 106
106 SqlCommand landSelectCmd = new SqlCommand(m_landSelect, m_connection); 107 m.Update();
107 m_landDataAdapter = new SqlDataAdapter(landSelectCmd);
108 108
109 SqlCommand landAccessListSelectCmd = new SqlCommand(m_landAccessListSelect, m_connection); 109 //Create Dataset. Not filled!!!
110 m_landAccessListDataAdapter = new SqlDataAdapter(landAccessListSelectCmd); 110 _PrimsDataSet = new DataSet("primsdata");
111 111
112 TestTables(m_connection); 112 using (SqlCommand primSelectCmd = new SqlCommand(_PrimSelect, connection))
113 {
114 primSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
115 primSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
116 primSelectCmd.Parameters.AddWithValue("@UUID", "");
117 _PrimDataAdapter = new SqlDataAdapter(primSelectCmd);
113 118
114 lock (m_dataSet) 119 DataTable primDataTable = new DataTable("prims");
115 { 120 _PrimDataAdapter.Fill(primDataTable);
116 m_primTable = createPrimTable(); 121 primDataTable.PrimaryKey = new DataColumn[] { primDataTable.Columns["UUID"] };
117 m_dataSet.Tables.Add(m_primTable); 122 _PrimsDataSet.Tables.Add(primDataTable);
118 setupPrimCommands(m_primDataAdapter, m_connection);
119 m_primDataAdapter.Fill(m_primTable);
120
121 m_shapeTable = createShapeTable();
122 m_dataSet.Tables.Add(m_shapeTable);
123 setupShapeCommands(m_shapeDataAdapter, m_connection);
124 m_shapeDataAdapter.Fill(m_shapeTable);
125
126 m_itemsTable = createItemsTable();
127 m_dataSet.Tables.Add(m_itemsTable);
128 SetupItemsCommands(m_itemsDataAdapter, m_connection);
129 m_itemsDataAdapter.Fill(m_itemsTable);
130
131 m_terrainTable = createTerrainTable();
132 m_dataSet.Tables.Add(m_terrainTable);
133 setupTerrainCommands(m_terrainDataAdapter, m_connection);
134 m_terrainDataAdapter.Fill(m_terrainTable);
135
136 m_landTable = createLandTable();
137 m_dataSet.Tables.Add(m_landTable);
138 setupLandCommands(m_landDataAdapter, m_connection);
139 m_landDataAdapter.Fill(m_landTable);
140
141 m_landAccessListTable = createLandAccessListTable();
142 m_dataSet.Tables.Add(m_landAccessListTable);
143 setupLandAccessCommands(m_landAccessListDataAdapter, m_connection);
144 m_landAccessListDataAdapter.Fill(m_landAccessListTable);
145 }
146 }
147 123
148 public void StoreRegionSettings(RegionSettings rs) 124 SetupCommands(_PrimDataAdapter); //, connection);
149 { 125 //SetupPrimCommands(_PrimDataAdapter, connection);
150 }
151 126
152 public RegionSettings LoadRegionSettings(LLUUID regionUUID) 127 primDataTable.Clear();
153 {
154 return null;
155 }
156
157 /// <summary>
158 ///
159 /// </summary>
160 /// <param name="obj"></param>
161 /// <param name="regionUUID"></param>
162 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
163 {
164 // Instance.StoreObject(obj, regionUUID);
165
166 lock (m_dataSet)
167 {
168 foreach (SceneObjectPart prim in obj.Children.Values)
169 {
170 if ((prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == 0
171 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Temporary) == 0
172 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) == 0)
173 {
174 //m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
175 addPrim(prim, obj.UUID, regionUUID);
176 }
177 else
178 {
179 // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID);
180 }
181 } 128 }
182 }
183 129
184 Commit(); 130 using (SqlCommand shapeSelectCmd = new SqlCommand(_ShapeSelect, connection))
185 } 131 {
132 shapeSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
133 shapeSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
134 shapeSelectCmd.Parameters.AddWithValue("@UUID", "");
135 _ShapeDataAdapter = new SqlDataAdapter(shapeSelectCmd);
186 136
187 /// <summary> 137 DataTable shapeDataTable = new DataTable("primshapes");
188 /// 138 _ShapeDataAdapter.Fill(shapeDataTable);
189 /// </summary> 139 shapeDataTable.PrimaryKey = new DataColumn[] { shapeDataTable.Columns["UUID"] };
190 /// <param name="obj"></param> 140 _PrimsDataSet.Tables.Add(shapeDataTable);
191 /// <param name="regionUUID"></param>
192 public void RemoveObject(LLUUID obj, LLUUID regionUUID)
193 {
194 // Instance.RemoveObject(obj, regionUUID);
195 141
196 m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID); 142 SetupCommands(_ShapeDataAdapter); //, connection);
143 //SetupShapeCommands(_ShapeDataAdapter, connection);
197 144
198 DataTable prims = m_primTable; 145 shapeDataTable.Clear();
199 DataTable shapes = m_shapeTable; 146 }
200 147
201 string selectExp = "SceneGroupID = '" + obj.ToString() + "'"; 148 using (SqlCommand itemSelectCmd = new SqlCommand(_ItemsSelect, connection))
202 lock (m_dataSet)
203 {
204 foreach (DataRow row in prims.Select(selectExp))
205 { 149 {
206 // Remove shapes row 150 itemSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
207 LLUUID uuid = new LLUUID((string)row["UUID"]); 151 itemSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
152 itemSelectCmd.Parameters.AddWithValue("@UUID", "");
153 _ItemsDataAdapter = new SqlDataAdapter(itemSelectCmd);
208 154
209 DataRow shapeRow = shapes.Rows.Find(uuid.UUID); 155 DataTable itemsDataTable = new DataTable("primitems");
210 if (shapeRow != null) 156 _ItemsDataAdapter.Fill(itemsDataTable);
211 { 157 itemsDataTable.PrimaryKey = new DataColumn[] { itemsDataTable.Columns["itemID"] };
212 shapeRow.Delete(); 158 _PrimsDataSet.Tables.Add(itemsDataTable);
213 }
214 159
215 RemoveItems(new LLUUID((string)row["UUID"])); 160 SetupCommands(_ItemsDataAdapter); //, connection);
161 //SetupItemsCommands(_ItemsDataAdapter, connection);
216 162
217 // Remove prim row 163 itemsDataTable.Clear();
218 row.Delete();
219 } 164 }
220 }
221
222 Commit();
223 }
224
225 /// <summary>
226 /// Remove all persisted items of the given prim.
227 /// The caller must acquire the necessrary synchronization locks and commit or rollback changes.
228 /// </summary>
229 /// <param name="uuid">The item UUID</param>
230 private void RemoveItems(LLUUID uuid)
231 {
232 String sql = String.Format("primID = '{0}'", uuid);
233 DataRow[] itemRows = m_itemsTable.Select(sql);
234 165
235 foreach (DataRow itemRow in itemRows) 166 connection.Close();
236 {
237 itemRow.Delete();
238 } 167 }
168
169 //After this we have a empty fully configured DataSet.
239 } 170 }
240 171
241 /// <summary> 172 /// <summary>
242 /// Load persisted objects from region storage. 173 /// Loads the objects present in the region.
243 /// </summary> 174 /// </summary>
244 /// <param name="regionUUID">The region UUID</param> 175 /// <param name="regionUUID">The region UUID.</param>
176 /// <returns></returns>
245 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID) 177 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
246 { 178 {
247 // return Instance.LoadObjects(regionUUID);
248
249 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>(); 179 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>();
250 180
251 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>(); 181 //Retrieve all values of current region
182 RetrievePrimsDataForRegion(regionUUID, LLUUID.Zero, "");
252 183
253 DataTable prims = m_primTable; 184 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
254 DataTable shapes = m_shapeTable;
255 185
256 string byRegion = "RegionUUID = '" + regionUUID.ToString() + "'"; 186 DataTable prims = _PrimsDataSet.Tables["prims"];
257 string orderByParent = "ParentID ASC"; 187 DataTable shapes = _PrimsDataSet.Tables["primshapes"];
258 188
259 lock (m_dataSet) 189 lock (_PrimsDataSet)
260 { 190 {
261 DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); 191 DataRow[] primsForRegion = prims.Select("", "ParentID ASC"); //.Select(byRegion, orderByParent);
262 m_log.Info("[REGION DB]: " + 192
263 "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); 193 _Log.Info("[REGION DB]: " + "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID);
264 194
265 foreach (DataRow primRow in primsForRegion) 195 foreach (DataRow primRow in primsForRegion)
266 { 196 {
@@ -275,14 +205,14 @@ namespace OpenSim.Data.MSSQL
275 { 205 {
276 SceneObjectGroup group = new SceneObjectGroup(); 206 SceneObjectGroup group = new SceneObjectGroup();
277 207
278 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 208 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
279 if (shapeRow != null) 209 if (shapeRow != null)
280 { 210 {
281 prim.Shape = buildShape(shapeRow); 211 prim.Shape = buildShape(shapeRow);
282 } 212 }
283 else 213 else
284 { 214 {
285 m_log.Info( 215 _Log.Info(
286 "No shape found for prim in storage, so setting default box shape"); 216 "No shape found for prim in storage, so setting default box shape");
287 prim.Shape = PrimitiveBaseShape.Default; 217 prim.Shape = PrimitiveBaseShape.Default;
288 } 218 }
@@ -294,572 +224,712 @@ namespace OpenSim.Data.MSSQL
294 } 224 }
295 else 225 else
296 { 226 {
297 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 227 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
298 if (shapeRow != null) 228 if (shapeRow != null)
299 { 229 {
300 prim.Shape = buildShape(shapeRow); 230 prim.Shape = buildShape(shapeRow);
301 } 231 }
302 else 232 else
303 { 233 {
304 m_log.Info( 234 _Log.Info(
305 "No shape found for prim in storage, so setting default box shape"); 235 "No shape found for prim in storage, so setting default box shape");
306 prim.Shape = PrimitiveBaseShape.Default; 236 prim.Shape = PrimitiveBaseShape.Default;
307 } 237 }
308 createdObjects[new LLUUID(objID)].AddPart(prim); 238 createdObjects[new LLUUID(objID)].AddPart(prim);
309 } 239 }
310 240
311 LoadItems(prim); 241 LoadItems(prim);
312 } 242 }
313 catch (Exception e) 243 catch (Exception e)
314 { 244 {
315 m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows"); 245 _Log.Error("[REGION DB]: Failed create prim object, exception and data follows");
316 m_log.Info("[DATASTORE]: " + e.ToString()); 246 _Log.Info("[REGION DB]: " + e.ToString());
317 foreach (DataColumn col in prims.Columns) 247 foreach (DataColumn col in prims.Columns)
318 { 248 {
319 m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]); 249 _Log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
320 } 250 }
321 } 251 }
322 } 252 }
253
254 _PrimsDataSet.Tables["prims"].Clear();
255 _PrimsDataSet.Tables["primshapes"].Clear();
256 _PrimsDataSet.Tables["primitems"].Clear();
323 } 257 }
324 return retvals; 258 return retvals;
259
260 #region Experimental
261
262//
263// //Get all prims
264// string sql = "select * from prims where RegionUUID = @RegionUUID";
265//
266// using (AutoClosingSqlCommand cmdPrims = _Database.Query(sql))
267// {
268// cmdPrims.Parameters.AddWithValue("@RegionUUID", regionUUID.ToString());
269// using (SqlDataReader readerPrims = cmdPrims.ExecuteReader())
270// {
271// while (readerPrims.Read())
272// {
273// string uuid = (string)readerPrims["UUID"];
274// string objID = (string)readerPrims["SceneGroupID"];
275// SceneObjectPart prim = buildPrim(readerPrims);
276//
277// //Setting default shape, will change shape ltr
278// prim.Shape = PrimitiveBaseShape.Default;
279//
280// //Load inventory items of prim
281// //LoadItems(prim);
282//
283// if (uuid == objID)
284// {
285// SceneObjectGroup group = new SceneObjectGroup();
286//
287// group.AddPart(prim);
288// group.RootPart = prim;
289//
290// createdObjects.Add(group.UUID, group);
291// retvals.Add(group);
292// }
293// else
294// {
295// createdObjects[new LLUUID(objID)].AddPart(prim);
296// }
297// }
298// }
299// }
300// m_log.Info("[REGION DB]: Loaded " + retvals.Count + " prim objects for region: " + regionUUID);
301//
302// //Find all shapes related with prims
303// sql = "select * from primshapes";
304// using (AutoClosingSqlCommand cmdShapes = _Database.Query(sql))
305// {
306// using (SqlDataReader readerShapes = cmdShapes.ExecuteReader())
307// {
308// while (readerShapes.Read())
309// {
310// LLUUID UUID = new LLUUID((string) readerShapes["UUID"]);
311//
312// foreach (SceneObjectGroup objectGroup in createdObjects.Values)
313// {
314// if (objectGroup.Children.ContainsKey(UUID))
315// {
316// objectGroup.Children[UUID].Shape = buildShape(readerShapes);
317// }
318// }
319// }
320// }
321// }
322// return retvals;
323
324 #endregion
325 } 325 }
326 326
327 /// <summary> 327 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
328 /// Load in a prim's persisted inventory.
329 /// </summary>
330 /// <param name="prim"></param>
331 private void LoadItems(SceneObjectPart prim)
332 { 328 {
333 //m_log.InfoFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); 329 //Retrieve all values of current region, and current scene/or prims
334 330 //Build primID's, we use IN so I can select all prims from objgroup
335 DataTable dbItems = m_itemsTable; 331 string primID = "";
332 foreach (SceneObjectPart prim in obj.Children.Values)
333 {
334 primID += prim.UUID + "', '";
335 }
336 primID = primID.Remove(primID.LastIndexOf("',"));
336 337
337 String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); 338 RetrievePrimsDataForRegion(regionUUID, obj.UUID, primID);
338 DataRow[] dbItemRows = dbItems.Select(sql);
339 339
340 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>(); 340 _Log.InfoFormat("[REGION DB]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count);
341 341
342 foreach (DataRow row in dbItemRows) 342 foreach (SceneObjectPart prim in obj.Children.Values)
343 { 343 {
344 TaskInventoryItem item = buildItem(row); 344 if ((prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == 0
345 inventory.Add(item); 345 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Temporary) == 0
346 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) == 0)
347 {
348 lock (_PrimsDataSet)
349 {
350 DataTable prims = _PrimsDataSet.Tables["prims"];
351 DataTable shapes = _PrimsDataSet.Tables["primshapes"];
346 352
347 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); 353 DataRow primRow = prims.Rows.Find(prim.UUID.ToString());
354 if (primRow == null)
355 {
356 primRow = prims.NewRow();
357 fillPrimRow(primRow, prim, obj.UUID, regionUUID);
358 prims.Rows.Add(primRow);
359 }
360 else
361 {
362 fillPrimRow(primRow, prim, obj.UUID, regionUUID);
363 }
364
365 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
366 if (shapeRow == null)
367 {
368 shapeRow = shapes.NewRow();
369 fillShapeRow(shapeRow, prim);
370 shapes.Rows.Add(shapeRow);
371 }
372 else
373 {
374 fillShapeRow(shapeRow, prim);
375 }
376 }
377 }
378 else
379 {
380 // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID);
381 }
348 } 382 }
349 383
350 prim.RestoreInventoryItems(inventory); 384 //Save changes
385 CommitDataSet();
386 }
351 387
352 // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in 388 /// <summary>
353 // every item). This data should really be stored in the prim table itself. 389 /// Removes a object from the database.
354 if (dbItemRows.Length > 0) 390 /// Meaning removing it from tables Prims, PrimShapes and PrimItems
391 /// </summary>
392 /// <param name="objectID">id of scenegroup</param>
393 /// <param name="regionUUID">regionUUID (is this used anyway</param>
394 public void RemoveObject(LLUUID objectID, LLUUID regionUUID)
395 {
396 _Log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", objectID, regionUUID);
397
398 //Remove from prims and primsitem table
399 string sqlPrims = string.Format("DELETE FROM PRIMS WHERE SceneGroupID = '{0}'", objectID);
400 string sqlPrimItems = string.Format("DELETE FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE SceneGroupID = '{0}')", objectID);
401 string sqlPrimShapes = string.Format("DELETE FROM PRIMSHAPES WHERE uuid in (SELECT UUID FROM PRIMS WHERE SceneGroupID = '{0}')", objectID);
402
403 //Using the non transaction mode.
404 using (AutoClosingSqlCommand cmd = _Database.Query(sqlPrimShapes))
355 { 405 {
356 prim.FolderID = inventory[0].ParentID; 406 cmd.ExecuteNonQuery();
407
408 cmd.CommandText = sqlPrimItems;
409 cmd.ExecuteNonQuery();
410
411 cmd.CommandText = sqlPrims;
412 cmd.ExecuteNonQuery();
357 } 413 }
358 } 414 }
359 415
360 /// <summary> 416 /// <summary>
361 /// Store a terrain revision in region storage. 417 /// Store the inventory of a prim. Warning deletes everything first and then adds all again.
362 /// </summary> 418 /// </summary>
363 /// <param name="ter">HeightField data</param> 419 /// <param name="primID"></param>
364 /// <param name="regionID">Region UUID</param> 420 /// <param name="items"></param>
365 public void StoreTerrain(double[,] ter, LLUUID regionID) 421 public void StorePrimInventory(LLUUID primID, ICollection<TaskInventoryItem> items)
366 { 422 {
367 int revision = Util.UnixTimeSinceEpoch(); 423 _Log.InfoFormat("[REGION DB]: Persisting Prim Inventory with prim ID {0}", primID);
368 m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); 424
425 //Statement from MySQL section!
426 // For now, we're just going to crudely remove all the previous inventory items
427 // no matter whether they have changed or not, and replace them with the current set.
369 428
370 // DataTable terrain = m_dataSet.Tables["terrain"]; 429 //Delete everything from PrimID
371 lock (m_dataSet) 430 //TODO add index on PrimID in DB, if not already exist
431 using (AutoClosingSqlCommand cmd = _Database.Query("DELETE PRIMITEMS WHERE primID = @primID"))
372 { 432 {
373 SqlCommand cmd = new SqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + 433 cmd.Parameters.AddWithValue("@primID", primID.ToString());
374 " values(@RegionUUID, @Revision, @Heightfield)", m_connection); 434 cmd.ExecuteNonQuery();
375 using (cmd) 435 }
436
437 string sql =
438 "INSERT INTO [primitems] ([itemID],[primID],[assetID],[parentFolderID],[invType],[assetType],[name],[description],[creationDate],[creatorID],[ownerID],[lastOwnerID],[groupID],[nextPermissions],[currentPermissions],[basePermissions],[everyonePermissions],[groupPermissions],[flags]) VALUES (@itemID,@primID,@assetID,@parentFolderID,@invType,@assetType,@name,@description,@creationDate,@creatorID,@ownerID,@lastOwnerID,@groupID,@nextPermissions,@currentPermissions,@basePermissions,@everyonePermissions,@groupPermissions,@flags)";
439
440 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
441 {
442 foreach (TaskInventoryItem newItem in items)
376 { 443 {
377 cmd.Parameters.Add(new SqlParameter("@RegionUUID", regionID.UUID)); 444 //
378 cmd.Parameters.Add(new SqlParameter("@Revision", revision)); 445 cmd.Parameters.AddRange(CreatePrimInventoryParameters(newItem));
379 cmd.Parameters.Add(new SqlParameter("@Heightfield", serializeTerrain(ter))); 446
380 cmd.ExecuteNonQuery(); 447 cmd.ExecuteNonQuery();
448
449 cmd.Parameters.Clear();
381 } 450 }
382 } 451 }
383 } 452 }
384 453
385 /// <summary> 454 /// <summary>
386 /// Load the latest terrain revision from region storage. 455 /// Loads the terrain map.
387 /// </summary> 456 /// </summary>
388 /// <param name="regionID">The Region UUID</param> 457 /// <param name="regionID">regionID.</param>
389 /// <returns>HeightField Data</returns> 458 /// <returns></returns>
390 public double[,] LoadTerrain(LLUUID regionID) 459 public double[,] LoadTerrain(LLUUID regionID)
391 { 460 {
392 double[,] terret = new double[256, 256]; 461 double[,] terrain = new double[256, 256];
393 terret.Initialize(); 462 terrain.Initialize();
394 463
395 SqlCommand cmd = new SqlCommand( 464 string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc";
396 @"select top 1 RegionUUID, Revision, Heightfield from terrain
397 where RegionUUID=@RegionUUID order by Revision desc"
398 , m_connection);
399 465
400 // SqlParameter param = new SqlParameter(); 466 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
401 cmd.Parameters.Add(new SqlParameter("@RegionUUID", regionID.UUID));
402
403 if (m_connection.State != ConnectionState.Open)
404 { 467 {
405 m_connection.Open(); 468 // MySqlParameter param = new MySqlParameter();
406 } 469 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
407 470
408 using (SqlDataReader row = cmd.ExecuteReader()) 471 using (SqlDataReader reader = cmd.ExecuteReader())
409 {
410 int rev = 0;
411 if (row.Read())
412 { 472 {
413 MemoryStream str = new MemoryStream((byte[])row["Heightfield"]); 473 int rev = 0;
414 BinaryReader br = new BinaryReader(str); 474 if (reader.Read())
415 for (int x = 0; x < 256; x++)
416 { 475 {
417 for (int y = 0; y < 256; y++) 476 MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
477 BinaryReader br = new BinaryReader(str);
478 for (int x = 0; x < 256; x++)
418 { 479 {
419 terret[x, y] = br.ReadDouble(); 480 for (int y = 0; y < 256; y++)
481 {
482 terrain[x, y] = br.ReadDouble();
483 }
420 } 484 }
485 rev = (int)reader["Revision"];
421 } 486 }
422 rev = (int)row["Revision"]; 487 else
423 } 488 {
424 else 489 _Log.Info("[REGION DB]: No terrain found for region");
425 { 490 return null;
426 m_log.Info("[REGION DB]: No terrain found for region"); 491 }
427 return null; 492 _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
428 } 493 }
429
430 m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString());
431 } 494 }
432 495
433 return terret; 496 return terrain;
434 } 497 }
435 498
436 /// <summary> 499 /// <summary>
437 /// 500 /// Stores the terrain map to DB.
438 /// </summary> 501 /// </summary>
439 /// <param name="globalID"></param> 502 /// <param name="terrain">terrain map data.</param>
440 public void RemoveLandObject(LLUUID globalID) 503 /// <param name="regionID">regionID.</param>
504 public void StoreTerrain(double[,] terrain, LLUUID regionID)
441 { 505 {
442 // Instance.RemoveLandObject(globalID); 506 int revision = Util.UnixTimeSinceEpoch();
443 507
444 lock (m_dataSet) 508 //Delete old terrain map
509 string sql = "delete from terrain where RegionUUID=@RegionUUID";
510 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
445 { 511 {
446 using (SqlCommand cmd = new SqlCommand("delete from land where UUID=@UUID", m_connection)) 512 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
447 { 513 cmd.ExecuteNonQuery();
448 cmd.Parameters.Add(new SqlParameter("@UUID", globalID.UUID)); 514 }
449 cmd.ExecuteNonQuery();
450 }
451 515
452 using ( 516 sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
453 SqlCommand cmd = new SqlCommand("delete from landaccesslist where LandUUID=@UUID", m_connection) 517 " values(@RegionUUID, @Revision, @Heightfield)";
454 ) 518
455 { 519 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
456 cmd.Parameters.Add(new SqlParameter("@UUID", globalID.UUID)); 520 {
457 cmd.ExecuteNonQuery(); 521 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
458 } 522 cmd.Parameters.AddWithValue("@Revision", revision);
523 cmd.Parameters.AddWithValue("@Heightfield", serializeTerrain(terrain));
524 cmd.ExecuteNonQuery();
459 } 525 }
526
527 _Log.Info("[REGION DB]: Stored terrain revision r" + revision);
460 } 528 }
461 529
462 /// <summary> 530 /// <summary>
463 /// 531 /// Loads all the land objects of a region.
464 /// </summary> 532 /// </summary>
465 /// <param name="parcel"></param> 533 /// <param name="regionUUID">The region UUID.</param>
466 public void StoreLandObject(ILandObject parcel) 534 /// <returns></returns>
535 public List<LandData> LoadLandObjects(LLUUID regionUUID)
467 { 536 {
468 lock (m_dataSet) 537 List<LandData> landDataForRegion = new List<LandData>();
538
539 string sql = "select * from land where RegionUUID = @RegionUUID";
540
541 //Retrieve all land data from region
542 using (AutoClosingSqlCommand cmdLandData = _Database.Query(sql))
469 { 543 {
470 DataTable land = m_landTable; 544 cmdLandData.Parameters.AddWithValue("@RegionUUID", regionUUID.ToString());
471 DataTable landaccesslist = m_landAccessListTable;
472 545
473 DataRow landRow = land.Rows.Find(parcel.landData.GlobalID.UUID); 546 using (SqlDataReader readerLandData = cmdLandData.ExecuteReader())
474 if (landRow == null)
475 {
476 landRow = land.NewRow();
477 fillLandRow(landRow, parcel.landData, parcel.regionUUID);
478 land.Rows.Add(landRow);
479 }
480 else
481 { 547 {
482 fillLandRow(landRow, parcel.landData, parcel.regionUUID); 548 while (readerLandData.Read())
483 } 549 {
550 LandData data = buildLandData(readerLandData);
484 551
485 using ( 552 }
486 SqlCommand cmd =
487 new SqlCommand("delete from landaccesslist where LandUUID=@LandUUID", m_connection))
488 {
489 cmd.Parameters.Add(new SqlParameter("@LandUUID", parcel.landData.GlobalID.UUID));
490 cmd.ExecuteNonQuery();
491 } 553 }
554 }
492 555
493 foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.ParcelAccessList) 556 //Retrieve all accesslist data for all landdata
557 foreach (LandData landData in landDataForRegion)
558 {
559 sql = "select * from landaccesslist where LandUUID = @LandUUID";
560 using (AutoClosingSqlCommand cmdAccessList = _Database.Query(sql))
494 { 561 {
495 DataRow newAccessRow = landaccesslist.NewRow(); 562 cmdAccessList.Parameters.AddWithValue("@LandUUID", landData.GlobalID);
496 fillLandAccessRow(newAccessRow, entry, parcel.landData.GlobalID); 563 using (SqlDataReader readerAccessList = cmdAccessList.ExecuteReader())
497 landaccesslist.Rows.Add(newAccessRow); 564 {
565 while (readerAccessList.Read())
566 {
567 landData.ParcelAccessList.Add(buildLandAccessData(readerAccessList));
568 }
569 }
498 } 570 }
499
500 } 571 }
501 Commit(); 572
573 //Return data
574 return landDataForRegion;
502 } 575 }
503 576
504 /// <summary> 577 /// <summary>
505 /// 578 /// Stores land object with landaccess list.
506 /// </summary> 579 /// </summary>
507 /// <param name="regionUUID">The region UUID</param> 580 /// <param name="parcel">parcel data.</param>
508 /// <returns></returns> 581 public void StoreLandObject(ILandObject parcel)
509 public List<LandData> LoadLandObjects(LLUUID regionUUID)
510 { 582 {
511 List<LandData> landDataForRegion = new List<LandData>(); 583 //As this is only one record in land table I just delete all and then add a new record.
512 lock (m_dataSet) 584 //As the delete landaccess is already in the mysql code
585
586 //Delete old values
587 RemoveLandObject(parcel.landData.GlobalID);
588
589 //Insert new values
590 string sql = @"INSERT INTO [land]
591([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID])
592VALUES
593(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID)";
594
595 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
513 { 596 {
514 DataTable land = m_landTable; 597 cmd.Parameters.AddRange(CreateLandParameters(parcel.landData, parcel.regionUUID));
515 DataTable landaccesslist = m_landAccessListTable; 598
516 string searchExp = "RegionUUID = '" + regionUUID.UUID + "'"; 599 cmd.ExecuteNonQuery();
517 DataRow[] rawDataForRegion = land.Select(searchExp); 600 }
518 foreach (DataRow rawDataLand in rawDataForRegion) 601
602 sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)";
603
604 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
605 {
606 foreach (ParcelManager.ParcelAccessEntry parcelAccessEntry in parcel.landData.ParcelAccessList)
519 { 607 {
520 LandData newLand = buildLandData(rawDataLand); 608 cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.regionUUID));
521 string accessListSearchExp = "LandUUID = '" + newLand.GlobalID.UUID + "'"; 609
522 DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); 610 cmd.ExecuteNonQuery();
523 foreach (DataRow rawDataLandAccess in rawDataForLandAccessList)
524 {
525 newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess));
526 }
527 611
528 landDataForRegion.Add(newLand); 612 cmd.Parameters.Clear();
529 } 613 }
530 } 614 }
531 return landDataForRegion;
532 } 615 }
533 616
534 /// <summary> 617 /// <summary>
535 /// Load (fetch?) the region banlist 618 /// Removes a land object from DB.
536 /// </summary> 619 /// </summary>
537 /// <param name="regionUUID">the region UUID</param> 620 /// <param name="globalID">UUID of landobject</param>
538 /// <returns>the banlist list</returns> 621 public void RemoveLandObject(LLUUID globalID)
539 public List<EstateBan> LoadRegionBanList(LLUUID regionUUID)
540 { 622 {
541 List<EstateBan> regionbanlist = new List<EstateBan>(); 623 using (AutoClosingSqlCommand cmd = _Database.Query("delete from land where UUID=@UUID"))
542 return regionbanlist; 624 {
625 cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID));
626 cmd.ExecuteNonQuery();
627 }
628
629 using (AutoClosingSqlCommand cmd = _Database.Query("delete from landaccesslist where LandUUID=@UUID"))
630 {
631 cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID));
632 cmd.ExecuteNonQuery();
633 }
543 } 634 }
544 635
545 /// <summary> 636 /// <summary>
546 /// STUB, add an item into region banlist 637 /// Loads the settings of a region.
547 /// </summary> 638 /// </summary>
548 /// <param name="item">the item</param> 639 /// <param name="regionUUID">The region UUID.</param>
549 public void AddToRegionBanlist(EstateBan item) 640 /// <returns></returns>
641 public RegionSettings LoadRegionSettings(LLUUID regionUUID)
550 { 642 {
643 string sql = "select * from regionsettings where regionUUID = @regionUUID";
644 RegionSettings regionSettings;
645 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
646 {
647 cmd.Parameters.AddWithValue("@regionUUID", regionUUID.ToString());
648 using(SqlDataReader reader = cmd.ExecuteReader())
649 {
650 if (reader.Read())
651 {
652 regionSettings = buildRegionSettings(reader);
653 regionSettings.OnSave += StoreRegionSettings;
551 654
552 } 655 return regionSettings;
656 }
657 }
658 }
553 659
554 /// <summary> 660 //If comes here then there is now region setting for that region
555 /// STUB, remove an item from region banlist 661 regionSettings = new RegionSettings();
556 /// </summary> 662 regionSettings.RegionUUID = regionUUID;
557 /// <param name="item"></param> 663 regionSettings.OnSave += StoreRegionSettings;
558 public void RemoveFromRegionBanlist(EstateBan item)
559 {
560 664
665 //Store new values
666 StoreNewRegionSettings(regionSettings);
667
668 return regionSettings;
561 } 669 }
562 670
563 /// <summary> 671 /// <summary>
564 /// Commit 672 /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region.
565 /// </summary> 673 /// </summary>
566 public void Commit() 674 /// <param name="regionSettings">region settings.</param>
675 public void StoreRegionSettings(RegionSettings regionSettings)
567 { 676 {
568 if (m_connection.State != ConnectionState.Open) 677 //Little check if regionUUID already exist in DB
678 string regionUUID = null;
679 using (AutoClosingSqlCommand cmd = _Database.Query("SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID"))
569 { 680 {
570 m_connection.Open(); 681 regionUUID = cmd.ExecuteScalar().ToString();
571 } 682 }
572 683
573 lock (m_dataSet) 684 if (string.IsNullOrEmpty(regionUUID))
574 { 685 {
575 // DisplayDataSet(m_dataSet, "Region DataSet"); 686 StoreNewRegionSettings(regionSettings);
576 687 }
577 m_primDataAdapter.Update(m_primTable); 688 else
578 m_shapeDataAdapter.Update(m_shapeTable); 689 {
579 690 //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB
580 m_itemsDataAdapter.Update(m_itemsTable); 691 string sql =
581 692 @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage
582 m_terrainDataAdapter.Update(m_terrainTable); 693,[restrict_pushing] = @restrict_pushing ,[allow_land_resell] = @allow_land_resell ,[allow_land_join_divide] = @allow_land_join_divide
583 m_landDataAdapter.Update(m_landTable); 694,[block_show_in_search] = @block_show_in_search ,[agent_limit] = @agent_limit ,[object_bonus] = @object_bonus ,[maturity] = @maturity
584 m_landAccessListDataAdapter.Update(m_landAccessListTable); 695,[disable_scripts] = @disable_scripts ,[disable_collisions] = @disable_collisions ,[disable_physics] = @disable_physics
696,[terrain_texture_1] = @terrain_texture_1 ,[terrain_texture_2] = @terrain_texture_2 ,[terrain_texture_3] = @terrain_texture_3
697,[terrain_texture_4] = @terrain_texture_4 ,[elevation_1_nw] = @elevation_1_nw ,[elevation_2_nw] = @elevation_2_nw
698,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se
699,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit
700,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position
701,[covenant] = @covenant ,[Sandbox] = @Sandbox WHERE [regionUUID] = @regionUUID";
702
703 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
704 {
705 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
585 706
586 m_dataSet.AcceptChanges(); 707 cmd.ExecuteNonQuery();
708 }
587 } 709 }
588 } 710 }
589 711
590 /// <summary>
591 /// See <see cref="Commit"/>
592 /// </summary>
593 public void Shutdown() 712 public void Shutdown()
594 { 713 {
595 Commit(); 714 //Not used??
596 } 715 }
597 716
598 /*********************************************************************** 717 #region Private Methods
599 *
600 * Database Definition Functions
601 *
602 * This should be db agnostic as we define them in ADO.NET terms
603 *
604 **********************************************************************/
605
606 /// <summary>
607 ///
608 /// </summary>
609 /// <param name="dt"></param>
610 /// <param name="name"></param>
611 /// <param name="type"></param>
612 /// <returns></returns>
613 private static DataColumn createCol(DataTable dt, string name, Type type)
614 {
615 DataColumn col = new DataColumn(name, type);
616 dt.Columns.Add(col);
617 return col;
618 }
619 718
620 /// <summary> 719 /// <summary>
621 /// Create the "terrain" table 720 /// Load in a prim's persisted inventory.
622 /// </summary> 721 /// </summary>
623 /// <returns>the datatable</returns> 722 /// <param name="prim">The prim</param>
624 private static DataTable createTerrainTable() 723 private void LoadItems(SceneObjectPart prim)
625 { 724 {
626 DataTable terrain = new DataTable("terrain"); 725 DataTable dbItems = _PrimsDataSet.Tables["primitems"];
627 726
628 createCol(terrain, "RegionUUID", typeof(String)); 727 String sql = String.Format("primID = '{0}'", prim.UUID.ToString());
629 createCol(terrain, "Revision", typeof(Int32)); 728 DataRow[] dbItemRows = dbItems.Select(sql);
630 createCol(terrain, "Heightfield", typeof(Byte[]));
631
632 return terrain;
633 }
634 729
635 /// <summary> 730 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
636 /// Create the "prims" table
637 /// </summary>
638 /// <returns>the datatable</returns>
639 private static DataTable createPrimTable()
640 {
641 DataTable prims = new DataTable("prims");
642
643 createCol(prims, "UUID", typeof(String));
644 createCol(prims, "RegionUUID", typeof(String));
645 createCol(prims, "ParentID", typeof(Int32));
646 createCol(prims, "CreationDate", typeof(Int32));
647 createCol(prims, "Name", typeof(String));
648 createCol(prims, "SceneGroupID", typeof(String));
649 // various text fields
650 createCol(prims, "Text", typeof(String));
651 createCol(prims, "Description", typeof(String));
652 createCol(prims, "SitName", typeof(String));
653 createCol(prims, "TouchName", typeof(String));
654 // permissions
655 createCol(prims, "ObjectFlags", typeof(Int32));
656 createCol(prims, "CreatorID", typeof(String));
657 createCol(prims, "OwnerID", typeof(String));
658 createCol(prims, "GroupID", typeof(String));
659 createCol(prims, "LastOwnerID", typeof(String));
660 createCol(prims, "OwnerMask", typeof(Int32));
661 createCol(prims, "NextOwnerMask", typeof(Int32));
662 createCol(prims, "GroupMask", typeof(Int32));
663 createCol(prims, "EveryoneMask", typeof(Int32));
664 createCol(prims, "BaseMask", typeof(Int32));
665 // vectors
666 createCol(prims, "PositionX", typeof(Double));
667 createCol(prims, "PositionY", typeof(Double));
668 createCol(prims, "PositionZ", typeof(Double));
669 createCol(prims, "GroupPositionX", typeof(Double));
670 createCol(prims, "GroupPositionY", typeof(Double));
671 createCol(prims, "GroupPositionZ", typeof(Double));
672 createCol(prims, "VelocityX", typeof(Double));
673 createCol(prims, "VelocityY", typeof(Double));
674 createCol(prims, "VelocityZ", typeof(Double));
675 createCol(prims, "AngularVelocityX", typeof(Double));
676 createCol(prims, "AngularVelocityY", typeof(Double));
677 createCol(prims, "AngularVelocityZ", typeof(Double));
678 createCol(prims, "AccelerationX", typeof(Double));
679 createCol(prims, "AccelerationY", typeof(Double));
680 createCol(prims, "AccelerationZ", typeof(Double));
681 // quaternions
682 createCol(prims, "RotationX", typeof(Double));
683 createCol(prims, "RotationY", typeof(Double));
684 createCol(prims, "RotationZ", typeof(Double));
685 createCol(prims, "RotationW", typeof(Double));
686 731
687 // sit target 732 foreach (DataRow row in dbItemRows)
688 createCol(prims, "SitTargetOffsetX", typeof(Double)); 733 {
689 createCol(prims, "SitTargetOffsetY", typeof(Double)); 734 TaskInventoryItem item = buildItem(row);
690 createCol(prims, "SitTargetOffsetZ", typeof(Double)); 735 inventory.Add(item);
691 736
692 createCol(prims, "SitTargetOrientW", typeof(Double)); 737 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID);
693 createCol(prims, "SitTargetOrientX", typeof(Double)); 738 }
694 createCol(prims, "SitTargetOrientY", typeof(Double));
695 createCol(prims, "SitTargetOrientZ", typeof(Double));
696 739
697 // Add in contraints 740 prim.RestoreInventoryItems(inventory);
698 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
699 741
700 return prims; 742 // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in
743 // every item). This data should really be stored in the prim table itself.
744 if (dbItemRows.Length > 0)
745 {
746 prim.FolderID = inventory[0].ParentID;
747 }
701 } 748 }
702 749
703 /// <summary> 750 /// <summary>
704 /// Create the "land" table 751 /// Serializes the terrain data for storage in DB.
705 /// </summary> 752 /// </summary>
706 /// <returns>the datatable</returns> 753 /// <param name="val">terrain data</param>
707 private static DataTable createLandTable() 754 /// <returns></returns>
755 private static Array serializeTerrain(double[,] val)
708 { 756 {
709 DataTable land = new DataTable("land"); 757 MemoryStream str = new MemoryStream(65536 * sizeof(double));
710 createCol(land, "UUID", typeof(String)); 758 BinaryWriter bw = new BinaryWriter(str);
711 createCol(land, "RegionUUID", typeof(String));
712 createCol(land, "LocalLandID", typeof(Int32));
713 759
714 // Bitmap is a byte[512] 760 // TODO: COMPATIBILITY - Add byte-order conversions
715 createCol(land, "Bitmap", typeof(Byte[])); 761 for (int x = 0; x < 256; x++)
716 762 for (int y = 0; y < 256; y++)
717 createCol(land, "Name", typeof(String)); 763 {
718 createCol(land, "Description", typeof(String)); 764 double height = val[x, y];
719 createCol(land, "OwnerUUID", typeof(String)); 765 if (height == 0.0)
720 createCol(land, "IsGroupOwned", typeof(Int32)); 766 height = double.Epsilon;
721 createCol(land, "Area", typeof(Int32)); 767
722 createCol(land, "AuctionID", typeof(Int32)); //Unemplemented 768 bw.Write(height);
723 createCol(land, "Category", typeof(Int32)); //Enum libsecondlife.Parcel.ParcelCategory 769 }
724 createCol(land, "ClaimDate", typeof(Int32)); 770
725 createCol(land, "ClaimPrice", typeof(Int32)); 771 return str.ToArray();
726 createCol(land, "GroupUUID", typeof(String));
727 createCol(land, "SalePrice", typeof(Int32));
728 createCol(land, "LandStatus", typeof(Int32)); //Enum. libsecondlife.Parcel.ParcelStatus
729 createCol(land, "LandFlags", typeof(Int32));
730 createCol(land, "LandingType", typeof(Int32));
731 createCol(land, "MediaAutoScale", typeof(Int32));
732 createCol(land, "MediaTextureUUID", typeof(String));
733 createCol(land, "MediaURL", typeof(String));
734 createCol(land, "MusicURL", typeof(String));
735 createCol(land, "PassHours", typeof(Double));
736 createCol(land, "PassPrice", typeof(Int32));
737 createCol(land, "SnapshotUUID", typeof(String));
738 createCol(land, "UserLocationX", typeof(Double));
739 createCol(land, "UserLocationY", typeof(Double));
740 createCol(land, "UserLocationZ", typeof(Double));
741 createCol(land, "UserLookAtX", typeof(Double));
742 createCol(land, "UserLookAtY", typeof(Double));
743 createCol(land, "UserLookAtZ", typeof(Double));
744
745 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] };
746
747 return land;
748 } 772 }
749 773
750 /// <summary> 774 /// <summary>
751 /// Create "landacceslist" table 775 /// Stores new regionsettings.
752 /// </summary> 776 /// </summary>
753 /// <returns>the datatable</returns> 777 /// <param name="regionSettings">The region settings.</param>
754 private static DataTable createLandAccessListTable() 778 private void StoreNewRegionSettings(RegionSettings regionSettings)
755 { 779 {
756 DataTable landaccess = new DataTable("landaccesslist"); 780 string sql = @"INSERT INTO [regionsettings]
757 createCol(landaccess, "LandUUID", typeof(String)); 781([regionUUID],[block_terraform],[block_fly],[allow_damage],[restrict_pushing],[allow_land_resell],[allow_land_join_divide],[block_show_in_search],[agent_limit],[object_bonus],[maturity],[disable_scripts],[disable_collisions],[disable_physics],[terrain_texture_1],[terrain_texture_2],[terrain_texture_3],[terrain_texture_4],[elevation_1_nw],[elevation_2_nw],[elevation_1_ne],[elevation_2_ne],[elevation_1_se],[elevation_2_se],[elevation_1_sw],[elevation_2_sw],[water_height],[terrain_raise_limit],[terrain_lower_limit],[use_estate_sun],[fixed_sun],[sun_position],[covenant],[Sandbox]) VALUES
758 createCol(landaccess, "AccessUUID", typeof(String)); 782(@regionUUID,@block_terraform,@block_fly,@allow_damage,@restrict_pushing,@allow_land_resell,@allow_land_join_divide,@block_show_in_search,@agent_limit,@object_bonus,@maturity,@disable_scripts,@disable_collisions,@disable_physics,@terrain_texture_1,@terrain_texture_2,@terrain_texture_3,@terrain_texture_4,@elevation_1_nw,@elevation_2_nw,@elevation_1_ne,@elevation_2_ne,@elevation_1_se,@elevation_2_se,@elevation_1_sw,@elevation_2_sw,@water_height,@terrain_raise_limit,@terrain_lower_limit,@use_estate_sun,@fixed_sun,@sun_position,@covenant,@Sandbox)";
759 createCol(landaccess, "Flags", typeof(Int32)); 783
784 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
785 {
786 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
760 787
761 return landaccess; 788 cmd.ExecuteNonQuery();
789 }
762 } 790 }
763 791
792 #region Private DataRecord conversion methods
793
764 /// <summary> 794 /// <summary>
765 /// Create "primsshapes" table 795 /// Builds the region settings from a datarecod.
766 /// </summary> 796 /// </summary>
767 /// <returns>the datatable</returns> 797 /// <param name="row">datarecord with regionsettings.</param>
768 private static DataTable createShapeTable() 798 /// <returns></returns>
799 private static RegionSettings buildRegionSettings(IDataRecord row)
769 { 800 {
770 DataTable shapes = new DataTable("primshapes"); 801 //TODO change this is some more generic code so we doesnt have to change it every time a new field is added?
771 createCol(shapes, "UUID", typeof(String)); 802 RegionSettings newSettings = new RegionSettings();
772 // shape is an enum 803
773 createCol(shapes, "Shape", typeof(Int32)); 804 newSettings.RegionUUID = new LLUUID((string)row["regionUUID"]);
774 // vectors 805 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
775 createCol(shapes, "ScaleX", typeof(Double)); 806 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
776 createCol(shapes, "ScaleY", typeof(Double)); 807 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
777 createCol(shapes, "ScaleZ", typeof(Double)); 808 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
778 // paths 809 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
779 createCol(shapes, "PCode", typeof(Int32)); 810 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
780 createCol(shapes, "PathBegin", typeof(Int32)); 811 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
781 createCol(shapes, "PathEnd", typeof(Int32)); 812 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
782 createCol(shapes, "PathScaleX", typeof(Int32)); 813 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
783 createCol(shapes, "PathScaleY", typeof(Int32)); 814 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
784 createCol(shapes, "PathShearX", typeof(Int32)); 815 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
785 createCol(shapes, "PathShearY", typeof(Int32)); 816 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
786 createCol(shapes, "PathSkew", typeof(Int32)); 817 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
787 createCol(shapes, "PathCurve", typeof(Int32)); 818 newSettings.TerrainTexture1 = new LLUUID((String)row["terrain_texture_1"]);
788 createCol(shapes, "PathRadiusOffset", typeof(Int32)); 819 newSettings.TerrainTexture2 = new LLUUID((String)row["terrain_texture_2"]);
789 createCol(shapes, "PathRevolutions", typeof(Int32)); 820 newSettings.TerrainTexture3 = new LLUUID((String)row["terrain_texture_3"]);
790 createCol(shapes, "PathTaperX", typeof(Int32)); 821 newSettings.TerrainTexture4 = new LLUUID((String)row["terrain_texture_4"]);
791 createCol(shapes, "PathTaperY", typeof(Int32)); 822 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
792 createCol(shapes, "PathTwist", typeof(Int32)); 823 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
793 createCol(shapes, "PathTwistBegin", typeof(Int32)); 824 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
794 // profile 825 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
795 createCol(shapes, "ProfileBegin", typeof(Int32)); 826 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
796 createCol(shapes, "ProfileEnd", typeof(Int32)); 827 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
797 createCol(shapes, "ProfileCurve", typeof(Int32)); 828 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
798 createCol(shapes, "ProfileHollow", typeof(Int32)); 829 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
799 createCol(shapes, "State", typeof(Int32)); 830 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
800 // text TODO: this isn't right, but I'm not sure the right 831 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
801 // way to specify this as a blob atm 832 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
802 createCol(shapes, "Texture", typeof(Byte[])); 833 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
803 createCol(shapes, "ExtraParams", typeof(Byte[])); 834 newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
804 835 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
805 shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] }; 836 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
806 837 newSettings.Covenant = new LLUUID((String)row["covenant"]);
807 return shapes; 838
839 return newSettings;
808 } 840 }
809 841
810 /// <summary> 842 /// <summary>
811 /// Create "primitems" table 843 /// Builds the land data from a datarecord.
812 /// </summary> 844 /// </summary>
813 /// <returns>the datatable</returns> 845 /// <param name="row">datarecord with land data</param>
814 private static DataTable createItemsTable() 846 /// <returns></returns>
847 private static LandData buildLandData(IDataRecord row)
815 { 848 {
816 DataTable items = new DataTable("primitems"); 849 LandData newData = new LandData();
817 850
818 createCol(items, "itemID", typeof(String)); 851 newData.GlobalID = new LLUUID((String)row["UUID"]);
819 createCol(items, "primID", typeof(String)); 852 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
820 createCol(items, "assetID", typeof(String)); 853
821 createCol(items, "parentFolderID", typeof(String)); 854 // Bitmap is a byte[512]
855 newData.Bitmap = (Byte[])row["Bitmap"];
856
857 newData.Name = (String)row["Name"];
858 newData.Description = (String)row["Description"];
859 newData.OwnerID = (String)row["OwnerUUID"];
860 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
861 newData.Area = Convert.ToInt32(row["Area"]);
862 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
863 newData.Category = (Parcel.ParcelCategory)Convert.ToInt32(row["Category"]);
864 //Enum libsecondlife.Parcel.ParcelCategory
865 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
866 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
867 newData.GroupID = new LLUUID((String)row["GroupUUID"]);
868 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
869 newData.Status = (Parcel.ParcelStatus)Convert.ToInt32(row["LandStatus"]);
870 //Enum. libsecondlife.Parcel.ParcelStatus
871 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
872 newData.LandingType = Convert.ToByte(row["LandingType"]);
873 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
874 newData.MediaID = new LLUUID((String)row["MediaTextureUUID"]);
875 newData.MediaURL = (String)row["MediaURL"];
876 newData.MusicURL = (String)row["MusicURL"];
877 newData.PassHours = Convert.ToSingle(row["PassHours"]);
878 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
822 879
823 createCol(items, "invType", typeof(Int32)); 880 LLUUID authedbuyer;
824 createCol(items, "assetType", typeof(Int32)); 881 LLUUID snapshotID;
825 882
826 createCol(items, "name", typeof(String)); 883 if (LLUUID.TryParse((string)row["AuthBuyerID"], out authedbuyer))
827 createCol(items, "description", typeof(String)); 884 newData.AuthBuyerID = authedbuyer;
828 885
829 createCol(items, "creationDate", typeof(Int64)); 886 if (LLUUID.TryParse((string)row["SnapshotUUID"], out snapshotID))
830 createCol(items, "creatorID", typeof(String)); 887 newData.SnapshotID = snapshotID;
831 createCol(items, "ownerID", typeof(String));
832 createCol(items, "lastOwnerID", typeof(String));
833 createCol(items, "groupID", typeof(String));
834 888
835 createCol(items, "nextPermissions", typeof(Int32)); 889 try
836 createCol(items, "currentPermissions", typeof(Int32)); 890 {
837 createCol(items, "basePermissions", typeof(Int32)); 891 newData.UserLocation =
838 createCol(items, "everyonePermissions", typeof(Int32)); 892 new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
839 createCol(items, "groupPermissions", typeof(Int32)); 893 Convert.ToSingle(row["UserLocationZ"]));
840// createCol(items, "flags", typeof(Int32)); 894 newData.UserLookAt =
895 new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
896 Convert.ToSingle(row["UserLookAtZ"]));
897 }
898 catch (InvalidCastException)
899 {
900 newData.UserLocation = LLVector3.Zero;
901 newData.UserLookAt = LLVector3.Zero;
902 _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name);
903 }
841 904
842 items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; 905 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
843 906
844 return items; 907 return newData;
845 } 908 }
846 909
847 /*********************************************************************** 910 /// <summary>
848 * 911 /// Builds the landaccess data from a data record.
849 * Convert between ADO.NET <=> OpenSim Objects 912 /// </summary>
850 * 913 /// <param name="row">datarecord with landaccess data</param>
851 * These should be database independant 914 /// <returns></returns>
852 * 915 private static ParcelManager.ParcelAccessEntry buildLandAccessData(IDataRecord row)
853 **********************************************************************/ 916 {
917 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
918 entry.AgentID = new LLUUID((string)row["AccessUUID"]);
919 entry.Flags = (ParcelManager.AccessList)Convert.ToInt32(row["Flags"]);
920 entry.Time = new DateTime();
921 return entry;
922 }
854 923
855 /// <summary> 924 /// <summary>
856 /// 925 /// Builds the prim from a datarecord.
857 /// </summary> 926 /// </summary>
858 /// <param name="row"></param> 927 /// <param name="row">datarecord</param>
859 /// <returns></returns> 928 /// <returns></returns>
860 private SceneObjectPart buildPrim(DataRow row) 929 private static SceneObjectPart buildPrim(DataRow row)
861 { 930 {
862 SceneObjectPart prim = new SceneObjectPart(); 931 SceneObjectPart prim = new SceneObjectPart();
932
863 prim.UUID = new LLUUID((String)row["UUID"]); 933 prim.UUID = new LLUUID((String)row["UUID"]);
864 // explicit conversion of integers is required, which sort 934 // explicit conversion of integers is required, which sort
865 // of sucks. No idea if there is a shortcut here or not. 935 // of sucks. No idea if there is a shortcut here or not.
@@ -915,330 +985,73 @@ namespace OpenSim.Data.MSSQL
915 Convert.ToSingle(row["RotationZ"]), 985 Convert.ToSingle(row["RotationZ"]),
916 Convert.ToSingle(row["RotationW"]) 986 Convert.ToSingle(row["RotationW"])
917 ); 987 );
918 try 988 prim.SitTargetPositionLL = new LLVector3(
919 { 989 Convert.ToSingle(row["SitTargetOffsetX"]),
920 prim.SitTargetPositionLL = new LLVector3( 990 Convert.ToSingle(row["SitTargetOffsetY"]),
921 Convert.ToSingle(row["SitTargetOffsetX"]), 991 Convert.ToSingle(row["SitTargetOffsetZ"])
922 Convert.ToSingle(row["SitTargetOffsetY"]), 992 );
923 Convert.ToSingle(row["SitTargetOffsetZ"])); 993 prim.SitTargetOrientationLL = new LLQuaternion(
924 prim.SitTargetOrientationLL = new LLQuaternion( 994 Convert.ToSingle(row["SitTargetOrientX"]),
925 Convert.ToSingle( 995 Convert.ToSingle(row["SitTargetOrientY"]),
926 row["SitTargetOrientX"]), 996 Convert.ToSingle(row["SitTargetOrientZ"]),
927 Convert.ToSingle( 997 Convert.ToSingle(row["SitTargetOrientW"])
928 row["SitTargetOrientY"]), 998 );
929 Convert.ToSingle(
930 row["SitTargetOrientZ"]),
931 Convert.ToSingle(
932 row["SitTargetOrientW"]));
933 }
934 catch (InvalidCastException)
935 {
936 // Database table was created before we got here and now has null values :P
937
938 using (
939 SqlCommand cmd =
940 new SqlCommand(
941 "ALTER TABLE [prims] ADD COLUMN [SitTargetOffsetX] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetY] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetZ] float NOT NULL default 0, ADD COLUMN [SitTargetOrientW] float NOT NULL default 0, ADD COLUMN [SitTargetOrientX] float NOT NULL default 0, ADD COLUMN [SitTargetOrientY] float NOT NULL default 0, ADD COLUMN [SitTargetOrientZ] float NOT NULL default 0;",
942 m_connection))
943 {
944 cmd.ExecuteNonQuery();
945 }
946 }
947
948 return prim;
949 }
950
951 /// <summary>
952 /// Build a prim inventory item from the persisted data.
953 /// </summary>
954 /// <param name="row"></param>
955 /// <returns></returns>
956 private static TaskInventoryItem buildItem(DataRow row)
957 {
958 TaskInventoryItem taskItem = new TaskInventoryItem();
959
960 taskItem.ItemID = new LLUUID((String)row["itemID"]);
961 taskItem.ParentPartID = new LLUUID((String)row["primID"]);
962 taskItem.AssetID = new LLUUID((String)row["assetID"]);
963 taskItem.ParentID = new LLUUID((String)row["parentFolderID"]);
964
965 taskItem.InvType = Convert.ToInt32(row["invType"]);
966 taskItem.Type = Convert.ToInt32(row["assetType"]);
967
968 taskItem.Name = (String)row["name"];
969 taskItem.Description = (String)row["description"];
970 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
971 taskItem.CreatorID = new LLUUID((String)row["creatorID"]);
972 taskItem.OwnerID = new LLUUID((String)row["ownerID"]);
973 taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]);
974 taskItem.GroupID = new LLUUID((String)row["groupID"]);
975
976 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
977 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
978 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
979 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
980 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
981// taskItem.Flags = Convert.ToUInt32(row["flags"]);
982
983 return taskItem;
984 }
985
986 /// <summary>
987 ///
988 /// </summary>
989 /// <param name="row"></param>
990 /// <returns></returns>
991 private static LandData buildLandData(DataRow row)
992 {
993 LandData newData = new LandData();
994 999
995 newData.GlobalID = new LLUUID((String)row["UUID"]); 1000 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]);
996 newData.LocalID = Convert.ToInt32(row["LocalLandID"]); 1001 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]);
1002 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]);
1003 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]);
1004 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]);
997 1005
998 // Bitmap is a byte[512] 1006 prim.Sound = new LLUUID(row["LoopedSound"].ToString());
999 newData.Bitmap = (Byte[])row["Bitmap"]; 1007 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1008 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1000 1009
1001 newData.Name = (String)row["Name"]; 1010 if (row["TextureAnimation"] != null && row["TextureAnimation"] != DBNull.Value)
1002 newData.Description = (String)row["Description"]; 1011 prim.TextureAnimation = (Byte[])row["TextureAnimation"];
1003 newData.OwnerID = (String)row["OwnerUUID"];
1004 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
1005 newData.Area = Convert.ToInt32(row["Area"]);
1006 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1007 newData.Category = (Parcel.ParcelCategory)Convert.ToInt32(row["Category"]);
1008 //Enum libsecondlife.Parcel.ParcelCategory
1009 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1010 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1011 newData.GroupID = new LLUUID((String)row["GroupUUID"]);
1012 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1013 newData.Status = (Parcel.ParcelStatus)Convert.ToInt32(row["LandStatus"]);
1014 //Enum. libsecondlife.Parcel.ParcelStatus
1015 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1016 newData.LandingType = Convert.ToByte(row["LandingType"]);
1017 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
1018 newData.MediaID = new LLUUID((String)row["MediaTextureUUID"]);
1019 newData.MediaURL = (String)row["MediaURL"];
1020 newData.MusicURL = (String)row["MusicURL"];
1021 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1022 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1023 newData.SnapshotID = (String)row["SnapshotUUID"];
1024
1025 newData.UserLocation =
1026 new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1027 Convert.ToSingle(row["UserLocationZ"]));
1028 newData.UserLookAt =
1029 new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1030 Convert.ToSingle(row["UserLookAtZ"]));
1031 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
1032 1012
1033 return newData; 1013 prim.RotationalVelocity = new LLVector3(
1034 } 1014 Convert.ToSingle(row["OmegaX"]),
1035 1015 Convert.ToSingle(row["OmegaY"]),
1036 /// <summary> 1016 Convert.ToSingle(row["OmegaZ"])
1037 /// 1017 );
1038 /// </summary>
1039 /// <param name="row"></param>
1040 /// <returns></returns>
1041 private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row)
1042 {
1043 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1044 entry.AgentID = new LLUUID((string)row["AccessUUID"]);
1045 entry.Flags = (ParcelManager.AccessList)Convert.ToInt32(row["Flags"]);
1046 entry.Time = new DateTime();
1047 return entry;
1048 }
1049
1050 /// <summary>
1051 /// Serialize terrain HeightField
1052 /// </summary>
1053 /// <param name="val">the terrain heightfield</param>
1054 /// <returns></returns>
1055 private static Array serializeTerrain(double[,] val)
1056 {
1057 MemoryStream str = new MemoryStream(65536 * sizeof(double));
1058 BinaryWriter bw = new BinaryWriter(str);
1059 1018
1060 // TODO: COMPATIBILITY - Add byte-order conversions 1019 // TODO: Rotation
1061 for (int x = 0; x < 256; x++) 1020 // OmegaX, OmegaY, OmegaZ
1062 for (int y = 0; y < 256; y++)
1063 bw.Write(val[x, y]);
1064 1021
1065 return str.ToArray(); 1022 prim.SetCameraEyeOffset(new LLVector3(
1066 } 1023 Convert.ToSingle(row["CameraEyeOffsetX"]),
1024 Convert.ToSingle(row["CameraEyeOffsetY"]),
1025 Convert.ToSingle(row["CameraEyeOffsetZ"])
1026 ));
1067 1027
1068 /// <summary> 1028 prim.SetCameraAtOffset(new LLVector3(
1069 /// 1029 Convert.ToSingle(row["CameraAtOffsetX"]),
1070 /// </summary> 1030 Convert.ToSingle(row["CameraAtOffsetY"]),
1071 /// <param name="row"></param> 1031 Convert.ToSingle(row["CameraAtOffsetZ"])
1072 /// <param name="prim"></param> 1032 ));
1073 /// <param name="sceneGroupID"></param>
1074 /// <param name="regionUUID"></param>
1075 private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1076 {
1077 row["UUID"] = prim.UUID;
1078 row["RegionUUID"] = regionUUID;
1079 row["ParentID"] = prim.ParentID;
1080 row["CreationDate"] = prim.CreationDate;
1081 row["Name"] = prim.Name;
1082 row["SceneGroupID"] = sceneGroupID;
1083 // the UUID of the root part for this SceneObjectGroup
1084 // various text fields
1085 row["Text"] = prim.Text;
1086 row["Description"] = prim.Description;
1087 row["SitName"] = prim.SitName;
1088 row["TouchName"] = prim.TouchName;
1089 // permissions
1090 row["ObjectFlags"] = prim.ObjectFlags;
1091 row["CreatorID"] = prim.CreatorID;
1092 row["OwnerID"] = prim.OwnerID;
1093 row["GroupID"] = prim.GroupID;
1094 row["LastOwnerID"] = prim.LastOwnerID;
1095 row["OwnerMask"] = prim.OwnerMask;
1096 row["NextOwnerMask"] = prim.NextOwnerMask;
1097 row["GroupMask"] = prim.GroupMask;
1098 row["EveryoneMask"] = prim.EveryoneMask;
1099 row["BaseMask"] = prim.BaseMask;
1100 // vectors
1101 row["PositionX"] = prim.OffsetPosition.X;
1102 row["PositionY"] = prim.OffsetPosition.Y;
1103 row["PositionZ"] = prim.OffsetPosition.Z;
1104 row["GroupPositionX"] = prim.GroupPosition.X;
1105 row["GroupPositionY"] = prim.GroupPosition.Y;
1106 row["GroupPositionZ"] = prim.GroupPosition.Z;
1107 row["VelocityX"] = prim.Velocity.X;
1108 row["VelocityY"] = prim.Velocity.Y;
1109 row["VelocityZ"] = prim.Velocity.Z;
1110 row["AngularVelocityX"] = prim.AngularVelocity.X;
1111 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1112 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1113 row["AccelerationX"] = prim.Acceleration.X;
1114 row["AccelerationY"] = prim.Acceleration.Y;
1115 row["AccelerationZ"] = prim.Acceleration.Z;
1116 // quaternions
1117 row["RotationX"] = prim.RotationOffset.X;
1118 row["RotationY"] = prim.RotationOffset.Y;
1119 row["RotationZ"] = prim.RotationOffset.Z;
1120 row["RotationW"] = prim.RotationOffset.W;
1121 1033
1122 try 1034 if (Convert.ToInt16(row["ForceMouselook"]) != 0)
1123 { 1035 prim.SetForceMouselook(true);
1124 // Sit target
1125 LLVector3 sitTargetPos = prim.SitTargetPositionLL;
1126 row["SitTargetOffsetX"] = sitTargetPos.X;
1127 row["SitTargetOffsetY"] = sitTargetPos.Y;
1128 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1129
1130 LLQuaternion sitTargetOrient = prim.SitTargetOrientationLL;
1131 row["SitTargetOrientW"] = sitTargetOrient.W;
1132 row["SitTargetOrientX"] = sitTargetOrient.X;
1133 row["SitTargetOrientY"] = sitTargetOrient.Y;
1134 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1135 }
1136 catch (Exception)
1137 {
1138 // Database table was created before we got here and needs to be created! :P
1139 1036
1140 using ( 1037 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]);
1141 SqlCommand cmd =
1142 new SqlCommand(
1143 "ALTER TABLE [prims] ADD COLUMN [SitTargetOffsetX] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetY] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetZ] float NOT NULL default 0, ADD COLUMN [SitTargetOrientW] float NOT NULL default 0, ADD COLUMN [SitTargetOrientX] float NOT NULL default 0, ADD COLUMN [SitTargetOrientY] float NOT NULL default 0, ADD COLUMN [SitTargetOrientZ] float NOT NULL default 0;",
1144 m_connection))
1145 {
1146 cmd.ExecuteNonQuery();
1147 }
1148 }
1149 }
1150 1038
1151 /// <summary> 1039 if (Convert.ToInt16(row["AllowedDrop"]) != 0)
1152 /// 1040 prim.AllowedDrop = true;
1153 /// </summary>
1154 /// <param name="row"></param>
1155 /// <param name="taskItem"></param>
1156 private static void fillItemRow(DataRow row, TaskInventoryItem taskItem)
1157 {
1158 row["itemID"] = taskItem.ItemID;
1159 row["primID"] = taskItem.ParentPartID;
1160 row["assetID"] = taskItem.AssetID;
1161 row["parentFolderID"] = taskItem.ParentID;
1162
1163 row["invType"] = taskItem.InvType;
1164 row["assetType"] = taskItem.Type;
1165
1166 row["name"] = taskItem.Name;
1167 row["description"] = taskItem.Description;
1168 row["creationDate"] = taskItem.CreationDate;
1169 row["creatorID"] = taskItem.CreatorID;
1170 row["ownerID"] = taskItem.OwnerID;
1171 row["lastOwnerID"] = taskItem.LastOwnerID;
1172 row["groupID"] = taskItem.GroupID;
1173 row["nextPermissions"] = taskItem.NextPermissions;
1174 row["currentPermissions"] = taskItem.CurrentPermissions;
1175 row["basePermissions"] = taskItem.BasePermissions;
1176 row["everyonePermissions"] = taskItem.EveryonePermissions;
1177 row["groupPermissions"] = taskItem.GroupPermissions;
1178// row["flags"] = taskItem.Flags;
1179 }
1180 1041
1181 /// <summary> 1042 if (Convert.ToInt16(row["DieAtEdge"]) != 0)
1182 /// 1043 prim.DIE_AT_EDGE = true;
1183 /// </summary>
1184 /// <param name="row"></param>
1185 /// <param name="land"></param>
1186 /// <param name="regionUUID"></param>
1187 private static void fillLandRow(DataRow row, LandData land, LLUUID regionUUID)
1188 {
1189 row["UUID"] = land.GlobalID.UUID;
1190 row["RegionUUID"] = regionUUID.UUID;
1191 row["LocalLandID"] = land.LocalID;
1192 1044
1193 // Bitmap is a byte[512] 1045 prim.SalePrice = Convert.ToInt32(row["SalePrice"]);
1194 row["Bitmap"] = land.Bitmap; 1046 prim.ObjectSaleType = Convert.ToByte(row["SaleType"]);
1195
1196 row["Name"] = land.Name;
1197 row["Description"] = land.Description;
1198 row["OwnerUUID"] = land.OwnerID.UUID;
1199 row["IsGroupOwned"] = land.IsGroupOwned;
1200 row["Area"] = land.Area;
1201 row["AuctionID"] = land.AuctionID; //Unemplemented
1202 row["Category"] = land.Category; //Enum libsecondlife.Parcel.ParcelCategory
1203 row["ClaimDate"] = land.ClaimDate;
1204 row["ClaimPrice"] = land.ClaimPrice;
1205 row["GroupUUID"] = land.GroupID.UUID;
1206 row["SalePrice"] = land.SalePrice;
1207 row["LandStatus"] = land.Status; //Enum. libsecondlife.Parcel.ParcelStatus
1208 row["LandFlags"] = land.Flags;
1209 row["LandingType"] = land.LandingType;
1210 row["MediaAutoScale"] = land.MediaAutoScale;
1211 row["MediaTextureUUID"] = land.MediaID.UUID;
1212 row["MediaURL"] = land.MediaURL;
1213 row["MusicURL"] = land.MusicURL;
1214 row["PassHours"] = land.PassHours;
1215 row["PassPrice"] = land.PassPrice;
1216 row["SnapshotUUID"] = land.SnapshotID.UUID;
1217 row["UserLocationX"] = land.UserLocation.X;
1218 row["UserLocationY"] = land.UserLocation.Y;
1219 row["UserLocationZ"] = land.UserLocation.Z;
1220 row["UserLookAtX"] = land.UserLookAt.X;
1221 row["UserLookAtY"] = land.UserLookAt.Y;
1222 row["UserLookAtZ"] = land.UserLookAt.Z;
1223 }
1224 1047
1225 /// <summary> 1048 return prim;
1226 ///
1227 /// </summary>
1228 /// <param name="row"></param>
1229 /// <param name="entry"></param>
1230 /// <param name="parcelID"></param>
1231 private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, LLUUID parcelID)
1232 {
1233 row["LandUUID"] = parcelID.UUID;
1234 row["AccessUUID"] = entry.AgentID.UUID;
1235 row["Flags"] = entry.Flags;
1236 } 1049 }
1237 1050
1238 /// <summary> 1051 /// <summary>
1239 /// 1052 /// Builds the prim shape from a datarecord.
1240 /// </summary> 1053 /// </summary>
1241 /// <param name="row"></param> 1054 /// <param name="row">The row.</param>
1242 /// <returns></returns> 1055 /// <returns></returns>
1243 private static PrimitiveBaseShape buildShape(DataRow row) 1056 private static PrimitiveBaseShape buildShape(DataRow row)
1244 { 1057 {
@@ -1269,572 +1082,445 @@ namespace OpenSim.Data.MSSQL
1269 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); 1082 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
1270 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); 1083 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
1271 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); 1084 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
1272 s.State = Convert.ToByte(row["State"]);
1273 1085
1274 byte[] textureEntry = (byte[])row["Texture"]; 1086 byte[] textureEntry = (byte[])row["Texture"];
1275 s.TextureEntry = textureEntry; 1087 s.TextureEntry = textureEntry;
1276 1088
1277 s.ExtraParams = (byte[])row["ExtraParams"]; 1089 s.ExtraParams = (byte[])row["ExtraParams"];
1278 1090
1279 return s; 1091 try
1280 }
1281
1282 /// <summary>
1283 ///
1284 /// </summary>
1285 /// <param name="row"></param>
1286 /// <param name="prim"></param>
1287 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1288 {
1289 PrimitiveBaseShape s = prim.Shape;
1290 row["UUID"] = prim.UUID;
1291 // shape is an enum
1292 row["Shape"] = 0;
1293 // vectors
1294 row["ScaleX"] = s.Scale.X;
1295 row["ScaleY"] = s.Scale.Y;
1296 row["ScaleZ"] = s.Scale.Z;
1297 // paths
1298 row["PCode"] = s.PCode;
1299 row["PathBegin"] = s.PathBegin;
1300 row["PathEnd"] = s.PathEnd;
1301 row["PathScaleX"] = s.PathScaleX;
1302 row["PathScaleY"] = s.PathScaleY;
1303 row["PathShearX"] = s.PathShearX;
1304 row["PathShearY"] = s.PathShearY;
1305 row["PathSkew"] = s.PathSkew;
1306 row["PathCurve"] = s.PathCurve;
1307 row["PathRadiusOffset"] = s.PathRadiusOffset;
1308 row["PathRevolutions"] = s.PathRevolutions;
1309 row["PathTaperX"] = s.PathTaperX;
1310 row["PathTaperY"] = s.PathTaperY;
1311 row["PathTwist"] = s.PathTwist;
1312 row["PathTwistBegin"] = s.PathTwistBegin;
1313 // profile
1314 row["ProfileBegin"] = s.ProfileBegin;
1315 row["ProfileEnd"] = s.ProfileEnd;
1316 row["ProfileCurve"] = s.ProfileCurve;
1317 row["ProfileHollow"] = s.ProfileHollow;
1318 row["State"] = s.State;
1319 row["Texture"] = s.TextureEntry;
1320 row["ExtraParams"] = s.ExtraParams;
1321 }
1322
1323 /// <summary>
1324 ///
1325 /// </summary>
1326 /// <param name="prim"></param>
1327 /// <param name="sceneGroupID"></param>
1328 /// <param name="regionUUID"></param>
1329 private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1330 {
1331 DataTable prims = m_dataSet.Tables["prims"];
1332 DataTable shapes = m_dataSet.Tables["primshapes"];
1333
1334 DataRow primRow = prims.Rows.Find(prim.UUID);
1335 if (primRow == null)
1336 { 1092 {
1337 primRow = prims.NewRow(); 1093 s.State = Convert.ToByte(row["State"]);
1338 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1339 prims.Rows.Add(primRow);
1340 } 1094 }
1341 else 1095 catch (InvalidCastException)
1342 { 1096 {
1343 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1344 } 1097 }
1345 1098
1346 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 1099 return s;
1347 if (shapeRow == null)
1348 {
1349 shapeRow = shapes.NewRow();
1350 fillShapeRow(shapeRow, prim);
1351 shapes.Rows.Add(shapeRow);
1352 }
1353 else
1354 {
1355 fillShapeRow(shapeRow, prim);
1356 }
1357 } 1100 }
1358 1101
1359 /// <summary> 1102 /// <summary>
1360 /// See <see cref="IRegionDatastore"/> 1103 /// Build a prim inventory item from the persisted data.
1361 /// </summary> 1104 /// </summary>
1362 /// <param name="primID"></param> 1105 /// <param name="row"></param>
1363 /// <param name="items"></param> 1106 /// <returns></returns>
1364 public void StorePrimInventory(LLUUID primID, ICollection<TaskInventoryItem> items) 1107 private static TaskInventoryItem buildItem(DataRow row)
1365 { 1108 {
1366 m_log.InfoFormat("[REGION DB]: Persisting Prim Inventory with prim ID {0}", primID); 1109 TaskInventoryItem taskItem = new TaskInventoryItem();
1367
1368 // For now, we're just going to crudely remove all the previous inventory items
1369 // no matter whether they have changed or not, and replace them with the current set.
1370 lock (m_dataSet)
1371 {
1372 RemoveItems(primID);
1373 1110
1374 // repalce with current inventory details 1111 taskItem.ItemID = new LLUUID((String)row["itemID"]);
1375 foreach (TaskInventoryItem newItem in items) 1112 taskItem.ParentPartID = new LLUUID((String)row["primID"]);
1376 { 1113 taskItem.AssetID = new LLUUID((String)row["assetID"]);
1377 // m_log.InfoFormat( 1114 taskItem.ParentID = new LLUUID((String)row["parentFolderID"]);
1378 // "[REGION DB]: " + 1115
1379 // "Adding item {0}, {1} to prim ID {2}", 1116 taskItem.InvType = Convert.ToInt32(row["invType"]);
1380 // newItem.Name, newItem.ItemID, newItem.ParentPartID); 1117 taskItem.Type = Convert.ToInt32(row["assetType"]);
1381 1118
1382 DataRow newItemRow = m_itemsTable.NewRow(); 1119 taskItem.Name = (String)row["name"];
1383 fillItemRow(newItemRow, newItem); 1120 taskItem.Description = (String)row["description"];
1384 m_itemsTable.Rows.Add(newItemRow); 1121 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
1385 } 1122 taskItem.CreatorID = new LLUUID((String)row["creatorID"]);
1386 } 1123 taskItem.OwnerID = new LLUUID((String)row["ownerID"]);
1124 taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]);
1125 taskItem.GroupID = new LLUUID((String)row["groupID"]);
1126
1127 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
1128 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
1129 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
1130 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
1131 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
1132 taskItem.Flags = Convert.ToUInt32(row["flags"]);
1387 1133
1388 Commit(); 1134 return taskItem;
1389 } 1135 }
1390 1136
1391 /*********************************************************************** 1137 #endregion
1392 * 1138
1393 * SQL Statement Creation Functions 1139 #region Create parameters methods
1394 *
1395 * These functions create SQL statements for update, insert, and create.
1396 * They can probably be factored later to have a db independant
1397 * portion and a db specific portion
1398 *
1399 **********************************************************************/
1400 1140
1401 /// <summary> 1141 /// <summary>
1402 /// Create an Insert command 1142 /// Creates the prim inventory parameters.
1403 /// </summary> 1143 /// </summary>
1404 /// <param name="table"></param> 1144 /// <param name="taskItem">item in inventory.</param>
1405 /// <param name="dt"></param> 1145 /// <returns></returns>
1406 /// <returns>the sql command</returns> 1146 private SqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem)
1407 private static SqlCommand createInsertCommand(string table, DataTable dt)
1408 { 1147 {
1409 /** 1148 SqlParameter[] parameters = new SqlParameter[19];
1410 * This is subtle enough to deserve some commentary. 1149
1411 * Instead of doing *lots* and *lots of hardcoded strings 1150 parameters[0] = _Database.CreateParameter("itemID", taskItem.ItemID);
1412 * for database definitions we'll use the fact that 1151 parameters[1] = _Database.CreateParameter("primID", taskItem.ParentPartID);
1413 * realistically all insert statements look like "insert 1152 parameters[2] = _Database.CreateParameter("assetID", taskItem.AssetID);
1414 * into A(b, c) values(:b, :c) on the parameterized query 1153 parameters[3] = _Database.CreateParameter("parentFolderID", taskItem.ParentID);
1415 * front. If we just have a list of b, c, etc... we can 1154
1416 * generate these strings instead of typing them out. 1155 parameters[4] = _Database.CreateParameter("invType", taskItem.InvType);
1417 */ 1156 parameters[5] = _Database.CreateParameter("assetType", taskItem.Type);
1418 string[] cols = new string[dt.Columns.Count]; 1157
1419 for (int i = 0; i < dt.Columns.Count; i++) 1158 parameters[6] = _Database.CreateParameter("name", taskItem.Name);
1420 { 1159 parameters[7] = _Database.CreateParameter("description", taskItem.Description);
1421 DataColumn col = dt.Columns[i]; 1160 parameters[8] = _Database.CreateParameter("creationDate", taskItem.CreationDate);
1422 cols[i] = col.ColumnName; 1161 parameters[9] = _Database.CreateParameter("creatorID", taskItem.CreatorID);
1423 } 1162 parameters[10] = _Database.CreateParameter("ownerID", taskItem.OwnerID);
1424 1163 parameters[11] = _Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID);
1425 string sql = "insert into " + table + "("; 1164 parameters[12] = _Database.CreateParameter("groupID", taskItem.GroupID);
1426 sql += String.Join(", ", cols); 1165 parameters[13] = _Database.CreateParameter("nextPermissions", taskItem.NextPermissions);
1427 // important, the first ':' needs to be here, the rest get added in the join 1166 parameters[14] = _Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions);
1428 sql += ") values (@"; 1167 parameters[15] = _Database.CreateParameter("basePermissions", taskItem.BasePermissions);
1429 sql += String.Join(", @", cols); 1168 parameters[16] = _Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions);
1430 sql += ")"; 1169 parameters[17] = _Database.CreateParameter("groupPermissions", taskItem.GroupPermissions);
1431 SqlCommand cmd = new SqlCommand(sql); 1170 parameters[18] = _Database.CreateParameter("flags", taskItem.Flags);
1432 1171
1433 // this provides the binding for all our parameters, so 1172 return parameters;
1434 // much less code than it used to be
1435 foreach (DataColumn col in dt.Columns)
1436 {
1437 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType));
1438 }
1439 return cmd;
1440 } 1173 }
1441 1174
1442 /// <summary> 1175 /// <summary>
1443 /// Create an update command 1176 /// Creates the region setting parameters.
1444 /// </summary> 1177 /// </summary>
1445 /// <param name="table"></param> 1178 /// <param name="settings">regionsettings.</param>
1446 /// <param name="pk"></param> 1179 /// <returns></returns>
1447 /// <param name="dt"></param> 1180 private SqlParameter[] CreateRegionSettingParameters(RegionSettings settings)
1448 /// <returns>the sql command</returns>
1449 private static SqlCommand createUpdateCommand(string table, string pk, DataTable dt)
1450 { 1181 {
1451 string sql = "update " + table + " set "; 1182 SqlParameter[] parameters = new SqlParameter[34];
1452 string subsql = String.Empty; 1183
1453 foreach (DataColumn col in dt.Columns) 1184 parameters[0] = _Database.CreateParameter("regionUUID", settings.RegionUUID);
1454 { 1185 parameters[1] = _Database.CreateParameter("block_terraform", settings.BlockTerraform);
1455 if (subsql.Length > 0) 1186 parameters[2] = _Database.CreateParameter("block_fly", settings.BlockFly);
1456 { 1187 parameters[3] = _Database.CreateParameter("allow_damage", settings.AllowDamage);
1457 // a map function would rock so much here 1188 parameters[4] = _Database.CreateParameter("restrict_pushing", settings.RestrictPushing);
1458 subsql += ", "; 1189 parameters[5] = _Database.CreateParameter("allow_land_resell", settings.AllowLandResell);
1459 } 1190 parameters[6] = _Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide);
1460 subsql += col.ColumnName + "= @" + col.ColumnName; 1191 parameters[7] = _Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch);
1461 } 1192 parameters[8] = _Database.CreateParameter("agent_limit", settings.AgentLimit);
1462 sql += subsql; 1193 parameters[9] = _Database.CreateParameter("object_bonus", settings.ObjectBonus);
1463 sql += " where " + pk; 1194 parameters[10] = _Database.CreateParameter("maturity", settings.Maturity);
1464 SqlCommand cmd = new SqlCommand(sql); 1195 parameters[11] = _Database.CreateParameter("disable_scripts", settings.DisableScripts);
1465 1196 parameters[12] = _Database.CreateParameter("disable_collisions", settings.DisableCollisions);
1466 // this provides the binding for all our parameters, so 1197 parameters[13] = _Database.CreateParameter("disable_physics", settings.DisablePhysics);
1467 // much less code than it used to be 1198 parameters[14] = _Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1);
1468 1199 parameters[15] = _Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2);
1469 foreach (DataColumn col in dt.Columns) 1200 parameters[16] = _Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3);
1470 { 1201 parameters[17] = _Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4);
1471 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType)); 1202 parameters[18] = _Database.CreateParameter("elevation_1_nw", settings.Elevation1NW);
1472 } 1203 parameters[19] = _Database.CreateParameter("elevation_2_nw", settings.Elevation2NW);
1473 return cmd; 1204 parameters[20] = _Database.CreateParameter("elevation_1_ne", settings.Elevation1NE);
1205 parameters[21] = _Database.CreateParameter("elevation_2_ne", settings.Elevation2NE);
1206 parameters[22] = _Database.CreateParameter("elevation_1_se", settings.Elevation1SE);
1207 parameters[23] = _Database.CreateParameter("elevation_2_se", settings.Elevation2SE);
1208 parameters[24] = _Database.CreateParameter("elevation_1_sw", settings.Elevation1SW);
1209 parameters[25] = _Database.CreateParameter("elevation_2_sw", settings.Elevation2SW);
1210 parameters[26] = _Database.CreateParameter("water_height", settings.WaterHeight);
1211 parameters[27] = _Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit);
1212 parameters[28] = _Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit);
1213 parameters[29] = _Database.CreateParameter("use_estate_sun", settings.UseEstateSun);
1214 parameters[30] = _Database.CreateParameter("sandbox", settings.Sandbox);
1215 parameters[31] = _Database.CreateParameter("fixed_sun", settings.FixedSun);
1216 parameters[32] = _Database.CreateParameter("sun_position", settings.SunPosition);
1217 parameters[33] = _Database.CreateParameter("covenant", settings.Covenant);
1218
1219 return parameters;
1474 } 1220 }
1475 1221
1476 /// <summary> 1222 /// <summary>
1477 /// 1223 /// Creates the land parameters.
1478 /// </summary> 1224 /// </summary>
1479 /// <param name="dt"></param> 1225 /// <param name="land">land parameters.</param>
1226 /// <param name="regionUUID">region UUID.</param>
1480 /// <returns></returns> 1227 /// <returns></returns>
1481 private static string defineTable(DataTable dt) 1228 private SqlParameter[] CreateLandParameters(LandData land, LLUUID regionUUID)
1482 { 1229 {
1483 string sql = "create table " + dt.TableName + "("; 1230 SqlParameter[] parameters = new SqlParameter[32];
1484 string subsql = String.Empty;
1485 foreach (DataColumn col in dt.Columns)
1486 {
1487 if (subsql.Length > 0)
1488 {
1489 // a map function would rock so much here
1490 subsql += ",\n";
1491 }
1492 subsql += col.ColumnName + " " + MSSQLManager.SqlType(col.DataType);
1493 if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0])
1494 {
1495 subsql += " primary key";
1496 }
1497 }
1498 sql += subsql;
1499 sql += ")";
1500 1231
1501 return sql; 1232 parameters[0] = _Database.CreateParameter("UUID", land.GlobalID);
1502 } 1233 parameters[1] = _Database.CreateParameter("RegionUUID", regionUUID);
1234 parameters[2] = _Database.CreateParameter("LocalLandID", land.LocalID);
1503 1235
1504 /*********************************************************************** 1236 // Bitmap is a byte[512]
1505 * 1237 parameters[3] = _Database.CreateParameter("Bitmap", land.Bitmap);
1506 * Database Binding functions 1238
1507 * 1239 parameters[4] = _Database.CreateParameter("Name", land.Name);
1508 * These will be db specific due to typing, and minor differences 1240 parameters[5] = _Database.CreateParameter("Description", land.Description);
1509 * in databases. 1241 parameters[6] = _Database.CreateParameter("OwnerUUID", land.OwnerID);
1510 * 1242 parameters[7] = _Database.CreateParameter("IsGroupOwned", land.IsGroupOwned);
1511 **********************************************************************/ 1243 parameters[8] = _Database.CreateParameter("Area", land.Area);
1512 1244 parameters[9] = _Database.CreateParameter("AuctionID", land.AuctionID); //Unemplemented
1513 ///<summary> 1245 parameters[10] = _Database.CreateParameter("Category", (int)land.Category); //Enum libsecondlife.Parcel.ParcelCategory
1514 /// <para> 1246 parameters[11] = _Database.CreateParameter("ClaimDate", land.ClaimDate);
1515 /// This is a convenience function that collapses 5 repetitive 1247 parameters[12] = _Database.CreateParameter("ClaimPrice", land.ClaimPrice);
1516 /// lines for defining SqlParameters to 2 parameters: 1248 parameters[13] = _Database.CreateParameter("GroupUUID", land.GroupID);
1517 /// column name and database type. 1249 parameters[14] = _Database.CreateParameter("SalePrice", land.SalePrice);
1518 /// </para> 1250 parameters[15] = _Database.CreateParameter("LandStatus", (int)land.Status); //Enum. libsecondlife.Parcel.ParcelStatus
1519 /// 1251 parameters[16] = _Database.CreateParameter("LandFlags", land.Flags);
1520 /// <para> 1252 parameters[17] = _Database.CreateParameter("LandingType", land.LandingType);
1521 /// It assumes certain conventions like :param as the param 1253 parameters[18] = _Database.CreateParameter("MediaAutoScale", land.MediaAutoScale);
1522 /// name to replace in parametrized queries, and that source 1254 parameters[19] = _Database.CreateParameter("MediaTextureUUID", land.MediaID);
1523 /// version is always current version, both of which are fine 1255 parameters[20] = _Database.CreateParameter("MediaURL", land.MediaURL);
1524 /// for us. 1256 parameters[21] = _Database.CreateParameter("MusicURL", land.MusicURL);
1525 /// </para> 1257 parameters[22] = _Database.CreateParameter("PassHours", land.PassHours);
1526 ///</summary> 1258 parameters[23] = _Database.CreateParameter("PassPrice", land.PassPrice);
1527 ///<returns>a built Sql parameter</returns> 1259 parameters[24] = _Database.CreateParameter("SnapshotUUID", land.SnapshotID);
1528 private static SqlParameter createSqlParameter(string name, Type type) 1260 parameters[25] = _Database.CreateParameter("UserLocationX", land.UserLocation.X);
1529 { 1261 parameters[26] = _Database.CreateParameter("UserLocationY", land.UserLocation.Y);
1530 SqlParameter param = new SqlParameter(); 1262 parameters[27] = _Database.CreateParameter("UserLocationZ", land.UserLocation.Z);
1531 param.ParameterName = "@" + name; 1263 parameters[28] = _Database.CreateParameter("UserLookAtX", land.UserLookAt.X);
1532 param.DbType = dbtypeFromType(type); 1264 parameters[29] = _Database.CreateParameter("UserLookAtY", land.UserLookAt.Y);
1533 param.SourceColumn = name; 1265 parameters[30] = _Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z);
1534 param.SourceVersion = DataRowVersion.Current; 1266 parameters[31] = _Database.CreateParameter("AuthBuyerID", land.AuthBuyerID);
1535 return param; 1267
1268 return parameters;
1536 } 1269 }
1537 1270
1538 /// <summary> 1271 /// <summary>
1539 /// 1272 /// Creates the land access parameters.
1540 /// </summary> 1273 /// </summary>
1541 /// <param name="da"></param> 1274 /// <param name="parcelAccessEntry">parcel access entry.</param>
1542 /// <param name="conn"></param> 1275 /// <param name="parcelID">parcel ID.</param>
1543 private void setupPrimCommands(SqlDataAdapter da, SqlConnection conn) 1276 /// <returns></returns>
1277 private SqlParameter[] CreateLandAccessParameters(ParcelManager.ParcelAccessEntry parcelAccessEntry, LLUUID parcelID)
1544 { 1278 {
1545 da.InsertCommand = createInsertCommand("prims", m_dataSet.Tables["prims"]); 1279 SqlParameter[] parameters = new SqlParameter[3];
1546 da.InsertCommand.Connection = conn;
1547 1280
1548 da.UpdateCommand = createUpdateCommand("prims", "UUID=@UUID", m_dataSet.Tables["prims"]); 1281 parameters[0] = _Database.CreateParameter("LandUUID", parcelID);
1549 da.UpdateCommand.Connection = conn; 1282 parameters[1] = _Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID);
1283 parameters[2] = _Database.CreateParameter("Flags", parcelAccessEntry.Flags);
1550 1284
1551 SqlCommand delete = new SqlCommand("delete from prims where UUID = @UUID"); 1285 return parameters;
1552 delete.Parameters.Add(createSqlParameter("UUID", typeof(String)));
1553 delete.Connection = conn;
1554 da.DeleteCommand = delete;
1555 } 1286 }
1556 1287
1557 /// <summary> 1288 /// <summary>
1558 /// 1289 /// Fills/Updates the prim datarow.
1559 /// </summary> 1290 /// </summary>
1560 /// <param name="da"></param> 1291 /// <param name="row">datarow.</param>
1561 /// <param name="conn"></param> 1292 /// <param name="prim">prim data.</param>
1562 private void SetupItemsCommands(SqlDataAdapter da, SqlConnection conn) 1293 /// <param name="sceneGroupID">scenegroup ID.</param>
1294 /// <param name="regionUUID">regionUUID.</param>
1295 private static void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1563 { 1296 {
1564 da.InsertCommand = createInsertCommand("primitems", m_itemsTable); 1297 row["UUID"] = prim.UUID.ToString();
1565 da.InsertCommand.Connection = conn; 1298 row["RegionUUID"] = regionUUID.ToString();
1299 row["ParentID"] = prim.ParentID;
1300 row["CreationDate"] = prim.CreationDate;
1301 row["Name"] = prim.Name;
1302 row["SceneGroupID"] = sceneGroupID.ToString();
1303 // the UUID of the root part for this SceneObjectGroup
1304 // various text fields
1305 row["Text"] = prim.Text;
1306 row["Description"] = prim.Description;
1307 row["SitName"] = prim.SitName;
1308 row["TouchName"] = prim.TouchName;
1309 // permissions
1310 row["ObjectFlags"] = prim.ObjectFlags;
1311 row["CreatorID"] = prim.CreatorID.ToString();
1312 row["OwnerID"] = prim.OwnerID.ToString();
1313 row["GroupID"] = prim.GroupID.ToString();
1314 row["LastOwnerID"] = prim.LastOwnerID.ToString();
1315 row["OwnerMask"] = prim.OwnerMask;
1316 row["NextOwnerMask"] = prim.NextOwnerMask;
1317 row["GroupMask"] = prim.GroupMask;
1318 row["EveryoneMask"] = prim.EveryoneMask;
1319 row["BaseMask"] = prim.BaseMask;
1320 // vectors
1321 row["PositionX"] = prim.OffsetPosition.X;
1322 row["PositionY"] = prim.OffsetPosition.Y;
1323 row["PositionZ"] = prim.OffsetPosition.Z;
1324 row["GroupPositionX"] = prim.GroupPosition.X;
1325 row["GroupPositionY"] = prim.GroupPosition.Y;
1326 row["GroupPositionZ"] = prim.GroupPosition.Z;
1327 row["VelocityX"] = prim.Velocity.X;
1328 row["VelocityY"] = prim.Velocity.Y;
1329 row["VelocityZ"] = prim.Velocity.Z;
1330 row["AngularVelocityX"] = prim.AngularVelocity.X;
1331 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1332 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1333 row["AccelerationX"] = prim.Acceleration.X;
1334 row["AccelerationY"] = prim.Acceleration.Y;
1335 row["AccelerationZ"] = prim.Acceleration.Z;
1336 // quaternions
1337 row["RotationX"] = prim.RotationOffset.X;
1338 row["RotationY"] = prim.RotationOffset.Y;
1339 row["RotationZ"] = prim.RotationOffset.Z;
1340 row["RotationW"] = prim.RotationOffset.W;
1341
1342 // Sit target
1343 LLVector3 sitTargetPos = prim.SitTargetPositionLL;
1344 row["SitTargetOffsetX"] = sitTargetPos.X;
1345 row["SitTargetOffsetY"] = sitTargetPos.Y;
1346 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1347
1348 LLQuaternion sitTargetOrient = prim.SitTargetOrientationLL;
1349 row["SitTargetOrientW"] = sitTargetOrient.W;
1350 row["SitTargetOrientX"] = sitTargetOrient.X;
1351 row["SitTargetOrientY"] = sitTargetOrient.Y;
1352 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1353
1354 row["PayPrice"] = prim.PayPrice[0];
1355 row["PayButton1"] = prim.PayPrice[1];
1356 row["PayButton2"] = prim.PayPrice[2];
1357 row["PayButton3"] = prim.PayPrice[3];
1358 row["PayButton4"] = prim.PayPrice[4];
1359
1360 if ((prim.SoundFlags & 1) != 0) // Looped
1361 {
1362 row["LoopedSound"] = prim.Sound.ToString();
1363 row["LoopedSoundGain"] = prim.SoundGain;
1364 }
1365 else
1366 {
1367 row["LoopedSound"] = LLUUID.Zero;
1368 row["LoopedSoundGain"] = 0.0f;
1369 }
1566 1370
1567 da.UpdateCommand = createUpdateCommand("primitems", "itemID = @itemID", m_itemsTable); 1371 row["TextureAnimation"] = prim.TextureAnimation;
1568 da.UpdateCommand.Connection = conn;
1569 1372
1570 SqlCommand delete = new SqlCommand("delete from primitems where itemID = @itemID"); 1373 row["OmegaX"] = prim.RotationalVelocity.X;
1571 delete.Parameters.Add(createSqlParameter("itemID", typeof(String))); 1374 row["OmegaY"] = prim.RotationalVelocity.Y;
1572 delete.Connection = conn; 1375 row["OmegaZ"] = prim.RotationalVelocity.Z;
1573 da.DeleteCommand = delete;
1574 }
1575 1376
1576 /// <summary> 1377 row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X;
1577 /// 1378 row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y;
1578 /// </summary> 1379 row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z;
1579 /// <param name="da"></param>
1580 /// <param name="conn"></param>
1581 private void setupTerrainCommands(SqlDataAdapter da, SqlConnection conn)
1582 {
1583 da.InsertCommand = createInsertCommand("terrain", m_dataSet.Tables["terrain"]);
1584 da.InsertCommand.Connection = conn;
1585 }
1586 1380
1587 /// <summary> 1381 row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X;
1588 /// 1382 row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y;
1589 /// </summary> 1383 row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z;
1590 /// <param name="da"></param>
1591 /// <param name="conn"></param>
1592 private void setupLandCommands(SqlDataAdapter da, SqlConnection conn)
1593 {
1594 da.InsertCommand = createInsertCommand("land", m_dataSet.Tables["land"]);
1595 da.InsertCommand.Connection = conn;
1596 1384
1597 da.UpdateCommand = createUpdateCommand("land", "UUID=@UUID", m_dataSet.Tables["land"]); 1385 if (prim.GetForceMouselook())
1598 da.UpdateCommand.Connection = conn; 1386 row["ForceMouselook"] = 1;
1599 } 1387 else
1388 row["ForceMouselook"] = 0;
1600 1389
1601 /// <summary> 1390 row["ScriptAccessPin"] = prim.ScriptAccessPin;
1602 ///
1603 /// </summary>
1604 /// <param name="da"></param>
1605 /// <param name="conn"></param>
1606 private void setupLandAccessCommands(SqlDataAdapter da, SqlConnection conn)
1607 {
1608 da.InsertCommand = createInsertCommand("landaccesslist", m_dataSet.Tables["landaccesslist"]);
1609 da.InsertCommand.Connection = conn;
1610 }
1611 1391
1612 /// <summary> 1392 if (prim.AllowedDrop)
1613 /// 1393 row["AllowedDrop"] = 1;
1614 /// </summary> 1394 else
1615 /// <param name="da"></param> 1395 row["AllowedDrop"] = 0;
1616 /// <param name="conn"></param>
1617 private void setupShapeCommands(SqlDataAdapter da, SqlConnection conn)
1618 {
1619 da.InsertCommand = createInsertCommand("primshapes", m_dataSet.Tables["primshapes"]);
1620 da.InsertCommand.Connection = conn;
1621 1396
1622 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=@UUID", m_dataSet.Tables["primshapes"]); 1397 if (prim.DIE_AT_EDGE)
1623 da.UpdateCommand.Connection = conn; 1398 row["DieAtEdge"] = 1;
1399 else
1400 row["DieAtEdge"] = 0;
1624 1401
1625 SqlCommand delete = new SqlCommand("delete from primshapes where UUID = @UUID"); 1402 row["SalePrice"] = prim.SalePrice;
1626 delete.Parameters.Add(createSqlParameter("UUID", typeof(String))); 1403 row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType);
1627 delete.Connection = conn;
1628 da.DeleteCommand = delete;
1629 } 1404 }
1630 1405
1631 /// <summary> 1406 /// <summary>
1632 /// 1407 /// Fills/Updates the shape datarow.
1633 /// </summary> 1408 /// </summary>
1634 /// <param name="conn"></param> 1409 /// <param name="row">datarow to fill/update.</param>
1635 private static void InitDB(SqlConnection conn) 1410 /// <param name="prim">prim shape data.</param>
1411 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1636 { 1412 {
1637 string createPrims = defineTable(createPrimTable()); 1413 PrimitiveBaseShape s = prim.Shape;
1638 string createShapes = defineTable(createShapeTable()); 1414 row["UUID"] = prim.UUID.ToString();
1639 string createItems = defineTable(createItemsTable()); 1415 // shape is an enum
1640 string createTerrain = defineTable(createTerrainTable()); 1416 row["Shape"] = 0;
1641 string createLand = defineTable(createLandTable()); 1417 // vectors
1642 string createLandAccessList = defineTable(createLandAccessListTable()); 1418 row["ScaleX"] = s.Scale.X;
1643 1419 row["ScaleY"] = s.Scale.Y;
1644 SqlCommand pcmd = new SqlCommand(createPrims, conn); 1420 row["ScaleZ"] = s.Scale.Z;
1645 SqlCommand scmd = new SqlCommand(createShapes, conn); 1421 // paths
1646 SqlCommand icmd = new SqlCommand(createItems, conn); 1422 row["PCode"] = s.PCode;
1647 SqlCommand tcmd = new SqlCommand(createTerrain, conn); 1423 row["PathBegin"] = s.PathBegin;
1648 SqlCommand lcmd = new SqlCommand(createLand, conn); 1424 row["PathEnd"] = s.PathEnd;
1649 SqlCommand lalcmd = new SqlCommand(createLandAccessList, conn); 1425 row["PathScaleX"] = s.PathScaleX;
1650 1426 row["PathScaleY"] = s.PathScaleY;
1651 conn.Open(); 1427 row["PathShearX"] = s.PathShearX;
1652 try 1428 row["PathShearY"] = s.PathShearY;
1653 { 1429 row["PathSkew"] = s.PathSkew;
1654 pcmd.ExecuteNonQuery(); 1430 row["PathCurve"] = s.PathCurve;
1655 } 1431 row["PathRadiusOffset"] = s.PathRadiusOffset;
1656 catch (SqlException e) 1432 row["PathRevolutions"] = s.PathRevolutions;
1657 { 1433 row["PathTaperX"] = s.PathTaperX;
1658 m_log.WarnFormat("[MSSql]: Primitives Table Already Exists: {0}", e); 1434 row["PathTaperY"] = s.PathTaperY;
1659 } 1435 row["PathTwist"] = s.PathTwist;
1660 1436 row["PathTwistBegin"] = s.PathTwistBegin;
1661 try 1437 // profile
1662 { 1438 row["ProfileBegin"] = s.ProfileBegin;
1663 scmd.ExecuteNonQuery(); 1439 row["ProfileEnd"] = s.ProfileEnd;
1664 } 1440 row["ProfileCurve"] = s.ProfileCurve;
1665 catch (SqlException e) 1441 row["ProfileHollow"] = s.ProfileHollow;
1666 { 1442 row["Texture"] = s.TextureEntry;
1667 m_log.WarnFormat("[MSSql]: Shapes Table Already Exists: {0}", e); 1443 row["ExtraParams"] = s.ExtraParams;
1668 } 1444 row["State"] = s.State;
1669
1670 try
1671 {
1672 icmd.ExecuteNonQuery();
1673 }
1674 catch (SqlException e)
1675 {
1676 m_log.WarnFormat("[MSSql]: Items Table Already Exists: {0}", e);
1677 }
1678
1679 try
1680 {
1681 tcmd.ExecuteNonQuery();
1682 }
1683 catch (SqlException e)
1684 {
1685 m_log.WarnFormat("[MSSql]: Terrain Table Already Exists: {0}", e);
1686 }
1687
1688 try
1689 {
1690 lcmd.ExecuteNonQuery();
1691 }
1692 catch (SqlException e)
1693 {
1694 m_log.WarnFormat("[MSSql]: Land Table Already Exists: {0}", e);
1695 }
1696
1697 try
1698 {
1699 lalcmd.ExecuteNonQuery();
1700 }
1701 catch (SqlException e)
1702 {
1703 m_log.WarnFormat("[MSSql]: LandAccessList Table Already Exists: {0}", e);
1704 }
1705 conn.Close();
1706 } 1445 }
1707 1446
1708 /// <summary> 1447 #endregion
1709 /// 1448
1710 /// </summary> 1449 private void RetrievePrimsDataForRegion(LLUUID regionUUID, LLUUID sceneGroupID, string primID)
1711 /// <param name="conn"></param>
1712 /// <returns></returns>
1713 private bool TestTables(SqlConnection conn)
1714 { 1450 {
1715 SqlCommand primSelectCmd = new SqlCommand(m_primSelect, conn); 1451 using (SqlConnection connection = _Database.DatabaseConnection())
1716 SqlDataAdapter pDa = new SqlDataAdapter(primSelectCmd);
1717 SqlCommand shapeSelectCmd = new SqlCommand(m_shapeSelect, conn);
1718 SqlDataAdapter sDa = new SqlDataAdapter(shapeSelectCmd);
1719 SqlCommand itemsSelectCmd = new SqlCommand(m_itemsSelect, conn);
1720 SqlDataAdapter iDa = new SqlDataAdapter(itemsSelectCmd);
1721 SqlCommand terrainSelectCmd = new SqlCommand(m_terrainSelect, conn);
1722 SqlDataAdapter tDa = new SqlDataAdapter(terrainSelectCmd);
1723 SqlCommand landSelectCmd = new SqlCommand(m_landSelect, conn);
1724 SqlDataAdapter lDa = new SqlDataAdapter(landSelectCmd);
1725 SqlCommand landAccessListSelectCmd = new SqlCommand(m_landAccessListSelect, conn);
1726 SqlDataAdapter lalDa = new SqlDataAdapter(landAccessListSelectCmd);
1727
1728 DataSet tmpDS = new DataSet();
1729 try
1730 { 1452 {
1731 pDa.Fill(tmpDS, "prims"); 1453 _PrimDataAdapter.SelectCommand.Connection = connection;
1732 sDa.Fill(tmpDS, "primshapes"); 1454 _PrimDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1733 1455 if (sceneGroupID != LLUUID.Zero)
1734 iDa.Fill(tmpDS, "primitems"); 1456 _PrimDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1457 else
1458 _PrimDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1459 _PrimDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1735 1460
1736 tDa.Fill(tmpDS, "terrain"); 1461 _PrimDataAdapter.Fill(_PrimsDataSet, "prims");
1737 lDa.Fill(tmpDS, "land");
1738 lalDa.Fill(tmpDS, "landaccesslist");
1739 }
1740 catch (SqlException)
1741 {
1742 m_log.Info("[REGION DB]: MS Sql Database doesn't exist... creating");
1743 InitDB(conn);
1744 }
1745 1462
1746 pDa.Fill(tmpDS, "prims"); 1463 _ShapeDataAdapter.SelectCommand.Connection = connection;
1747 sDa.Fill(tmpDS, "primshapes"); 1464 _ShapeDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1465 if (sceneGroupID != LLUUID.Zero)
1466 _ShapeDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1467 else
1468 _ShapeDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1469 _ShapeDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1748 1470
1749 iDa.Fill(tmpDS, "primitems"); 1471 _ShapeDataAdapter.Fill(_PrimsDataSet, "primshapes");
1750 1472
1751 tDa.Fill(tmpDS, "terrain"); 1473 _ItemsDataAdapter.SelectCommand.Connection = connection;
1752 lDa.Fill(tmpDS, "land"); 1474 _ItemsDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1753 lalDa.Fill(tmpDS, "landaccesslist"); 1475 if (sceneGroupID != LLUUID.Zero)
1476 _ItemsDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1477 else
1478 _ItemsDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1479 _ItemsDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1754 1480
1755 foreach (DataColumn col in createPrimTable().Columns) 1481 _ItemsDataAdapter.Fill(_PrimsDataSet, "primitems");
1756 {
1757 if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName))
1758 {
1759 m_log.Info("[REGION DB]: Missing required column:" + col.ColumnName);
1760 return false;
1761 }
1762 } 1482 }
1483 }
1763 1484
1764 foreach (DataColumn col in createShapeTable().Columns) 1485 private void CommitDataSet()
1486 {
1487 lock (_PrimsDataSet)
1765 { 1488 {
1766 if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) 1489 using (SqlConnection connection = _Database.DatabaseConnection())
1767 { 1490 {
1768 m_log.Info("[REGION DB]: Missing required column:" + col.ColumnName); 1491 _PrimDataAdapter.InsertCommand.Connection = connection;
1769 return false; 1492 _PrimDataAdapter.UpdateCommand.Connection = connection;
1770 } 1493 _PrimDataAdapter.DeleteCommand.Connection = connection;
1771 }
1772 1494
1773 // XXX primitems should probably go here eventually 1495 _ShapeDataAdapter.InsertCommand.Connection = connection;
1496 _ShapeDataAdapter.UpdateCommand.Connection = connection;
1497 _ShapeDataAdapter.DeleteCommand.Connection = connection;
1774 1498
1775 foreach (DataColumn col in createTerrainTable().Columns) 1499 _ItemsDataAdapter.InsertCommand.Connection = connection;
1776 { 1500 _ItemsDataAdapter.UpdateCommand.Connection = connection;
1777 if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) 1501 _ItemsDataAdapter.DeleteCommand.Connection = connection;
1778 {
1779 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName);
1780 return false;
1781 }
1782 }
1783 1502
1784 foreach (DataColumn col in createLandTable().Columns) 1503 _PrimDataAdapter.Update(_PrimsDataSet.Tables["prims"]);
1785 { 1504 _ShapeDataAdapter.Update(_PrimsDataSet.Tables["primshapes"]);
1786 if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) 1505 _ItemsDataAdapter.Update(_PrimsDataSet.Tables["primitems"]);
1787 {
1788 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName);
1789 return false;
1790 }
1791 }
1792 1506
1793 foreach (DataColumn col in createLandAccessListTable().Columns) 1507 _PrimsDataSet.AcceptChanges();
1794 { 1508
1795 if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) 1509 _PrimsDataSet.Tables["prims"].Clear();
1796 { 1510 _PrimsDataSet.Tables["primshapes"].Clear();
1797 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName); 1511 _PrimsDataSet.Tables["primitems"].Clear();
1798 return false;
1799 } 1512 }
1800 } 1513 }
1801
1802 return true;
1803 } 1514 }
1804 1515
1805 /*********************************************************************** 1516 private static void SetupCommands(SqlDataAdapter dataAdapter)
1806 *
1807 * Type conversion functions
1808 *
1809 **********************************************************************/
1810
1811 /// <summary>
1812 /// Type conversion function
1813 /// </summary>
1814 /// <param name="type">a Type</param>
1815 /// <returns>a DbType</returns>
1816 private static DbType dbtypeFromType(Type type)
1817 { 1517 {
1818 if (type == typeof(String)) 1518 SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
1819 { 1519
1820 return DbType.String; 1520 dataAdapter.InsertCommand = commandBuilder.GetInsertCommand(true);
1821 } 1521 dataAdapter.UpdateCommand = commandBuilder.GetUpdateCommand(true);
1822 else if (type == typeof(Int32)) 1522 dataAdapter.DeleteCommand = commandBuilder.GetDeleteCommand(true);
1823 {
1824 return DbType.Int32;
1825 }
1826 else if (type == typeof(Double))
1827 {
1828 return DbType.Double;
1829 }
1830 else if (type == typeof(Byte[]))
1831 {
1832 return DbType.Binary;
1833 }
1834 else
1835 {
1836 return DbType.String;
1837 }
1838 } 1523 }
1524 #endregion
1839 } 1525 }
1840} 1526}