diff options
Diffstat (limited to 'OpenSim/Data/MySQL/MySQLRegionData.cs')
-rw-r--r-- | OpenSim/Data/MySQL/MySQLRegionData.cs | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs new file mode 100644 index 0000000..46df421 --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs | |||
@@ -0,0 +1,421 @@ | |||
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; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Data; | ||
32 | using System.Reflection; | ||
33 | using MySql.Data.MySqlClient; | ||
34 | using OpenMetaverse; | ||
35 | using OpenSim.Framework; | ||
36 | using OpenSim.Data; | ||
37 | using RegionFlags = OpenSim.Framework.RegionFlags; | ||
38 | |||
39 | namespace OpenSim.Data.MySQL | ||
40 | { | ||
41 | public class MySqlRegionData : MySqlFramework, IRegionData | ||
42 | { | ||
43 | private string m_Realm; | ||
44 | private List<string> m_ColumnNames; | ||
45 | //private string m_connectionString; | ||
46 | |||
47 | protected virtual Assembly Assembly | ||
48 | { | ||
49 | get { return GetType().Assembly; } | ||
50 | } | ||
51 | |||
52 | public MySqlRegionData(string connectionString, string realm) | ||
53 | : base(connectionString) | ||
54 | { | ||
55 | m_Realm = realm; | ||
56 | m_connectionString = connectionString; | ||
57 | |||
58 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||
59 | { | ||
60 | dbcon.Open(); | ||
61 | Migration m = new Migration(dbcon, Assembly, "GridStore"); | ||
62 | m.Update(); | ||
63 | dbcon.Close(); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | public List<RegionData> Get(string regionName, UUID scopeID) | ||
68 | { | ||
69 | string command = "select * from `"+m_Realm+"` where regionName like ?regionName"; | ||
70 | if (scopeID != UUID.Zero) | ||
71 | command += " and ScopeID = ?scopeID"; | ||
72 | |||
73 | command += " order by regionName"; | ||
74 | |||
75 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
76 | { | ||
77 | cmd.Parameters.AddWithValue("?regionName", regionName); | ||
78 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
79 | |||
80 | return RunCommand(cmd); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | public RegionData Get(int posX, int posY, UUID scopeID) | ||
85 | { | ||
86 | /* fixed size regions | ||
87 | string command = "select * from `"+m_Realm+"` where locX = ?posX and locY = ?posY"; | ||
88 | if (scopeID != UUID.Zero) | ||
89 | command += " and ScopeID = ?scopeID"; | ||
90 | |||
91 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
92 | { | ||
93 | cmd.Parameters.AddWithValue("?posX", posX.ToString()); | ||
94 | cmd.Parameters.AddWithValue("?posY", posY.ToString()); | ||
95 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
96 | |||
97 | List<RegionData> ret = RunCommand(cmd); | ||
98 | if (ret.Count == 0) | ||
99 | return null; | ||
100 | |||
101 | return ret[0]; | ||
102 | } | ||
103 | */ | ||
104 | // extend database search for maximum region size area | ||
105 | string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY"; | ||
106 | if (scopeID != UUID.Zero) | ||
107 | command += " and ScopeID = ?scopeID"; | ||
108 | |||
109 | int startX = posX - (int)Constants.MaximumRegionSize; | ||
110 | int startY = posY - (int)Constants.MaximumRegionSize; | ||
111 | int endX = posX; | ||
112 | int endY = posY; | ||
113 | |||
114 | List<RegionData> ret; | ||
115 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
116 | { | ||
117 | cmd.Parameters.AddWithValue("?startX", startX.ToString()); | ||
118 | cmd.Parameters.AddWithValue("?startY", startY.ToString()); | ||
119 | cmd.Parameters.AddWithValue("?endX", endX.ToString()); | ||
120 | cmd.Parameters.AddWithValue("?endY", endY.ToString()); | ||
121 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
122 | |||
123 | ret = RunCommand(cmd); | ||
124 | } | ||
125 | |||
126 | if (ret.Count == 0) | ||
127 | return null; | ||
128 | |||
129 | // find the first that contains pos | ||
130 | RegionData rg = null; | ||
131 | foreach (RegionData r in ret) | ||
132 | { | ||
133 | if (posX >= r.posX && posX < r.posX + r.sizeX | ||
134 | && posY >= r.posY && posY < r.posY + r.sizeY) | ||
135 | { | ||
136 | rg = r; | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | return rg; | ||
142 | } | ||
143 | |||
144 | public RegionData Get(UUID regionID, UUID scopeID) | ||
145 | { | ||
146 | string command = "select * from `"+m_Realm+"` where uuid = ?regionID"; | ||
147 | if (scopeID != UUID.Zero) | ||
148 | command += " and ScopeID = ?scopeID"; | ||
149 | |||
150 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
151 | { | ||
152 | cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); | ||
153 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
154 | |||
155 | List<RegionData> ret = RunCommand(cmd); | ||
156 | if (ret.Count == 0) | ||
157 | return null; | ||
158 | |||
159 | return ret[0]; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID) | ||
164 | { | ||
165 | /* fix size regions | ||
166 | string command = "select * from `"+m_Realm+"` where locX between ?startX and ?endX and locY between ?startY and ?endY"; | ||
167 | if (scopeID != UUID.Zero) | ||
168 | command += " and ScopeID = ?scopeID"; | ||
169 | |||
170 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
171 | { | ||
172 | cmd.Parameters.AddWithValue("?startX", startX.ToString()); | ||
173 | cmd.Parameters.AddWithValue("?startY", startY.ToString()); | ||
174 | cmd.Parameters.AddWithValue("?endX", endX.ToString()); | ||
175 | cmd.Parameters.AddWithValue("?endY", endY.ToString()); | ||
176 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
177 | |||
178 | return RunCommand(cmd); | ||
179 | } | ||
180 | */ | ||
181 | string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY"; | ||
182 | if (scopeID != UUID.Zero) | ||
183 | command += " and ScopeID = ?scopeID"; | ||
184 | |||
185 | int qstartX = startX - (int)Constants.MaximumRegionSize; | ||
186 | int qstartY = startY - (int)Constants.MaximumRegionSize; | ||
187 | |||
188 | List<RegionData> dbret; | ||
189 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
190 | { | ||
191 | cmd.Parameters.AddWithValue("?startX", qstartX.ToString()); | ||
192 | cmd.Parameters.AddWithValue("?startY", qstartY.ToString()); | ||
193 | cmd.Parameters.AddWithValue("?endX", endX.ToString()); | ||
194 | cmd.Parameters.AddWithValue("?endY", endY.ToString()); | ||
195 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
196 | |||
197 | dbret = RunCommand(cmd); | ||
198 | } | ||
199 | |||
200 | List<RegionData> ret = new List<RegionData>(); | ||
201 | |||
202 | if (dbret.Count == 0) | ||
203 | return ret; | ||
204 | |||
205 | foreach (RegionData r in dbret) | ||
206 | { | ||
207 | if (r.posX + r.sizeX > startX && r.posX <= endX | ||
208 | && r.posY + r.sizeY > startY && r.posY <= endY) | ||
209 | ret.Add(r); | ||
210 | } | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | public List<RegionData> RunCommand(MySqlCommand cmd) | ||
215 | { | ||
216 | List<RegionData> retList = new List<RegionData>(); | ||
217 | |||
218 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||
219 | { | ||
220 | dbcon.Open(); | ||
221 | cmd.Connection = dbcon; | ||
222 | |||
223 | using (IDataReader result = cmd.ExecuteReader()) | ||
224 | { | ||
225 | while (result.Read()) | ||
226 | { | ||
227 | RegionData ret = new RegionData(); | ||
228 | ret.Data = new Dictionary<string, object>(); | ||
229 | |||
230 | ret.RegionID = DBGuid.FromDB(result["uuid"]); | ||
231 | ret.ScopeID = DBGuid.FromDB(result["ScopeID"]); | ||
232 | |||
233 | ret.RegionName = result["regionName"].ToString(); | ||
234 | ret.posX = Convert.ToInt32(result["locX"]); | ||
235 | ret.posY = Convert.ToInt32(result["locY"]); | ||
236 | ret.sizeX = Convert.ToInt32(result["sizeX"]); | ||
237 | ret.sizeY = Convert.ToInt32(result["sizeY"]); | ||
238 | |||
239 | CheckColumnNames(result); | ||
240 | |||
241 | foreach (string s in m_ColumnNames) | ||
242 | { | ||
243 | if (s == "uuid") | ||
244 | continue; | ||
245 | if (s == "ScopeID") | ||
246 | continue; | ||
247 | if (s == "regionName") | ||
248 | continue; | ||
249 | if (s == "locX") | ||
250 | continue; | ||
251 | if (s == "locY") | ||
252 | continue; | ||
253 | |||
254 | object value = result[s]; | ||
255 | if (value is DBNull) | ||
256 | ret.Data[s] = null; | ||
257 | else | ||
258 | ret.Data[s] = result[s].ToString(); | ||
259 | } | ||
260 | |||
261 | retList.Add(ret); | ||
262 | } | ||
263 | } | ||
264 | cmd.Connection = null; | ||
265 | dbcon.Close(); | ||
266 | } | ||
267 | |||
268 | return retList; | ||
269 | } | ||
270 | |||
271 | private void CheckColumnNames(IDataReader result) | ||
272 | { | ||
273 | if (m_ColumnNames != null) | ||
274 | return; | ||
275 | |||
276 | List<string> columnNames = new List<string>(); | ||
277 | |||
278 | DataTable schemaTable = result.GetSchemaTable(); | ||
279 | foreach (DataRow row in schemaTable.Rows) | ||
280 | { | ||
281 | if (row["ColumnName"] != null) | ||
282 | columnNames.Add(row["ColumnName"].ToString()); | ||
283 | } | ||
284 | |||
285 | m_ColumnNames = columnNames; | ||
286 | } | ||
287 | |||
288 | public bool Store(RegionData data) | ||
289 | { | ||
290 | if (data.Data.ContainsKey("uuid")) | ||
291 | data.Data.Remove("uuid"); | ||
292 | if (data.Data.ContainsKey("ScopeID")) | ||
293 | data.Data.Remove("ScopeID"); | ||
294 | if (data.Data.ContainsKey("regionName")) | ||
295 | data.Data.Remove("regionName"); | ||
296 | if (data.Data.ContainsKey("posX")) | ||
297 | data.Data.Remove("posX"); | ||
298 | if (data.Data.ContainsKey("posY")) | ||
299 | data.Data.Remove("posY"); | ||
300 | if (data.Data.ContainsKey("sizeX")) | ||
301 | data.Data.Remove("sizeX"); | ||
302 | if (data.Data.ContainsKey("sizeY")) | ||
303 | data.Data.Remove("sizeY"); | ||
304 | if (data.Data.ContainsKey("locX")) | ||
305 | data.Data.Remove("locX"); | ||
306 | if (data.Data.ContainsKey("locY")) | ||
307 | data.Data.Remove("locY"); | ||
308 | |||
309 | if (data.RegionName.Length > 128) | ||
310 | data.RegionName = data.RegionName.Substring(0, 128); | ||
311 | |||
312 | string[] fields = new List<string>(data.Data.Keys).ToArray(); | ||
313 | |||
314 | using (MySqlCommand cmd = new MySqlCommand()) | ||
315 | { | ||
316 | string update = "update `" + m_Realm + "` set locX=?posX, locY=?posY, sizeX=?sizeX, sizeY=?sizeY"; | ||
317 | foreach (string field in fields) | ||
318 | { | ||
319 | update += ", "; | ||
320 | update += "`" + field + "` = ?" + field; | ||
321 | |||
322 | cmd.Parameters.AddWithValue("?" + field, data.Data[field]); | ||
323 | } | ||
324 | |||
325 | update += " where uuid = ?regionID"; | ||
326 | |||
327 | if (data.ScopeID != UUID.Zero) | ||
328 | update += " and ScopeID = ?scopeID"; | ||
329 | |||
330 | cmd.CommandText = update; | ||
331 | cmd.Parameters.AddWithValue("?regionID", data.RegionID.ToString()); | ||
332 | cmd.Parameters.AddWithValue("?regionName", data.RegionName); | ||
333 | cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString()); | ||
334 | cmd.Parameters.AddWithValue("?posX", data.posX.ToString()); | ||
335 | cmd.Parameters.AddWithValue("?posY", data.posY.ToString()); | ||
336 | cmd.Parameters.AddWithValue("?sizeX", data.sizeX.ToString()); | ||
337 | cmd.Parameters.AddWithValue("?sizeY", data.sizeY.ToString()); | ||
338 | |||
339 | if (ExecuteNonQuery(cmd) < 1) | ||
340 | { | ||
341 | string insert = "insert into `" + m_Realm + "` (`uuid`, `ScopeID`, `locX`, `locY`, `sizeX`, `sizeY`, `regionName`, `" + | ||
342 | String.Join("`, `", fields) + | ||
343 | "`) values ( ?regionID, ?scopeID, ?posX, ?posY, ?sizeX, ?sizeY, ?regionName, ?" + String.Join(", ?", fields) + ")"; | ||
344 | |||
345 | cmd.CommandText = insert; | ||
346 | |||
347 | if (ExecuteNonQuery(cmd) < 1) | ||
348 | { | ||
349 | return false; | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return true; | ||
355 | } | ||
356 | |||
357 | public bool SetDataItem(UUID regionID, string item, string value) | ||
358 | { | ||
359 | using (MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + "` set `" + item + "` = ?" + item + " where uuid = ?UUID")) | ||
360 | { | ||
361 | cmd.Parameters.AddWithValue("?" + item, value); | ||
362 | cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); | ||
363 | |||
364 | if (ExecuteNonQuery(cmd) > 0) | ||
365 | return true; | ||
366 | } | ||
367 | |||
368 | return false; | ||
369 | } | ||
370 | |||
371 | public bool Delete(UUID regionID) | ||
372 | { | ||
373 | using (MySqlCommand cmd = new MySqlCommand("delete from `" + m_Realm + "` where uuid = ?UUID")) | ||
374 | { | ||
375 | cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); | ||
376 | |||
377 | if (ExecuteNonQuery(cmd) > 0) | ||
378 | return true; | ||
379 | } | ||
380 | |||
381 | return false; | ||
382 | } | ||
383 | |||
384 | public List<RegionData> GetDefaultRegions(UUID scopeID) | ||
385 | { | ||
386 | return Get((int)RegionFlags.DefaultRegion, scopeID); | ||
387 | } | ||
388 | |||
389 | public List<RegionData> GetDefaultHypergridRegions(UUID scopeID) | ||
390 | { | ||
391 | return Get((int)RegionFlags.DefaultHGRegion, scopeID); | ||
392 | } | ||
393 | |||
394 | public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) | ||
395 | { | ||
396 | List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); | ||
397 | RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y); | ||
398 | regions.Sort(distanceComparer); | ||
399 | return regions; | ||
400 | } | ||
401 | |||
402 | public List<RegionData> GetHyperlinks(UUID scopeID) | ||
403 | { | ||
404 | return Get((int)RegionFlags.Hyperlink, scopeID); | ||
405 | } | ||
406 | |||
407 | private List<RegionData> Get(int regionFlags, UUID scopeID) | ||
408 | { | ||
409 | string command = "select * from `" + m_Realm + "` where (flags & " + regionFlags.ToString() + ") <> 0"; | ||
410 | if (scopeID != UUID.Zero) | ||
411 | command += " and ScopeID = ?scopeID"; | ||
412 | |||
413 | using (MySqlCommand cmd = new MySqlCommand(command)) | ||
414 | { | ||
415 | cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); | ||
416 | |||
417 | return RunCommand(cmd); | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | } \ No newline at end of file | ||