PageRenderTime 271ms CodeModel.GetById 228ms app.highlight 35ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Services/DataService/Connectors/Database/Grid/LocalGridConnector.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 594 lines | 478 code | 90 blank | 26 comment | 77 complexity | 37851c40ef8962a3ef5173a7270762d0 MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.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 Aurora-Sim 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 Aurora.Framework;
 29using Aurora.Framework.ConsoleFramework;
 30using Aurora.Framework.DatabaseInterfaces;
 31using Aurora.Framework.Modules;
 32using Aurora.Framework.SceneInfo;
 33using Aurora.Framework.Services;
 34using Aurora.Framework.Utilities;
 35using Nini.Config;
 36using OpenMetaverse;
 37using OpenMetaverse.StructuredData;
 38using System;
 39using System.Collections.Generic;
 40using GridRegion = Aurora.Framework.Services.GridRegion;
 41using RegionFlags = Aurora.Framework.Services.RegionFlags;
 42
 43namespace Aurora.Services.DataService
 44{
 45    public class LocalGridConnector : IRegionData
 46    {
 47        private IGenericData GD;
 48        private string m_realm = "gridregions";
 49
 50        #region IRegionData Members
 51
 52        public void Initialize(IGenericData GenericData, IConfigSource source, IRegistryCore simBase,
 53                               string defaultConnectionString)
 54        {
 55            if (source.Configs["AuroraConnectors"].GetString("GridConnector", "LocalConnector") == "LocalConnector")
 56            {
 57                GD = GenericData;
 58
 59                string connectionString = (source.Configs[Name] != null)
 60                                              ? connectionString =
 61                                                source.Configs[Name].GetString("ConnectionString",
 62                                                                               defaultConnectionString)
 63                                              : defaultConnectionString;
 64
 65                if (GD != null)
 66                    GD.ConnectToDatabase(connectionString, "GridRegions",
 67                                         source.Configs["AuroraConnectors"].GetBoolean("ValidateTables", true));
 68
 69                Framework.Utilities.DataManager.RegisterPlugin(this);
 70
 71                if (MainConsole.Instance != null)
 72                {
 73                    MainConsole.Instance.Commands.AddCommand("fix missing region owner", "fix missing region owner",
 74                                                             "Attempts to fix missing region owners in the database.",
 75                                                             delegate(string[] cmd) { FixMissingRegionOwners(); });
 76                }
 77            }
 78        }
 79
 80        public string Name
 81        {
 82            get { return "IRegionData"; }
 83        }
 84
 85        private void FixMissingRegionOwners()
 86        {
 87            QueryFilter filter = new QueryFilter();
 88            filter.andFilters["OwnerUUID"] = UUID.Zero;
 89
 90            List<GridRegion> borked = ParseQuery(null, GD.Query(new string[1] {"*"}, m_realm, filter, null, null, null));
 91
 92            if (borked.Count < 1)
 93            {
 94                MainConsole.Instance.Debug("[LocalGridConnector] No regions found with missing owners.");
 95            }
 96            IEstateConnector estatePlugin = Framework.Utilities.DataManager.RequestPlugin<IEstateConnector>();
 97
 98            if (estatePlugin == null)
 99            {
100                MainConsole.Instance.Error("[LocalGridConnector] " + borked.Count +
101                                           " regions found with missing owners, but could not get IEstateConnector plugin.");
102                return;
103            }
104            else
105            {
106                MainConsole.Instance.Error("[LocalGridConnector] " + borked.Count +
107                                           " regions found with missing owners, attempting fix.");
108            }
109
110            Dictionary<int, List<GridRegion>> borkedByEstate = new Dictionary<int, List<GridRegion>>();
111            foreach (GridRegion region in borked)
112            {
113                int estateID = estatePlugin.GetEstateID(region.RegionID);
114                if (!borkedByEstate.ContainsKey(estateID))
115                {
116                    borkedByEstate[estateID] = new List<GridRegion>();
117                }
118                borkedByEstate[estateID].Add(region);
119            }
120
121            Dictionary<int, UUID> estateOwnerIDs = new Dictionary<int, UUID>();
122            uint estateFail = 0;
123            foreach (int estateID in borkedByEstate.Keys)
124            {
125                EstateSettings es = estatePlugin.GetEstateSettings(estateID);
126                if (es == null)
127                {
128                    MainConsole.Instance.Error("[LocalGridConnector] Cannot fix missing owner for regions in Estate " +
129                                               estateID + ", could not get estate settings.");
130                }
131                else if (es.EstateOwner == UUID.Zero)
132                {
133                    MainConsole.Instance.Error("[LocalGridConnector] Cannot fix missing owner for regions in Estate " +
134                                               estateID + ", Estate Owner is also missing.");
135                }
136                if (es == null || es.EstateOwner == UUID.Zero)
137                {
138                    ++estateFail;
139                    continue;
140                }
141                estateOwnerIDs[estateID] = es.EstateOwner;
142            }
143
144            if (estateFail > 0)
145            {
146                if (estateFail == borkedByEstate.Count)
147                {
148                    MainConsole.Instance.Error("[LocalGridConnector] " + borked.Count +
149                                               " regions found with missing owners, could not locate any estate settings from IEstateConnector plugin.");
150                    return;
151                }
152                else
153                {
154                    MainConsole.Instance.Error("[LocalGridConnector] " + borked.Count +
155                                               " regions found with missing owners, could not locate estate settings for " +
156                                               estateFail + " estates.");
157                }
158            }
159
160            uint storeSuccess = 0;
161            uint storeFail = 0;
162            int borkedCount = borked.Count;
163            foreach (KeyValuePair<int, UUID> kvp in estateOwnerIDs)
164            {
165                List<GridRegion> regions = borkedByEstate[kvp.Key];
166                foreach (GridRegion region in regions)
167                {
168                    region.EstateOwner = kvp.Value;
169                    if (!Store(region))
170                    {
171                        MainConsole.Instance.Error("[LocalGridConnector] Failed to fix missing region for " +
172                                                   region.RegionName + " (" + region.RegionID + ")");
173                        ++storeFail;
174                    }
175                    else
176                    {
177                        ++storeSuccess;
178                        borked.Remove(region);
179                    }
180                }
181            }
182
183            if (storeFail > 0)
184            {
185                MainConsole.Instance.Error("[LocalGridConnector] " + borkedCount +
186                                           " regions found with missing owners, fix failed on " + storeFail +
187                                           " regions, fix attempted on " + storeSuccess + " regions.");
188            }
189            else if (storeSuccess != borked.Count)
190            {
191                MainConsole.Instance.Error("[LocalGridConnector] " + borkedCount +
192                                           " regions found with missing owners, fix attempted on " + storeSuccess +
193                                           " regions.");
194            }
195            else
196            {
197                MainConsole.Instance.Info(
198                    "[LocalGridConnector] All regions found with missing owners should have their owners restored.");
199            }
200            if (borked.Count > 0)
201            {
202                List<string> blurbs = new List<string>(borked.Count);
203                foreach (GridRegion region in borked)
204                {
205                    blurbs.Add(region.RegionName + " (" + region.RegionID + ")");
206                }
207                MainConsole.Instance.Info("[LocalGridConnector] Failed to fix missing region owners for regions " +
208                                          string.Join(", ", blurbs.ToArray()));
209            }
210        }
211
212        public uint GetCount(string regionName, List<UUID> scopeIDs)
213        {
214            QueryFilter filter = new QueryFilter();
215            filter.andLikeFilters["RegionName"] = regionName;
216
217            return uint.Parse(GD.Query(new[] {"COUNT(*)"}, m_realm, filter, null, null, null)[0]);
218        }
219
220        public List<GridRegion> Get(string regionName, List<UUID> scopeIDs, uint? start, uint? count)
221        {
222            QueryFilter filter = new QueryFilter();
223            filter.andLikeFilters["RegionName"] = regionName;
224
225            List<string> query = GD.Query(new string[1] {"*"}, m_realm, filter, null, start, count);
226
227            return (query.Count == 0) ? null : ParseQuery(scopeIDs, query);
228        }
229
230        public List<GridRegion> Get(RegionFlags flags)
231        {
232            QueryFilter filter = new QueryFilter();
233            filter.andBitfieldAndFilters["Flags"] = (uint) flags;
234            return ParseQuery(null, GD.Query(new string[1] {"*"}, m_realm, filter, null, null, null));
235        }
236
237        public GridRegion GetZero(int posX, int posY, List<UUID> scopeIDs)
238        {
239            QueryFilter filter = new QueryFilter();
240            filter.andFilters["LocX"] = posX;
241            filter.andFilters["LocY"] = posY;
242
243            List<string> query = GD.Query(new string[1] {"*"}, m_realm, filter, null, null, null);
244
245            return (query.Count == 0) ? null : ParseQuery(scopeIDs, query)[0];
246        }
247
248        public List<GridRegion> Get(int posX, int posY, List<UUID> scopeIDs)
249        {
250            QueryFilter filter = new QueryFilter();
251            filter.andFilters["LocX"] = posX;
252            filter.andFilters["LocY"] = posY;
253
254            Dictionary<string, bool> sort = new Dictionary<string, bool>(1);
255            sort["LocZ"] = true;
256
257            return ParseQuery(scopeIDs, GD.Query(new string[1] {"*"}, m_realm, filter, sort, null, null));
258        }
259
260        public GridRegion Get(UUID regionID, List<UUID> scopeIDs)
261        {
262            List<string> query;
263            Dictionary<string, object> where = new Dictionary<string, object>();
264
265            where["RegionUUID"] = regionID;
266
267            query = GD.Query(new string[1] {"*"}, m_realm, new QueryFilter
268                                                               {
269                                                                   andFilters = where
270                                                               }, null, null, null);
271
272            return (query.Count == 0) ? null : ParseQuery(scopeIDs, query)[0];
273        }
274
275        public List<GridRegion> Get(int startX, int startY, int endX, int endY, List<UUID> scopeIDs)
276        {
277            int foo;
278            if (startX > endX)
279            {
280                foo = endX;
281                endX = startX;
282                startX = foo;
283            }
284            if (startY > endY)
285            {
286                foo = endY;
287                endY = startY;
288                startY = foo;
289            }
290            QueryFilter filter = new QueryFilter();
291            filter.andGreaterThanEqFilters["LocX"] = startX;
292            filter.andLessThanEqFilters["LocX"] = endX;
293            filter.andGreaterThanEqFilters["LocY"] = startY;
294            filter.andLessThanEqFilters["LocY"] = endY;
295
296            return ParseQuery(scopeIDs, GD.Query(new string[1] {"*"}, m_realm, filter, null, null, null));
297        }
298
299        public List<GridRegion> Get(RegionFlags flags, Dictionary<string, bool> sort)
300        {
301            return Get(flags, 0, null, null, sort);
302        }
303
304        public List<GridRegion> Get(uint start, uint count, uint estateID, RegionFlags flags,
305                                    Dictionary<string, bool> sort)
306        {
307            List<GridRegion> resp = new List<GridRegion>();
308            IEstateConnector estates = Framework.Utilities.DataManager.RequestPlugin<IEstateConnector>();
309
310            if (count == 0 || estates == null)
311            {
312                return resp;
313            }
314
315            EstateSettings es = estates.GetEstateSettings((int) estateID);
316
317            QueryFilter filter = new QueryFilter();
318            filter.andBitfieldAndFilters["Flags"] = (uint) flags;
319
320            while (resp.Count < count)
321            {
322                uint limit = count - (uint) resp.Count;
323                List<GridRegion> query = ParseQuery(null,
324                                                    GD.Query(new string[] {"*"}, m_realm, filter, sort, start, count));
325
326                if (query.Count == 0)
327                {
328                    break;
329                }
330
331                query.ForEach(delegate(GridRegion region)
332                                  {
333                                      if (region.EstateOwner == es.EstateOwner &&
334                                          estates.GetEstateID(region.RegionID) == es.EstateID)
335                                      {
336                                          resp.Add(region);
337                                      }
338                                  });
339
340                start += limit;
341            }
342
343            return resp;
344        }
345
346        public List<GridRegion> Get(RegionFlags includeFlags, RegionFlags excludeFlags, uint? start, uint? count,
347                                    Dictionary<string, bool> sort)
348        {
349            QueryFilter filter = new QueryFilter();
350            if (includeFlags > 0)
351            {
352                filter.andBitfieldAndFilters["Flags"] = (uint) includeFlags;
353            }
354            if (excludeFlags > 0)
355            {
356                filter.andBitfieldNandFilters["Flags"] = (uint) excludeFlags;
357            }
358
359            return ParseQuery(null, GD.Query(new string[1] {"*"}, m_realm, filter, sort, start, count));
360        }
361
362        public uint Count(RegionFlags includeFlags, RegionFlags excludeFlags)
363        {
364            QueryFilter filter = new QueryFilter();
365            if (includeFlags > 0)
366            {
367                filter.andBitfieldAndFilters["Flags"] = (uint) includeFlags;
368            }
369            if (excludeFlags > 0)
370            {
371                filter.andBitfieldNandFilters["Flags"] = (uint) excludeFlags;
372            }
373
374            return uint.Parse(GD.Query(new string[1] {"COUNT(*)"}, m_realm, filter, null, null, null)[0]);
375        }
376
377        public List<GridRegion> GetNeighbours(UUID regionID, List<UUID> scopeIDs, uint squareRangeFromCenterInMeters)
378        {
379            List<GridRegion> regions = new List<GridRegion>(0);
380            GridRegion region = Get(regionID, scopeIDs);
381
382            if (region != null)
383            {
384                int centerX = region.RegionLocX + (region.RegionSizeX/2); // calculate center of region
385                int centerY = region.RegionLocY + (region.RegionSizeY/2); // calculate center of region
386
387                regions = Get(scopeIDs, region.RegionID, centerX, centerY, squareRangeFromCenterInMeters);
388            }
389
390            return regions;
391        }
392
393        public List<GridRegion> Get(List<UUID> scopeIDs, UUID excludeRegion, float centerX, float centerY,
394                                    uint squareRangeFromCenterInMeters)
395        {
396            QueryFilter filter = new QueryFilter();
397
398            if (excludeRegion != UUID.Zero)
399            {
400                filter.andNotFilters["RegionUUID"] = excludeRegion;
401            }
402            filter.andGreaterThanEqFilters["(LocX + SizeX)"] = centerX - squareRangeFromCenterInMeters;
403            filter.andGreaterThanEqFilters["(LocY + SizeY)"] = centerY - squareRangeFromCenterInMeters;
404            filter.andLessThanEqFilters["(LocX - SizeX)"] = centerX + squareRangeFromCenterInMeters;
405            filter.andLessThanEqFilters["(LocY - SizeY)"] = centerY + squareRangeFromCenterInMeters;
406
407            Dictionary<string, bool> sort = new Dictionary<string, bool>(3);
408            sort["LocZ"] = true;
409            sort["LocX"] = true;
410            sort["LocY"] = true;
411
412            return ParseQuery(scopeIDs, GD.Query(new string[] {"*"}, m_realm, filter, sort, null, null));
413        }
414
415        public uint Count(uint estateID, RegionFlags flags)
416        {
417            IEstateConnector estates = Framework.Utilities.DataManager.RequestPlugin<IEstateConnector>();
418
419            if (estates == null)
420            {
421                return 0;
422            }
423
424            EstateSettings es = estates.GetEstateSettings((int) estateID);
425
426            QueryFilter filter = new QueryFilter();
427            filter.andBitfieldAndFilters["Flags"] = (uint) flags;
428
429            List<GridRegion> query = ParseQuery(null, GD.Query(new string[] {"*"}, m_realm, filter, null, null, null));
430
431            uint count = 0;
432            query.ForEach(delegate(GridRegion region)
433                              {
434                                  if (region.EstateOwner == es.EstateOwner &&
435                                      estates.GetEstateID(region.RegionID) == es.EstateID)
436                                  {
437                                      ++count;
438                                  }
439                              });
440
441            return count;
442        }
443
444        public bool Store(GridRegion region)
445        {
446            if (region.EstateOwner == UUID.Zero)
447            {
448                IEstateConnector EstateConnector = Framework.Utilities.DataManager.RequestPlugin<IEstateConnector>();
449                EstateSettings ES = null;
450                if (EstateConnector != null)
451                {
452                    ES = EstateConnector.GetEstateSettings(region.RegionID);
453                    if (ES != null)
454                        region.EstateOwner = ES.EstateOwner;
455                }
456                if (region.EstateOwner == UUID.Zero && ES != null && ES.EstateID != 0)
457                {
458                    MainConsole.Instance.Error(
459                        "[LocalGridConnector] Attempt to store region with owner of UUID.Zero detected:" +
460                        (new System.Diagnostics.StackTrace()).GetFrame(1).ToString());
461                }
462            }
463
464            Dictionary<string, object> row = new Dictionary<string, object>(14);
465            row["ScopeID"] = region.ScopeID;
466            row["RegionUUID"] = region.RegionID;
467            row["RegionName"] = region.RegionName;
468            row["LocX"] = region.RegionLocX;
469            row["LocY"] = region.RegionLocY;
470            row["LocZ"] = region.RegionLocZ;
471            row["OwnerUUID"] = region.EstateOwner;
472            row["Access"] = region.Access;
473            row["SizeX"] = region.RegionSizeX;
474            row["SizeY"] = region.RegionSizeY;
475            row["SizeZ"] = region.RegionSizeZ;
476            row["Flags"] = region.Flags;
477            row["SessionID"] = region.SessionID;
478            row["Info"] = OSDParser.SerializeJsonString(region.ToOSD());
479
480            return GD.Replace(m_realm, row);
481        }
482
483        public bool Delete(UUID regionID)
484        {
485            QueryFilter filter = new QueryFilter();
486            filter.andFilters["RegionUUID"] = regionID;
487            return GD.Delete(m_realm, filter);
488        }
489
490        public bool DeleteAll(string[] criteriaKey, object[] criteriaValue)
491        {
492            QueryFilter filter = new QueryFilter();
493            int i = 0;
494            foreach (object value in criteriaValue)
495            {
496                filter.andFilters[criteriaKey[i++]] = value;
497            }
498            return GD.Delete(m_realm, filter);
499        }
500
501        public List<GridRegion> GetDefaultRegions(List<UUID> scopeIDs)
502        {
503            return Get((int) RegionFlags.DefaultRegion, scopeIDs);
504        }
505
506        public List<GridRegion> GetFallbackRegions(List<UUID> scopeIDs, int x, int y)
507        {
508            List<GridRegion> regions = Get((int) RegionFlags.FallbackRegion, scopeIDs);
509            RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
510            regions.Sort(distanceComparer);
511            return regions;
512        }
513
514        public List<GridRegion> GetSafeRegions(List<UUID> scopeIDs, int x, int y)
515        {
516            List<GridRegion> Regions = Get((int) RegionFlags.Safe, scopeIDs);
517            Regions.AddRange(Get((int) RegionFlags.RegionOnline, scopeIDs));
518
519            RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
520            Regions.Sort(distanceComparer);
521            return Regions;
522        }
523
524        #endregion
525
526        public void Dispose()
527        {
528        }
529
530        private List<GridRegion> Get(int regionFlags, List<UUID> scopeIDs)
531        {
532            QueryFilter filter = new QueryFilter();
533            filter.andBitfieldAndFilters["Flags"] = (uint) regionFlags;
534
535            return ParseQuery(scopeIDs, GD.Query(new string[1] {"*"}, m_realm, filter, null, null, null));
536        }
537
538        protected List<GridRegion> ParseQuery(List<UUID> scopeIDs, List<string> query)
539        {
540            List<GridRegion> regionData = new List<GridRegion>();
541
542            if ((query.Count%14) == 0)
543            {
544                for (int i = 0; i < query.Count; i += 14)
545                {
546                    GridRegion data = new GridRegion();
547                    OSDMap map = (OSDMap) OSDParser.DeserializeJson(query[i + 13]);
548                    map["owner_uuid"] = (!map.ContainsKey("owner_uuid") || map["owner_uuid"].AsUUID() == UUID.Zero)
549                                            ? OSD.FromUUID(UUID.Parse(query[i + 6]))
550                                            : map["owner_uuid"];
551                    map["EstateOwner"] = (!map.ContainsKey("EstateOwner") || map["EstateOwner"].AsUUID() == UUID.Zero)
552                                             ? OSD.FromUUID(UUID.Parse(query[i + 6]))
553                                             : map["EstateOwner"];
554                    data.FromOSD(map);
555
556                    if (!regionData.Contains(data))
557                        regionData.Add(data);
558                }
559            }
560
561            return AllScopeIDImpl.CheckScopeIDs(scopeIDs, regionData);
562        }
563
564        #region Nested type: RegionDataDistanceCompare
565
566        public class RegionDataDistanceCompare : IComparer<GridRegion>
567        {
568            private readonly Vector2 m_origin;
569
570            public RegionDataDistanceCompare(int x, int y)
571            {
572                m_origin = new Vector2(x, y);
573            }
574
575            #region IComparer<GridRegion> Members
576
577            public int Compare(GridRegion regionA, GridRegion regionB)
578            {
579                Vector2 vectorA = new Vector2(regionA.RegionLocX, regionA.RegionLocY);
580                Vector2 vectorB = new Vector2(regionB.RegionLocX, regionB.RegionLocY);
581                return Math.Sign(VectorDistance(m_origin, vectorA) - VectorDistance(m_origin, vectorB));
582            }
583
584            #endregion
585
586            private float VectorDistance(Vector2 x, Vector2 y)
587            {
588                return (x - y).Length();
589            }
590        }
591
592        #endregion
593    }
594}