aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie Thielker2008-11-30 05:20:19 +0000
committerMelanie Thielker2008-11-30 05:20:19 +0000
commit38380def178150d66a307702bcc4484f21934bba (patch)
tree38316acc87b60205916a4fabe19162ef91cc254e
parentRevert r7548 and r7549 until someone with prebuild-fu can help structure the ... (diff)
downloadopensim-SC-38380def178150d66a307702bcc4484f21934bba.zip
opensim-SC-38380def178150d66a307702bcc4484f21934bba.tar.gz
opensim-SC-38380def178150d66a307702bcc4484f21934bba.tar.bz2
opensim-SC-38380def178150d66a307702bcc4484f21934bba.tar.xz
More changes to the MySQL adapter. take advantage of pooling and run lock-free.
This should finally kill the "There is already an open data reader associated with this connection, which must be closed first" error that makes people's builds not save
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs979
1 files changed, 472 insertions, 507 deletions
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 33e005b..3fb0a8a 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -72,69 +72,10 @@ namespace OpenSim.Data.MySQL
72 cmd.CommandText = "delete from prims, primshapes using prims " + 72 cmd.CommandText = "delete from prims, primshapes using prims " +
73 "left join primshapes on prims.uuid = primshapes.uuid " + 73 "left join primshapes on prims.uuid = primshapes.uuid " +
74 "where PCode = 9 and State <> 0"; 74 "where PCode = 9 and State <> 0";
75 ExecuteNonQuery(cmd); 75 cmd.ExecuteNonQuery();
76 cmd.Dispose(); 76 cmd.Dispose();
77 }
78
79 private IDataReader ExecuteReader(MySqlCommand c)
80 {
81 IDataReader r = null;
82 bool errorSeen = false;
83
84 while (true)
85 {
86 try
87 {
88 r = c.ExecuteReader();
89 }
90 catch (MySqlException)
91 {
92 System.Threading.Thread.Sleep(500);
93
94 m_Connection.Close();
95 m_Connection.Open();
96
97 if (!errorSeen)
98 {
99 errorSeen = true;
100 continue;
101 }
102 throw;
103 }
104
105 break;
106 }
107
108 return r;
109 }
110
111 private void ExecuteNonQuery(MySqlCommand c)
112 {
113 bool errorSeen = false;
114
115 while (true)
116 {
117 try
118 {
119 c.ExecuteNonQuery();
120 }
121 catch (MySqlException)
122 {
123 System.Threading.Thread.Sleep(500);
124
125 m_Connection.Close();
126 m_Connection.Open();
127 77
128 if (!errorSeen) 78 m_Connection.Close();
129 {
130 errorSeen = true;
131 continue;
132 }
133 throw;
134 }
135
136 break;
137 }
138 } 79 }
139 80
140 public void Dispose() {} 81 public void Dispose() {}
@@ -150,115 +91,116 @@ namespace OpenSim.Data.MySQL
150 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) 91 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
151 return; 92 return;
152 93
153 lock (m_Connection) 94 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
95 c.Open();
96
97 MySqlCommand cmd = c.CreateCommand();
98
99 foreach (SceneObjectPart prim in obj.Children.Values)
154 { 100 {
155 MySqlCommand cmd = m_Connection.CreateCommand(); 101 cmd.Parameters.Clear();
156 102
157 foreach (SceneObjectPart prim in obj.Children.Values) 103 cmd.CommandText = "replace into prims ("+
158 { 104 "UUID, ParentID, CreationDate, "+
159 cmd.Parameters.Clear(); 105 "Name, Text, Description, "+
160 106 "SitName, TouchName, ObjectFlags, "+
161 cmd.CommandText = "replace into prims ("+ 107 "OwnerMask, NextOwnerMask, GroupMask, "+
162 "UUID, ParentID, CreationDate, "+ 108 "EveryoneMask, BaseMask, PositionX, "+
163 "Name, Text, Description, "+ 109 "PositionY, PositionZ, GroupPositionX, "+
164 "SitName, TouchName, ObjectFlags, "+ 110 "GroupPositionY, GroupPositionZ, VelocityX, "+
165 "OwnerMask, NextOwnerMask, GroupMask, "+ 111 "VelocityY, VelocityZ, AngularVelocityX, "+
166 "EveryoneMask, BaseMask, PositionX, "+ 112 "AngularVelocityY, AngularVelocityZ, "+
167 "PositionY, PositionZ, GroupPositionX, "+ 113 "AccelerationX, AccelerationY, "+
168 "GroupPositionY, GroupPositionZ, VelocityX, "+ 114 "AccelerationZ, RotationX, "+
169 "VelocityY, VelocityZ, AngularVelocityX, "+ 115 "RotationY, RotationZ, "+
170 "AngularVelocityY, AngularVelocityZ, "+ 116 "RotationW, SitTargetOffsetX, "+
171 "AccelerationX, AccelerationY, "+ 117 "SitTargetOffsetY, SitTargetOffsetZ, "+
172 "AccelerationZ, RotationX, "+ 118 "SitTargetOrientW, SitTargetOrientX, "+
173 "RotationY, RotationZ, "+ 119 "SitTargetOrientY, SitTargetOrientZ, "+
174 "RotationW, SitTargetOffsetX, "+ 120 "RegionUUID, CreatorID, "+
175 "SitTargetOffsetY, SitTargetOffsetZ, "+ 121 "OwnerID, GroupID, "+
176 "SitTargetOrientW, SitTargetOrientX, "+ 122 "LastOwnerID, SceneGroupID, "+
177 "SitTargetOrientY, SitTargetOrientZ, "+ 123 "PayPrice, PayButton1, "+
178 "RegionUUID, CreatorID, "+ 124 "PayButton2, PayButton3, "+
179 "OwnerID, GroupID, "+ 125 "PayButton4, LoopedSound, "+
180 "LastOwnerID, SceneGroupID, "+ 126 "LoopedSoundGain, TextureAnimation, "+
181 "PayPrice, PayButton1, "+ 127 "OmegaX, OmegaY, OmegaZ, "+
182 "PayButton2, PayButton3, "+ 128 "CameraEyeOffsetX, CameraEyeOffsetY, "+
183 "PayButton4, LoopedSound, "+ 129 "CameraEyeOffsetZ, CameraAtOffsetX, "+
184 "LoopedSoundGain, TextureAnimation, "+ 130 "CameraAtOffsetY, CameraAtOffsetZ, "+
185 "OmegaX, OmegaY, OmegaZ, "+ 131 "ForceMouselook, ScriptAccessPin, "+
186 "CameraEyeOffsetX, CameraEyeOffsetY, "+ 132 "AllowedDrop, DieAtEdge, "+
187 "CameraEyeOffsetZ, CameraAtOffsetX, "+ 133 "SalePrice, SaleType, "+
188 "CameraAtOffsetY, CameraAtOffsetZ, "+ 134 "ColorR, ColorG, ColorB, ColorA, "+
189 "ForceMouselook, ScriptAccessPin, "+ 135 "ParticleSystem, ClickAction, Material, "+
190 "AllowedDrop, DieAtEdge, "+ 136 "CollisionSound, CollisionSoundVolume, "+
191 "SalePrice, SaleType, "+ 137 "LinkNumber) values (" + "?UUID, ?ParentID, "+
192 "ColorR, ColorG, ColorB, ColorA, "+ 138 "?CreationDate, ?Name, ?Text, "+
193 "ParticleSystem, ClickAction, Material, "+ 139 "?Description, ?SitName, ?TouchName, "+
194 "CollisionSound, CollisionSoundVolume, "+ 140 "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+
195 "LinkNumber) values (" + "?UUID, ?ParentID, "+ 141 "?GroupMask, ?EveryoneMask, ?BaseMask, "+
196 "?CreationDate, ?Name, ?Text, "+ 142 "?PositionX, ?PositionY, ?PositionZ, "+
197 "?Description, ?SitName, ?TouchName, "+ 143 "?GroupPositionX, ?GroupPositionY, "+
198 "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+ 144 "?GroupPositionZ, ?VelocityX, "+
199 "?GroupMask, ?EveryoneMask, ?BaseMask, "+ 145 "?VelocityY, ?VelocityZ, ?AngularVelocityX, "+
200 "?PositionX, ?PositionY, ?PositionZ, "+ 146 "?AngularVelocityY, ?AngularVelocityZ, "+
201 "?GroupPositionX, ?GroupPositionY, "+ 147 "?AccelerationX, ?AccelerationY, "+
202 "?GroupPositionZ, ?VelocityX, "+ 148 "?AccelerationZ, ?RotationX, "+
203 "?VelocityY, ?VelocityZ, ?AngularVelocityX, "+ 149 "?RotationY, ?RotationZ, "+
204 "?AngularVelocityY, ?AngularVelocityZ, "+ 150 "?RotationW, ?SitTargetOffsetX, "+
205 "?AccelerationX, ?AccelerationY, "+ 151 "?SitTargetOffsetY, ?SitTargetOffsetZ, "+
206 "?AccelerationZ, ?RotationX, "+ 152 "?SitTargetOrientW, ?SitTargetOrientX, "+
207 "?RotationY, ?RotationZ, "+ 153 "?SitTargetOrientY, ?SitTargetOrientZ, "+
208 "?RotationW, ?SitTargetOffsetX, "+ 154 "?RegionUUID, ?CreatorID, ?OwnerID, "+
209 "?SitTargetOffsetY, ?SitTargetOffsetZ, "+ 155 "?GroupID, ?LastOwnerID, ?SceneGroupID, "+
210 "?SitTargetOrientW, ?SitTargetOrientX, "+ 156 "?PayPrice, ?PayButton1, ?PayButton2, "+
211 "?SitTargetOrientY, ?SitTargetOrientZ, "+ 157 "?PayButton3, ?PayButton4, ?LoopedSound, "+
212 "?RegionUUID, ?CreatorID, ?OwnerID, "+ 158 "?LoopedSoundGain, ?TextureAnimation, "+
213 "?GroupID, ?LastOwnerID, ?SceneGroupID, "+ 159 "?OmegaX, ?OmegaY, ?OmegaZ, "+
214 "?PayPrice, ?PayButton1, ?PayButton2, "+ 160 "?CameraEyeOffsetX, ?CameraEyeOffsetY, "+
215 "?PayButton3, ?PayButton4, ?LoopedSound, "+ 161 "?CameraEyeOffsetZ, ?CameraAtOffsetX, "+
216 "?LoopedSoundGain, ?TextureAnimation, "+ 162 "?CameraAtOffsetY, ?CameraAtOffsetZ, "+
217 "?OmegaX, ?OmegaY, ?OmegaZ, "+ 163 "?ForceMouselook, ?ScriptAccessPin, "+
218 "?CameraEyeOffsetX, ?CameraEyeOffsetY, "+ 164 "?AllowedDrop, ?DieAtEdge, ?SalePrice, "+
219 "?CameraEyeOffsetZ, ?CameraAtOffsetX, "+ 165 "?SaleType, ?ColorR, ?ColorG, "+
220 "?CameraAtOffsetY, ?CameraAtOffsetZ, "+ 166 "?ColorB, ?ColorA, ?ParticleSystem, "+
221 "?ForceMouselook, ?ScriptAccessPin, "+ 167 "?ClickAction, ?Material, ?CollisionSound, "+
222 "?AllowedDrop, ?DieAtEdge, ?SalePrice, "+ 168 "?CollisionSoundVolume, ?LinkNumber)";
223 "?SaleType, ?ColorR, ?ColorG, "+ 169
224 "?ColorB, ?ColorA, ?ParticleSystem, "+ 170 FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
225 "?ClickAction, ?Material, ?CollisionSound, "+ 171
226 "?CollisionSoundVolume, ?LinkNumber)"; 172 cmd.ExecuteNonQuery();
227 173
228 FillPrimCommand(cmd, prim, obj.UUID, regionUUID); 174 cmd.Parameters.Clear();
229 175
230 ExecuteNonQuery(cmd); 176 cmd.CommandText = "replace into primshapes ("+
231 177 "UUID, Shape, ScaleX, ScaleY, "+
232 cmd.Parameters.Clear(); 178 "ScaleZ, PCode, PathBegin, PathEnd, "+
233 179 "PathScaleX, PathScaleY, PathShearX, "+
234 cmd.CommandText = "replace into primshapes ("+ 180 "PathShearY, PathSkew, PathCurve, "+
235 "UUID, Shape, ScaleX, ScaleY, "+ 181 "PathRadiusOffset, PathRevolutions, "+
236 "ScaleZ, PCode, PathBegin, PathEnd, "+ 182 "PathTaperX, PathTaperY, PathTwist, "+
237 "PathScaleX, PathScaleY, PathShearX, "+ 183 "PathTwistBegin, ProfileBegin, ProfileEnd, "+
238 "PathShearY, PathSkew, PathCurve, "+ 184 "ProfileCurve, ProfileHollow, Texture, "+
239 "PathRadiusOffset, PathRevolutions, "+ 185 "ExtraParams, State) values (?UUID, "+
240 "PathTaperX, PathTaperY, PathTwist, "+ 186 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+
241 "PathTwistBegin, ProfileBegin, ProfileEnd, "+ 187 "?PCode, ?PathBegin, ?PathEnd, "+
242 "ProfileCurve, ProfileHollow, Texture, "+ 188 "?PathScaleX, ?PathScaleY, "+
243 "ExtraParams, State) values (?UUID, "+ 189 "?PathShearX, ?PathShearY, "+
244 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+ 190 "?PathSkew, ?PathCurve, ?PathRadiusOffset, "+
245 "?PCode, ?PathBegin, ?PathEnd, "+ 191 "?PathRevolutions, ?PathTaperX, "+
246 "?PathScaleX, ?PathScaleY, "+ 192 "?PathTaperY, ?PathTwist, "+
247 "?PathShearX, ?PathShearY, "+ 193 "?PathTwistBegin, ?ProfileBegin, "+
248 "?PathSkew, ?PathCurve, ?PathRadiusOffset, "+ 194 "?ProfileEnd, ?ProfileCurve, "+
249 "?PathRevolutions, ?PathTaperX, "+ 195 "?ProfileHollow, ?Texture, ?ExtraParams, "+
250 "?PathTaperY, ?PathTwist, "+ 196 "?State)";
251 "?PathTwistBegin, ?ProfileBegin, "+ 197
252 "?ProfileEnd, ?ProfileCurve, "+ 198 FillShapeCommand(cmd, prim);
253 "?ProfileHollow, ?Texture, ?ExtraParams, "+ 199
254 "?State)"; 200 cmd.ExecuteNonQuery();
255
256 FillShapeCommand(cmd, prim);
257
258 ExecuteNonQuery(cmd);
259 }
260 cmd.Dispose();
261 } 201 }
202 cmd.Dispose();
203 c.Close();
262 } 204 }
263 205
264 public void RemoveObject(UUID obj, UUID regionUUID) 206 public void RemoveObject(UUID obj, UUID regionUUID)
@@ -271,43 +213,51 @@ namespace OpenSim.Data.MySQL
271 // cause the loss of a prim, but is cleaner. 213 // cause the loss of a prim, but is cleaner.
272 // It's also faster because it uses the primary key. 214 // It's also faster because it uses the primary key.
273 // 215 //
274 lock (m_Connection) 216 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
275 { 217 c.Open();
276 MySqlCommand cmd = m_Connection.CreateCommand();
277 218
278 cmd.CommandText = "select UUID from prims where "+ 219 MySqlCommand cmd = c.CreateCommand();
279 "SceneGroupID= ?UUID";
280 220
281 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(obj)); 221 cmd.CommandText = "select UUID from prims where "+
222 "SceneGroupID= ?UUID";
282 223
283 List<UUID> uuids = new List<UUID>(); 224 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(obj));
284 225
285 IDataReader reader = ExecuteReader(cmd); 226 List<UUID> uuids = new List<UUID>();
286 227
287 try 228 IDataReader reader = cmd.ExecuteReader();
288 { 229
289 while (reader.Read()) 230 try
290 { 231 {
291 uuids.Add(new UUID(reader["UUID"].ToString())); 232 while(reader.Read())
292 }
293 }
294 finally
295 { 233 {
296 reader.Close(); 234 uuids.Add(new UUID(reader["UUID"].ToString()));
297 } 235 }
236 }
237 finally
238 {
239 reader.Close();
240 }
298 241
299 foreach (UUID uuid in uuids) 242 cmd.CommandText = "delete from prims where SceneGroupID= ?UUID";
300 RemoveItems(uuid);
301 243
302 cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; 244 cmd.ExecuteNonQuery();
303 245
304 ExecuteNonQuery(cmd); 246 cmd.CommandText = "delete from primshapes where UUID = ?UUID";
305 247
306 cmd.CommandText = "delete from primshapes where UUID = ?UUID"; 248 foreach (UUID uuid in uuids)
249 {
250 cmd.Parameters.Clear();
251 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(uuid));
307 252
308 ExecuteNonQuery(cmd); 253 cmd.ExecuteNonQuery();
309 cmd.Dispose();
310 } 254 }
255
256 cmd.Dispose();
257 c.Close();
258
259 foreach (UUID uuid in uuids)
260 RemoveItems(uuid);
311 } 261 }
312 262
313 /// <summary> 263 /// <summary>
@@ -317,18 +267,19 @@ namespace OpenSim.Data.MySQL
317 /// <param name="uuid">the Item UUID</param> 267 /// <param name="uuid">the Item UUID</param>
318 private void RemoveItems(UUID uuid) 268 private void RemoveItems(UUID uuid)
319 { 269 {
320 lock (m_Connection) 270 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
321 { 271 c.Open();
322 MySqlCommand cmd = m_Connection.CreateCommand();
323 272
324 cmd.CommandText = "delete from primitems where " + 273 MySqlCommand cmd = c.CreateCommand();
325 "PrimID = ?PrimID";
326 274
327 cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); 275 cmd.CommandText = "delete from primitems where " +
276 "PrimID = ?PrimID";
328 277
329 ExecuteNonQuery(cmd); 278 cmd.Parameters.AddWithValue("PrimID", uuid.ToString());
330 cmd.Dispose(); 279
331 } 280 cmd.ExecuteNonQuery();
281 cmd.Dispose();
282 c.Close();
332 } 283 }
333 284
334 public List<SceneObjectGroup> LoadObjects(UUID regionUUID) 285 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
@@ -338,71 +289,72 @@ namespace OpenSim.Data.MySQL
338 List<SceneObjectPart> prims = new List<SceneObjectPart>(); 289 List<SceneObjectPart> prims = new List<SceneObjectPart>();
339 SceneObjectGroup grp = null; 290 SceneObjectGroup grp = null;
340 291
341 lock (m_Connection) 292 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
342 { 293 c.Open();
343 MySqlCommand cmd = m_Connection.CreateCommand();
344 294
345 cmd.CommandText = "select *, " + 295 MySqlCommand cmd = c.CreateCommand();
346 "case when prims.UUID = SceneGroupID " +
347 "then 0 else 1 end as sort from prims " +
348 "left join primshapes on prims.UUID = primshapes.UUID "+
349 "where RegionUUID = ?RegionUUID " +
350 "order by SceneGroupID asc, sort asc, LinkNumber asc";
351
352 cmd.Parameters.AddWithValue("RegionUUID",
353 Util.ToRawUuidString(regionUUID));
354 296
355 IDataReader reader = ExecuteReader(cmd); 297 cmd.CommandText = "select *, " +
298 "case when prims.UUID = SceneGroupID " +
299 "then 0 else 1 end as sort from prims " +
300 "left join primshapes on prims.UUID = primshapes.UUID "+
301 "where RegionUUID = ?RegionUUID " +
302 "order by SceneGroupID asc, sort asc, LinkNumber asc";
303
304 cmd.Parameters.AddWithValue("RegionUUID",
305 Util.ToRawUuidString(regionUUID));
356 306
357 try 307 IDataReader reader = cmd.ExecuteReader();
308
309 try
310 {
311 while (reader.Read())
358 { 312 {
359 while (reader.Read()) 313 SceneObjectPart prim = BuildPrim(reader);
360 { 314 if (reader["Shape"] is DBNull)
361 SceneObjectPart prim = BuildPrim(reader); 315 prim.Shape = PrimitiveBaseShape.Default;
362 if (reader["Shape"] is DBNull) 316 else
363 prim.Shape = PrimitiveBaseShape.Default; 317 prim.Shape = BuildShape(reader);
364 else
365 prim.Shape = BuildShape(reader);
366 318
367 prim.FolderID = prim.UUID; // A relic from when we 319 prim.FolderID = prim.UUID; // A relic from when we
368 // we thought prims contained 320 // we thought prims contained
369 // folder objects. In 321 // folder objects. In
370 // reality, prim == folder 322 // reality, prim == folder
371 prims.Add(prim); 323 prims.Add(prim);
372 324
373 UUID groupID = new UUID(reader["SceneGroupID"].ToString()); 325 UUID groupID = new UUID(reader["SceneGroupID"].ToString());
374 326
375 if (groupID != lastGroupID) // New SOG 327 if (groupID != lastGroupID) // New SOG
376 { 328 {
377 if (grp != null) 329 if (grp != null)
378 objects.Add(grp); 330 objects.Add(grp);
379 331
380 lastGroupID = groupID; 332 lastGroupID = groupID;
381 333
382 grp = new SceneObjectGroup(prim); 334 grp = new SceneObjectGroup(prim);
383 } 335 }
384 else 336 else
385 { 337 {
386 // Black magic to preserve link numbers 338 // Black magic to preserve link numbers
387 // 339 //
388 int link = prim.LinkNum; 340 int link = prim.LinkNum;
389 341
390 grp.AddPart(prim); 342 grp.AddPart(prim);
391 343
392 if (link != 0) 344 if (link != 0)
393 prim.LinkNum = link; 345 prim.LinkNum = link;
394 }
395 } 346 }
396 } 347 }
397 finally
398 {
399 reader.Close();
400 }
401
402 if (grp != null)
403 objects.Add(grp);
404 cmd.Dispose();
405 } 348 }
349 finally
350 {
351 reader.Close();
352 }
353
354 if (grp != null)
355 objects.Add(grp);
356 cmd.Dispose();
357 c.Close();
406 358
407 foreach (SceneObjectPart part in prims) 359 foreach (SceneObjectPart part in prims)
408 LoadItems(part); 360 LoadItems(part);
@@ -418,65 +370,67 @@ namespace OpenSim.Data.MySQL
418 /// <param name="prim">The prim</param> 370 /// <param name="prim">The prim</param>
419 private void LoadItems(SceneObjectPart prim) 371 private void LoadItems(SceneObjectPart prim)
420 { 372 {
421 lock (m_Connection) 373 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
422 { 374 c.Open();
423 MySqlCommand cmd = m_Connection.CreateCommand();
424 375
425 cmd.CommandText = "select * from primitems where "+ 376 MySqlCommand cmd = c.CreateCommand();
426 "PrimID = ?PrimID";
427 377
428 cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); 378 cmd.CommandText = "select * from primitems where "+
379 "PrimID = ?PrimID";
429 380
430 IDataReader reader = ExecuteReader(cmd); 381 cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString());
431 List<TaskInventoryItem> inventory =
432 new List<TaskInventoryItem>();
433 382
434 try 383 IDataReader reader = cmd.ExecuteReader();
435 { 384 List<TaskInventoryItem> inventory =
436 while (reader.Read()) 385 new List<TaskInventoryItem>();
437 {
438 TaskInventoryItem item = BuildItem(reader);
439 386
440 item.ParentID = prim.UUID; // Values in database are 387 try
441 // often wrong 388 {
442 inventory.Add(item); 389 while (reader.Read())
443 }
444 }
445 finally
446 { 390 {
447 reader.Close(); 391 TaskInventoryItem item = BuildItem(reader);
448 }
449 392
450 cmd.Dispose(); 393 item.ParentID = prim.UUID; // Values in database are
451 prim.Inventory.RestoreInventoryItems(inventory); 394 // often wrong
395 inventory.Add(item);
396 }
452 } 397 }
398 finally
399 {
400 reader.Close();
401 }
402
403 cmd.Dispose();
404 c.Close();
405 prim.Inventory.RestoreInventoryItems(inventory);
453 } 406 }
454 407
455 public void StoreTerrain(double[,] ter, UUID regionID) 408 public void StoreTerrain(double[,] ter, UUID regionID)
456 { 409 {
457 m_log.Info("[REGION DB]: Storing terrain"); 410 m_log.Info("[REGION DB]: Storing terrain");
458 411
459 lock (m_Connection) 412 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
460 { 413 c.Open();
461 MySqlCommand cmd = m_Connection.CreateCommand(); 414
462 415 MySqlCommand cmd = c.CreateCommand();
463 cmd.CommandText = "delete from terrain where " + 416
464 "RegionUUID = ?RegionUUID"; 417 cmd.CommandText = "delete from terrain where " +
465 cmd.Parameters.AddWithValue("RegionUUID", 418 "RegionUUID = ?RegionUUID";
466 Util.ToRawUuidString(regionID)); 419 cmd.Parameters.AddWithValue("RegionUUID",
467 420 Util.ToRawUuidString(regionID));
468 ExecuteNonQuery(cmd); 421
469 422 cmd.ExecuteNonQuery();
470 cmd.CommandText = "insert into terrain (RegionUUID, " + 423
471 "Revision, Heightfield) values (?RegionUUID, " + 424 cmd.CommandText = "insert into terrain (RegionUUID, " +
472 "1, ?Heightfield)"; 425 "Revision, Heightfield) values (?RegionUUID, " +
473 426 "1, ?Heightfield)";
474 cmd.Parameters.AddWithValue("Heightfield", 427
475 SerializeTerrain(ter)); 428 cmd.Parameters.AddWithValue("Heightfield",
476 429 SerializeTerrain(ter));
477 ExecuteNonQuery(cmd); 430
478 cmd.Dispose(); 431 cmd.ExecuteNonQuery();
479 } 432 cmd.Dispose();
433 c.Close();
480 } 434 }
481 435
482 public double[,] LoadTerrain(UUID regionID) 436 public double[,] LoadTerrain(UUID regionID)
@@ -484,254 +438,264 @@ namespace OpenSim.Data.MySQL
484 double[,] terrain = new double[256,256]; 438 double[,] terrain = new double[256,256];
485 terrain.Initialize(); 439 terrain.Initialize();
486 440
487 lock (m_Connection) 441 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
488 { 442 c.Open();
489 MySqlCommand cmd = m_Connection.CreateCommand();
490 cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
491 "from terrain where RegionUUID = ?RegionUUID "+
492 "order by Revision desc limit 1";
493 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
494 443
495 IDataReader reader = ExecuteReader(cmd); 444 MySqlCommand cmd = c.CreateCommand();
496 445
497 try 446 cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
447 "from terrain where RegionUUID = ?RegionUUID "+
448 "order by Revision desc limit 1";
449 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
450
451 IDataReader reader = cmd.ExecuteReader();
452
453 try
454 {
455 while (reader.Read())
498 { 456 {
499 while (reader.Read()) 457 MemoryStream mstr = new MemoryStream((byte[]) reader["Heightfield"]);
500 { 458 int rev = 0;
501 MemoryStream mstr = new MemoryStream((byte[]) reader["Heightfield"]);
502 int rev = 0;
503 459
504 BinaryReader br = new BinaryReader(mstr); 460 BinaryReader br = new BinaryReader(mstr);
505 for (int x = 0; x < 256; x++) 461 for (int x = 0; x < 256; x++)
462 {
463 for (int y = 0; y < 256; y++)
506 { 464 {
507 for (int y = 0; y < 256; y++) 465 terrain[x, y] = br.ReadDouble();
508 {
509 terrain[x, y] = br.ReadDouble();
510 }
511 rev = Convert.ToInt32(reader["Revision"]);
512 } 466 }
513 m_log.InfoFormat("[REGION DB]: Loaded terrain " + 467 rev = Convert.ToInt32(reader["Revision"]);
514 "revision r{0}", rev);
515
516 return terrain;
517 } 468 }
518 } 469 m_log.InfoFormat("[REGION DB]: Loaded terrain " +
519 finally 470 "revision r{0}", rev);
520 { 471
521 reader.Close(); 472 reader.Close();
473 cmd.Dispose();
474 c.Close();
475 return terrain;
522 } 476 }
523 cmd.Dispose();
524 } 477 }
478 catch (Exception)
479 {
480 }
481 reader.Close();
482 cmd.Dispose();
483 c.Close();
525 484
526 return null; 485 return null;
527 } 486 }
528 487
529 public void RemoveLandObject(UUID globalID) 488 public void RemoveLandObject(UUID globalID)
530 { 489 {
531 lock (m_Connection) 490 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
532 { 491 c.Open();
533 MySqlCommand cmd = m_Connection.CreateCommand();
534 492
535 cmd.CommandText = "delete from land where UUID = ?UUID"; 493 MySqlCommand cmd = c.CreateCommand();
536 494
537 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID)); 495 cmd.CommandText = "delete from land where UUID = ?UUID";
538 496
539 ExecuteNonQuery(cmd); 497 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID));
540 cmd.Dispose(); 498
541 } 499 cmd.ExecuteNonQuery();
500 cmd.Dispose();
501 c.Close();
542 } 502 }
543 503
544 public void StoreLandObject(ILandObject parcel) 504 public void StoreLandObject(ILandObject parcel)
545 { 505 {
546 lock (m_Connection) 506 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
507 c.Open();
508
509 MySqlCommand cmd = c.CreateCommand();
510
511 cmd.CommandText = "replace into land (UUID, RegionUUID, " +
512 "LocalLandID, Bitmap, Name, Description, " +
513 "OwnerUUID, IsGroupOwned, Area, AuctionID, " +
514 "Category, ClaimDate, ClaimPrice, GroupUUID, " +
515 "SalePrice, LandStatus, LandFlags, LandingType, " +
516 "MediaAutoScale, MediaTextureUUID, MediaURL, " +
517 "MusicURL, PassHours, PassPrice, SnapshotUUID, " +
518 "UserLocationX, UserLocationY, UserLocationZ, " +
519 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
520 "AuthbuyerID, OtherCleanTime, Dwell) values (" +
521 "?UUID, ?RegionUUID, " +
522 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
523 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
524 "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " +
525 "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " +
526 "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " +
527 "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
528 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
529 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
530 "?AuthbuyerID, ?OtherCleanTime, ?Dwell)";
531
532 FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
533
534 cmd.ExecuteNonQuery();
535
536 cmd.CommandText = "delete from landaccesslist where " +
537 "LandUUID = ?UUID";
538
539 cmd.ExecuteNonQuery();
540
541 cmd.Parameters.Clear();
542 cmd.CommandText = "insert into landaccesslist (LandUUID, " +
543 "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " +
544 "?Flags)";
545
546 foreach (ParcelManager.ParcelAccessEntry entry in
547 parcel.landData.ParcelAccessList)
547 { 548 {
548 MySqlCommand cmd = m_Connection.CreateCommand(); 549 FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
549 550 cmd.ExecuteNonQuery();
550 cmd.CommandText = "replace into land (UUID, RegionUUID, " +
551 "LocalLandID, Bitmap, Name, Description, " +
552 "OwnerUUID, IsGroupOwned, Area, AuctionID, " +
553 "Category, ClaimDate, ClaimPrice, GroupUUID, " +
554 "SalePrice, LandStatus, LandFlags, LandingType, " +
555 "MediaAutoScale, MediaTextureUUID, MediaURL, " +
556 "MusicURL, PassHours, PassPrice, SnapshotUUID, " +
557 "UserLocationX, UserLocationY, UserLocationZ, " +
558 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
559 "AuthbuyerID, OtherCleanTime, Dwell) values (" +
560 "?UUID, ?RegionUUID, " +
561 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
562 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
563 "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " +
564 "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " +
565 "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " +
566 "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
567 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
568 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
569 "?AuthbuyerID, ?OtherCleanTime, ?Dwell)";
570
571 FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
572
573 ExecuteNonQuery(cmd);
574
575 cmd.CommandText = "delete from landaccesslist where " +
576 "LandUUID = ?UUID";
577
578 ExecuteNonQuery(cmd);
579
580 cmd.Parameters.Clear(); 551 cmd.Parameters.Clear();
581 cmd.CommandText = "insert into landaccesslist (LandUUID, " +
582 "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " +
583 "?Flags)";
584
585 foreach (ParcelManager.ParcelAccessEntry entry in
586 parcel.landData.ParcelAccessList)
587 {
588 FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
589 ExecuteNonQuery(cmd);
590 cmd.Parameters.Clear();
591 }
592 cmd.Dispose();
593 } 552 }
553 cmd.Dispose();
554 c.Close();
594 } 555 }
595 556
596 public RegionSettings LoadRegionSettings(UUID regionUUID) 557 public RegionSettings LoadRegionSettings(UUID regionUUID)
597 { 558 {
598 RegionSettings rs = null; 559 RegionSettings rs = null;
599 560
600 lock (m_Connection) 561 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
601 { 562 c.Open();
602 MySqlCommand cmd = m_Connection.CreateCommand();
603 563
604 cmd.CommandText = "select * from regionsettings where " + 564 MySqlCommand cmd = c.CreateCommand();
605 "regionUUID = ?RegionUUID";
606 cmd.Parameters.AddWithValue("regionUUID", regionUUID);
607 565
608 IDataReader reader = ExecuteReader(cmd); 566 cmd.CommandText = "select * from regionsettings where " +
567 "regionUUID = ?RegionUUID";
568 cmd.Parameters.AddWithValue("regionUUID", regionUUID);
609 569
610 try 570 IDataReader reader = cmd.ExecuteReader();
611 {
612 if (reader.Read())
613 {
614 rs = BuildRegionSettings(reader);
615 rs.OnSave += StoreRegionSettings;
616 }
617 else
618 {
619 rs = new RegionSettings();
620 rs.RegionUUID = regionUUID;
621 rs.OnSave += StoreRegionSettings;
622 571
623 StoreRegionSettings(rs); 572 try
624 } 573 {
574 if (reader.Read())
575 {
576 rs = BuildRegionSettings(reader);
577 rs.OnSave += StoreRegionSettings;
625 } 578 }
626 finally 579 else
627 { 580 {
628 reader.Close(); 581 rs = new RegionSettings();
582 rs.RegionUUID = regionUUID;
583 rs.OnSave += StoreRegionSettings;
584
585 StoreRegionSettings(rs);
629 } 586 }
630 cmd.Dispose();
631 } 587 }
588 finally
589 {
590 reader.Close();
591 }
592 cmd.Dispose();
593 c.Close();
632 594
633 return rs; 595 return rs;
634 } 596 }
635 597
636 public void StoreRegionSettings(RegionSettings rs) 598 public void StoreRegionSettings(RegionSettings rs)
637 { 599 {
638 lock (m_Connection) 600 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
639 { 601 c.Open();
640 MySqlCommand cmd = m_Connection.CreateCommand(); 602
641 603 MySqlCommand cmd = c.CreateCommand();
642 cmd.CommandText = "replace into regionsettings (regionUUID, " + 604
643 "block_terraform, block_fly, allow_damage, " + 605 cmd.CommandText = "replace into regionsettings (regionUUID, " +
644 "restrict_pushing, allow_land_resell, " + 606 "block_terraform, block_fly, allow_damage, " +
645 "allow_land_join_divide, block_show_in_search, " + 607 "restrict_pushing, allow_land_resell, " +
646 "agent_limit, object_bonus, maturity, " + 608 "allow_land_join_divide, block_show_in_search, " +
647 "disable_scripts, disable_collisions, " + 609 "agent_limit, object_bonus, maturity, " +
648 "disable_physics, terrain_texture_1, " + 610 "disable_scripts, disable_collisions, " +
649 "terrain_texture_2, terrain_texture_3, " + 611 "disable_physics, terrain_texture_1, " +
650 "terrain_texture_4, elevation_1_nw, " + 612 "terrain_texture_2, terrain_texture_3, " +
651 "elevation_2_nw, elevation_1_ne, " + 613 "terrain_texture_4, elevation_1_nw, " +
652 "elevation_2_ne, elevation_1_se, "+ 614 "elevation_2_nw, elevation_1_ne, " +
653 "elevation_2_se, elevation_1_sw, "+ 615 "elevation_2_ne, elevation_1_se, "+
654 "elevation_2_sw, water_height, " + 616 "elevation_2_se, elevation_1_sw, "+
655 "terrain_raise_limit, terrain_lower_limit, " + 617 "elevation_2_sw, water_height, " +
656 "use_estate_sun, fixed_sun, sun_position, " + 618 "terrain_raise_limit, terrain_lower_limit, " +
657 "covenant, Sandbox, sunvectorx, sunvectory, " + 619 "use_estate_sun, fixed_sun, sun_position, " +
658 "sunvectorz) values ( ?RegionUUID, ?BlockTerraform, " + 620 "covenant, Sandbox, sunvectorx, sunvectory, " +
659 "?BlockFly, ?AllowDamage, ?RestrictPushing, " + 621 "sunvectorz) values ( ?RegionUUID, ?BlockTerraform, " +
660 "?AllowLandResell, ?AllowLandJoinDivide, " + 622 "?BlockFly, ?AllowDamage, ?RestrictPushing, " +
661 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + 623 "?AllowLandResell, ?AllowLandJoinDivide, " +
662 "?Maturity, ?DisableScripts, ?DisableCollisions, " + 624 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " +
663 "?DisablePhysics, ?TerrainTexture1, " + 625 "?Maturity, ?DisableScripts, ?DisableCollisions, " +
664 "?TerrainTexture2, ?TerrainTexture3, " + 626 "?DisablePhysics, ?TerrainTexture1, " +
665 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " + 627 "?TerrainTexture2, ?TerrainTexture3, " +
666 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " + 628 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " +
667 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " + 629 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " +
668 "?WaterHeight, ?TerrainRaiseLimit, " + 630 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " +
669 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " + 631 "?WaterHeight, ?TerrainRaiseLimit, " +
670 "?SunPosition, ?Covenant, ?Sandbox, " + 632 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " +
671 "?SunVectorX, ?SunVectorY, ?SunVectorZ)"; 633 "?SunPosition, ?Covenant, ?Sandbox, " +
672 634 "?SunVectorX, ?SunVectorY, ?SunVectorZ)";
673 FillRegionSettingsCommand(cmd, rs); 635
674 636 FillRegionSettingsCommand(cmd, rs);
675 ExecuteNonQuery(cmd); 637
676 cmd.Dispose(); 638 cmd.ExecuteNonQuery();
677 } 639 cmd.Dispose();
640 c.Close();
678 } 641 }
679 642
680 public List<LandData> LoadLandObjects(UUID regionUUID) 643 public List<LandData> LoadLandObjects(UUID regionUUID)
681 { 644 {
682 List<LandData> landData = new List<LandData>(); 645 List<LandData> landData = new List<LandData>();
683 646
684 lock (m_Connection) 647 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
648 c.Open();
649
650 MySqlCommand cmd = c.CreateCommand();
651
652 cmd.CommandText = "select * from land where " +
653 "RegionUUID = ?RegionUUID";
654
655 cmd.Parameters.AddWithValue("RegionUUID",
656 Util.ToRawUuidString(regionUUID));
657
658 IDataReader reader = cmd.ExecuteReader();
659
660 try
661 {
662 while (reader.Read())
663 {
664 LandData newLand = BuildLandData(reader);
665 landData.Add(newLand);
666 }
667 }
668 finally
685 { 669 {
686 MySqlCommand cmd = m_Connection.CreateCommand(); 670 reader.Close();
671 }
687 672
688 cmd.CommandText = "select * from land where " + 673 foreach (LandData land in landData)
689 "RegionUUID = ?RegionUUID"; 674 {
675 cmd.Parameters.Clear();
690 676
691 cmd.Parameters.AddWithValue("RegionUUID", 677 cmd.CommandText = "select * from landaccesslist " +
692 Util.ToRawUuidString(regionUUID)); 678 "where LandUUID = ?LandUUID";
693 679
694 IDataReader reader = ExecuteReader(cmd); 680 cmd.Parameters.AddWithValue("LandUUID",
681 Util.ToRawUuidString(land.GlobalID));
682
683 reader = cmd.ExecuteReader();
695 684
696 try 685 try
697 { 686 {
698 while (reader.Read()) 687 while (reader.Read())
699 { 688 {
700 LandData newLand = BuildLandData(reader); 689 land.ParcelAccessList.Add(BuildLandAccessData(reader));
701 landData.Add(newLand);
702 } 690 }
703 } 691 }
704 finally 692 finally
705 { 693 {
706 reader.Close(); 694 reader.Close();
707 } 695 }
708
709 foreach (LandData land in landData)
710 {
711 cmd.Parameters.Clear();
712
713 cmd.CommandText = "select * from landaccesslist " +
714 "where LandUUID = ?LandUUID";
715
716 cmd.Parameters.AddWithValue("LandUUID",
717 Util.ToRawUuidString(land.GlobalID));
718
719 reader = ExecuteReader(cmd);
720
721 try
722 {
723 while (reader.Read())
724 {
725 land.ParcelAccessList.Add(BuildLandAccessData(reader));
726 }
727 }
728 finally
729 {
730 reader.Close();
731 }
732 }
733 cmd.Dispose();
734 } 696 }
697 cmd.Dispose();
698 c.Close();
735 699
736 return landData; 700 return landData;
737 } 701 }
@@ -1415,41 +1379,42 @@ byte[] textureEntry = (byte[]) row["Texture"];
1415 1379
1416 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1380 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1417 { 1381 {
1418 lock (m_Connection) 1382 RemoveItems(primID);
1383
1384 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
1385 c.Open();
1386
1387 MySqlCommand cmd = c.CreateCommand();
1388
1389 if (items.Count == 0)
1390 return;
1391
1392 cmd.CommandText = "insert into primitems ("+
1393 "invType, assetType, name, "+
1394 "description, creationDate, nextPermissions, "+
1395 "currentPermissions, basePermissions, "+
1396 "everyonePermissions, groupPermissions, "+
1397 "flags, itemID, primID, assetID, "+
1398 "parentFolderID, creatorID, ownerID, "+
1399 "groupID, lastOwnerID) values (?invType, "+
1400 "?assetType, ?name, ?description, "+
1401 "?creationDate, ?nextPermissions, "+
1402 "?currentPermissions, ?basePermissions, "+
1403 "?everyonePermissions, ?groupPermissions, "+
1404 "?flags, ?itemID, ?primID, ?assetID, "+
1405 "?parentFolderID, ?creatorID, ?ownerID, "+
1406 "?groupID, ?lastOwnerID)";
1407
1408 foreach (TaskInventoryItem item in items)
1419 { 1409 {
1420 RemoveItems(primID); 1410 cmd.Parameters.Clear();
1421
1422 MySqlCommand cmd = m_Connection.CreateCommand();
1423
1424 if (items.Count == 0)
1425 return;
1426
1427 cmd.CommandText = "insert into primitems ("+
1428 "invType, assetType, name, "+
1429 "description, creationDate, nextPermissions, "+
1430 "currentPermissions, basePermissions, "+
1431 "everyonePermissions, groupPermissions, "+
1432 "flags, itemID, primID, assetID, "+
1433 "parentFolderID, creatorID, ownerID, "+
1434 "groupID, lastOwnerID) values (?invType, "+
1435 "?assetType, ?name, ?description, "+
1436 "?creationDate, ?nextPermissions, "+
1437 "?currentPermissions, ?basePermissions, "+
1438 "?everyonePermissions, ?groupPermissions, "+
1439 "?flags, ?itemID, ?primID, ?assetID, "+
1440 "?parentFolderID, ?creatorID, ?ownerID, "+
1441 "?groupID, ?lastOwnerID)";
1442
1443 foreach (TaskInventoryItem item in items)
1444 {
1445 cmd.Parameters.Clear();
1446 1411
1447 FillItemCommand(cmd, item); 1412 FillItemCommand(cmd, item);
1448 1413
1449 ExecuteNonQuery(cmd); 1414 cmd.ExecuteNonQuery();
1450 }
1451 cmd.Dispose();
1452 } 1415 }
1416 cmd.Dispose();
1417 c.Close();
1453 } 1418 }
1454 } 1419 }
1455} 1420}