aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs2212
-rw-r--r--OpenSim/Data/MySQL/Resources/023_RegionStore.sql6
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs1
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs20
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs10
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs8
6 files changed, 778 insertions, 1479 deletions
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 2e36123..743c0d9 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -48,1107 +48,678 @@ namespace OpenSim.Data.MySQL
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private const string m_primSelect = "select * from prims"; 51 private string m_ConnectionString;
52 private const string m_shapeSelect = "select * from primshapes";
53 private const string m_itemsSelect = "select * from primitems";
54 private const string m_terrainSelect = "select * from terrain limit 1";
55 private const string m_landSelect = "select * from land";
56 private const string m_landAccessListSelect = "select * from landaccesslist";
57 private const string m_regionSettingsSelect = "select * from regionsettings";
58 private const string m_waitTimeoutSelect = "select @@wait_timeout";
59
60 private MySqlConnection m_connection;
61 private string m_connectionString;
62 52
63 /// <summary> 53 private MySqlConnection m_Connection = null;
64 /// Wait timeout for our connection in ticks.
65 /// </summary>
66 private long m_waitTimeout;
67
68 /// <summary>
69 /// Make our storage of the timeout this amount smaller than it actually is, to give us a margin on long
70 /// running database operations.
71 /// </summary>
72 private long m_waitTimeoutLeeway = 60 * TimeSpan.TicksPerSecond;
73
74 /// <summary>
75 /// Holds the last tick time that the connection was used.
76 /// </summary>
77 private long m_lastConnectionUse;
78
79 private DataSet m_dataSet;
80 private MySqlDataAdapter m_primDataAdapter;
81 private MySqlDataAdapter m_shapeDataAdapter;
82 private MySqlDataAdapter m_itemsDataAdapter;
83 private MySqlDataAdapter m_terrainDataAdapter;
84 private MySqlDataAdapter m_landDataAdapter;
85 private MySqlDataAdapter m_landAccessListDataAdapter;
86 private MySqlDataAdapter m_regionSettingsDataAdapter;
87
88 private DataTable m_primTable;
89 private DataTable m_shapeTable;
90 private DataTable m_itemsTable;
91 private DataTable m_terrainTable;
92 private DataTable m_landTable;
93 private DataTable m_landAccessListTable;
94 private DataTable m_regionSettingsTable;
95
96 /***********************************************************************
97 *
98 * Public Interface Functions
99 *
100 **********************************************************************/
101 54
102 /// <summary>
103 /// see IRegionDataStore
104 /// </summary>
105 /// <param name="connectionstring"></param>
106 public void Initialise(string connectionString) 55 public void Initialise(string connectionString)
107 { 56 {
108 m_connectionString = connectionString; 57 m_ConnectionString = connectionString;
109 58
110 m_dataSet = new DataSet(); 59 m_Connection = new MySqlConnection(m_ConnectionString);
111 60
112 int passPosition = 0; 61 m_Connection.Open();
113 int passEndPosition = 0;
114 string displayConnectionString = null;
115
116 try
117 { // hide the password in the connection string
118 passPosition = m_connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase);
119 passPosition = m_connectionString.IndexOf("=", passPosition);
120 if (passPosition < m_connectionString.Length)
121 passPosition += 1;
122 passEndPosition = m_connectionString.IndexOf(";", passPosition);
123
124 displayConnectionString = m_connectionString.Substring(0, passPosition);
125 displayConnectionString += "***";
126 displayConnectionString += m_connectionString.Substring(passEndPosition, m_connectionString.Length - passEndPosition);
127 }
128 catch (Exception e )
129 {
130 m_log.Debug("Exception: password not found in connection string\n" + e.ToString());
131 }
132 62
133 m_log.Info("[REGION DB]: MySql - connecting: " + displayConnectionString); 63 // Apply new Migrations
134 m_connection = new MySqlConnection(m_connectionString); 64 //
135 m_connection.Open();
136
137 GetWaitTimeout();
138
139 // This actually does the roll forward assembly stuff
140 Assembly assem = GetType().Assembly; 65 Assembly assem = GetType().Assembly;
141 Migration m = new Migration(m_connection, assem, "RegionStore"); 66 Migration m = new Migration(m_Connection, assem, "RegionStore");
142 m.Update(); 67 m.Update();
143 68
144 69 // Clean dropped attachments
145 MySqlCommand primSelectCmd = new MySqlCommand(m_primSelect, m_connection); 70 //
146 m_primDataAdapter = new MySqlDataAdapter(primSelectCmd); 71 MySqlCommand cmd = m_Connection.CreateCommand();
147 72 cmd.CommandText = "delete from prims, primshapes using prims " +
148 MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, m_connection); 73 "left join primshapes on prims.uuid = primshapes.uuid " +
149 m_shapeDataAdapter = new MySqlDataAdapter(shapeSelectCmd); 74 "where PCode = 9 and State <> 0";
150 75 ExecuteNonQuery(cmd);
151 MySqlCommand itemsSelectCmd = new MySqlCommand(m_itemsSelect, m_connection);
152 m_itemsDataAdapter = new MySqlDataAdapter(itemsSelectCmd);
153
154 MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, m_connection);
155 m_terrainDataAdapter = new MySqlDataAdapter(terrainSelectCmd);
156
157 MySqlCommand landSelectCmd = new MySqlCommand(m_landSelect, m_connection);
158 m_landDataAdapter = new MySqlDataAdapter(landSelectCmd);
159
160 MySqlCommand landAccessListSelectCmd = new MySqlCommand(m_landAccessListSelect, m_connection);
161 m_landAccessListDataAdapter = new MySqlDataAdapter(landAccessListSelectCmd);
162
163 MySqlCommand regionSettingsSelectCmd = new MySqlCommand(m_regionSettingsSelect, m_connection);
164 m_regionSettingsDataAdapter = new MySqlDataAdapter(regionSettingsSelectCmd);
165
166 // TODO: move out the ADO.NET pieces here and just go to the db directly
167 lock (m_dataSet)
168 {
169 m_primTable = createPrimTable();
170 m_dataSet.Tables.Add(m_primTable);
171 SetupPrimCommands(m_primDataAdapter, m_connection);
172 m_primDataAdapter.Fill(m_primTable);
173
174 m_shapeTable = createShapeTable();
175 m_dataSet.Tables.Add(m_shapeTable);
176 SetupShapeCommands(m_shapeDataAdapter, m_connection);
177 m_shapeDataAdapter.Fill(m_shapeTable);
178
179 m_itemsTable = createItemsTable();
180 m_dataSet.Tables.Add(m_itemsTable);
181 SetupItemsCommands(m_itemsDataAdapter, m_connection);
182 m_itemsDataAdapter.Fill(m_itemsTable);
183
184 m_terrainTable = createTerrainTable();
185 m_dataSet.Tables.Add(m_terrainTable);
186 SetupTerrainCommands(m_terrainDataAdapter, m_connection);
187 m_terrainDataAdapter.Fill(m_terrainTable);
188
189 m_landTable = createLandTable();
190 m_dataSet.Tables.Add(m_landTable);
191 setupLandCommands(m_landDataAdapter, m_connection);
192 m_landDataAdapter.Fill(m_landTable);
193
194 m_landAccessListTable = createLandAccessListTable();
195 m_dataSet.Tables.Add(m_landAccessListTable);
196 setupLandAccessCommands(m_landAccessListDataAdapter, m_connection);
197 m_landAccessListDataAdapter.Fill(m_landAccessListTable);
198
199 m_regionSettingsTable = createRegionSettingsTable();
200 m_dataSet.Tables.Add(m_regionSettingsTable);
201 SetupRegionSettingsCommands(m_regionSettingsDataAdapter, m_connection);
202 m_regionSettingsDataAdapter.Fill(m_regionSettingsTable);
203 }
204 } 76 }
205 77
206 public void Dispose() {} 78 private IDataReader ExecuteReader(MySqlCommand c)
207
208 /// <summary>
209 /// Get the wait_timeout value for our connection
210 /// </summary>
211 protected void GetWaitTimeout()
212 { 79 {
213 MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, m_connection); 80 IDataReader r = null;
81 bool errorSeen = false;
214 82
215 lock (m_dataSet) 83 while (true)
216 { 84 {
217 MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow);
218 try 85 try
219 { 86 {
220 if (dbReader.Read()) 87 r = c.ExecuteReader();
221 {
222 m_waitTimeout
223 = Convert.ToInt32(dbReader["@@wait_timeout"]) * TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
224 }
225
226 cmd.Dispose();
227 } 88 }
228 finally 89 catch (MySqlException)
229 { 90 {
230 dbReader.Close(); 91 System.Threading.Thread.Sleep(500);
92
93 m_Connection.Close();
94 m_Connection.Open();
95
96 if (!errorSeen)
97 {
98 errorSeen = true;
99 continue;
100 continue;
101 }
102 throw;
231 } 103 }
232 }
233 104
234 m_lastConnectionUse = System.DateTime.Now.Ticks; 105 break;
106 }
235 107
236 m_log.DebugFormat( 108 return r;
237 "[REGION DB]: Connection wait timeout {0} seconds", m_waitTimeout / TimeSpan.TicksPerSecond);
238 } 109 }
239 110
240 /// <summary> 111 private void ExecuteNonQuery(MySqlCommand c)
241 /// Should be called before any db operation. This checks to see if the connection has not timed out
242 /// </summary>
243 protected void CheckConnection()
244 { 112 {
245 //m_log.Debug("[REGION DB]: Checking connection"); 113 bool errorSeen = false;
246 114
247 long timeNow = System.DateTime.Now.Ticks; 115 while (true)
248 if (timeNow - m_lastConnectionUse > m_waitTimeout || m_connection.State != ConnectionState.Open)
249 { 116 {
250 m_log.DebugFormat("[REGION DB]: Database connection has gone away - reconnecting"); 117 try
251
252 lock (m_connection)
253 { 118 {
254 m_connection.Close(); 119 c.ExecuteNonQuery();
255 m_connection = new MySqlConnection(m_connectionString);
256 m_connection.Open();
257 } 120 }
258 } 121 catch (MySqlException)
259 122 {
260 // Strictly, we should set this after the actual db operation. But it's more convenient to set here rather 123 System.Threading.Thread.Sleep(500);
261 // than require the code to call another method - the timeout leeway should be large enough to cover the
262 // inaccuracy.
263 m_lastConnectionUse = timeNow;
264 }
265
266 /// <summary>
267 /// Execute a SQL statement stored in a resource, as a string
268 /// </summary>
269 /// <param name="name">the ressource name</param>
270 /// <param name="dbcon">The database connection handler</param>
271 public void ExecuteResourceSql(string name, MySqlConnection dbcon)
272 {
273 MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon);
274 cmd.ExecuteNonQuery();
275 }
276 124
277 /// <summary> 125 m_Connection.Close();
278 /// Extract a named string resource from the embedded resources 126 m_Connection.Open();
279 /// </summary>
280 /// <param name="name">name of embedded resource</param>
281 /// <returns>string contained within the embedded resource</returns>
282 private string getResourceString(string name)
283 {
284 Assembly assem = GetType().Assembly;
285 string[] names = assem.GetManifestResourceNames();
286 127
287 foreach (string s in names) 128 if (!errorSeen)
288 {
289 if (s.EndsWith(name))
290 {
291 using (Stream resource = assem.GetManifestResourceStream(s))
292 { 129 {
293 using (StreamReader resourceReader = new StreamReader(resource)) 130 errorSeen = true;
294 { 131 continue;
295 string resourceString = resourceReader.ReadToEnd();
296 return resourceString;
297 }
298 } 132 }
133 throw;
299 } 134 }
135
136 break;
300 } 137 }
301 throw new Exception(string.Format("Resource '{0}' was not found", name));
302 } 138 }
303 139
304 /// <summary> 140 public void Dispose() {}
305 /// Adds an object into region storage 141
306 /// </summary>
307 /// <param name="obj">The object</param>
308 /// <param name="regionUUID">The region UUID</param>
309 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 142 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
310 { 143 {
311 lock (m_dataSet) 144 uint flags = obj.RootPart.GetEffectiveObjectFlags();
145
146 // Eligibility check
147 //
148 if ((flags & (uint)PrimFlags.Temporary) != 0)
149 return;
150 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
151 return;
152
153 lock (m_Connection)
312 { 154 {
155 MySqlCommand cmd = m_Connection.CreateCommand();
156
313 foreach (SceneObjectPart prim in obj.Children.Values) 157 foreach (SceneObjectPart prim in obj.Children.Values)
314 { 158 {
315 if ((prim.GetEffectiveObjectFlags() & (uint)PrimFlags.Temporary) == 0 159 cmd.Parameters.Clear();
316 && (prim.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) == 0) 160
317 { 161 cmd.CommandText = "replace into prims ("+
318 //m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); 162 "UUID, ParentID, CreationDate, "+
319 addPrim(prim, obj.UUID, regionUUID); 163 "Name, Text, Description, "+
320 } 164 "SitName, TouchName, ObjectFlags, "+
321 else 165 "OwnerMask, NextOwnerMask, GroupMask, "+
322 { 166 "EveryoneMask, BaseMask, PositionX, "+
323 // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID); 167 "PositionY, PositionZ, GroupPositionX, "+
324 } 168 "GroupPositionY, GroupPositionZ, VelocityX, "+
169 "VelocityY, VelocityZ, AngularVelocityX, "+
170 "AngularVelocityY, AngularVelocityZ, "+
171 "AccelerationX, AccelerationY, "+
172 "AccelerationZ, RotationX, "+
173 "RotationY, RotationZ, "+
174 "RotationW, SitTargetOffsetX, "+
175 "SitTargetOffsetY, SitTargetOffsetZ, "+
176 "SitTargetOrientW, SitTargetOrientX, "+
177 "SitTargetOrientY, SitTargetOrientZ, "+
178 "RegionUUID, CreatorID, "+
179 "OwnerID, GroupID, "+
180 "LastOwnerID, SceneGroupID, "+
181 "PayPrice, PayButton1, "+
182 "PayButton2, PayButton3, "+
183 "PayButton4, LoopedSound, "+
184 "LoopedSoundGain, TextureAnimation, "+
185 "OmegaX, OmegaY, OmegaZ, "+
186 "CameraEyeOffsetX, CameraEyeOffsetY, "+
187 "CameraEyeOffsetZ, CameraAtOffsetX, "+
188 "CameraAtOffsetY, CameraAtOffsetZ, "+
189 "ForceMouselook, ScriptAccessPin, "+
190 "AllowedDrop, DieAtEdge, "+
191 "SalePrice, SaleType, "+
192 "ColorR, ColorG, ColorB, ColorA, "+
193 "ParticleSystem, ClickAction, Material, "+
194 "CollisionSound, CollisionSoundVolume, "+
195 "LinkNumber) values (" + "?UUID, ?ParentID, "+
196 "?CreationDate, ?Name, ?Text, "+
197 "?Description, ?SitName, ?TouchName, "+
198 "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+
199 "?GroupMask, ?EveryoneMask, ?BaseMask, "+
200 "?PositionX, ?PositionY, ?PositionZ, "+
201 "?GroupPositionX, ?GroupPositionY, "+
202 "?GroupPositionZ, ?VelocityX, "+
203 "?VelocityY, ?VelocityZ, ?AngularVelocityX, "+
204 "?AngularVelocityY, ?AngularVelocityZ, "+
205 "?AccelerationX, ?AccelerationY, "+
206 "?AccelerationZ, ?RotationX, "+
207 "?RotationY, ?RotationZ, "+
208 "?RotationW, ?SitTargetOffsetX, "+
209 "?SitTargetOffsetY, ?SitTargetOffsetZ, "+
210 "?SitTargetOrientW, ?SitTargetOrientX, "+
211 "?SitTargetOrientY, ?SitTargetOrientZ, "+
212 "?RegionUUID, ?CreatorID, ?OwnerID, "+
213 "?GroupID, ?LastOwnerID, ?SceneGroupID, "+
214 "?PayPrice, ?PayButton1, ?PayButton2, "+
215 "?PayButton3, ?PayButton4, ?LoopedSound, "+
216 "?LoopedSoundGain, ?TextureAnimation, "+
217 "?OmegaX, ?OmegaY, ?OmegaZ, "+
218 "?CameraEyeOffsetX, ?CameraEyeOffsetY, "+
219 "?CameraEyeOffsetZ, ?CameraAtOffsetX, "+
220 "?CameraAtOffsetY, ?CameraAtOffsetZ, "+
221 "?ForceMouselook, ?ScriptAccessPin, "+
222 "?AllowedDrop, ?DieAtEdge, ?SalePrice, "+
223 "?SaleType, ?ColorR, ?ColorG, "+
224 "?ColorB, ?ColorA, ?ParticleSystem, "+
225 "?ClickAction, ?Material, ?CollisionSound, "+
226 "?CollisionSoundVolume, ?LinkNumber)";
227
228 FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
229
230 ExecuteNonQuery(cmd);
231
232 cmd.Parameters.Clear();
233
234 cmd.CommandText = "replace into primshapes ("+
235 "UUID, Shape, ScaleX, ScaleY, "+
236 "ScaleZ, PCode, PathBegin, PathEnd, "+
237 "PathScaleX, PathScaleY, PathShearX, "+
238 "PathShearY, PathSkew, PathCurve, "+
239 "PathRadiusOffset, PathRevolutions, "+
240 "PathTaperX, PathTaperY, PathTwist, "+
241 "PathTwistBegin, ProfileBegin, ProfileEnd, "+
242 "ProfileCurve, ProfileHollow, Texture, "+
243 "ExtraParams, State) values (?UUID, "+
244 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+
245 "?PCode, ?PathBegin, ?PathEnd, "+
246 "?PathScaleX, ?PathScaleY, "+
247 "?PathShearX, ?PathShearY, "+
248 "?PathSkew, ?PathCurve, ?PathRadiusOffset, "+
249 "?PathRevolutions, ?PathTaperX, "+
250 "?PathTaperY, ?PathTwist, "+
251 "?PathTwistBegin, ?ProfileBegin, "+
252 "?ProfileEnd, ?ProfileCurve, "+
253 "?ProfileHollow, ?Texture, ?ExtraParams, "+
254 "?State)";
255
256 FillShapeCommand(cmd, prim);
257
258 ExecuteNonQuery(cmd);
325 } 259 }
326 Commit();
327 } 260 }
328 } 261 }
329 262
330 /// <summary>
331 /// removes an object from region storage
332 /// </summary>
333 /// <param name="obj">The object</param>
334 /// <param name="regionUUID">The Region UUID</param>
335 public void RemoveObject(UUID obj, UUID regionUUID) 263 public void RemoveObject(UUID obj, UUID regionUUID)
336 { 264 {
337 m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj, regionUUID); 265 // Formerly, this used to check the region UUID.
266 // That makes no sense, as we remove the contents of a prim
267 // unconditionally, but the prim dependent on the region ID.
268 // So, we would destroy an object and cause hard to detect
269 // issues if we delete the contents only. Deleting it all may
270 // cause the loss of a prim, but is cleaner.
271 // It's also faster because it uses the primary key.
272 //
273 lock (m_Connection)
274 {
275 MySqlCommand cmd = m_Connection.CreateCommand();
338 276
339 DataTable prims = m_primTable; 277 cmd.CommandText = "select UUID from prims where "+
340 DataTable shapes = m_shapeTable; 278 "SceneGroupID= ?UUID";
341 279
342 string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "' and RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; 280 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(obj));
343 lock (m_dataSet) 281
344 { 282 List<UUID> uuids = new List<UUID>();
345 DataRow[] primRows = prims.Select(selectExp); 283
346 foreach (DataRow row in primRows) 284 IDataReader reader = ExecuteReader(cmd);
285
286 try
347 { 287 {
348 // Remove shapes row 288 while(reader.Read())
349 UUID uuid = new UUID((string) row["UUID"]);
350 DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid));
351 if (shapeRow != null)
352 { 289 {
353 shapeRow.Delete(); 290 uuids.Add(new UUID(reader["UUID"].ToString()));
354 } 291 }
292 }
293 finally
294 {
295 reader.Close();
296 }
355 297
298 foreach (UUID uuid in uuids)
356 RemoveItems(uuid); 299 RemoveItems(uuid);
357 300
358 // Remove prim row 301 cmd.CommandText = "delete from prims where SceneGroupID= ?UUID";
359 row.Delete(); 302
360 } 303 ExecuteNonQuery(cmd);
361 Commit(); 304
305 cmd.CommandText = "delete from primshapes where UUID = ?UUID";
306
307 ExecuteNonQuery(cmd);
362 } 308 }
363 } 309 }
364 310
365 /// <summary>
366 /// Remove all persisted items of the given prim.
367 /// The caller must acquire the necessrary synchronization locks and commit or rollback changes.
368 /// </summary>
369 /// <param name="uuid">the Item UUID</param>
370 private void RemoveItems(UUID uuid) 311 private void RemoveItems(UUID uuid)
371 { 312 {
372 String sql = String.Format("primID = '{0}'", uuid); 313 lock (m_Connection)
373 DataRow[] itemRows = m_itemsTable.Select(sql);
374
375 foreach (DataRow itemRow in itemRows)
376 { 314 {
377 itemRow.Delete(); 315 MySqlCommand cmd = m_Connection.CreateCommand();
316
317 cmd.CommandText = "delete from primitems where " +
318 "PrimID = ?PrimID";
319
320 cmd.Parameters.AddWithValue("PrimID", uuid.ToString());
321
322 ExecuteNonQuery(cmd);
378 } 323 }
379 } 324 }
380 325
381 /// <summary>
382 /// Load persisted objects from region storage.
383 /// </summary>
384 /// <param name="regionUUID">the Region UUID</param>
385 /// <returns>List of loaded groups</returns>
386 public List<SceneObjectGroup> LoadObjects(UUID regionUUID) 326 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
387 { 327 {
388 Dictionary<UUID, SceneObjectGroup> createdObjects = new Dictionary<UUID, SceneObjectGroup>(); 328 UUID lastGroupID = UUID.Zero;
389 329 List<SceneObjectGroup> objects = new List<SceneObjectGroup>();
390 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>(); 330 List<SceneObjectPart> prims = new List<SceneObjectPart>();
391 331 SceneObjectGroup grp = null;
392 DataTable prims = m_primTable;
393 DataTable shapes = m_shapeTable;
394 332
395 string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; 333 lock (m_Connection)
396 string orderByParent = "ParentID ASC";
397
398 lock (m_dataSet)
399 { 334 {
400 CheckConnection(); 335 MySqlCommand cmd = m_Connection.CreateCommand();
401 DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); 336
402 m_log.Info("[REGION DB]: " + 337 cmd.CommandText = "select *, " +
403 "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); 338 "case when prims.UUID = SceneGroupID " +
339 "then 0 else 1 end as sort from prims " +
340 "left join primshapes on prims.UUID = primshapes.UUID "+
341 "where RegionUUID = ?RegionUUID " +
342 "order by SceneGroupID asc, sort asc, LinkNumber asc";
404 343
405 // First, create all groups 344 cmd.Parameters.AddWithValue("RegionUUID",
406 foreach (DataRow primRow in primsForRegion) 345 Util.ToRawUuidString(regionUUID));
346
347 IDataReader reader = ExecuteReader(cmd);
348
349 try
407 { 350 {
408 try 351 while (reader.Read())
409 { 352 {
410 string uuid = (string) primRow["UUID"]; 353 SceneObjectPart prim = BuildPrim(reader);
411 string objID = (string) primRow["SceneGroupID"]; 354 if (reader["Shape"] is DBNull)
355 prim.Shape = PrimitiveBaseShape.Default;
356 else
357 prim.Shape = BuildShape(reader);
412 358
413 SceneObjectPart prim = buildPrim(primRow); 359 prim.FolderID = prim.UUID; // A relic from when we
360 // we thought prims contained
361 // folder objects. In
362 // reality, prim == folder
363 prims.Add(prim);
414 364
415 if (uuid == objID) //is new SceneObjectGroup ? 365 UUID groupID = new UUID(reader["SceneGroupID"].ToString());
416 {
417 SceneObjectGroup group = new SceneObjectGroup();
418 366
419 DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); 367 if (groupID != lastGroupID) // New SOG
420 if (shapeRow != null)
421 {
422 prim.Shape = buildShape(shapeRow);
423 }
424 else
425 {
426 m_log.Info(
427 "No shape found for prim in storage, so setting default box shape");
428 prim.Shape = PrimitiveBaseShape.Default;
429 }
430
431 group.SetRootPart(prim);
432 createdObjects.Add(group.UUID, group);
433 retvals.Add(group);
434 LoadItems(prim);
435 }
436 }
437 catch (Exception e)
438 {
439 m_log.Error("[REGION DB]: Failed create prim object, exception and data follows");
440 m_log.Info("[REGION DB]: " + e.ToString());
441 foreach (DataColumn col in prims.Columns)
442 { 368 {
443 m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); 369 if (grp != null)
444 } 370 objects.Add(grp);
445 }
446 }
447
448 // Now fill the groups with part data
449 foreach (DataRow primRow in primsForRegion)
450 {
451 try
452 {
453 string uuid = (string) primRow["UUID"];
454 string objID = (string) primRow["SceneGroupID"];
455 371
456 SceneObjectPart prim = buildPrim(primRow); 372 lastGroupID = groupID;
457 373
458 if (uuid != objID) //is new SceneObjectGroup ? 374 grp = new SceneObjectGroup(prim);
459 {
460 DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID));
461 if (shapeRow != null)
462 {
463 prim.Shape = buildShape(shapeRow);
464 }
465 else
466 {
467 m_log.Info(
468 "No shape found for prim in storage, so setting default box shape");
469 prim.Shape = PrimitiveBaseShape.Default;
470 }
471 createdObjects[new UUID(objID)].AddPart(prim);
472 LoadItems(prim);
473 } 375 }
474 } 376 else
475 catch (Exception e)
476 {
477 m_log.Error("[REGION DB]: Failed create prim object, exception and data follows");
478 m_log.Info("[REGION DB]: " + e.ToString());
479 foreach (DataColumn col in prims.Columns)
480 { 377 {
481 m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); 378 // Black magic to preserve link numbers
379 //
380 int link = prim.LinkNum;
381
382 grp.AddPart(prim);
383
384 if (link != 0)
385 prim.LinkNum = link;
482 } 386 }
483 } 387 }
484 } 388 }
389 finally
390 {
391 reader.Close();
392 }
393
394 if (grp != null)
395 objects.Add(grp);
485 } 396 }
486 return retvals; 397
398 foreach (SceneObjectPart part in prims)
399 LoadItems(part);
400
401 m_log.DebugFormat("[DATABASE] Loaded {0} objects using {1} prims", objects.Count, prims.Count);
402
403 return objects;
487 } 404 }
488 405
489 /// <summary>
490 /// Load in a prim's persisted inventory.
491 /// </summary>
492 /// <param name="prim">The prim</param>
493 private void LoadItems(SceneObjectPart prim) 406 private void LoadItems(SceneObjectPart prim)
494 { 407 {
495 lock (m_dataSet) 408 lock (m_Connection)
496 { 409 {
497 CheckConnection(); 410 MySqlCommand cmd = m_Connection.CreateCommand();
498 //m_log.InfoFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID);
499 411
500 DataTable dbItems = m_itemsTable; 412 cmd.CommandText = "select * from primitems where "+
413 "PrimID = ?PrimID";
501 414
502 String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); 415 cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString());
503 DataRow[] dbItemRows = dbItems.Select(sql);
504 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
505 416
506 foreach (DataRow row in dbItemRows) 417 IDataReader reader = ExecuteReader(cmd);
418 List<TaskInventoryItem> inventory =
419 new List<TaskInventoryItem>();
420
421 try
507 { 422 {
508 TaskInventoryItem item = buildItem(row); 423 while (reader.Read())
509 inventory.Add(item); 424 {
425 TaskInventoryItem item = BuildItem(reader);
510 426
511 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); 427 item.ParentID = prim.UUID; // Values in database are
428 // often wrong
429 inventory.Add(item);
430 }
512 } 431 }
513 432 finally
514 prim.Inventory.RestoreInventoryItems(inventory);
515
516 // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in
517 // every item). This data should really be stored in the prim table itself.
518 if (dbItemRows.Length > 0)
519 { 433 {
520 prim.FolderID = inventory[0].ParentID; 434 reader.Close();
521 } 435 }
436
437 prim.Inventory.RestoreInventoryItems(inventory);
522 } 438 }
523 } 439 }
524 440
525 /// <summary>
526 /// Store a terrain revision in region storage
527 /// </summary>
528 /// <param name="ter">HeightField data</param>
529 /// <param name="regionID">region UUID</param>
530 public void StoreTerrain(double[,] ter, UUID regionID) 441 public void StoreTerrain(double[,] ter, UUID regionID)
531 { 442 {
532 int revision = 1; 443 m_log.Info("[REGION DB]: Storing terrain");
533 m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString());
534 444
535 lock (m_dataSet) 445 lock (m_Connection)
536 { 446 {
537 MySqlCommand delete = new MySqlCommand("delete from terrain where RegionUUID=?RegionUUID", m_connection); 447 MySqlCommand cmd = m_Connection.CreateCommand();
538 MySqlCommand cmd = new MySqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" +
539 " values(?RegionUUID, ?Revision, ?Heightfield)", m_connection);
540 using (cmd)
541 {
542 delete.Parameters.Add(new MySqlParameter("?RegionUUID", Util.ToRawUuidString(regionID)));
543 448
544 CheckConnection(); 449 cmd.CommandText = "delete from terrain where " +
545 delete.ExecuteNonQuery(); 450 "RegionUUID = ?RegionUUID";
451 cmd.Parameters.AddWithValue("RegionUUID",
452 Util.ToRawUuidString(regionID));
546 453
547 cmd.Parameters.Add(new MySqlParameter("?RegionUUID", Util.ToRawUuidString(regionID))); 454 ExecuteNonQuery(cmd);
548 cmd.Parameters.Add(new MySqlParameter("?Revision", revision)); 455
549 cmd.Parameters.Add(new MySqlParameter("?Heightfield", serializeTerrain(ter))); 456 cmd.CommandText = "insert into terrain (RegionUUID, " +
550 cmd.ExecuteNonQuery(); 457 "Revision, Heightfield) values (?RegionUUID, " +
551 } 458 "1, ?Heightfield)";
459
460 cmd.Parameters.AddWithValue("Heightfield",
461 SerializeTerrain(ter));
462
463 ExecuteNonQuery(cmd);
552 } 464 }
553 } 465 }
554 466
555 /// <summary>
556 /// Load the latest terrain revision from region storage
557 /// </summary>
558 /// <param name="regionID">the region UUID</param>
559 /// <returns>Heightfield data</returns>
560 public double[,] LoadTerrain(UUID regionID) 467 public double[,] LoadTerrain(UUID regionID)
561 { 468 {
562 double[,] terret = new double[256,256]; 469 double[,] terrain = new double[256,256];
563 terret.Initialize(); 470 terrain.Initialize();
564 471
565 MySqlCommand cmd = new MySqlCommand( 472 lock (m_Connection)
566 @"select RegionUUID, Revision, Heightfield from terrain
567 where RegionUUID=?RegionUUID order by Revision desc limit 1"
568 , m_connection);
569
570 // MySqlParameter param = new MySqlParameter();
571 cmd.Parameters.Add(new MySqlParameter("?RegionUUID", Util.ToRawUuidString(regionID)));
572
573 if (m_connection.State != ConnectionState.Open)
574 { 473 {
575 m_connection.Open(); 474 MySqlCommand cmd = m_Connection.CreateCommand();
576 } 475 cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
476 "from terrain where RegionUUID = ?RegionUUID "+
477 "order by Revision desc limit 1";
478 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
479
480 IDataReader reader = ExecuteReader(cmd);
577 481
578 lock (m_dataSet)
579 {
580 CheckConnection();
581 MySqlDataReader row = cmd.ExecuteReader();
582 try 482 try
583 { 483 {
584 int rev = 0; 484 while (reader.Read())
585 if (row.Read())
586 { 485 {
587 MemoryStream str = new MemoryStream((byte[]) row["Heightfield"]); 486 MemoryStream mstr = new MemoryStream((byte[]) reader["Heightfield"]);
588 BinaryReader br = new BinaryReader(str); 487 int rev = 0;
488
489 BinaryReader br = new BinaryReader(mstr);
589 for (int x = 0; x < 256; x++) 490 for (int x = 0; x < 256; x++)
590 { 491 {
591 for (int y = 0; y < 256; y++) 492 for (int y = 0; y < 256; y++)
592 { 493 {
593 terret[x, y] = br.ReadDouble(); 494 terrain[x, y] = br.ReadDouble();
594 } 495 }
496 rev = Convert.ToInt32(reader["Revision"]);
595 } 497 }
596 rev = (int) row["Revision"]; 498 m_log.InfoFormat("[REGION DB]: Loaded terrain " +
597 } 499 "revision r{0}", rev);
598 else
599 {
600 m_log.Info("[REGION DB]: No terrain found for region");
601 return null;
602 }
603 500
604 m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); 501 return terrain;
502 }
605 } 503 }
606 finally 504 finally
607 { 505 {
608 row.Close(); 506 reader.Close();
609 } 507 }
610 } 508 }
611 return terret; 509
510 return terrain;
612 } 511 }
613 512
614 /// <summary>
615 /// <list type="bullet">
616 /// <item>delete from land where UUID=globalID</item>
617 /// <item>delete from landaccesslist where LandUUID=globalID</item>
618 /// </list>
619 /// </summary>
620 /// <param name="globalID"></param>
621 public void RemoveLandObject(UUID globalID) 513 public void RemoveLandObject(UUID globalID)
622 { 514 {
623 lock (m_dataSet) 515 lock (m_Connection)
624 { 516 {
625 CheckConnection(); 517 MySqlCommand cmd = m_Connection.CreateCommand();
626 using (MySqlCommand cmd = new MySqlCommand("delete from land where UUID=?UUID", m_connection))
627 {
628 cmd.Parameters.Add(new MySqlParameter("?UUID", Util.ToRawUuidString(globalID)));
629 cmd.ExecuteNonQuery();
630 }
631 518
632 using ( 519 cmd.CommandText = "delete from land where UUID = ?UUID";
633 MySqlCommand cmd = new MySqlCommand("delete from landaccesslist where LandUUID=?UUID", m_connection) 520
634 ) 521 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID));
635 { 522
636 cmd.Parameters.Add(new MySqlParameter("?UUID", Util.ToRawUuidString(globalID))); 523 ExecuteNonQuery(cmd);
637 cmd.ExecuteNonQuery();
638 }
639 } 524 }
640 } 525 }
641 526
642 /// <summary>
643 /// </summary>
644 /// <param name="parcel"></param>
645 public void StoreLandObject(ILandObject parcel) 527 public void StoreLandObject(ILandObject parcel)
646 { 528 {
647 lock (m_dataSet) 529 lock (m_Connection)
648 { 530 {
649 CheckConnection(); 531 MySqlCommand cmd = m_Connection.CreateCommand();
650 DataTable land = m_landTable; 532
651 DataTable landaccesslist = m_landAccessListTable; 533 cmd.CommandText = "replace into land (UUID, RegionUUID, " +
652 534 "LocalLandID, Bitmap, Name, Description, " +
653 DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.GlobalID)); 535 "OwnerUUID, IsGroupOwned, Area, AuctionID, " +
654 if (landRow == null) 536 "Category, ClaimDate, ClaimPrice, GroupUUID, " +
655 { 537 "SalePrice, LandStatus, LandFlags, LandingType, " +
656 landRow = land.NewRow(); 538 "MediaAutoScale, MediaTextureUUID, MediaURL, " +
657 fillLandRow(landRow, parcel.landData, parcel.regionUUID); 539 "MusicURL, PassHours, PassPrice, SnapshotUUID, " +
658 land.Rows.Add(landRow); 540 "UserLocationX, UserLocationY, UserLocationZ, " +
659 } 541 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
660 else 542 "AuthbuyerID, OtherCleanTime, Dwell) values (" +
661 { 543 "?UUID, ?RegionUUID, " +
662 fillLandRow(landRow, parcel.landData, parcel.regionUUID); 544 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
663 } 545 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
664 546 "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " +
665 using ( 547 "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " +
666 MySqlCommand cmd = 548 "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " +
667 new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) 549 "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
550 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
551 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
552 "?AuthbuyerID, ?OtherCleanTime, ?Dwell)";
553
554 FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
555
556 ExecuteNonQuery(cmd);
557
558 cmd.CommandText = "delete from landaccesslist where " +
559 "LandUUID = ?UUID";
560
561 ExecuteNonQuery(cmd);
562
563 cmd.Parameters.Clear();
564 cmd.CommandText = "insert into landaccesslist (LandUUID, " +
565 "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " +
566 "?Flags)";
567
568 foreach (ParcelManager.ParcelAccessEntry entry in
569 parcel.landData.ParcelAccessList)
668 { 570 {
669 cmd.Parameters.Add(new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.GlobalID))); 571 FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
670 cmd.ExecuteNonQuery(); 572 ExecuteNonQuery(cmd);
573 cmd.Parameters.Clear();
671 } 574 }
672
673 foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.ParcelAccessList)
674 {
675 DataRow newAccessRow = landaccesslist.NewRow();
676 fillLandAccessRow(newAccessRow, entry, parcel.landData.GlobalID);
677 landaccesslist.Rows.Add(newAccessRow);
678 }
679
680 Commit();
681 } 575 }
682 } 576 }
683 577
684 public RegionSettings LoadRegionSettings(UUID regionUUID) 578 public RegionSettings LoadRegionSettings(UUID regionUUID)
685 { 579 {
686 lock (m_dataSet) 580 RegionSettings rs = null;
687 {
688 CheckConnection();
689 DataTable regionsettings = m_regionSettingsTable;
690 string searchExp = "regionUUID = '" + regionUUID.ToString() + "'";
691 DataRow[] rawsettings = regionsettings.Select(searchExp);
692 if (rawsettings.Length == 0)
693 {
694 RegionSettings rs = new RegionSettings();
695 rs.RegionUUID = regionUUID;
696 rs.OnSave += StoreRegionSettings;
697
698 StoreRegionSettings(rs);
699 581
700 return rs; 582 lock (m_Connection)
701 }
702 DataRow row = rawsettings[0];
703
704 RegionSettings newSettings = buildRegionSettings(row);
705 newSettings.OnSave += StoreRegionSettings;
706
707 return newSettings;
708 }
709 }
710
711 public void StoreRegionSettings(RegionSettings rs)
712 {
713 lock (m_dataSet)
714 { 583 {
715 CheckConnection(); 584 MySqlCommand cmd = m_Connection.CreateCommand();
716 DataTable regionsettings = m_dataSet.Tables["regionsettings"];
717 585
718 DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); 586 cmd.CommandText = "select * from regionsettings where " +
719 if (settingsRow == null) 587 "regionUUID = ?RegionUUID";
720 { 588 cmd.Parameters.AddWithValue("regionUUID", regionUUID);
721 settingsRow = regionsettings.NewRow();
722 fillRegionSettingsRow(settingsRow, rs);
723 regionsettings.Rows.Add(settingsRow);
724 }
725 else
726 {
727 fillRegionSettingsRow(settingsRow, rs);
728 }
729 589
730 Commit(); 590 IDataReader reader = ExecuteReader(cmd);
731 }
732 }
733 591
734 /// <summary> 592 try
735 ///
736 /// </summary>
737 /// <param name="regionUUID"></param>
738 /// <returns></returns>
739 public List<LandData> LoadLandObjects(UUID regionUUID)
740 {
741 List<LandData> landDataForRegion = new List<LandData>();
742 lock (m_dataSet)
743 {
744 CheckConnection();
745 DataTable land = m_landTable;
746 DataTable landaccesslist = m_landAccessListTable;
747 string searchExp = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'";
748 DataRow[] rawDataForRegion = land.Select(searchExp);
749 foreach (DataRow rawDataLand in rawDataForRegion)
750 { 593 {
751 LandData newLand = buildLandData(rawDataLand); 594 if (reader.Read())
752 string accessListSearchExp = "LandUUID = '" + Util.ToRawUuidString(newLand.GlobalID) + "'";
753 DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp);
754 foreach (DataRow rawDataLandAccess in rawDataForLandAccessList)
755 { 595 {
756 newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); 596 rs = BuildRegionSettings(reader);
597 rs.OnSave += StoreRegionSettings;
757 } 598 }
599 else
600 {
601 rs = new RegionSettings();
602 rs.RegionUUID = regionUUID;
603 rs.OnSave += StoreRegionSettings;
758 604
759 landDataForRegion.Add(newLand); 605 StoreRegionSettings(rs);
606 }
607 }
608 finally
609 {
610 reader.Close();
760 } 611 }
761 } 612 }
762 return landDataForRegion; 613
614 return rs;
763 } 615 }
764 616
765 /// <summary> 617 public void StoreRegionSettings(RegionSettings rs)
766 ///
767 /// </summary>
768 public void Commit()
769 { 618 {
770 lock (m_dataSet) 619 lock (m_Connection)
771 { 620 {
772 CheckConnection(); 621 MySqlCommand cmd = m_Connection.CreateCommand();
773 // DisplayDataSet(m_dataSet, "Region DataSet"); 622
774 623 cmd.CommandText = "replace into regionsettings (regionUUID, " +
775 m_primDataAdapter.Update(m_primTable); 624 "block_terraform, block_fly, allow_damage, " +
776 m_shapeDataAdapter.Update(m_shapeTable); 625 "restrict_pushing, allow_land_resell, " +
777 626 "allow_land_join_divide, block_show_in_search, " +
778 m_itemsDataAdapter.Update(m_itemsTable); 627 "agent_limit, object_bonus, maturity, " +
779 628 "disable_scripts, disable_collisions, " +
780 m_terrainDataAdapter.Update(m_terrainTable); 629 "disable_physics, terrain_texture_1, " +
781 m_landDataAdapter.Update(m_landTable); 630 "terrain_texture_2, terrain_texture_3, " +
782 m_landAccessListDataAdapter.Update(m_landAccessListTable); 631 "terrain_texture_4, elevation_1_nw, " +
783 m_regionSettingsDataAdapter.Update(m_regionSettingsTable); 632 "elevation_2_nw, elevation_1_ne, " +
784 633 "elevation_2_ne, elevation_1_se, "+
785 m_dataSet.AcceptChanges(); 634 "elevation_2_se, elevation_1_sw, "+
635 "elevation_2_sw, water_height, " +
636 "terrain_raise_limit, terrain_lower_limit, " +
637 "use_estate_sun, fixed_sun, sun_position, " +
638 "covenant, Sandbox, sunvectorx, sunvectory, " +
639 "sunvectorz) values ( ?RegionUUID, ?BlockTerraform, " +
640 "?BlockFly, ?AllowDamage, ?RestrictPushing, " +
641 "?AllowLandResell, ?AllowLandJoinDivide, " +
642 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " +
643 "?Maturity, ?DisableScripts, ?DisableCollisions, " +
644 "?DisablePhysics, ?TerrainTexture1, " +
645 "?TerrainTexture2, ?TerrainTexture3, " +
646 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " +
647 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " +
648 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " +
649 "?WaterHeight, ?TerrainRaiseLimit, " +
650 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " +
651 "?SunPosition, ?Covenant, ?Sandbox, " +
652 "?SunVectorX, ?SunVectorY, ?SunVectorZ)";
653
654 FillRegionSettingsCommand(cmd, rs);
655
656 ExecuteNonQuery(cmd);
786 } 657 }
787 } 658 }
788 659
789 /// <summary> 660 public List<LandData> LoadLandObjects(UUID regionUUID)
790 /// See <see cref="Commit"/>
791 /// </summary>
792 public void Shutdown()
793 {
794 Commit();
795 }
796
797 /***********************************************************************
798 *
799 * Database Definition Functions
800 *
801 * This should be db agnostic as we define them in ADO.NET terms
802 *
803 **********************************************************************/
804
805 /// <summary>
806 ///
807 /// </summary>
808 /// <param name="dt"></param>
809 /// <param name="name"></param>
810 /// <param name="type"></param>
811 /// <returns></returns>
812 private static DataColumn createCol(DataTable dt, string name, Type type)
813 {
814 DataColumn col = new DataColumn(name, type);
815 dt.Columns.Add(col);
816 return col;
817 }
818
819 /// <summary>
820 /// Create the "terrain" table
821 /// </summary>
822 /// <returns></returns>
823 private static DataTable createTerrainTable()
824 {
825 DataTable terrain = new DataTable("terrain");
826
827 createCol(terrain, "RegionUUID", typeof (String));
828 createCol(terrain, "Revision", typeof (Int32));
829 createCol(terrain, "Heightfield", typeof (Byte[]));
830 return terrain;
831 }
832
833 /// <summary>
834 /// Create the "regionsettings" table
835 /// </summary>
836 /// <returns></returns>
837 private static DataTable createRegionSettingsTable()
838 {
839 DataTable regionsettings = new DataTable("regionsettings");
840 createCol(regionsettings, "regionUUID", typeof(String));
841 createCol(regionsettings, "block_terraform", typeof (Int32));
842 createCol(regionsettings, "block_fly", typeof (Int32));
843 createCol(regionsettings, "allow_damage", typeof (Int32));
844 createCol(regionsettings, "restrict_pushing", typeof (Int32));
845 createCol(regionsettings, "allow_land_resell", typeof (Int32));
846 createCol(regionsettings, "allow_land_join_divide", typeof (Int32));
847 createCol(regionsettings, "block_show_in_search", typeof (Int32));
848 createCol(regionsettings, "agent_limit", typeof (Int32));
849 createCol(regionsettings, "object_bonus", typeof (Double));
850 createCol(regionsettings, "maturity", typeof (Int32));
851 createCol(regionsettings, "disable_scripts", typeof (Int32));
852 createCol(regionsettings, "disable_collisions", typeof (Int32));
853 createCol(regionsettings, "disable_physics", typeof (Int32));
854 createCol(regionsettings, "terrain_texture_1", typeof(String));
855 createCol(regionsettings, "terrain_texture_2", typeof(String));
856 createCol(regionsettings, "terrain_texture_3", typeof(String));
857 createCol(regionsettings, "terrain_texture_4", typeof(String));
858 createCol(regionsettings, "elevation_1_nw", typeof (Double));
859 createCol(regionsettings, "elevation_2_nw", typeof (Double));
860 createCol(regionsettings, "elevation_1_ne", typeof (Double));
861 createCol(regionsettings, "elevation_2_ne", typeof (Double));
862 createCol(regionsettings, "elevation_1_se", typeof (Double));
863 createCol(regionsettings, "elevation_2_se", typeof (Double));
864 createCol(regionsettings, "elevation_1_sw", typeof (Double));
865 createCol(regionsettings, "elevation_2_sw", typeof (Double));
866 createCol(regionsettings, "water_height", typeof (Double));
867 createCol(regionsettings, "terrain_raise_limit", typeof (Double));
868 createCol(regionsettings, "terrain_lower_limit", typeof (Double));
869 createCol(regionsettings, "use_estate_sun", typeof (Int32));
870 createCol(regionsettings, "sandbox", typeof (Int32));
871 createCol(regionsettings, "sunvectorx",typeof (Double));
872 createCol(regionsettings, "sunvectory",typeof (Double));
873 createCol(regionsettings, "sunvectorz",typeof (Double));
874 createCol(regionsettings, "fixed_sun", typeof (Int32));
875 createCol(regionsettings, "sun_position", typeof (Double));
876 createCol(regionsettings, "covenant", typeof(String));
877
878 regionsettings.PrimaryKey = new DataColumn[] {regionsettings.Columns["RegionUUID"]};
879
880 return regionsettings;
881 }
882
883 /// <summary>
884 /// Create the "prims" table
885 /// </summary>
886 /// <returns></returns>
887 private static DataTable createPrimTable()
888 { 661 {
889 DataTable prims = new DataTable("prims"); 662 List<LandData> landData = new List<LandData>();
890
891 createCol(prims, "UUID", typeof (String));
892 createCol(prims, "RegionUUID", typeof (String));
893 createCol(prims, "ParentID", typeof (Int32));
894 createCol(prims, "CreationDate", typeof (Int32));
895 createCol(prims, "Name", typeof (String));
896 createCol(prims, "SceneGroupID", typeof (String));
897 // various text fields
898 createCol(prims, "Text", typeof (String));
899 createCol(prims, "ColorR", typeof (Int32));
900 createCol(prims, "ColorG", typeof (Int32));
901 createCol(prims, "ColorB", typeof (Int32));
902 createCol(prims, "ColorA", typeof (Int32));
903 createCol(prims, "Description", typeof (String));
904 createCol(prims, "SitName", typeof (String));
905 createCol(prims, "TouchName", typeof (String));
906 // permissions
907 createCol(prims, "ObjectFlags", typeof (Int32));
908 createCol(prims, "CreatorID", typeof (String));
909 createCol(prims, "OwnerID", typeof (String));
910 createCol(prims, "GroupID", typeof (String));
911 createCol(prims, "LastOwnerID", typeof (String));
912 createCol(prims, "OwnerMask", typeof (Int32));
913 createCol(prims, "NextOwnerMask", typeof (Int32));
914 createCol(prims, "GroupMask", typeof (Int32));
915 createCol(prims, "EveryoneMask", typeof (Int32));
916 createCol(prims, "BaseMask", typeof (Int32));
917 // vectors
918 createCol(prims, "PositionX", typeof (Double));
919 createCol(prims, "PositionY", typeof (Double));
920 createCol(prims, "PositionZ", typeof (Double));
921 createCol(prims, "GroupPositionX", typeof (Double));
922 createCol(prims, "GroupPositionY", typeof (Double));
923 createCol(prims, "GroupPositionZ", typeof (Double));
924 createCol(prims, "VelocityX", typeof (Double));
925 createCol(prims, "VelocityY", typeof (Double));
926 createCol(prims, "VelocityZ", typeof (Double));
927 createCol(prims, "AngularVelocityX", typeof (Double));
928 createCol(prims, "AngularVelocityY", typeof (Double));
929 createCol(prims, "AngularVelocityZ", typeof (Double));
930 createCol(prims, "AccelerationX", typeof (Double));
931 createCol(prims, "AccelerationY", typeof (Double));
932 createCol(prims, "AccelerationZ", typeof (Double));
933 // quaternions
934 createCol(prims, "RotationX", typeof (Double));
935 createCol(prims, "RotationY", typeof (Double));
936 createCol(prims, "RotationZ", typeof (Double));
937 createCol(prims, "RotationW", typeof (Double));
938 // sit target
939 createCol(prims, "SitTargetOffsetX", typeof (Double));
940 createCol(prims, "SitTargetOffsetY", typeof (Double));
941 createCol(prims, "SitTargetOffsetZ", typeof (Double));
942
943 createCol(prims, "SitTargetOrientW", typeof (Double));
944 createCol(prims, "SitTargetOrientX", typeof (Double));
945 createCol(prims, "SitTargetOrientY", typeof (Double));
946 createCol(prims, "SitTargetOrientZ", typeof (Double));
947
948 createCol(prims, "PayPrice", typeof(Int32));
949 createCol(prims, "PayButton1", typeof(Int32));
950 createCol(prims, "PayButton2", typeof(Int32));
951 createCol(prims, "PayButton3", typeof(Int32));
952 createCol(prims, "PayButton4", typeof(Int32));
953
954 createCol(prims, "LoopedSound", typeof(String));
955 createCol(prims, "LoopedSoundGain", typeof(Double));
956 createCol(prims, "TextureAnimation", typeof(Byte[]));
957 createCol(prims, "ParticleSystem", typeof(Byte[]));
958
959 createCol(prims, "OmegaX", typeof (Double));
960 createCol(prims, "OmegaY", typeof (Double));
961 createCol(prims, "OmegaZ", typeof (Double));
962
963 createCol(prims, "CameraEyeOffsetX", typeof (Double));
964 createCol(prims, "CameraEyeOffsetY", typeof (Double));
965 createCol(prims, "CameraEyeOffsetZ", typeof (Double));
966 663
967 createCol(prims, "CameraAtOffsetX", typeof (Double)); 664 lock (m_Connection)
968 createCol(prims, "CameraAtOffsetY", typeof (Double)); 665 {
969 createCol(prims, "CameraAtOffsetZ", typeof (Double)); 666 MySqlCommand cmd = m_Connection.CreateCommand();
970
971 createCol(prims, "ForceMouselook", typeof (Int16));
972
973 createCol(prims, "ScriptAccessPin", typeof(Int32));
974
975 createCol(prims, "AllowedDrop", typeof (Int16));
976 createCol(prims, "DieAtEdge", typeof (Int16));
977
978 createCol(prims, "SalePrice", typeof(Int32));
979 createCol(prims, "SaleType", typeof (Int16));
980
981 createCol(prims, "ClickAction", typeof (Byte));
982 createCol(prims, "Material", typeof (Byte));
983 667
984 createCol(prims, "CollisionSound", typeof(String)); 668 cmd.CommandText = "select * from land where " +
985 createCol(prims, "CollisionSoundVolume", typeof(Double)); 669 "RegionUUID = ?RegionUUID";
986 670
987 // Add in contraints 671 cmd.Parameters.AddWithValue("RegionUUID",
988 prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; 672 Util.ToRawUuidString(regionUUID));
989 673
990 return prims; 674 IDataReader reader = ExecuteReader(cmd);
991 }
992 675
993 /// <summary> 676 try
994 /// Create the "land" table 677 {
995 /// </summary> 678 while (reader.Read())
996 /// <returns></returns> 679 {
997 private static DataTable createLandTable() 680 LandData newLand = BuildLandData(reader);
998 { 681 landData.Add(newLand);
999 DataTable land = new DataTable("land"); 682 }
1000 createCol(land, "UUID", typeof (String)); 683 }
1001 createCol(land, "RegionUUID", typeof (String)); 684 finally
1002 createCol(land, "LocalLandID", typeof (Int32)); 685 {
686 reader.Close();
687 }
1003 688
1004 // Bitmap is a byte[512] 689 foreach (LandData land in landData)
1005 createCol(land, "Bitmap", typeof (Byte[])); 690 {
1006 691 cmd.Parameters.Clear();
1007 createCol(land, "Name", typeof (String));
1008 createCol(land, "Description", typeof (String));
1009 createCol(land, "OwnerUUID", typeof (String));
1010 createCol(land, "IsGroupOwned", typeof (Int32));
1011 createCol(land, "Area", typeof (Int32));
1012 createCol(land, "AuctionID", typeof (Int32)); //Unemplemented
1013 createCol(land, "Category", typeof (Int32)); //Enum libsecondlife.Parcel.ParcelCategory
1014 createCol(land, "ClaimDate", typeof (Int32));
1015 createCol(land, "ClaimPrice", typeof (Int32));
1016 createCol(land, "GroupUUID", typeof (String));
1017 createCol(land, "SalePrice", typeof (Int32));
1018 createCol(land, "LandStatus", typeof (Int32)); //Enum. libsecondlife.Parcel.ParcelStatus
1019 createCol(land, "LandFlags", typeof (UInt32));
1020 createCol(land, "LandingType", typeof (Int32));
1021 createCol(land, "MediaAutoScale", typeof (Int32));
1022 createCol(land, "MediaTextureUUID", typeof (String));
1023 createCol(land, "MediaURL", typeof (String));
1024 createCol(land, "MusicURL", typeof (String));
1025 createCol(land, "PassHours", typeof (Double));
1026 createCol(land, "PassPrice", typeof (Int32));
1027 createCol(land, "SnapshotUUID", typeof (String));
1028 createCol(land, "UserLocationX", typeof (Double));
1029 createCol(land, "UserLocationY", typeof (Double));
1030 createCol(land, "UserLocationZ", typeof (Double));
1031 createCol(land, "UserLookAtX", typeof (Double));
1032 createCol(land, "UserLookAtY", typeof (Double));
1033 createCol(land, "UserLookAtZ", typeof (Double));
1034 createCol(land, "AuthBuyerID", typeof (String));
1035 createCol(land, "OtherCleanTime", typeof(Int32));
1036 createCol(land, "Dwell", typeof(Int32));
1037
1038 land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]};
1039
1040 return land;
1041 }
1042 692
1043 /// <summary> 693 cmd.CommandText = "select * from landaccesslist " +
1044 /// Create the "landaccesslist" table 694 "where LandUUID = ?LandUUID";
1045 /// </summary>
1046 /// <returns></returns>
1047 private static DataTable createLandAccessListTable()
1048 {
1049 DataTable landaccess = new DataTable("landaccesslist");
1050 createCol(landaccess, "LandUUID", typeof (String));
1051 createCol(landaccess, "AccessUUID", typeof (String));
1052 createCol(landaccess, "Flags", typeof (Int32));
1053 695
1054 return landaccess; 696 cmd.Parameters.AddWithValue("LandUUID",
1055 } 697 Util.ToRawUuidString(land.GlobalID));
1056 698
1057 /// <summary> 699 reader = ExecuteReader(cmd);
1058 /// Create the "primshapes" table
1059 /// </summary>
1060 /// <returns></returns>
1061 private static DataTable createShapeTable()
1062 {
1063 DataTable shapes = new DataTable("primshapes");
1064 createCol(shapes, "UUID", typeof (String));
1065 // shape is an enum
1066 createCol(shapes, "Shape", typeof (Int32));
1067 // vectors
1068 createCol(shapes, "ScaleX", typeof (Double));
1069 createCol(shapes, "ScaleY", typeof (Double));
1070 createCol(shapes, "ScaleZ", typeof (Double));
1071 // paths
1072 createCol(shapes, "PCode", typeof (Int32));
1073 createCol(shapes, "PathBegin", typeof (Int32));
1074 createCol(shapes, "PathEnd", typeof (Int32));
1075 createCol(shapes, "PathScaleX", typeof (Int32));
1076 createCol(shapes, "PathScaleY", typeof (Int32));
1077 createCol(shapes, "PathShearX", typeof (Int32));
1078 createCol(shapes, "PathShearY", typeof (Int32));
1079 createCol(shapes, "PathSkew", typeof (Int32));
1080 createCol(shapes, "PathCurve", typeof (Int32));
1081 createCol(shapes, "PathRadiusOffset", typeof (Int32));
1082 createCol(shapes, "PathRevolutions", typeof (Int32));
1083 createCol(shapes, "PathTaperX", typeof (Int32));
1084 createCol(shapes, "PathTaperY", typeof (Int32));
1085 createCol(shapes, "PathTwist", typeof (Int32));
1086 createCol(shapes, "PathTwistBegin", typeof (Int32));
1087 // profile
1088 createCol(shapes, "ProfileBegin", typeof (Int32));
1089 createCol(shapes, "ProfileEnd", typeof (Int32));
1090 createCol(shapes, "ProfileCurve", typeof (Int32));
1091 createCol(shapes, "ProfileHollow", typeof (Int32));
1092 createCol(shapes, "State", typeof(Int32));
1093 createCol(shapes, "Texture", typeof (Byte[]));
1094 createCol(shapes, "ExtraParams", typeof (Byte[]));
1095 700
1096 shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; 701 try
702 {
703 while (reader.Read())
704 {
705 land.ParcelAccessList.Add(BuildLandAccessData(reader));
706 }
707 }
708 finally
709 {
710 reader.Close();
711 }
712 }
713 }
1097 714
1098 return shapes; 715 return landData;
1099 } 716 }
1100 717
1101 /// <summary> 718 public void Shutdown()
1102 /// Create the "primitems" table
1103 /// </summary>
1104 /// <returns></returns>
1105 private static DataTable createItemsTable()
1106 { 719 {
1107 DataTable items = new DataTable("primitems");
1108
1109 createCol(items, "itemID", typeof (String));
1110 createCol(items, "primID", typeof (String));
1111 createCol(items, "assetID", typeof (String));
1112 createCol(items, "parentFolderID", typeof (String));
1113
1114 createCol(items, "invType", typeof (Int32));
1115 createCol(items, "assetType", typeof (Int32));
1116
1117 createCol(items, "name", typeof (String));
1118 createCol(items, "description", typeof (String));
1119
1120 createCol(items, "creationDate", typeof (Int64));
1121 createCol(items, "creatorID", typeof (String));
1122 createCol(items, "ownerID", typeof (String));
1123 createCol(items, "lastOwnerID", typeof (String));
1124 createCol(items, "groupID", typeof (String));
1125
1126 createCol(items, "nextPermissions", typeof (Int32));
1127 createCol(items, "currentPermissions", typeof (Int32));
1128 createCol(items, "basePermissions", typeof (Int32));
1129 createCol(items, "everyonePermissions", typeof (Int32));
1130 createCol(items, "groupPermissions", typeof (Int32));
1131 createCol(items, "flags", typeof (Int32));
1132
1133 items.PrimaryKey = new DataColumn[] {items.Columns["itemID"]};
1134
1135 return items;
1136 } 720 }
1137 721
1138 /*********************************************************************** 722 private SceneObjectPart BuildPrim(IDataReader row)
1139 *
1140 * Convert between ADO.NET <=> OpenSim Objects
1141 *
1142 * These should be database independant
1143 *
1144 **********************************************************************/
1145
1146 /// <summary>
1147 ///
1148 /// </summary>
1149 /// <param name="row"></param>
1150 /// <returns></returns>
1151 private SceneObjectPart buildPrim(DataRow row)
1152 { 723 {
1153 SceneObjectPart prim = new SceneObjectPart(); 724 SceneObjectPart prim = new SceneObjectPart();
1154 prim.UUID = new UUID((String) row["UUID"]); 725 prim.UUID = new UUID((String) row["UUID"]);
@@ -1232,9 +803,9 @@ namespace OpenSim.Data.MySQL
1232 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); 803 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1233 prim.SoundFlags = 1; // If it's persisted at all, it's looped 804 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1234 805
1235 if (!row.IsNull("TextureAnimation")) 806 if (!(row["TextureAnimation"] is DBNull))
1236 prim.TextureAnimation = (Byte[])row["TextureAnimation"]; 807 prim.TextureAnimation = (Byte[])row["TextureAnimation"];
1237 if (!row.IsNull("ParticleSystem")) 808 if (!(row["ParticleSystem"] is DBNull))
1238 prim.ParticleSystem = (Byte[])row["ParticleSystem"]; 809 prim.ParticleSystem = (Byte[])row["ParticleSystem"];
1239 810
1240 prim.RotationalVelocity = new Vector3( 811 prim.RotationalVelocity = new Vector3(
@@ -1271,11 +842,12 @@ namespace OpenSim.Data.MySQL
1271 842
1272 prim.Material = Convert.ToByte(row["Material"]); 843 prim.Material = Convert.ToByte(row["Material"]);
1273 844
1274 if (!row.IsNull("ClickAction")) 845 if (!(row["ClickAction"] is DBNull))
1275 prim.ClickAction = Convert.ToByte(row["ClickAction"]); 846 prim.ClickAction = (byte)Convert.ToByte(row["ClickAction"]);
1276 847
1277 prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); 848 prim.CollisionSound = new UUID(row["CollisionSound"].ToString());
1278 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); 849 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]);
850 prim.LinkNum = Convert.ToInt32(row["LinkNumber"]);
1279 851
1280 return prim; 852 return prim;
1281 } 853 }
@@ -1286,7 +858,7 @@ namespace OpenSim.Data.MySQL
1286 /// </summary> 858 /// </summary>
1287 /// <param name="row"></param> 859 /// <param name="row"></param>
1288 /// <returns></returns> 860 /// <returns></returns>
1289 private static TaskInventoryItem buildItem(DataRow row) 861 private static TaskInventoryItem BuildItem(IDataReader row)
1290 { 862 {
1291 TaskInventoryItem taskItem = new TaskInventoryItem(); 863 TaskInventoryItem taskItem = new TaskInventoryItem();
1292 864
@@ -1316,7 +888,7 @@ namespace OpenSim.Data.MySQL
1316 return taskItem; 888 return taskItem;
1317 } 889 }
1318 890
1319 private static RegionSettings buildRegionSettings(DataRow row) 891 private static RegionSettings BuildRegionSettings(IDataReader row)
1320 { 892 {
1321 RegionSettings newSettings = new RegionSettings(); 893 RegionSettings newSettings = new RegionSettings();
1322 894
@@ -1368,7 +940,7 @@ namespace OpenSim.Data.MySQL
1368 /// </summary> 940 /// </summary>
1369 /// <param name="row"></param> 941 /// <param name="row"></param>
1370 /// <returns></returns> 942 /// <returns></returns>
1371 private static LandData buildLandData(DataRow row) 943 private static LandData BuildLandData(IDataReader row)
1372 { 944 {
1373 LandData newData = new LandData(); 945 LandData newData = new LandData();
1374 946
@@ -1436,7 +1008,7 @@ namespace OpenSim.Data.MySQL
1436 /// </summary> 1008 /// </summary>
1437 /// <param name="row"></param> 1009 /// <param name="row"></param>
1438 /// <returns></returns> 1010 /// <returns></returns>
1439 private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) 1011 private static ParcelManager.ParcelAccessEntry BuildLandAccessData(IDataReader row)
1440 { 1012 {
1441 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 1013 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1442 entry.AgentID = new UUID((string) row["AccessUUID"]); 1014 entry.AgentID = new UUID((string) row["AccessUUID"]);
@@ -1450,7 +1022,7 @@ namespace OpenSim.Data.MySQL
1450 /// </summary> 1022 /// </summary>
1451 /// <param name="val"></param> 1023 /// <param name="val"></param>
1452 /// <returns></returns> 1024 /// <returns></returns>
1453 private static Array serializeTerrain(double[,] val) 1025 private static Array SerializeTerrain(double[,] val)
1454 { 1026 {
1455 MemoryStream str = new MemoryStream(65536*sizeof (double)); 1027 MemoryStream str = new MemoryStream(65536*sizeof (double));
1456 BinaryWriter bw = new BinaryWriter(str); 1028 BinaryWriter bw = new BinaryWriter(str);
@@ -1476,128 +1048,129 @@ namespace OpenSim.Data.MySQL
1476 /// <param name="prim"></param> 1048 /// <param name="prim"></param>
1477 /// <param name="sceneGroupID"></param> 1049 /// <param name="sceneGroupID"></param>
1478 /// <param name="regionUUID"></param> 1050 /// <param name="regionUUID"></param>
1479 private void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) 1051 private void FillPrimCommand(MySqlCommand cmd, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1480 { 1052 {
1481 row["UUID"] = Util.ToRawUuidString(prim.UUID); 1053 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(prim.UUID));
1482 row["RegionUUID"] = Util.ToRawUuidString(regionUUID); 1054 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionUUID));
1483 row["ParentID"] = prim.ParentID; 1055 cmd.Parameters.AddWithValue("ParentID", prim.ParentID);
1484 row["CreationDate"] = prim.CreationDate; 1056 cmd.Parameters.AddWithValue("CreationDate", prim.CreationDate);
1485 row["Name"] = prim.Name; 1057 cmd.Parameters.AddWithValue("Name", prim.Name);
1486 row["SceneGroupID"] = Util.ToRawUuidString(sceneGroupID); 1058 cmd.Parameters.AddWithValue("SceneGroupID", Util.ToRawUuidString(sceneGroupID));
1487 // the UUID of the root part for this SceneObjectGroup 1059 // the UUID of the root part for this SceneObjectGroup
1488 // various text fields 1060 // various text fields
1489 row["Text"] = prim.Text; 1061 cmd.Parameters.AddWithValue("Text", prim.Text);
1490 row["ColorR"] = prim.Color.R; 1062 cmd.Parameters.AddWithValue("ColorR", prim.Color.R);
1491 row["ColorG"] = prim.Color.G; 1063 cmd.Parameters.AddWithValue("ColorG", prim.Color.G);
1492 row["ColorB"] = prim.Color.B; 1064 cmd.Parameters.AddWithValue("ColorB", prim.Color.B);
1493 row["ColorA"] = prim.Color.A; 1065 cmd.Parameters.AddWithValue("ColorA", prim.Color.A);
1494 row["Description"] = prim.Description; 1066 cmd.Parameters.AddWithValue("Description", prim.Description);
1495 row["SitName"] = prim.SitName; 1067 cmd.Parameters.AddWithValue("SitName", prim.SitName);
1496 row["TouchName"] = prim.TouchName; 1068 cmd.Parameters.AddWithValue("TouchName", prim.TouchName);
1497 // permissions 1069 // permissions
1498 row["ObjectFlags"] = prim.ObjectFlags; 1070 cmd.Parameters.AddWithValue("ObjectFlags", prim.ObjectFlags);
1499 row["CreatorID"] = Util.ToRawUuidString(prim.CreatorID); 1071 cmd.Parameters.AddWithValue("CreatorID", Util.ToRawUuidString(prim.CreatorID));
1500 row["OwnerID"] = Util.ToRawUuidString(prim.OwnerID); 1072 cmd.Parameters.AddWithValue("OwnerID", Util.ToRawUuidString(prim.OwnerID));
1501 row["GroupID"] = Util.ToRawUuidString(prim.GroupID); 1073 cmd.Parameters.AddWithValue("GroupID", Util.ToRawUuidString(prim.GroupID));
1502 row["LastOwnerID"] = Util.ToRawUuidString(prim.LastOwnerID); 1074 cmd.Parameters.AddWithValue("LastOwnerID", Util.ToRawUuidString(prim.LastOwnerID));
1503 row["OwnerMask"] = prim.OwnerMask; 1075 cmd.Parameters.AddWithValue("OwnerMask", prim.OwnerMask);
1504 row["NextOwnerMask"] = prim.NextOwnerMask; 1076 cmd.Parameters.AddWithValue("NextOwnerMask", prim.NextOwnerMask);
1505 row["GroupMask"] = prim.GroupMask; 1077 cmd.Parameters.AddWithValue("GroupMask", prim.GroupMask);
1506 row["EveryoneMask"] = prim.EveryoneMask; 1078 cmd.Parameters.AddWithValue("EveryoneMask", prim.EveryoneMask);
1507 row["BaseMask"] = prim.BaseMask; 1079 cmd.Parameters.AddWithValue("BaseMask", prim.BaseMask);
1508 // vectors 1080 // vectors
1509 row["PositionX"] = prim.OffsetPosition.X; 1081 cmd.Parameters.AddWithValue("PositionX", prim.OffsetPosition.X);
1510 row["PositionY"] = prim.OffsetPosition.Y; 1082 cmd.Parameters.AddWithValue("PositionY", prim.OffsetPosition.Y);
1511 row["PositionZ"] = prim.OffsetPosition.Z; 1083 cmd.Parameters.AddWithValue("PositionZ", prim.OffsetPosition.Z);
1512 row["GroupPositionX"] = prim.GroupPosition.X; 1084 cmd.Parameters.AddWithValue("GroupPositionX", prim.GroupPosition.X);
1513 row["GroupPositionY"] = prim.GroupPosition.Y; 1085 cmd.Parameters.AddWithValue("GroupPositionY", prim.GroupPosition.Y);
1514 row["GroupPositionZ"] = prim.GroupPosition.Z; 1086 cmd.Parameters.AddWithValue("GroupPositionZ", prim.GroupPosition.Z);
1515 row["VelocityX"] = prim.Velocity.X; 1087 cmd.Parameters.AddWithValue("VelocityX", prim.Velocity.X);
1516 row["VelocityY"] = prim.Velocity.Y; 1088 cmd.Parameters.AddWithValue("VelocityY", prim.Velocity.Y);
1517 row["VelocityZ"] = prim.Velocity.Z; 1089 cmd.Parameters.AddWithValue("VelocityZ", prim.Velocity.Z);
1518 row["AngularVelocityX"] = prim.AngularVelocity.X; 1090 cmd.Parameters.AddWithValue("AngularVelocityX", prim.AngularVelocity.X);
1519 row["AngularVelocityY"] = prim.AngularVelocity.Y; 1091 cmd.Parameters.AddWithValue("AngularVelocityY", prim.AngularVelocity.Y);
1520 row["AngularVelocityZ"] = prim.AngularVelocity.Z; 1092 cmd.Parameters.AddWithValue("AngularVelocityZ", prim.AngularVelocity.Z);
1521 row["AccelerationX"] = prim.Acceleration.X; 1093 cmd.Parameters.AddWithValue("AccelerationX", prim.Acceleration.X);
1522 row["AccelerationY"] = prim.Acceleration.Y; 1094 cmd.Parameters.AddWithValue("AccelerationY", prim.Acceleration.Y);
1523 row["AccelerationZ"] = prim.Acceleration.Z; 1095 cmd.Parameters.AddWithValue("AccelerationZ", prim.Acceleration.Z);
1524 // quaternions 1096 // quaternions
1525 row["RotationX"] = prim.RotationOffset.X; 1097 cmd.Parameters.AddWithValue("RotationX", prim.RotationOffset.X);
1526 row["RotationY"] = prim.RotationOffset.Y; 1098 cmd.Parameters.AddWithValue("RotationY", prim.RotationOffset.Y);
1527 row["RotationZ"] = prim.RotationOffset.Z; 1099 cmd.Parameters.AddWithValue("RotationZ", prim.RotationOffset.Z);
1528 row["RotationW"] = prim.RotationOffset.W; 1100 cmd.Parameters.AddWithValue("RotationW", prim.RotationOffset.W);
1529 1101
1530 // Sit target 1102 // Sit target
1531 Vector3 sitTargetPos = prim.SitTargetPositionLL; 1103 Vector3 sitTargetPos = prim.SitTargetPositionLL;
1532 row["SitTargetOffsetX"] = sitTargetPos.X; 1104 cmd.Parameters.AddWithValue("SitTargetOffsetX", sitTargetPos.X);
1533 row["SitTargetOffsetY"] = sitTargetPos.Y; 1105 cmd.Parameters.AddWithValue("SitTargetOffsetY", sitTargetPos.Y);
1534 row["SitTargetOffsetZ"] = sitTargetPos.Z; 1106 cmd.Parameters.AddWithValue("SitTargetOffsetZ", sitTargetPos.Z);
1535 1107
1536 Quaternion sitTargetOrient = prim.SitTargetOrientationLL; 1108 Quaternion sitTargetOrient = prim.SitTargetOrientationLL;
1537 row["SitTargetOrientW"] = sitTargetOrient.W; 1109 cmd.Parameters.AddWithValue("SitTargetOrientW", sitTargetOrient.W);
1538 row["SitTargetOrientX"] = sitTargetOrient.X; 1110 cmd.Parameters.AddWithValue("SitTargetOrientX", sitTargetOrient.X);
1539 row["SitTargetOrientY"] = sitTargetOrient.Y; 1111 cmd.Parameters.AddWithValue("SitTargetOrientY", sitTargetOrient.Y);
1540 row["SitTargetOrientZ"] = sitTargetOrient.Z; 1112 cmd.Parameters.AddWithValue("SitTargetOrientZ", sitTargetOrient.Z);
1541 1113
1542 row["PayPrice"] = prim.PayPrice[0]; 1114 cmd.Parameters.AddWithValue("PayPrice", prim.PayPrice[0]);
1543 row["PayButton1"] = prim.PayPrice[1]; 1115 cmd.Parameters.AddWithValue("PayButton1", prim.PayPrice[1]);
1544 row["PayButton2"] = prim.PayPrice[2]; 1116 cmd.Parameters.AddWithValue("PayButton2", prim.PayPrice[2]);
1545 row["PayButton3"] = prim.PayPrice[3]; 1117 cmd.Parameters.AddWithValue("PayButton3", prim.PayPrice[3]);
1546 row["PayButton4"] = prim.PayPrice[4]; 1118 cmd.Parameters.AddWithValue("PayButton4", prim.PayPrice[4]);
1547 1119
1548 if ((prim.SoundFlags & 1) != 0) // Looped 1120 if ((prim.SoundFlags & 1) != 0) // Looped
1549 { 1121 {
1550 row["LoopedSound"] = prim.Sound.ToString(); 1122 cmd.Parameters.AddWithValue("LoopedSound", prim.Sound.ToString());
1551 row["LoopedSoundGain"] = prim.SoundGain; 1123 cmd.Parameters.AddWithValue("LoopedSoundGain", prim.SoundGain);
1552 } 1124 }
1553 else 1125 else
1554 { 1126 {
1555 row["LoopedSound"] = UUID.Zero; 1127 cmd.Parameters.AddWithValue("LoopedSound", UUID.Zero);
1556 row["LoopedSoundGain"] = 0.0f; 1128 cmd.Parameters.AddWithValue("LoopedSoundGain", 0.0f);
1557 } 1129 }
1558 1130
1559 row["TextureAnimation"] = prim.TextureAnimation; 1131 cmd.Parameters.AddWithValue("TextureAnimation", prim.TextureAnimation);
1560 row["ParticleSystem"] = prim.ParticleSystem; 1132 cmd.Parameters.AddWithValue("ParticleSystem", prim.ParticleSystem);
1561 1133
1562 row["OmegaX"] = prim.RotationalVelocity.X; 1134 cmd.Parameters.AddWithValue("OmegaX", prim.RotationalVelocity.X);
1563 row["OmegaY"] = prim.RotationalVelocity.Y; 1135 cmd.Parameters.AddWithValue("OmegaY", prim.RotationalVelocity.Y);
1564 row["OmegaZ"] = prim.RotationalVelocity.Z; 1136 cmd.Parameters.AddWithValue("OmegaZ", prim.RotationalVelocity.Z);
1565 1137
1566 row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; 1138 cmd.Parameters.AddWithValue("CameraEyeOffsetX", prim.GetCameraEyeOffset().X);
1567 row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; 1139 cmd.Parameters.AddWithValue("CameraEyeOffsetY", prim.GetCameraEyeOffset().Y);
1568 row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; 1140 cmd.Parameters.AddWithValue("CameraEyeOffsetZ", prim.GetCameraEyeOffset().Z);
1569 1141
1570 row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; 1142 cmd.Parameters.AddWithValue("CameraAtOffsetX", prim.GetCameraAtOffset().X);
1571 row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; 1143 cmd.Parameters.AddWithValue("CameraAtOffsetY", prim.GetCameraAtOffset().Y);
1572 row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; 1144 cmd.Parameters.AddWithValue("CameraAtOffsetZ", prim.GetCameraAtOffset().Z);
1573 1145
1574 if (prim.GetForceMouselook()) 1146 if (prim.GetForceMouselook())
1575 row["ForceMouselook"] = 1; 1147 cmd.Parameters.AddWithValue("ForceMouselook", 1);
1576 else 1148 else
1577 row["ForceMouselook"] = 0; 1149 cmd.Parameters.AddWithValue("ForceMouselook", 0);
1578 1150
1579 row["ScriptAccessPin"] = prim.ScriptAccessPin; 1151 cmd.Parameters.AddWithValue("ScriptAccessPin", prim.ScriptAccessPin);
1580 1152
1581 if (prim.AllowedDrop) 1153 if (prim.AllowedDrop)
1582 row["AllowedDrop"] = 1; 1154 cmd.Parameters.AddWithValue("AllowedDrop", 1);
1583 else 1155 else
1584 row["AllowedDrop"] = 0; 1156 cmd.Parameters.AddWithValue("AllowedDrop", 0);
1585 1157
1586 if (prim.DIE_AT_EDGE) 1158 if (prim.DIE_AT_EDGE)
1587 row["DieAtEdge"] = 1; 1159 cmd.Parameters.AddWithValue("DieAtEdge", 1);
1588 else 1160 else
1589 row["DieAtEdge"] = 0; 1161 cmd.Parameters.AddWithValue("DieAtEdge", 0);
1590 1162
1591 row["SalePrice"] = prim.SalePrice; 1163 cmd.Parameters.AddWithValue("SalePrice", prim.SalePrice);
1592 row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); 1164 cmd.Parameters.AddWithValue("SaleType", Convert.ToInt16(prim.ObjectSaleType));
1593 1165
1594 byte clickAction = prim.ClickAction; 1166 byte clickAction = prim.ClickAction;
1595 row["ClickAction"] = clickAction; 1167 cmd.Parameters.AddWithValue("ClickAction", clickAction);
1596 1168
1597 row["Material"] = prim.Material; 1169 cmd.Parameters.AddWithValue("Material", prim.Material);
1598 1170
1599 row["CollisionSound"] = prim.CollisionSound.ToString(); 1171 cmd.Parameters.AddWithValue("CollisionSound", prim.CollisionSound.ToString());
1600 row["CollisionSoundVolume"] = prim.CollisionSoundVolume; 1172 cmd.Parameters.AddWithValue("CollisionSoundVolume", prim.CollisionSoundVolume);
1173 cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
1601 } 1174 }
1602 1175
1603 /// <summary> 1176 /// <summary>
@@ -1605,73 +1178,73 @@ namespace OpenSim.Data.MySQL
1605 /// </summary> 1178 /// </summary>
1606 /// <param name="row"></param> 1179 /// <param name="row"></param>
1607 /// <param name="taskItem"></param> 1180 /// <param name="taskItem"></param>
1608 private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) 1181 private static void FillItemCommand(MySqlCommand cmd, TaskInventoryItem taskItem)
1609 { 1182 {
1610 row["itemID"] = taskItem.ItemID; 1183 cmd.Parameters.AddWithValue("itemID", taskItem.ItemID);
1611 row["primID"] = taskItem.ParentPartID; 1184 cmd.Parameters.AddWithValue("primID", taskItem.ParentPartID);
1612 row["assetID"] = taskItem.AssetID; 1185 cmd.Parameters.AddWithValue("assetID", taskItem.AssetID);
1613 row["parentFolderID"] = taskItem.ParentID; 1186 cmd.Parameters.AddWithValue("parentFolderID", taskItem.ParentID);
1614 1187
1615 row["invType"] = taskItem.InvType; 1188 cmd.Parameters.AddWithValue("invType", taskItem.InvType);
1616 row["assetType"] = taskItem.Type; 1189 cmd.Parameters.AddWithValue("assetType", taskItem.Type);
1617 1190
1618 row["name"] = taskItem.Name; 1191 cmd.Parameters.AddWithValue("name", taskItem.Name);
1619 row["description"] = taskItem.Description; 1192 cmd.Parameters.AddWithValue("description", taskItem.Description);
1620 row["creationDate"] = taskItem.CreationDate; 1193 cmd.Parameters.AddWithValue("creationDate", taskItem.CreationDate);
1621 row["creatorID"] = taskItem.CreatorID; 1194 cmd.Parameters.AddWithValue("creatorID", taskItem.CreatorID);
1622 row["ownerID"] = taskItem.OwnerID; 1195 cmd.Parameters.AddWithValue("ownerID", taskItem.OwnerID);
1623 row["lastOwnerID"] = taskItem.LastOwnerID; 1196 cmd.Parameters.AddWithValue("lastOwnerID", taskItem.LastOwnerID);
1624 row["groupID"] = taskItem.GroupID; 1197 cmd.Parameters.AddWithValue("groupID", taskItem.GroupID);
1625 row["nextPermissions"] = taskItem.NextPermissions; 1198 cmd.Parameters.AddWithValue("nextPermissions", taskItem.NextPermissions);
1626 row["currentPermissions"] = taskItem.CurrentPermissions; 1199 cmd.Parameters.AddWithValue("currentPermissions", taskItem.CurrentPermissions);
1627 row["basePermissions"] = taskItem.BasePermissions; 1200 cmd.Parameters.AddWithValue("basePermissions", taskItem.BasePermissions);
1628 row["everyonePermissions"] = taskItem.EveryonePermissions; 1201 cmd.Parameters.AddWithValue("everyonePermissions", taskItem.EveryonePermissions);
1629 row["groupPermissions"] = taskItem.GroupPermissions; 1202 cmd.Parameters.AddWithValue("groupPermissions", taskItem.GroupPermissions);
1630 row["flags"] = taskItem.Flags; 1203 cmd.Parameters.AddWithValue("flags", taskItem.Flags);
1631 } 1204 }
1632 1205
1633 /// <summary> 1206 /// <summary>
1634 /// 1207 ///
1635 /// </summary> 1208 /// </summary>
1636 private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) 1209 private static void FillRegionSettingsCommand(MySqlCommand cmd, RegionSettings settings)
1637 { 1210 {
1638 row["regionUUID"] = settings.RegionUUID.ToString(); 1211 cmd.Parameters.AddWithValue("RegionUUID", settings.RegionUUID.ToString());
1639 row["block_terraform"] = settings.BlockTerraform; 1212 cmd.Parameters.AddWithValue("BlockTerraform", settings.BlockTerraform);
1640 row["block_fly"] = settings.BlockFly; 1213 cmd.Parameters.AddWithValue("BlockFly", settings.BlockFly);
1641 row["allow_damage"] = settings.AllowDamage; 1214 cmd.Parameters.AddWithValue("AllowDamage", settings.AllowDamage);
1642 row["restrict_pushing"] = settings.RestrictPushing; 1215 cmd.Parameters.AddWithValue("RestrictPushing", settings.RestrictPushing);
1643 row["allow_land_resell"] = settings.AllowLandResell; 1216 cmd.Parameters.AddWithValue("AllowLandResell", settings.AllowLandResell);
1644 row["allow_land_join_divide"] = settings.AllowLandJoinDivide; 1217 cmd.Parameters.AddWithValue("AllowLandJoinDivide", settings.AllowLandJoinDivide);
1645 row["block_show_in_search"] = settings.BlockShowInSearch; 1218 cmd.Parameters.AddWithValue("BlockShowInSearch", settings.BlockShowInSearch);
1646 row["agent_limit"] = settings.AgentLimit; 1219 cmd.Parameters.AddWithValue("AgentLimit", settings.AgentLimit);
1647 row["object_bonus"] = settings.ObjectBonus; 1220 cmd.Parameters.AddWithValue("ObjectBonus", settings.ObjectBonus);
1648 row["maturity"] = settings.Maturity; 1221 cmd.Parameters.AddWithValue("Maturity", settings.Maturity);
1649 row["disable_scripts"] = settings.DisableScripts; 1222 cmd.Parameters.AddWithValue("DisableScripts", settings.DisableScripts);
1650 row["disable_collisions"] = settings.DisableCollisions; 1223 cmd.Parameters.AddWithValue("DisableCollisions", settings.DisableCollisions);
1651 row["disable_physics"] = settings.DisablePhysics; 1224 cmd.Parameters.AddWithValue("DisablePhysics", settings.DisablePhysics);
1652 row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); 1225 cmd.Parameters.AddWithValue("TerrainTexture1", settings.TerrainTexture1.ToString());
1653 row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); 1226 cmd.Parameters.AddWithValue("TerrainTexture2", settings.TerrainTexture2.ToString());
1654 row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); 1227 cmd.Parameters.AddWithValue("TerrainTexture3", settings.TerrainTexture3.ToString());
1655 row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); 1228 cmd.Parameters.AddWithValue("TerrainTexture4", settings.TerrainTexture4.ToString());
1656 row["elevation_1_nw"] = settings.Elevation1NW; 1229 cmd.Parameters.AddWithValue("Elevation1NW", settings.Elevation1NW);
1657 row["elevation_2_nw"] = settings.Elevation2NW; 1230 cmd.Parameters.AddWithValue("Elevation2NW", settings.Elevation2NW);
1658 row["elevation_1_ne"] = settings.Elevation1NE; 1231 cmd.Parameters.AddWithValue("Elevation1NE", settings.Elevation1NE);
1659 row["elevation_2_ne"] = settings.Elevation2NE; 1232 cmd.Parameters.AddWithValue("Elevation2NE", settings.Elevation2NE);
1660 row["elevation_1_se"] = settings.Elevation1SE; 1233 cmd.Parameters.AddWithValue("Elevation1SE", settings.Elevation1SE);
1661 row["elevation_2_se"] = settings.Elevation2SE; 1234 cmd.Parameters.AddWithValue("Elevation2SE", settings.Elevation2SE);
1662 row["elevation_1_sw"] = settings.Elevation1SW; 1235 cmd.Parameters.AddWithValue("Elevation1SW", settings.Elevation1SW);
1663 row["elevation_2_sw"] = settings.Elevation2SW; 1236 cmd.Parameters.AddWithValue("Elevation2SW", settings.Elevation2SW);
1664 row["water_height"] = settings.WaterHeight; 1237 cmd.Parameters.AddWithValue("WaterHeight", settings.WaterHeight);
1665 row["terrain_raise_limit"] = settings.TerrainRaiseLimit; 1238 cmd.Parameters.AddWithValue("TerrainRaiseLimit", settings.TerrainRaiseLimit);
1666 row["terrain_lower_limit"] = settings.TerrainLowerLimit; 1239 cmd.Parameters.AddWithValue("TerrainLowerLimit", settings.TerrainLowerLimit);
1667 row["use_estate_sun"] = settings.UseEstateSun; 1240 cmd.Parameters.AddWithValue("UseEstateSun", settings.UseEstateSun);
1668 row["sandbox"] = settings.Sandbox; 1241 cmd.Parameters.AddWithValue("Sandbox", settings.Sandbox);
1669 row["sunvectorx"] = settings.SunVector.X; 1242 cmd.Parameters.AddWithValue("SunVectorX", settings.SunVector.X);
1670 row["sunvectory"] = settings.SunVector.Y; 1243 cmd.Parameters.AddWithValue("SunVectorY", settings.SunVector.Y);
1671 row["sunvectorz"] = settings.SunVector.Z; 1244 cmd.Parameters.AddWithValue("SunVectorZ", settings.SunVector.Z);
1672 row["fixed_sun"] = settings.FixedSun; 1245 cmd.Parameters.AddWithValue("FixedSun", settings.FixedSun);
1673 row["sun_position"] = settings.SunPosition; 1246 cmd.Parameters.AddWithValue("SunPosition", settings.SunPosition);
1674 row["covenant"] = settings.Covenant.ToString(); 1247 cmd.Parameters.AddWithValue("Covenant", settings.Covenant.ToString());
1675 } 1248 }
1676 1249
1677 /// <summary> 1250 /// <summary>
@@ -1680,45 +1253,45 @@ namespace OpenSim.Data.MySQL
1680 /// <param name="row"></param> 1253 /// <param name="row"></param>
1681 /// <param name="land"></param> 1254 /// <param name="land"></param>
1682 /// <param name="regionUUID"></param> 1255 /// <param name="regionUUID"></param>
1683 private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) 1256 private static void FillLandCommand(MySqlCommand cmd, LandData land, UUID regionUUID)
1684 { 1257 {
1685 row["UUID"] = Util.ToRawUuidString(land.GlobalID); 1258 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(land.GlobalID));
1686 row["RegionUUID"] = Util.ToRawUuidString(regionUUID); 1259 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionUUID));
1687 row["LocalLandID"] = land.LocalID; 1260 cmd.Parameters.AddWithValue("LocalLandID", land.LocalID);
1688 1261
1689 // Bitmap is a byte[512] 1262 // Bitmap is a byte[512]
1690 row["Bitmap"] = land.Bitmap; 1263 cmd.Parameters.AddWithValue("Bitmap", land.Bitmap);
1691 1264
1692 row["Name"] = land.Name; 1265 cmd.Parameters.AddWithValue("Name", land.Name);
1693 row["Description"] = land.Description; 1266 cmd.Parameters.AddWithValue("Description", land.Description);
1694 row["OwnerUUID"] = Util.ToRawUuidString(land.OwnerID); 1267 cmd.Parameters.AddWithValue("OwnerUUID", Util.ToRawUuidString(land.OwnerID));
1695 row["IsGroupOwned"] = land.IsGroupOwned; 1268 cmd.Parameters.AddWithValue("IsGroupOwned", land.IsGroupOwned);
1696 row["Area"] = land.Area; 1269 cmd.Parameters.AddWithValue("Area", land.Area);
1697 row["AuctionID"] = land.AuctionID; //Unemplemented 1270 cmd.Parameters.AddWithValue("AuctionID", land.AuctionID); //Unemplemented
1698 row["Category"] = land.Category; //Enum libsecondlife.Parcel.ParcelCategory 1271 cmd.Parameters.AddWithValue("Category", land.Category); //Enum libsecondlife.Parcel.ParcelCategory
1699 row["ClaimDate"] = land.ClaimDate; 1272 cmd.Parameters.AddWithValue("ClaimDate", land.ClaimDate);
1700 row["ClaimPrice"] = land.ClaimPrice; 1273 cmd.Parameters.AddWithValue("ClaimPrice", land.ClaimPrice);
1701 row["GroupUUID"] = Util.ToRawUuidString(land.GroupID); 1274 cmd.Parameters.AddWithValue("GroupUUID", Util.ToRawUuidString(land.GroupID));
1702 row["SalePrice"] = land.SalePrice; 1275 cmd.Parameters.AddWithValue("SalePrice", land.SalePrice);
1703 row["LandStatus"] = land.Status; //Enum. libsecondlife.Parcel.ParcelStatus 1276 cmd.Parameters.AddWithValue("LandStatus", land.Status); //Enum. libsecondlife.Parcel.ParcelStatus
1704 row["LandFlags"] = land.Flags; 1277 cmd.Parameters.AddWithValue("LandFlags", land.Flags);
1705 row["LandingType"] = land.LandingType; 1278 cmd.Parameters.AddWithValue("LandingType", land.LandingType);
1706 row["MediaAutoScale"] = land.MediaAutoScale; 1279 cmd.Parameters.AddWithValue("MediaAutoScale", land.MediaAutoScale);
1707 row["MediaTextureUUID"] = Util.ToRawUuidString(land.MediaID); 1280 cmd.Parameters.AddWithValue("MediaTextureUUID", Util.ToRawUuidString(land.MediaID));
1708 row["MediaURL"] = land.MediaURL; 1281 cmd.Parameters.AddWithValue("MediaURL", land.MediaURL);
1709 row["MusicURL"] = land.MusicURL; 1282 cmd.Parameters.AddWithValue("MusicURL", land.MusicURL);
1710 row["PassHours"] = land.PassHours; 1283 cmd.Parameters.AddWithValue("PassHours", land.PassHours);
1711 row["PassPrice"] = land.PassPrice; 1284 cmd.Parameters.AddWithValue("PassPrice", land.PassPrice);
1712 row["SnapshotUUID"] = Util.ToRawUuidString(land.SnapshotID); 1285 cmd.Parameters.AddWithValue("SnapshotUUID", Util.ToRawUuidString(land.SnapshotID));
1713 row["UserLocationX"] = land.UserLocation.X; 1286 cmd.Parameters.AddWithValue("UserLocationX", land.UserLocation.X);
1714 row["UserLocationY"] = land.UserLocation.Y; 1287 cmd.Parameters.AddWithValue("UserLocationY", land.UserLocation.Y);
1715 row["UserLocationZ"] = land.UserLocation.Z; 1288 cmd.Parameters.AddWithValue("UserLocationZ", land.UserLocation.Z);
1716 row["UserLookAtX"] = land.UserLookAt.X; 1289 cmd.Parameters.AddWithValue("UserLookAtX", land.UserLookAt.X);
1717 row["UserLookAtY"] = land.UserLookAt.Y; 1290 cmd.Parameters.AddWithValue("UserLookAtY", land.UserLookAt.Y);
1718 row["UserLookAtZ"] = land.UserLookAt.Z; 1291 cmd.Parameters.AddWithValue("UserLookAtZ", land.UserLookAt.Z);
1719 row["AuthBuyerID"] = land.AuthBuyerID; 1292 cmd.Parameters.AddWithValue("AuthBuyerID", land.AuthBuyerID);
1720 row["OtherCleanTime"] = land.OtherCleanTime; 1293 cmd.Parameters.AddWithValue("OtherCleanTime", land.OtherCleanTime);
1721 row["Dwell"] = land.Dwell; 1294 cmd.Parameters.AddWithValue("Dwell", land.Dwell);
1722 } 1295 }
1723 1296
1724 /// <summary> 1297 /// <summary>
@@ -1727,11 +1300,11 @@ namespace OpenSim.Data.MySQL
1727 /// <param name="row"></param> 1300 /// <param name="row"></param>
1728 /// <param name="entry"></param> 1301 /// <param name="entry"></param>
1729 /// <param name="parcelID"></param> 1302 /// <param name="parcelID"></param>
1730 private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) 1303 private static void FillLandAccessCommand(MySqlCommand cmd, ParcelManager.ParcelAccessEntry entry, UUID parcelID)
1731 { 1304 {
1732 row["LandUUID"] = Util.ToRawUuidString(parcelID); 1305 cmd.Parameters.AddWithValue("LandUUID", Util.ToRawUuidString(parcelID));
1733 row["AccessUUID"] = Util.ToRawUuidString(entry.AgentID); 1306 cmd.Parameters.AddWithValue("AccessUUID", Util.ToRawUuidString(entry.AgentID));
1734 row["Flags"] = entry.Flags; 1307 cmd.Parameters.AddWithValue("Flags", entry.Flags);
1735 } 1308 }
1736 1309
1737 /// <summary> 1310 /// <summary>
@@ -1739,7 +1312,7 @@ namespace OpenSim.Data.MySQL
1739 /// </summary> 1312 /// </summary>
1740 /// <param name="row"></param> 1313 /// <param name="row"></param>
1741 /// <returns></returns> 1314 /// <returns></returns>
1742 private PrimitiveBaseShape buildShape(DataRow row) 1315 private PrimitiveBaseShape BuildShape(IDataReader row)
1743 { 1316 {
1744 PrimitiveBaseShape s = new PrimitiveBaseShape(); 1317 PrimitiveBaseShape s = new PrimitiveBaseShape();
1745 s.Scale = new Vector3( 1318 s.Scale = new Vector3(
@@ -1768,8 +1341,7 @@ namespace OpenSim.Data.MySQL
1768 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); 1341 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
1769 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); 1342 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
1770 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); 1343 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
1771 1344byte[] textureEntry = (byte[]) row["Texture"];
1772 byte[] textureEntry = (byte[]) row["Texture"];
1773 s.TextureEntry = textureEntry; 1345 s.TextureEntry = textureEntry;
1774 1346
1775 s.ExtraParams = (byte[]) row["ExtraParams"]; 1347 s.ExtraParams = (byte[]) row["ExtraParams"];
@@ -1784,382 +1356,78 @@ namespace OpenSim.Data.MySQL
1784 /// </summary> 1356 /// </summary>
1785 /// <param name="row"></param> 1357 /// <param name="row"></param>
1786 /// <param name="prim"></param> 1358 /// <param name="prim"></param>
1787 private void fillShapeRow(DataRow row, SceneObjectPart prim) 1359 private void FillShapeCommand(MySqlCommand cmd, SceneObjectPart prim)
1788 { 1360 {
1789 PrimitiveBaseShape s = prim.Shape; 1361 PrimitiveBaseShape s = prim.Shape;
1790 row["UUID"] = Util.ToRawUuidString(prim.UUID); 1362 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(prim.UUID));
1791 // shape is an enum 1363 // shape is an enum
1792 row["Shape"] = 0; 1364 cmd.Parameters.AddWithValue("Shape", 0);
1793 // vectors 1365 // vectors
1794 row["ScaleX"] = s.Scale.X; 1366 cmd.Parameters.AddWithValue("ScaleX", s.Scale.X);
1795 row["ScaleY"] = s.Scale.Y; 1367 cmd.Parameters.AddWithValue("ScaleY", s.Scale.Y);
1796 row["ScaleZ"] = s.Scale.Z; 1368 cmd.Parameters.AddWithValue("ScaleZ", s.Scale.Z);
1797 // paths 1369 // paths
1798 row["PCode"] = s.PCode; 1370 cmd.Parameters.AddWithValue("PCode", s.PCode);
1799 row["PathBegin"] = s.PathBegin; 1371 cmd.Parameters.AddWithValue("PathBegin", s.PathBegin);
1800 row["PathEnd"] = s.PathEnd; 1372 cmd.Parameters.AddWithValue("PathEnd", s.PathEnd);
1801 row["PathScaleX"] = s.PathScaleX; 1373 cmd.Parameters.AddWithValue("PathScaleX", s.PathScaleX);
1802 row["PathScaleY"] = s.PathScaleY; 1374 cmd.Parameters.AddWithValue("PathScaleY", s.PathScaleY);
1803 row["PathShearX"] = s.PathShearX; 1375 cmd.Parameters.AddWithValue("PathShearX", s.PathShearX);
1804 row["PathShearY"] = s.PathShearY; 1376 cmd.Parameters.AddWithValue("PathShearY", s.PathShearY);
1805 row["PathSkew"] = s.PathSkew; 1377 cmd.Parameters.AddWithValue("PathSkew", s.PathSkew);
1806 row["PathCurve"] = s.PathCurve; 1378 cmd.Parameters.AddWithValue("PathCurve", s.PathCurve);
1807 row["PathRadiusOffset"] = s.PathRadiusOffset; 1379 cmd.Parameters.AddWithValue("PathRadiusOffset", s.PathRadiusOffset);
1808 row["PathRevolutions"] = s.PathRevolutions; 1380 cmd.Parameters.AddWithValue("PathRevolutions", s.PathRevolutions);
1809 row["PathTaperX"] = s.PathTaperX; 1381 cmd.Parameters.AddWithValue("PathTaperX", s.PathTaperX);
1810 row["PathTaperY"] = s.PathTaperY; 1382 cmd.Parameters.AddWithValue("PathTaperY", s.PathTaperY);
1811 row["PathTwist"] = s.PathTwist; 1383 cmd.Parameters.AddWithValue("PathTwist", s.PathTwist);
1812 row["PathTwistBegin"] = s.PathTwistBegin; 1384 cmd.Parameters.AddWithValue("PathTwistBegin", s.PathTwistBegin);
1813 // profile 1385 // profile
1814 row["ProfileBegin"] = s.ProfileBegin; 1386 cmd.Parameters.AddWithValue("ProfileBegin", s.ProfileBegin);
1815 row["ProfileEnd"] = s.ProfileEnd; 1387 cmd.Parameters.AddWithValue("ProfileEnd", s.ProfileEnd);
1816 row["ProfileCurve"] = s.ProfileCurve; 1388 cmd.Parameters.AddWithValue("ProfileCurve", s.ProfileCurve);
1817 row["ProfileHollow"] = s.ProfileHollow; 1389 cmd.Parameters.AddWithValue("ProfileHollow", s.ProfileHollow);
1818 row["Texture"] = s.TextureEntry; 1390 cmd.Parameters.AddWithValue("Texture", s.TextureEntry);
1819 row["ExtraParams"] = s.ExtraParams; 1391 cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams);
1820 row["State"] = s.State; 1392 cmd.Parameters.AddWithValue("State", s.State);
1821 } 1393 }
1822 1394
1823 /// <summary>
1824 ///
1825 /// </summary>
1826 /// <param name="prim"></param>
1827 /// <param name="sceneGroupID"></param>
1828 /// <param name="regionUUID"></param>
1829 private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1830 {
1831 lock (m_dataSet)
1832 {
1833 DataTable prims = m_dataSet.Tables["prims"];
1834 DataTable shapes = m_dataSet.Tables["primshapes"];
1835
1836 DataRow primRow = prims.Rows.Find(Util.ToRawUuidString(prim.UUID));
1837 if (primRow == null)
1838 {
1839 primRow = prims.NewRow();
1840 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1841 prims.Rows.Add(primRow);
1842 }
1843 else
1844 {
1845 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1846 }
1847
1848 DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID));
1849 if (shapeRow == null)
1850 {
1851 shapeRow = shapes.NewRow();
1852 fillShapeRow(shapeRow, prim);
1853 shapes.Rows.Add(shapeRow);
1854 }
1855 else
1856 {
1857 fillShapeRow(shapeRow, prim);
1858 }
1859 }
1860 }
1861
1862 /// <summary>
1863 /// see IRegionDatastore
1864 /// </summary>
1865 /// <param name="primID"></param>
1866 /// <param name="items"></param>
1867 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1395 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1868 { 1396 {
1869 //m_log.InfoFormat("[REGION DB]: Persisting Prim Inventory with prim ID {0}", primID); 1397 lock (m_Connection)
1870
1871 // For now, we're just going to crudely remove all the previous inventory items
1872 // no matter whether they have changed or not, and replace them with the current set.
1873 lock (m_dataSet)
1874 { 1398 {
1875 RemoveItems(primID); 1399 RemoveItems(primID);
1876 1400
1877 // repalce with current inventory details 1401 MySqlCommand cmd = m_Connection.CreateCommand();
1878 foreach (TaskInventoryItem newItem in items) 1402
1403 if (items.Count == 0)
1404 return;
1405
1406 cmd.CommandText = "insert into primitems ("+
1407 "invType, assetType, name, "+
1408 "description, creationDate, nextPermissions, "+
1409 "currentPermissions, basePermissions, "+
1410 "everyonePermissions, groupPermissions, "+
1411 "flags, itemID, primID, assetID, "+
1412 "parentFolderID, creatorID, ownerID, "+
1413 "groupID, lastOwnerID) values (?invType, "+
1414 "?assetType, ?name, ?description, "+
1415 "?creationDate, ?nextPermissions, "+
1416 "?currentPermissions, ?basePermissions, "+
1417 "?everyonePermissions, ?groupPermissions, "+
1418 "?flags, ?itemID, ?primID, ?assetID, "+
1419 "?parentFolderID, ?creatorID, ?ownerID, "+
1420 "?groupID, ?lastOwnerID)";
1421
1422 foreach (TaskInventoryItem item in items)
1879 { 1423 {
1880// m_log.InfoFormat( 1424 cmd.Parameters.Clear();
1881// "[REGION DB]: " +
1882// "Adding item {0}, {1} to prim ID {2}",
1883// newItem.Name, newItem.ItemID, newItem.ParentPartID);
1884
1885 DataRow newItemRow = m_itemsTable.NewRow();
1886 fillItemRow(newItemRow, newItem);
1887 m_itemsTable.Rows.Add(newItemRow);
1888 }
1889 }
1890
1891 Commit();
1892 }
1893
1894 /***********************************************************************
1895 *
1896 * SQL Statement Creation Functions
1897 *
1898 * These functions create SQL statements for update, insert, and create.
1899 * They can probably be factored later to have a db independant
1900 * portion and a db specific portion
1901 *
1902 **********************************************************************/
1903
1904 /// <summary>
1905 /// Create a MySQL insert command
1906 /// </summary>
1907 /// <param name="table"></param>
1908 /// <param name="dt"></param>
1909 /// <returns></returns>
1910 /// <remarks>
1911 /// This is subtle enough to deserve some commentary.
1912 /// Instead of doing *lots* and *lots of hardcoded strings
1913 /// for database definitions we'll use the fact that
1914 /// realistically all insert statements look like "insert
1915 /// into A(b, c) values(:b, :c) on the parameterized query
1916 /// front. If we just have a list of b, c, etc... we can
1917 /// generate these strings instead of typing them out.
1918 /// </remarks>
1919 private static MySqlCommand createInsertCommand(string table, DataTable dt)
1920 {
1921 1425
1922 string[] cols = new string[dt.Columns.Count]; 1426 FillItemCommand(cmd, item);
1923 for (int i = 0; i < dt.Columns.Count; i++)
1924 {
1925 DataColumn col = dt.Columns[i];
1926 cols[i] = col.ColumnName;
1927 }
1928 1427
1929 string sql = "insert into " + table + "("; 1428 ExecuteNonQuery(cmd);
1930 sql += String.Join(", ", cols);
1931 // important, the first ':' needs to be here, the rest get added in the join
1932 sql += ") values (?";
1933 sql += String.Join(", ?", cols);
1934 sql += ")";
1935 MySqlCommand cmd = new MySqlCommand(sql);
1936
1937 // this provides the binding for all our parameters, so
1938 // much less code than it used to be
1939 foreach (DataColumn col in dt.Columns)
1940 {
1941 cmd.Parameters.Add(createMySqlParameter(col.ColumnName, col.DataType));
1942 }
1943 return cmd;
1944 }
1945
1946 /// <summary>
1947 /// Create a MySQL update command
1948 /// </summary>
1949 /// <param name="table"></param>
1950 /// <param name="pk"></param>
1951 /// <param name="dt"></param>
1952 /// <returns></returns>
1953 private static MySqlCommand createUpdateCommand(string table, string pk, DataTable dt)
1954 {
1955 string sql = "update " + table + " set ";
1956 string subsql = String.Empty;
1957 foreach (DataColumn col in dt.Columns)
1958 {
1959 if (subsql.Length > 0)
1960 {
1961 // a map function would rock so much here
1962 subsql += ", ";
1963 } 1429 }
1964 subsql += col.ColumnName + "=?" + col.ColumnName;
1965 }
1966 sql += subsql;
1967 sql += " where " + pk;
1968 MySqlCommand cmd = new MySqlCommand(sql);
1969
1970 // this provides the binding for all our parameters, so
1971 // much less code than it used to be
1972
1973 foreach (DataColumn col in dt.Columns)
1974 {
1975 cmd.Parameters.Add(createMySqlParameter(col.ColumnName, col.DataType));
1976 }
1977 return cmd;
1978 }
1979
1980 /***********************************************************************
1981 *
1982 * Database Binding functions
1983 *
1984 * These will be db specific due to typing, and minor differences
1985 * in databases.
1986 *
1987 **********************************************************************/
1988
1989 ///<summary>
1990 /// <para>This is a convenience function that collapses 5 repetitive
1991 /// lines for defining MySqlParameters to 2 parameters:
1992 /// column name and database type.
1993 /// </para>
1994 /// <para>
1995 /// It assumes certain conventions like ?param as the param
1996 /// name to replace in parametrized queries, and that source
1997 /// version is always current version, both of which are fine
1998 /// for us.
1999 /// </para>
2000 /// </summary>
2001 /// <returns>a built MySql parameter</returns>
2002 private static MySqlParameter createMySqlParameter(string name, Type type)
2003 {
2004 MySqlParameter param = new MySqlParameter();
2005 param.ParameterName = "?" + name;
2006 param.DbType = dbtypeFromType(type);
2007 param.SourceColumn = name;
2008 param.SourceVersion = DataRowVersion.Current;
2009 return param;
2010 }
2011
2012 /// <summary>
2013 ///
2014 /// </summary>
2015 /// <param name="da"></param>
2016 /// <param name="conn"></param>
2017 private void SetupPrimCommands(MySqlDataAdapter da, MySqlConnection conn)
2018 {
2019 MySqlCommand insertCommand = createInsertCommand("prims", m_primTable);
2020 insertCommand.Connection = conn;
2021 da.InsertCommand = insertCommand;
2022
2023 MySqlCommand updateCommand = createUpdateCommand("prims", "UUID=?UUID", m_primTable);
2024 updateCommand.Connection = conn;
2025 da.UpdateCommand = updateCommand;
2026
2027 MySqlCommand delete = new MySqlCommand("delete from prims where UUID=?UUID");
2028 delete.Parameters.Add(createMySqlParameter("UUID", typeof (String)));
2029 delete.Connection = conn;
2030 da.DeleteCommand = delete;
2031 }
2032
2033 /// <summary>
2034 ///
2035 /// </summary>
2036 /// <param name="da"></param>
2037 /// <param name="conn"></param>
2038 private void SetupItemsCommands(MySqlDataAdapter da, MySqlConnection conn)
2039 {
2040 da.InsertCommand = createInsertCommand("primitems", m_itemsTable);
2041 da.InsertCommand.Connection = conn;
2042
2043 da.UpdateCommand = createUpdateCommand("primitems", "itemID = ?itemID", m_itemsTable);
2044 da.UpdateCommand.Connection = conn;
2045
2046 MySqlCommand delete = new MySqlCommand("delete from primitems where itemID = ?itemID");
2047 delete.Parameters.Add(createMySqlParameter("itemID", typeof (String)));
2048 delete.Connection = conn;
2049 da.DeleteCommand = delete;
2050 }
2051
2052 private void SetupRegionSettingsCommands(MySqlDataAdapter da, MySqlConnection conn)
2053 {
2054 da.InsertCommand = createInsertCommand("regionsettings", m_regionSettingsTable);
2055 da.InsertCommand.Connection = conn;
2056
2057 da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID = ?regionUUID", m_regionSettingsTable);
2058 da.UpdateCommand.Connection = conn;
2059
2060 MySqlCommand delete = new MySqlCommand("delete from regionsettings where regionUUID = ?regionUUID");
2061 delete.Parameters.Add(createMySqlParameter("regionUUID", typeof(String)));
2062 delete.Connection = conn;
2063 da.DeleteCommand = delete;
2064 }
2065
2066 /// <summary>
2067 ///
2068 /// </summary>
2069 /// <param name="da"></param>
2070 /// <param name="conn"></param>
2071 private void SetupTerrainCommands(MySqlDataAdapter da, MySqlConnection conn)
2072 {
2073 da.InsertCommand = createInsertCommand("terrain", m_dataSet.Tables["terrain"]);
2074 da.InsertCommand.Connection = conn;
2075 }
2076
2077 /// <summary>
2078 ///
2079 /// </summary>
2080 /// <param name="da"></param>
2081 /// <param name="conn"></param>
2082 private void setupLandCommands(MySqlDataAdapter da, MySqlConnection conn)
2083 {
2084 da.InsertCommand = createInsertCommand("land", m_dataSet.Tables["land"]);
2085 da.InsertCommand.Connection = conn;
2086
2087 da.UpdateCommand = createUpdateCommand("land", "UUID=?UUID", m_dataSet.Tables["land"]);
2088 da.UpdateCommand.Connection = conn;
2089 }
2090
2091 /// <summary>
2092 ///
2093 /// </summary>
2094 /// <param name="da"></param>
2095 /// <param name="conn"></param>
2096 private void setupLandAccessCommands(MySqlDataAdapter da, MySqlConnection conn)
2097 {
2098 da.InsertCommand = createInsertCommand("landaccesslist", m_dataSet.Tables["landaccesslist"]);
2099 da.InsertCommand.Connection = conn;
2100 }
2101
2102 /// <summary>
2103 ///
2104 /// </summary>
2105 /// <param name="da"></param>
2106 /// <param name="conn"></param>
2107 private void SetupShapeCommands(MySqlDataAdapter da, MySqlConnection conn)
2108 {
2109 da.InsertCommand = createInsertCommand("primshapes", m_dataSet.Tables["primshapes"]);
2110 da.InsertCommand.Connection = conn;
2111
2112 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=?UUID", m_dataSet.Tables["primshapes"]);
2113 da.UpdateCommand.Connection = conn;
2114
2115 MySqlCommand delete = new MySqlCommand("delete from primshapes where UUID = ?UUID");
2116 delete.Parameters.Add(createMySqlParameter("UUID", typeof (String)));
2117 delete.Connection = conn;
2118 da.DeleteCommand = delete;
2119 }
2120
2121 /***********************************************************************
2122 *
2123 * Type conversion functions
2124 *
2125 **********************************************************************/
2126
2127 /// <summary>
2128 /// Type conversion functions
2129 /// </summary>
2130 /// <param name="type"></param>
2131 /// <returns></returns>
2132 private static DbType dbtypeFromType(Type type)
2133 {
2134 if (type == typeof (String))
2135 {
2136 return DbType.String;
2137 }
2138 else if (type == typeof (Int32))
2139 {
2140 return DbType.Int32;
2141 }
2142 else if (type == typeof (Double))
2143 {
2144 return DbType.Double;
2145 }
2146 else if (type == typeof (Byte))
2147 {
2148 return DbType.Byte;
2149 }
2150 else if (type == typeof (Double))
2151 {
2152 return DbType.Double;
2153 }
2154 else if (type == typeof (Byte[]))
2155 {
2156 return DbType.Binary;
2157 }
2158 else
2159 {
2160 return DbType.String;
2161 } 1430 }
2162 } 1431 }
2163
2164 } 1432 }
2165} 1433}
diff --git a/OpenSim/Data/MySQL/Resources/023_RegionStore.sql b/OpenSim/Data/MySQL/Resources/023_RegionStore.sql
new file mode 100644
index 0000000..559591f
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/023_RegionStore.sql
@@ -0,0 +1,6 @@
1BEGIN;
2
3ALTER TABLE prims ADD COLUMN LinkNumber integer not null default 0;
4
5COMMIT;
6
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 1443e74..43d28e7 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -329,6 +329,7 @@ namespace OpenSim.Framework
329 { 329 {
330 _itemID = UUID.Random(); 330 _itemID = UUID.Random();
331 _parentPartID = partID; 331 _parentPartID = partID;
332 _parentID = partID;
332 } 333 }
333 334
334 public TaskInventoryItem() 335 public TaskInventoryItem()
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 9839126..7bdcb5c 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -1336,6 +1336,8 @@ namespace OpenSim.Region.Environment.Scenes
1336 1336
1337 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1337 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1338 1338
1339 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1340
1339 if (userExposed) 1341 if (userExposed)
1340 dupe.m_rootPart.TrimPermissions(); 1342 dupe.m_rootPart.TrimPermissions();
1341 1343
@@ -1368,16 +1370,25 @@ namespace OpenSim.Region.Environment.Scenes
1368 } 1370 }
1369 1371
1370 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.Values); 1372 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.Values);
1373 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1374 {
1375 return p1.LinkNum.CompareTo(p2.LinkNum);
1376 }
1377 );
1378
1371 foreach (SceneObjectPart part in partList) 1379 foreach (SceneObjectPart part in partList)
1372 { 1380 {
1373 if (part.UUID != m_rootPart.UUID) 1381 if (part.UUID != m_rootPart.UUID)
1374 { 1382 {
1375 dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1383 SceneObjectPart newPart =
1384 dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1385
1386 newPart.LinkNum = part.LinkNum;
1376 1387
1377 if (userExposed) 1388 if (userExposed)
1378 { 1389 {
1379 SetPartOwner(part, cAgentID, cGroupID); 1390 SetPartOwner(newPart, cAgentID, cGroupID);
1380 part.ScheduleFullUpdate(); 1391 newPart.ScheduleFullUpdate();
1381 } 1392 }
1382 } 1393 }
1383 } 1394 }
@@ -1507,7 +1518,7 @@ namespace OpenSim.Region.Environment.Scenes
1507 /// <param name="part"></param> 1518 /// <param name="part"></param>
1508 /// <param name="cAgentID"></param> 1519 /// <param name="cAgentID"></param>
1509 /// <param name="cGroupID"></param> 1520 /// <param name="cGroupID"></param>
1510 public void CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1521 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1511 { 1522 {
1512 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1523 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1513 newPart.SetParent(this); 1524 newPart.SetParent(this);
@@ -1519,6 +1530,7 @@ namespace OpenSim.Region.Environment.Scenes
1519 1530
1520 SetPartAsNonRoot(newPart); 1531 SetPartAsNonRoot(newPart);
1521 1532
1533 return newPart;
1522 } 1534 }
1523 1535
1524 /// <summary> 1536 /// <summary>
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index e97b99f..5b494d3 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -1263,10 +1263,18 @@ if (m_shape != null) {
1263 dupe._category = _category; 1263 dupe._category = _category;
1264 dupe.m_rezzed = m_rezzed; 1264 dupe.m_rezzed = m_rezzed;
1265 1265
1266 dupe.m_inventory.Items = (TaskInventoryDictionary)dupe.m_inventory.Items.Clone(); 1266 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1267 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1267 1268
1268 if (userExposed) 1269 if (userExposed)
1270 {
1269 dupe.ResetIDs(linkNum); 1271 dupe.ResetIDs(linkNum);
1272 dupe.m_inventory.HasInventoryChanged = true;
1273 }
1274 else
1275 {
1276 dupe.m_inventory.HasInventoryChanged = m_inventory.HasInventoryChanged;
1277 }
1270 1278
1271 // Move afterwards ResetIDs as it clears the localID 1279 // Move afterwards ResetIDs as it clears the localID
1272 dupe.LocalId = localID; 1280 dupe.LocalId = localID;
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs
index ae43c5e..3f94a7e 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.Environment.Scenes
64 /// <summary> 64 /// <summary>
65 /// Tracks whether inventory has changed since the last persistent backup 65 /// Tracks whether inventory has changed since the last persistent backup
66 /// </summary> 66 /// </summary>
67 protected bool HasInventoryChanged; 67 internal bool HasInventoryChanged;
68 68
69 /// <value> 69 /// <value>
70 /// Inventory serial number 70 /// Inventory serial number
@@ -81,7 +81,11 @@ namespace OpenSim.Region.Environment.Scenes
81 protected internal TaskInventoryDictionary Items 81 protected internal TaskInventoryDictionary Items
82 { 82 {
83 get { return m_items; } 83 get { return m_items; }
84 set { m_items = value; } 84 set
85 {
86 m_items = value;
87 m_inventorySerial++;
88 }
85 } 89 }
86 90
87 /// <summary> 91 /// <summary>