OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ServiceThrottleModule.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 System.Threading;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenSim.Framework;
37 using OpenSim.Region.Framework.Interfaces;
38 using OpenSim.Framework.Monitoring;
39 using OpenSim.Region.Framework.Scenes;
41 
42 namespace OpenSim.Region.CoreModules.Framework
43 {
44  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
46  {
47  private static readonly ILog m_log = LogManager.GetLogger(
48  MethodBase.GetCurrentMethod().DeclaringType);
49 
50  private readonly List<Scene> m_scenes = new List<Scene>();
51  private System.Timers.Timer m_timer = new System.Timers.Timer();
52 
53  private Queue<Action> m_RequestQueue = new Queue<Action>();
54  private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55  private int m_Interval;
56 
57  #region ISharedRegionModule
58 
59  public void Initialise(IConfigSource config)
60  {
61  m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
62 
63  m_timer = new System.Timers.Timer();
64  m_timer.AutoReset = false;
65  m_timer.Enabled = true;
66  m_timer.Interval = 15000; // 15 secs at first
67  m_timer.Elapsed += ProcessQueue;
68  m_timer.Start();
69 
70  //WorkManager.StartThread(
71  // ProcessQueue,
72  // "GridServiceRequestThread",
73  // ThreadPriority.BelowNormal,
74  // true,
75  // false);
76  }
77 
78  public void AddRegion(Scene scene)
79  {
80  lock (m_scenes)
81  {
82  m_scenes.Add(scene);
83  scene.RegisterModuleInterface<IServiceThrottleModule>(this);
84  scene.EventManager.OnNewClient += OnNewClient;
85  scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
86  }
87  }
88 
89  public void RegionLoaded(Scene scene)
90  {
91  }
92 
93  public void RemoveRegion(Scene scene)
94  {
95  lock (m_scenes)
96  {
97  m_scenes.Remove(scene);
98  scene.EventManager.OnNewClient -= OnNewClient;
99  }
100  }
101 
102  public void PostInitialise()
103  {
104  }
105 
106  public void Close()
107  {
108  }
109 
110  public string Name
111  {
112  get { return "ServiceThrottleModule"; }
113  }
114 
115  public Type ReplaceableInterface
116  {
117  get { return null; }
118  }
119 
120  #endregion ISharedRegionMOdule
121 
122  #region Events
123 
124  void OnNewClient(IClientAPI client)
125  {
126  client.OnRegionHandleRequest += OnRegionHandleRequest;
127  }
128 
129  void OnMakeRootAgent(ScenePresence obj)
130  {
131  lock (m_timer)
132  {
133  if (!m_timer.Enabled)
134  {
135  m_timer.Interval = m_Interval;
136  m_timer.Enabled = true;
137  m_timer.Start();
138  }
139  }
140  }
141 
142  public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
143  {
144  //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
145  ulong handle = 0;
146  if (IsLocalRegionHandle(regionID, out handle))
147  {
148  client.SendRegionHandle(regionID, handle);
149  return;
150  }
151 
152  Action action = delegate
153  {
154  GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155 
156  if (r != null && r.RegionHandle != 0)
157  client.SendRegionHandle(regionID, r.RegionHandle);
158  };
159 
160  Enqueue("region", regionID.ToString(), action);
161  }
162 
163  #endregion Events
164 
165  #region IServiceThrottleModule
166 
167  public void Enqueue(string category, string itemid, Action continuation)
168  {
169  lock (m_RequestQueue)
170  {
171  if (m_Pending.ContainsKey(category))
172  {
173  if (m_Pending[category].Contains(itemid))
174  // Don't enqueue, it's already pending
175  return;
176  }
177  else
178  m_Pending.Add(category, new List<string>());
179 
180  m_Pending[category].Add(itemid);
181 
182  m_RequestQueue.Enqueue(delegate
183  {
184  lock (m_RequestQueue)
185  m_Pending[category].Remove(itemid);
186 
187  continuation();
188  });
189  }
190  }
191 
192  #endregion IServiceThrottleModule
193 
194  #region Process Continuation Queue
195 
196  private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197  {
198  //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199 
200  while (m_RequestQueue.Count > 0)
201  {
202  Action continuation = null;
203  lock (m_RequestQueue)
204  continuation = m_RequestQueue.Dequeue();
205 
206  if (continuation != null)
207  continuation();
208  }
209 
210  if (AreThereRootAgents())
211  {
212  lock (m_timer)
213  {
214  m_timer.Interval = 1000; // 1 sec
215  m_timer.Enabled = true;
216  m_timer.Start();
217  }
218  }
219  else
220  lock (m_timer)
221  m_timer.Enabled = false;
222 
223  }
224 
225  #endregion Process Continuation Queue
226 
227  #region Misc
228 
229  private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
230  {
231  regionHandle = 0;
232  foreach (Scene s in m_scenes)
233  if (s.RegionInfo.RegionID == regionID)
234  {
235  regionHandle = s.RegionInfo.RegionHandle;
236  return true;
237  }
238  return false;
239  }
240 
241  private bool AreThereRootAgents()
242  {
243  foreach (Scene s in m_scenes)
244  {
245  foreach (ScenePresence sp in s.GetScenePresences())
246  if (!sp.IsChildAgent)
247  return true;
248  }
249 
250  return false;
251  }
252 
253  #endregion Misc
254  }
255 
256 }
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
OpenSim.Services.Interfaces.GridRegion GridRegion
void Enqueue(string category, string itemid, Action continuation)
Enqueue a continuation meant to get a resource from elsewhere. As usual with CPS, caller beware: if t...
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void OnRegionHandleRequest(IClientAPI client, UUID regionID)
List< ScenePresence > GetScenePresences()
Gets all the scene presences in this scene.
Definition: Scene.cs:5259
OpenSim.Services.Interfaces.GridRegion GridRegion
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...