OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
PGSQLEstateData.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using log4net;
32 using OpenMetaverse;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 using System.Data;
36 using Npgsql;
37 using NpgsqlTypes;
38 
39 namespace OpenSim.Data.PGSQL
40 {
42  {
43  private const string _migrationStore = "EstateStore";
44 
45  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 
47  private PGSQLManager _Database;
48  private string m_connectionString;
49  private FieldInfo[] _Fields;
50  private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
51 
52  #region Public methods
53 
55  {
56  }
57 
58  public PGSQLEstateStore(string connectionString)
59  {
60  Initialise(connectionString);
61  }
62 
63  protected virtual Assembly Assembly
64  {
65  get { return GetType().Assembly; }
66  }
67 
72  public void Initialise(string connectionString)
73  {
74  if (!string.IsNullOrEmpty(connectionString))
75  {
76  m_connectionString = connectionString;
77  _Database = new PGSQLManager(connectionString);
78  }
79 
80  //Migration settings
81  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
82  {
83  conn.Open();
84  Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
85  m.Update();
86  }
87 
88  //Interesting way to get parameters! Maybe implement that also with other types
89  Type t = typeof(EstateSettings);
90  _Fields = t.GetFields(BindingFlags.NonPublic |
91  BindingFlags.Instance |
92  BindingFlags.DeclaredOnly);
93 
94  foreach (FieldInfo f in _Fields)
95  {
96  if (f.Name.Substring(0, 2) == "m_")
97  _FieldMap[f.Name.Substring(2)] = f;
98  }
99  }
100 
106  public EstateSettings LoadEstateSettings(UUID regionID, bool create)
107  {
108  EstateSettings es = new EstateSettings();
109 
110  string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) +
111  "\" from estate_map left join estate_settings on estate_map.\"EstateID\" = estate_settings.\"EstateID\" " +
112  " where estate_settings.\"EstateID\" is not null and \"RegionID\" = :RegionID";
113 
114  bool insertEstate = false;
115  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
116  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
117  {
118  cmd.Parameters.Add(_Database.CreateParameter("RegionID", regionID));
119  conn.Open();
120  using (NpgsqlDataReader reader = cmd.ExecuteReader())
121  {
122  if (reader.Read())
123  {
124  foreach (string name in FieldList)
125  {
126  FieldInfo f = _FieldMap[name];
127  object v = reader[name];
128  if (f.FieldType == typeof(bool))
129  {
130  f.SetValue(es, v);
131  }
132  else if (f.FieldType == typeof(UUID))
133  {
134  UUID estUUID = UUID.Zero;
135 
136  UUID.TryParse(v.ToString(), out estUUID);
137 
138  f.SetValue(es, estUUID);
139  }
140  else if (f.FieldType == typeof(string))
141  {
142  f.SetValue(es, v.ToString());
143  }
144  else if (f.FieldType == typeof(UInt32))
145  {
146  f.SetValue(es, Convert.ToUInt32(v));
147  }
148  else if (f.FieldType == typeof(Single))
149  {
150  f.SetValue(es, Convert.ToSingle(v));
151  }
152  else
153  f.SetValue(es, v);
154  }
155  }
156  else
157  {
158  insertEstate = true;
159  }
160  }
161  }
162 
163  if (insertEstate && create)
164  {
165  DoCreate(es);
166  LinkRegion(regionID, (int)es.EstateID);
167  }
168 
169  LoadBanList(es);
170 
171  es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
172  es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
173  es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
174 
175  //Set event
176  es.OnSave += StoreEstateSettings;
177  return es;
178  }
179 
181  {
182  EstateSettings es = new EstateSettings();
183  es.OnSave += StoreEstateSettings;
184 
185  DoCreate(es);
186 
187  LoadBanList(es);
188 
189  es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
190  es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
191  es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
192 
193  return es;
194  }
195 
196  private void DoCreate(EstateSettings es)
197  {
198  List<string> names = new List<string>(FieldList);
199 
200  names.Remove("EstateID");
201 
202  string sql = string.Format("insert into estate_settings (\"{0}\") values ( :{1} )", String.Join("\",\"", names.ToArray()), String.Join(", :", names.ToArray()));
203 
204  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
205  using (NpgsqlCommand insertCommand = new NpgsqlCommand(sql, conn))
206  {
207  insertCommand.CommandText = sql;
208 
209  foreach (string name in names)
210  {
211  insertCommand.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
212  }
213  //NpgsqlParameter idParameter = new NpgsqlParameter("ID", SqlDbType.Int);
214  //idParameter.Direction = ParameterDirection.Output;
215  //insertCommand.Parameters.Add(idParameter);
216  conn.Open();
217 
218  es.EstateID = 100;
219 
220  if (insertCommand.ExecuteNonQuery() > 0)
221  {
222  insertCommand.CommandText = "Select cast(lastval() as int) as ID ;";
223 
224  using (NpgsqlDataReader result = insertCommand.ExecuteReader())
225  {
226  if (result.Read())
227  {
228  es.EstateID = (uint)result.GetInt32(0);
229  }
230  }
231  }
232 
233  }
234 
235  //TODO check if this is needed??
236  es.Save();
237  }
238 
244  {
245  List<string> names = new List<string>(FieldList);
246 
247  names.Remove("EstateID");
248 
249  string sql = string.Format("UPDATE estate_settings SET ");
250  foreach (string name in names)
251  {
252  sql += "\"" + name + "\" = :" + name + ", ";
253  }
254  sql = sql.Remove(sql.LastIndexOf(","));
255  sql += " WHERE \"EstateID\" = :EstateID";
256 
257  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
258  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
259  {
260  foreach (string name in names)
261  {
262  cmd.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
263  }
264 
265  cmd.Parameters.Add(_Database.CreateParameter("EstateID", es.EstateID));
266  conn.Open();
267  cmd.ExecuteNonQuery();
268  }
269 
270  SaveBanList(es);
271  SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
272  SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
273  SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
274  }
275 
276  #endregion
277 
278  #region Private methods
279 
280  private string[] FieldList
281  {
282  get { return new List<string>(_FieldMap.Keys).ToArray(); }
283  }
284 
285  private void LoadBanList(EstateSettings es)
286  {
287  es.ClearBans();
288 
289  string sql = "select \"bannedUUID\" from estateban where \"EstateID\" = :EstateID";
290 
291  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
292  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
293  {
294  NpgsqlParameter idParameter = new NpgsqlParameter("EstateID", DbType.Int32);
295  idParameter.Value = es.EstateID;
296  cmd.Parameters.Add(idParameter);
297  conn.Open();
298  using (NpgsqlDataReader reader = cmd.ExecuteReader())
299  {
300  while (reader.Read())
301  {
302  EstateBan eb = new EstateBan();
303 
304  eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
305  eb.BannedHostAddress = "0.0.0.0";
306  eb.BannedHostIPMask = "0.0.0.0";
307  es.AddBan(eb);
308  }
309  }
310  }
311  }
312 
313  private UUID[] LoadUUIDList(uint estateID, string table)
314  {
315  List<UUID> uuids = new List<UUID>();
316 
317  string sql = string.Format("select uuid from {0} where \"EstateID\" = :EstateID", table);
318 
319  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
320  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
321  {
322  cmd.Parameters.Add(_Database.CreateParameter("EstateID", estateID));
323  conn.Open();
324  using (NpgsqlDataReader reader = cmd.ExecuteReader())
325  {
326  while (reader.Read())
327  {
328  uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
329  }
330  }
331  }
332 
333  return uuids.ToArray();
334  }
335 
336  private void SaveBanList(EstateSettings es)
337  {
338  //Delete first
339  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
340  {
341  conn.Open();
342  using (NpgsqlCommand cmd = conn.CreateCommand())
343  {
344  cmd.CommandText = "delete from estateban where \"EstateID\" = :EstateID";
345  cmd.Parameters.AddWithValue("EstateID", (int)es.EstateID);
346  cmd.ExecuteNonQuery();
347 
348  //Insert after
349  cmd.CommandText = "insert into estateban (\"EstateID\", \"bannedUUID\",\"bannedIp\", \"bannedIpHostMask\", \"bannedNameMask\") values ( :EstateID, :bannedUUID, '','','' )";
350  cmd.Parameters.AddWithValue("bannedUUID", Guid.Empty);
351  foreach (EstateBan b in es.EstateBans)
352  {
353  cmd.Parameters["bannedUUID"].Value = b.BannedUserID.Guid;
354  cmd.ExecuteNonQuery();
355  }
356  }
357  }
358  }
359 
360  private void SaveUUIDList(uint estateID, string table, UUID[] data)
361  {
362  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
363  {
364  conn.Open();
365  using (NpgsqlCommand cmd = conn.CreateCommand())
366  {
367  cmd.Parameters.AddWithValue("EstateID", (int)estateID);
368  cmd.CommandText = string.Format("delete from {0} where \"EstateID\" = :EstateID", table);
369  cmd.ExecuteNonQuery();
370 
371  cmd.CommandText = string.Format("insert into {0} (\"EstateID\", uuid) values ( :EstateID, :uuid )", table);
372  cmd.Parameters.AddWithValue("uuid", Guid.Empty);
373  foreach (UUID uuid in data)
374  {
375  cmd.Parameters["uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
376  cmd.ExecuteNonQuery();
377  }
378  }
379  }
380  }
381 
382  public EstateSettings LoadEstateSettings(int estateID)
383  {
384  EstateSettings es = new EstateSettings();
385  string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + "\" from estate_settings where \"EstateID\" = :EstateID";
386  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
387  {
388  conn.Open();
389  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
390  {
391  cmd.Parameters.AddWithValue("EstateID", (int)estateID);
392  using (NpgsqlDataReader reader = cmd.ExecuteReader())
393  {
394  if (reader.Read())
395  {
396  foreach (string name in FieldList)
397  {
398  FieldInfo f = _FieldMap[name];
399  object v = reader[name];
400  if (f.FieldType == typeof(bool))
401  {
402  f.SetValue(es, Convert.ToInt32(v) != 0);
403  }
404  else if (f.FieldType == typeof(UUID))
405  {
406  f.SetValue(es, new UUID((Guid)v)); // uuid);
407  }
408  else if (f.FieldType == typeof(string))
409  {
410  f.SetValue(es, v.ToString());
411  }
412  else if (f.FieldType == typeof(UInt32))
413  {
414  f.SetValue(es, Convert.ToUInt32(v));
415  }
416  else if (f.FieldType == typeof(Single))
417  {
418  f.SetValue(es, Convert.ToSingle(v));
419  }
420  else
421  f.SetValue(es, v);
422  }
423  }
424 
425  }
426  }
427  }
428  LoadBanList(es);
429 
430  es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
431  es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
432  es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
433 
434  //Set event
435  es.OnSave += StoreEstateSettings;
436  return es;
437 
438  }
439 
440  public List<EstateSettings> LoadEstateSettingsAll()
441  {
442  List<EstateSettings> allEstateSettings = new List<EstateSettings>();
443 
444  List<int> allEstateIds = GetEstatesAll();
445 
446  foreach (int estateId in allEstateIds)
447  allEstateSettings.Add(LoadEstateSettings(estateId));
448 
449  return allEstateSettings;
450  }
451 
452  public List<int> GetEstates(string search)
453  {
454  List<int> result = new List<int>();
455  string sql = "select \"EstateID\" from estate_settings where lower(\"EstateName\") = lower(:EstateName)";
456  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
457  {
458  conn.Open();
459  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
460  {
461  cmd.Parameters.AddWithValue("EstateName", search);
462 
463  using (IDataReader reader = cmd.ExecuteReader())
464  {
465  while (reader.Read())
466  {
467  result.Add(Convert.ToInt32(reader["EstateID"]));
468  }
469  reader.Close();
470  }
471  }
472  }
473 
474  return result;
475  }
476 
477  public List<int> GetEstatesAll()
478  {
479  List<int> result = new List<int>();
480  string sql = "select \"EstateID\" from estate_settings";
481  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
482  {
483  conn.Open();
484  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
485  {
486  using (IDataReader reader = cmd.ExecuteReader())
487  {
488  while (reader.Read())
489  {
490  result.Add(Convert.ToInt32(reader["EstateID"]));
491  }
492  reader.Close();
493  }
494  }
495  }
496 
497  return result;
498  }
499 
500  public List<int> GetEstatesByOwner(UUID ownerID)
501  {
502  List<int> result = new List<int>();
503  string sql = "select \"EstateID\" from estate_settings where \"EstateOwner\" = :EstateOwner";
504  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
505  {
506  conn.Open();
507  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
508  {
509  cmd.Parameters.AddWithValue("EstateOwner", ownerID);
510 
511  using (IDataReader reader = cmd.ExecuteReader())
512  {
513  while (reader.Read())
514  {
515  result.Add(Convert.ToInt32(reader["EstateID"]));
516  }
517  reader.Close();
518  }
519  }
520  }
521 
522  return result;
523  }
524 
525  public bool LinkRegion(UUID regionID, int estateID)
526  {
527  string deleteSQL = "delete from estate_map where \"RegionID\" = :RegionID";
528  string insertSQL = "insert into estate_map values (:RegionID, :EstateID)";
529  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
530  {
531  conn.Open();
532 
533  NpgsqlTransaction transaction = conn.BeginTransaction();
534 
535  try
536  {
537  using (NpgsqlCommand cmd = new NpgsqlCommand(deleteSQL, conn))
538  {
539  cmd.Transaction = transaction;
540  cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
541 
542  cmd.ExecuteNonQuery();
543  }
544 
545  using (NpgsqlCommand cmd = new NpgsqlCommand(insertSQL, conn))
546  {
547  cmd.Transaction = transaction;
548  cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
549  cmd.Parameters.AddWithValue("EstateID", estateID);
550 
551  int ret = cmd.ExecuteNonQuery();
552 
553  if (ret != 0)
554  transaction.Commit();
555  else
556  transaction.Rollback();
557 
558  return (ret != 0);
559  }
560  }
561  catch (Exception ex)
562  {
563  m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
564  transaction.Rollback();
565  }
566  }
567  return false;
568  }
569 
570  public List<UUID> GetRegions(int estateID)
571  {
572  List<UUID> result = new List<UUID>();
573  string sql = "select \"RegionID\" from estate_map where \"EstateID\" = :EstateID";
574  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
575  {
576  conn.Open();
577  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
578  {
579  cmd.Parameters.AddWithValue("EstateID", estateID);
580 
581  using (IDataReader reader = cmd.ExecuteReader())
582  {
583  while (reader.Read())
584  {
585  result.Add(DBGuid.FromDB(reader["RegionID"]));
586  }
587  reader.Close();
588  }
589  }
590  }
591 
592  return result;
593  }
594 
595  public bool DeleteEstate(int estateID)
596  {
597  // TODO: Implementation!
598  return false;
599  }
600  #endregion
601  }
602 }
List< EstateSettings > LoadEstateSettingsAll()
Load/Get all estate settings.
PGSQLEstateStore(string connectionString)
List< UUID > GetRegions(int estateID)
Get the UUIDs of all the regions in an estate.
List< int > GetEstates(string search)
Get estate IDs.
void Initialise(string connectionString)
Initialises the estatedata class.
A management class for the MS SQL Storage Engine
Definition: PGSQLManager.cs:44
bool DeleteEstate(int estateID)
Delete an estate
List< int > GetEstatesAll()
Get the IDs of all estates.
EstateSettings CreateNewEstate()
Create a new estate.
void StoreEstateSettings(EstateSettings es)
Stores the estate settings.
bool LinkRegion(UUID regionID, int estateID)
Link a region to an estate.
EstateSettings LoadEstateSettings(UUID regionID, bool create)
Loads the estate settings.
List< int > GetEstatesByOwner(UUID ownerID)
Get the IDs of all estates owned by the given user.
EstateSettings LoadEstateSettings(int estateID)
Load estate settings for an estate ID.