aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs')
-rw-r--r--OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs581
1 files changed, 581 insertions, 0 deletions
diff --git a/OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs b/OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs
new file mode 100644
index 0000000..76d3faf
--- /dev/null
+++ b/OpenGridServices/OpenGrid.Framework.Data.MySQL/MySQLManager.cs
@@ -0,0 +1,581 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections.Generic;
30using System.Text;
31using System.Data;
32
33// MySQL Native
34using MySql;
35using MySql.Data;
36using MySql.Data.Types;
37using MySql.Data.MySqlClient;
38
39using OpenGrid.Framework.Data;
40
41namespace OpenGrid.Framework.Data.MySQL
42{
43 /// <summary>
44 /// A MySQL Database manager
45 /// </summary>
46 class MySQLManager
47 {
48 /// <summary>
49 /// The database connection object
50 /// </summary>
51 IDbConnection dbcon;
52 /// <summary>
53 /// Connection string for ADO.net
54 /// </summary>
55 string connectionString;
56
57 /// <summary>
58 /// Initialises and creates a new MySQL connection and maintains it.
59 /// </summary>
60 /// <param name="hostname">The MySQL server being connected to</param>
61 /// <param name="database">The name of the MySQL database being used</param>
62 /// <param name="username">The username logging into the database</param>
63 /// <param name="password">The password for the user logging in</param>
64 /// <param name="cpooling">Whether to use connection pooling or not, can be one of the following: 'yes', 'true', 'no' or 'false', if unsure use 'false'.</param>
65 public MySQLManager(string hostname, string database, string username, string password, string cpooling, string port)
66 {
67 try
68 {
69 connectionString = "Server=" + hostname + ";Port=" + port + ";Database=" + database + ";User ID=" + username + ";Password=" + password + ";Pooling=" + cpooling + ";";
70 dbcon = new MySqlConnection(connectionString);
71
72 dbcon.Open();
73
74 System.Console.WriteLine("MySQL connection established");
75 }
76 catch (Exception e)
77 {
78 throw new Exception("Error initialising MySql Database: " + e.ToString());
79 }
80 }
81
82 /// <summary>
83 /// Shuts down the database connection
84 /// </summary>
85 public void Close()
86 {
87 dbcon.Close();
88 dbcon = null;
89 }
90
91 /// <summary>
92 /// Reconnects to the database
93 /// </summary>
94 public void Reconnect()
95 {
96 lock (dbcon)
97 {
98 try
99 {
100 // Close the DB connection
101 dbcon.Close();
102 // Try reopen it
103 dbcon = new MySqlConnection(connectionString);
104 dbcon.Open();
105 }
106 catch (Exception e)
107 {
108 Console.WriteLine("Unable to reconnect to database " + e.ToString());
109 }
110 }
111 }
112
113 /// <summary>
114 /// Runs a query with protection against SQL Injection by using parameterised input.
115 /// </summary>
116 /// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param>
117 /// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param>
118 /// <returns>A MySQL DB Command</returns>
119 public IDbCommand Query(string sql, Dictionary<string, string> parameters)
120 {
121 try
122 {
123 MySqlCommand dbcommand = (MySqlCommand)dbcon.CreateCommand();
124 dbcommand.CommandText = sql;
125 foreach (KeyValuePair<string, string> param in parameters)
126 {
127 dbcommand.Parameters.Add(param.Key, param.Value);
128 }
129
130 return (IDbCommand)dbcommand;
131 }
132 catch
133 {
134 lock (dbcon)
135 {
136 // Close the DB connection
137 try
138 {
139 dbcon.Close();
140 }
141 catch { }
142
143 // Try reopen it
144 try
145 {
146 dbcon = new MySqlConnection(connectionString);
147 dbcon.Open();
148 }
149 catch (Exception e)
150 {
151 Console.WriteLine("Unable to reconnect to database " + e.ToString());
152 }
153
154 // Run the query again
155 try
156 {
157 MySqlCommand dbcommand = (MySqlCommand)dbcon.CreateCommand();
158 dbcommand.CommandText = sql;
159 foreach (KeyValuePair<string, string> param in parameters)
160 {
161 dbcommand.Parameters.Add(param.Key, param.Value);
162 }
163
164 return (IDbCommand)dbcommand;
165 }
166 catch (Exception e)
167 {
168 // Return null if it fails.
169 Console.WriteLine("Failed during Query generation: " + e.ToString());
170 return null;
171 }
172 }
173 }
174 }
175
176 /// <summary>
177 /// Reads a region row from a database reader
178 /// </summary>
179 /// <param name="reader">An active database reader</param>
180 /// <returns>A region profile</returns>
181 public SimProfileData readSimRow(IDataReader reader)
182 {
183 SimProfileData retval = new SimProfileData();
184
185 if (reader.Read())
186 {
187 // Region Main
188 retval.regionHandle = Convert.ToUInt64(reader["regionHandle"].ToString());
189 retval.regionName = (string)reader["regionName"];
190 retval.UUID = new libsecondlife.LLUUID((string)reader["uuid"]);
191
192 // Secrets
193 retval.regionRecvKey = (string)reader["regionRecvKey"];
194 retval.regionSecret = (string)reader["regionSecret"];
195 retval.regionSendKey = (string)reader["regionSendKey"];
196
197 // Region Server
198 retval.regionDataURI = (string)reader["regionDataURI"];
199 retval.regionOnline = false; // Needs to be pinged before this can be set.
200 retval.serverIP = (string)reader["serverIP"];
201 retval.serverPort = (uint)reader["serverPort"];
202 retval.serverURI = (string)reader["serverURI"];
203
204 // Location
205 retval.regionLocX = Convert.ToUInt32(reader["locX"].ToString());
206 retval.regionLocY = Convert.ToUInt32(reader["locY"].ToString());
207 retval.regionLocZ = Convert.ToUInt32(reader["locZ"].ToString());
208
209 // Neighbours - 0 = No Override
210 retval.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"].ToString());
211 retval.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"].ToString());
212 retval.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"].ToString());
213 retval.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"].ToString());
214
215 // Assets
216 retval.regionAssetURI = (string)reader["regionAssetURI"];
217 retval.regionAssetRecvKey = (string)reader["regionAssetRecvKey"];
218 retval.regionAssetSendKey = (string)reader["regionAssetSendKey"];
219
220 // Userserver
221 retval.regionUserURI = (string)reader["regionUserURI"];
222 retval.regionUserRecvKey = (string)reader["regionUserRecvKey"];
223 retval.regionUserSendKey = (string)reader["regionUserSendKey"];
224
225 // World Map Addition
226 string tempRegionMap = reader["regionMapTexture"].ToString();
227 if (tempRegionMap != "")
228 {
229 retval.regionMapTextureID = new libsecondlife.LLUUID(tempRegionMap);
230 }
231 else
232 {
233 retval.regionMapTextureID = new libsecondlife.LLUUID();
234 }
235 }
236 else
237 {
238 return null;
239 }
240 return retval;
241 }
242
243 /// <summary>
244 /// Reads an agent row from a database reader
245 /// </summary>
246 /// <param name="reader">An active database reader</param>
247 /// <returns>A user session agent</returns>
248 public UserAgentData readAgentRow(IDataReader reader)
249 {
250 UserAgentData retval = new UserAgentData();
251
252 if (reader.Read())
253 {
254 // Agent IDs
255 retval.UUID = new libsecondlife.LLUUID((string)reader["UUID"]);
256 retval.sessionID = new libsecondlife.LLUUID((string)reader["sessionID"]);
257 retval.secureSessionID = new libsecondlife.LLUUID((string)reader["secureSessionID"]);
258
259 // Agent Who?
260 retval.agentIP = (string)reader["agentIP"];
261 retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString());
262 retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString());
263
264 // Login/Logout times (UNIX Epoch)
265 retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString());
266 retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString());
267
268 // Current position
269 retval.currentRegion = (string)reader["currentRegion"];
270 retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString());
271 libsecondlife.LLVector3.TryParse((string)reader["currentPos"], out retval.currentPos);
272 }
273 else
274 {
275 return null;
276 }
277 return retval;
278 }
279
280 /// <summary>
281 /// Reads a user profile from an active data reader
282 /// </summary>
283 /// <param name="reader">An active database reader</param>
284 /// <returns>A user profile</returns>
285 public UserProfileData readUserRow(IDataReader reader)
286 {
287 UserProfileData retval = new UserProfileData();
288
289 if (reader.Read())
290 {
291 retval.UUID = new libsecondlife.LLUUID((string)reader["UUID"]);
292 retval.username = (string)reader["username"];
293 retval.surname = (string)reader["lastname"];
294
295 retval.passwordHash = (string)reader["passwordHash"];
296 retval.passwordSalt = (string)reader["passwordSalt"];
297
298 retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString());
299 retval.homeLocation = new libsecondlife.LLVector3(
300 Convert.ToSingle(reader["homeLocationX"].ToString()),
301 Convert.ToSingle(reader["homeLocationY"].ToString()),
302 Convert.ToSingle(reader["homeLocationZ"].ToString()));
303 retval.homeLookAt = new libsecondlife.LLVector3(
304 Convert.ToSingle(reader["homeLookAtX"].ToString()),
305 Convert.ToSingle(reader["homeLookAtY"].ToString()),
306 Convert.ToSingle(reader["homeLookAtZ"].ToString()));
307
308 retval.created = Convert.ToInt32(reader["created"].ToString());
309 retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString());
310
311 retval.userInventoryURI = (string)reader["userInventoryURI"];
312 retval.userAssetURI = (string)reader["userAssetURI"];
313
314 retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString());
315 retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString());
316
317 retval.profileAboutText = (string)reader["profileAboutText"];
318 retval.profileFirstText = (string)reader["profileFirstText"];
319
320 retval.profileImage = new libsecondlife.LLUUID((string)reader["profileImage"]);
321 retval.profileFirstImage = new libsecondlife.LLUUID((string)reader["profileFirstImage"]);
322
323 }
324 else
325 {
326 return null;
327 }
328 return retval;
329 }
330
331 /// <summary>
332 /// Reads a list of inventory folders returned by a query.
333 /// </summary>
334 /// <param name="reader">A MySQL Data Reader</param>
335 /// <returns>A List containing inventory folders</returns>
336 public List<InventoryFolderBase> readInventoryFolders(IDataReader reader)
337 {
338 List<InventoryFolderBase> rows = new List<InventoryFolderBase>();
339
340 while(reader.Read())
341 {
342 try
343 {
344 InventoryFolderBase folder = new InventoryFolderBase();
345
346 folder.agentID = new libsecondlife.LLUUID((string)reader["agentID"]);
347 folder.parentID = new libsecondlife.LLUUID((string)reader["parentFolderID"]);
348 folder.folderID = new libsecondlife.LLUUID((string)reader["folderID"]);
349 folder.name = (string)reader["folderName"];
350
351 rows.Add(folder);
352 }
353 catch (Exception e)
354 {
355 Console.WriteLine(e.ToString());
356 }
357 }
358
359 return rows;
360 }
361
362 /// <summary>
363 /// Reads a collection of items from an SQL result
364 /// </summary>
365 /// <param name="reader">The SQL Result</param>
366 /// <returns>A List containing Inventory Items</returns>
367 public List<InventoryItemBase> readInventoryItems(IDataReader reader)
368 {
369 List<InventoryItemBase> rows = new List<InventoryItemBase>();
370
371 while (reader.Read())
372 {
373 try
374 {
375 InventoryItemBase item = new InventoryItemBase();
376
377 item.assetID = new libsecondlife.LLUUID((string)reader["assetID"]);
378 item.avatarID = new libsecondlife.LLUUID((string)reader["avatarID"]);
379 item.inventoryCurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"].ToString());
380 item.inventoryDescription = (string)reader["inventoryDescription"];
381 item.inventoryID = new libsecondlife.LLUUID((string)reader["inventoryID"]);
382 item.inventoryName = (string)reader["inventoryName"];
383 item.inventoryNextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"].ToString());
384 item.parentFolderID = new libsecondlife.LLUUID((string)reader["parentFolderID"]);
385 item.type = Convert.ToInt32(reader["type"].ToString());
386
387 rows.Add(item);
388 }
389 catch (Exception e)
390 {
391 Console.WriteLine(e.ToString());
392 }
393 }
394
395 return rows;
396 }
397
398 /// <summary>
399 /// Inserts a new row into the log database
400 /// </summary>
401 /// <param name="serverDaemon">The daemon which triggered this event</param>
402 /// <param name="target">Who were we operating on when this occured (region UUID, user UUID, etc)</param>
403 /// <param name="methodCall">The method call where the problem occured</param>
404 /// <param name="arguments">The arguments passed to the method</param>
405 /// <param name="priority">How critical is this?</param>
406 /// <param name="logMessage">Extra message info</param>
407 /// <returns>Saved successfully?</returns>
408 public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority, string logMessage)
409 {
410 string sql = "INSERT INTO logs (`target`, `server`, `method`, `arguments`, `priority`, `message`) VALUES ";
411 sql += "(?target, ?server, ?method, ?arguments, ?priority, ?message)";
412
413 Dictionary<string, string> parameters = new Dictionary<string, string>();
414 parameters["?server"] = serverDaemon;
415 parameters["?target"] = target;
416 parameters["?method"] = methodCall;
417 parameters["?arguments"] = arguments;
418 parameters["?priority"] = priority.ToString();
419 parameters["?message"] = logMessage;
420
421 bool returnval = false;
422
423 try
424 {
425 IDbCommand result = Query(sql, parameters);
426
427 if (result.ExecuteNonQuery() == 1)
428 returnval = true;
429
430 result.Dispose();
431 }
432 catch (Exception e)
433 {
434 Console.WriteLine(e.ToString());
435 return false;
436 }
437
438 return returnval;
439 }
440
441 /// <summary>
442 /// Inserts a new item into the database
443 /// </summary>
444 /// <param name="item">The item</param>
445 /// <returns>Success?</returns>
446 public bool insertItem(InventoryItemBase item)
447 {
448 string sql = "REPLACE INTO inventoryitems (inventoryID, assetID, type, parentFolderID, avatarID, inventoryName, inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions) VALUES ";
449 sql += "(?inventoryID, ?assetID, ?type, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription, ?inventoryNextPermissions, ?inventoryCurrentPermissions)";
450
451 Dictionary<string, string> parameters = new Dictionary<string, string>();
452 parameters["?inventoryID"] = item.inventoryID.ToStringHyphenated();
453 parameters["?assetID"] = item.assetID.ToStringHyphenated();
454 parameters["?type"] = item.type.ToString();
455 parameters["?parentFolderID"] = item.parentFolderID.ToStringHyphenated();
456 parameters["?avatarID"] = item.avatarID.ToStringHyphenated();
457 parameters["?inventoryName"] = item.inventoryName;
458 parameters["?inventoryDescription"] = item.inventoryDescription;
459 parameters["?inventoryNextPermissions"] = item.inventoryNextPermissions.ToString();
460 parameters["?inventoryCurrentPermissions"] = item.inventoryCurrentPermissions.ToString();
461
462 bool returnval = false;
463
464 try
465 {
466 IDbCommand result = Query(sql, parameters);
467
468 if (result.ExecuteNonQuery() == 1)
469 returnval = true;
470
471 result.Dispose();
472 }
473 catch (Exception e)
474 {
475 Console.WriteLine(e.ToString());
476 return false;
477 }
478
479 return returnval;
480 }
481
482 /// <summary>
483 /// Inserts a new folder into the database
484 /// </summary>
485 /// <param name="folder">The folder</param>
486 /// <returns>Success?</returns>
487 public bool insertFolder(InventoryFolderBase folder)
488 {
489 string sql = "REPLACE INTO inventoryfolders (folderID, agentID, parentFolderID, folderName) VALUES ";
490 sql += "(?folderID, ?agentID, ?parentFolderID, ?folderName)";
491
492 Dictionary<string, string> parameters = new Dictionary<string, string>();
493 parameters["?folderID"] = folder.folderID.ToStringHyphenated();
494 parameters["?agentID"] = folder.agentID.ToStringHyphenated();
495 parameters["?parentFolderID"] = folder.parentID.ToStringHyphenated();
496 parameters["?folderName"] = folder.name;
497
498 bool returnval = false;
499 try
500 {
501 IDbCommand result = Query(sql, parameters);
502
503 if (result.ExecuteNonQuery() == 1)
504 returnval = true;
505
506 result.Dispose();
507 }
508 catch (Exception e)
509 {
510 Console.WriteLine(e.ToString());
511 return false;
512 }
513 return returnval;
514 }
515
516 /// <summary>
517 /// Inserts a new region into the database
518 /// </summary>
519 /// <param name="profile">The region to insert</param>
520 /// <returns>Success?</returns>
521 public bool insertRegion(SimProfileData regiondata)
522 {
523 string sql = "REPLACE INTO regions (regionHandle, regionName, uuid, regionRecvKey, regionSecret, regionSendKey, regionDataURI, ";
524 sql += "serverIP, serverPort, serverURI, locX, locY, locZ, eastOverrideHandle, westOverrideHandle, southOverrideHandle, northOverrideHandle, regionAssetURI, regionAssetRecvKey, ";
525 sql += "regionAssetSendKey, regionUserURI, regionUserRecvKey, regionUserSendKey, regionMapTexture) VALUES ";
526
527 sql += "(?regionHandle, ?regionName, ?uuid, ?regionRecvKey, ?regionSecret, ?regionSendKey, ?regionDataURI, ";
528 sql += "?serverIP, ?serverPort, ?serverURI, ?locX, ?locY, ?locZ, ?eastOverrideHandle, ?westOverrideHandle, ?southOverrideHandle, ?northOverrideHandle, ?regionAssetURI, ?regionAssetRecvKey, ";
529 sql += "?regionAssetSendKey, ?regionUserURI, ?regionUserRecvKey, ?regionUserSendKey, ?regionMapTexture);";
530
531 Dictionary<string, string> parameters = new Dictionary<string, string>();
532
533 parameters["?regionHandle"] = regiondata.regionHandle.ToString();
534 parameters["?regionName"] = regiondata.regionName.ToString();
535 parameters["?uuid"] = regiondata.UUID.ToStringHyphenated();
536 parameters["?regionRecvKey"] = regiondata.regionRecvKey.ToString();
537 parameters["?regionSecret"] = regiondata.regionSecret.ToString();
538 parameters["?regionSendKey"] = regiondata.regionSendKey.ToString();
539 parameters["?regionDataURI"] = regiondata.regionDataURI.ToString();
540 parameters["?serverIP"] = regiondata.serverIP.ToString();
541 parameters["?serverPort"] = regiondata.serverPort.ToString();
542 parameters["?serverURI"] = regiondata.serverURI.ToString();
543 parameters["?locX"] = regiondata.regionLocX.ToString();
544 parameters["?locY"] = regiondata.regionLocY.ToString();
545 parameters["?locZ"] = regiondata.regionLocZ.ToString();
546 parameters["?eastOverrideHandle"] = regiondata.regionEastOverrideHandle.ToString();
547 parameters["?westOverrideHandle"] = regiondata.regionWestOverrideHandle.ToString();
548 parameters["?northOverrideHandle"] = regiondata.regionNorthOverrideHandle.ToString();
549 parameters["?southOverrideHandle"] = regiondata.regionSouthOverrideHandle.ToString();
550 parameters["?regionAssetURI"] = regiondata.regionAssetURI.ToString();
551 parameters["?regionAssetRecvKey"] = regiondata.regionAssetRecvKey.ToString();
552 parameters["?regionAssetSendKey"] = regiondata.regionAssetSendKey.ToString();
553 parameters["?regionUserURI"] = regiondata.regionUserURI.ToString();
554 parameters["?regionUserRecvKey"] = regiondata.regionUserRecvKey.ToString();
555 parameters["?regionUserSendKey"] = regiondata.regionUserSendKey.ToString();
556 parameters["?regionMapTexture"] = regiondata.regionMapTextureID.ToStringHyphenated();
557
558 bool returnval = false;
559
560 try
561 {
562
563 IDbCommand result = Query(sql, parameters);
564
565 //Console.WriteLine(result.CommandText);
566
567 if (result.ExecuteNonQuery() == 1)
568 returnval = true;
569
570 result.Dispose();
571 }
572 catch (Exception e)
573 {
574 Console.WriteLine(e.ToString());
575 return false;
576 }
577
578 return returnval;
579 }
580 }
581}