SQLiteEstateData.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Data;
  30. using System.Reflection;
  31. using log4net;
  32. #if CSharpSqlite
  33. using Community.CsharpSqlite.Sqlite;
  34. #else
  35. using Mono.Data.Sqlite;
  36. #endif
  37. using OpenMetaverse;
  38. using OpenSim.Framework;
  39. using OpenSim.Region.Framework.Interfaces;
  40. namespace OpenSim.Data.SQLite
  41. {
  42. public class SQLiteEstateStore : IEstateDataStore
  43. {
  44. private static readonly ILog m_log =
  45. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  46. private SqliteConnection m_connection;
  47. private string m_connectionString;
  48. private FieldInfo[] m_Fields;
  49. private Dictionary<string, FieldInfo> m_FieldMap =
  50. new Dictionary<string, FieldInfo>();
  51. protected virtual Assembly Assembly
  52. {
  53. get { return GetType().Assembly; }
  54. }
  55. public SQLiteEstateStore()
  56. {
  57. }
  58. public SQLiteEstateStore(string connectionString)
  59. {
  60. Initialise(connectionString);
  61. }
  62. public void Initialise(string connectionString)
  63. {
  64. DllmapConfigHelper.RegisterAssembly(typeof(SqliteConnection).Assembly);
  65. m_connectionString = connectionString;
  66. m_log.Info("[ESTATE DB]: Sqlite - connecting: "+m_connectionString);
  67. m_connection = new SqliteConnection(m_connectionString);
  68. m_connection.Open();
  69. Migration m = new Migration(m_connection, Assembly, "EstateStore");
  70. m.Update();
  71. //m_connection.Close();
  72. // m_connection.Open();
  73. Type t = typeof(EstateSettings);
  74. m_Fields = t.GetFields(BindingFlags.NonPublic |
  75. BindingFlags.Instance |
  76. BindingFlags.DeclaredOnly);
  77. foreach (FieldInfo f in m_Fields)
  78. if (f.Name.Substring(0, 2) == "m_")
  79. m_FieldMap[f.Name.Substring(2)] = f;
  80. }
  81. private string[] FieldList
  82. {
  83. get { return new List<string>(m_FieldMap.Keys).ToArray(); }
  84. }
  85. public EstateSettings LoadEstateSettings(UUID regionID, bool create)
  86. {
  87. string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID";
  88. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  89. {
  90. cmd.CommandText = sql;
  91. cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
  92. return DoLoad(cmd, regionID, create);
  93. }
  94. }
  95. private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create)
  96. {
  97. EstateSettings es = new EstateSettings();
  98. es.OnSave += StoreEstateSettings;
  99. IDataReader r = null;
  100. try
  101. {
  102. r = cmd.ExecuteReader();
  103. }
  104. catch (SqliteException)
  105. {
  106. m_log.Error("[SQLITE]: There was an issue loading the estate settings. This can happen the first time running OpenSimulator with CSharpSqlite the first time. OpenSimulator will probably crash, restart it and it should be good to go.");
  107. }
  108. if (r != null && r.Read())
  109. {
  110. foreach (string name in FieldList)
  111. {
  112. if (m_FieldMap[name].GetValue(es) is bool)
  113. {
  114. int v = Convert.ToInt32(r[name]);
  115. if (v != 0)
  116. m_FieldMap[name].SetValue(es, true);
  117. else
  118. m_FieldMap[name].SetValue(es, false);
  119. }
  120. else if (m_FieldMap[name].GetValue(es) is UUID)
  121. {
  122. UUID uuid = UUID.Zero;
  123. UUID.TryParse(r[name].ToString(), out uuid);
  124. m_FieldMap[name].SetValue(es, uuid);
  125. }
  126. else
  127. {
  128. m_FieldMap[name].SetValue(es, Convert.ChangeType(r[name], m_FieldMap[name].FieldType));
  129. }
  130. }
  131. r.Close();
  132. }
  133. else if (create)
  134. {
  135. DoCreate(es);
  136. LinkRegion(regionID, (int)es.EstateID);
  137. }
  138. LoadBanList(es);
  139. es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
  140. es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
  141. es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
  142. return es;
  143. }
  144. public EstateSettings CreateNewEstate(int estateID)
  145. {
  146. EstateSettings es = new EstateSettings();
  147. es.OnSave += StoreEstateSettings;
  148. es.EstateID = Convert.ToUInt32(estateID);
  149. DoCreate(es);
  150. LoadBanList(es);
  151. es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
  152. es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
  153. es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
  154. return es;
  155. }
  156. private void DoCreate(EstateSettings es)
  157. {
  158. List<string> names = new List<string>(FieldList);
  159. using (SqliteCommand cmd = m_connection.CreateCommand())
  160. {
  161. if (es.EstateID < 100)
  162. {
  163. cmd.CommandText = "select MAX(EstateID) FROM estate_settings";
  164. cmd.Parameters.Clear();
  165. uint a = 0;
  166. object r = cmd.ExecuteScalar();
  167. if(r!=null && !(r is DBNull))
  168. {
  169. a = Convert.ToUInt32(r);
  170. }
  171. if (a < 100)
  172. a = 100;
  173. ++a;
  174. es.EstateID = a;
  175. }
  176. cmd.CommandText = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")";
  177. cmd.Parameters.Clear();
  178. foreach (string name in FieldList)
  179. {
  180. if (m_FieldMap[name].GetValue(es) is bool)
  181. {
  182. if ((bool)m_FieldMap[name].GetValue(es))
  183. cmd.Parameters.AddWithValue(":"+name, "1");
  184. else
  185. cmd.Parameters.AddWithValue(":"+name, "0");
  186. }
  187. else
  188. {
  189. cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
  190. }
  191. }
  192. cmd.ExecuteNonQuery();
  193. }
  194. }
  195. public void StoreEstateSettings(EstateSettings es)
  196. {
  197. List<string> fields = new List<string>(FieldList);
  198. fields.Remove("EstateID");
  199. List<string> terms = new List<string>();
  200. foreach (string f in fields)
  201. terms.Add(f+" = :"+f);
  202. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  203. {
  204. cmd.CommandText = "update estate_settings set " + String.Join(", ", terms.ToArray()) + " where EstateID = :EstateID";
  205. cmd.Parameters.AddWithValue(":EstateID", es.EstateID);
  206. foreach (string name in FieldList)
  207. {
  208. if (m_FieldMap[name].GetValue(es) is bool)
  209. {
  210. if ((bool)m_FieldMap[name].GetValue(es))
  211. cmd.Parameters.AddWithValue(":"+name, "1");
  212. else
  213. cmd.Parameters.AddWithValue(":"+name, "0");
  214. }
  215. else
  216. {
  217. cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
  218. }
  219. }
  220. cmd.ExecuteNonQuery();
  221. }
  222. SaveBanList(es);
  223. SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
  224. SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
  225. SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
  226. }
  227. private void LoadBanList(EstateSettings es)
  228. {
  229. es.ClearBans();
  230. IDataReader r;
  231. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  232. {
  233. cmd.CommandText = "select * from estateban where EstateID = :EstateID";
  234. cmd.Parameters.AddWithValue(":EstateID", es.EstateID);
  235. r = cmd.ExecuteReader();
  236. }
  237. while (r.Read())
  238. {
  239. EstateBan eb = new EstateBan();
  240. eb.BannedUserID = DBGuid.FromDB(r["bannedUUID"]);
  241. eb.BannedHostAddress = "0.0.0.0";
  242. eb.BannedHostIPMask = "0.0.0.0";
  243. eb.BanningUserID = DBGuid.FromDB(r["banningUUID"]);
  244. eb.BanTime = Convert.ToInt32(r["banTime"]);
  245. es.AddBan(eb);
  246. }
  247. r.Close();
  248. }
  249. private void SaveBanList(EstateSettings es)
  250. {
  251. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  252. {
  253. cmd.CommandText = "delete from estateban where EstateID = :EstateID";
  254. cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
  255. cmd.ExecuteNonQuery();
  256. cmd.Parameters.Clear();
  257. cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask, banningUUID, banTime) values ( :EstateID, :bannedUUID, '', '', '', :banningUUID, :banTime )";
  258. foreach (EstateBan b in es.EstateBans)
  259. {
  260. cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
  261. cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString());
  262. cmd.Parameters.AddWithValue(":banningUUID", b.BanningUserID.ToString());
  263. cmd.Parameters.AddWithValue(":banTime", b.BanTime);
  264. cmd.ExecuteNonQuery();
  265. cmd.Parameters.Clear();
  266. }
  267. }
  268. }
  269. void SaveUUIDList(uint EstateID, string table, UUID[] data)
  270. {
  271. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  272. {
  273. cmd.CommandText = "delete from "+table+" where EstateID = :EstateID";
  274. cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString());
  275. cmd.ExecuteNonQuery();
  276. cmd.Parameters.Clear();
  277. cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )";
  278. foreach (UUID uuid in data)
  279. {
  280. cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString());
  281. cmd.Parameters.AddWithValue(":uuid", uuid.ToString());
  282. cmd.ExecuteNonQuery();
  283. cmd.Parameters.Clear();
  284. }
  285. }
  286. }
  287. UUID[] LoadUUIDList(uint EstateID, string table)
  288. {
  289. List<UUID> uuids = new List<UUID>();
  290. IDataReader r;
  291. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  292. {
  293. cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID";
  294. cmd.Parameters.AddWithValue(":EstateID", EstateID);
  295. r = cmd.ExecuteReader();
  296. }
  297. while (r.Read())
  298. {
  299. // EstateBan eb = new EstateBan();
  300. UUID uuid = new UUID();
  301. UUID.TryParse(r["uuid"].ToString(), out uuid);
  302. uuids.Add(uuid);
  303. }
  304. r.Close();
  305. return uuids.ToArray();
  306. }
  307. public EstateSettings LoadEstateSettings(int estateID)
  308. {
  309. string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID = :EstateID";
  310. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  311. {
  312. cmd.CommandText = sql;
  313. cmd.Parameters.AddWithValue(":EstateID", estateID.ToString());
  314. return DoLoad(cmd, UUID.Zero, false);
  315. }
  316. }
  317. public List<EstateSettings> LoadEstateSettingsAll()
  318. {
  319. List<EstateSettings> estateSettings = new List<EstateSettings>();
  320. List<int> estateIds = GetEstatesAll();
  321. foreach (int estateId in estateIds)
  322. estateSettings.Add(LoadEstateSettings(estateId));
  323. return estateSettings;
  324. }
  325. public List<int> GetEstates(string search)
  326. {
  327. List<int> result = new List<int>();
  328. string sql = "select EstateID from estate_settings where estate_settings.EstateName = :EstateName";
  329. IDataReader r;
  330. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  331. {
  332. cmd.CommandText = sql;
  333. cmd.Parameters.AddWithValue(":EstateName", search);
  334. r = cmd.ExecuteReader();
  335. }
  336. while (r.Read())
  337. {
  338. result.Add(Convert.ToInt32(r["EstateID"]));
  339. }
  340. r.Close();
  341. return result;
  342. }
  343. public List<int> GetEstatesAll()
  344. {
  345. List<int> result = new List<int>();
  346. string sql = "select EstateID from estate_settings";
  347. IDataReader r;
  348. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  349. {
  350. cmd.CommandText = sql;
  351. r = cmd.ExecuteReader();
  352. }
  353. while (r.Read())
  354. {
  355. result.Add(Convert.ToInt32(r["EstateID"]));
  356. }
  357. r.Close();
  358. return result;
  359. }
  360. public List<int> GetEstatesByOwner(UUID ownerID)
  361. {
  362. List<int> result = new List<int>();
  363. string sql = "select EstateID from estate_settings where estate_settings.EstateOwner = :EstateOwner";
  364. IDataReader r;
  365. using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  366. {
  367. cmd.CommandText = sql;
  368. cmd.Parameters.AddWithValue(":EstateOwner", ownerID);
  369. r = cmd.ExecuteReader();
  370. }
  371. while (r.Read())
  372. {
  373. result.Add(Convert.ToInt32(r["EstateID"]));
  374. }
  375. r.Close();
  376. return result;
  377. }
  378. public bool LinkRegion(UUID regionID, int estateID)
  379. {
  380. using(SqliteTransaction transaction = m_connection.BeginTransaction())
  381. {
  382. // Delete any existing estate mapping for this region.
  383. using(SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  384. {
  385. cmd.CommandText = "delete from estate_map where RegionID = :RegionID";
  386. cmd.Transaction = transaction;
  387. cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
  388. cmd.ExecuteNonQuery();
  389. }
  390. using(SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
  391. {
  392. cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)";
  393. cmd.Transaction = transaction;
  394. cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
  395. cmd.Parameters.AddWithValue(":EstateID", estateID.ToString());
  396. if (cmd.ExecuteNonQuery() == 0)
  397. {
  398. transaction.Rollback();
  399. return false;
  400. }
  401. else
  402. {
  403. transaction.Commit();
  404. return true;
  405. }
  406. }
  407. }
  408. }
  409. public List<UUID> GetRegions(int estateID)
  410. {
  411. return new List<UUID>();
  412. }
  413. public bool DeleteEstate(int estateID)
  414. {
  415. return false;
  416. }
  417. }
  418. }