clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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.Net;
32 using System.IO;
33 using System.Timers;
34 using System.Drawing;
35 using System.Drawing.Imaging;
36  
37 using log4net;
38 using Mono.Addins;
39 using Nini.Config;
40 using OpenSim.Framework;
41 using OpenSim.Region.Framework.Interfaces;
42 using OpenSim.Region.Framework.Scenes;
43 using OpenSim.Services.Interfaces;
44 using OpenSim.Server.Base;
45 using OpenMetaverse;
46 using OpenMetaverse.StructuredData;
47  
48 namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
49 {
50 /// <summary>
51 /// </summary>
52 /// <remarks>
53 /// </remarks>
54  
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")]
56 public class MapImageServiceModule : ISharedRegionModule
57 {
58 private static readonly ILog m_log =
59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60  
61 private bool m_enabled = false;
62 private IMapImageService m_MapService;
63  
64 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
65  
66 private int m_refreshtime = 0;
67 private int m_lastrefresh = 0;
68 private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
69  
70 #region ISharedRegionModule
71  
72 public Type ReplaceableInterface { get { return null; } }
73 public string Name { get { return "MapImageServiceModule"; } }
74 public void RegionLoaded(Scene scene) { }
75 public void Close() { }
76 public void PostInitialise() { }
77  
78 ///<summary>
79 ///
80 ///</summary>
81 public void Initialise(IConfigSource source)
82 {
83 IConfig moduleConfig = source.Configs["Modules"];
84 if (moduleConfig != null)
85 {
86 string name = moduleConfig.GetString("MapImageService", "");
87 if (name != Name)
88 return;
89 }
90  
91 IConfig config = source.Configs["MapImageService"];
92 if (config == null)
93 return;
94  
95 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime"));
96 if (refreshminutes <= 0)
97 {
98 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled.");
99 return;
100 }
101  
102 m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms
103  
104 string service = config.GetString("LocalServiceModule", string.Empty);
105 if (service == string.Empty)
106 {
107 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed.");
108 return;
109 }
110  
111 Object[] args = new Object[] { source };
112 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(service, args);
113 if (m_MapService == null)
114 {
115 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service);
116 return;
117 }
118  
119 m_refreshTimer.Enabled = true;
120 m_refreshTimer.AutoReset = true;
121 m_refreshTimer.Interval = m_refreshtime;
122 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
123  
124 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}",
125 refreshminutes, service);
126  
127 m_enabled = true;
128 }
129  
130 ///<summary>
131 ///
132 ///</summary>
133 public void AddRegion(Scene scene)
134 {
135 if (!m_enabled)
136 return;
137  
138 // Every shared region module has to maintain an indepedent list of
139 // currently running regions
140 lock (m_scenes)
141 m_scenes[scene.RegionInfo.RegionID] = scene;
142  
143 scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); };
144 }
145  
146 ///<summary>
147 ///
148 ///</summary>
149 public void RemoveRegion(Scene scene)
150 {
151 if (! m_enabled)
152 return;
153  
154 lock (m_scenes)
155 m_scenes.Remove(scene.RegionInfo.RegionID);
156 }
157  
158 #endregion ISharedRegionModule
159  
160 ///<summary>
161 ///
162 ///</summary>
163 private void HandleMaptileRefresh(object sender, EventArgs ea)
164 {
165 // this approach is a bit convoluted becase we want to wait for the
166 // first upload to happen on startup but after all the objects are
167 // loaded and initialized
168 if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
169 return;
170  
171 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!");
172 lock (m_scenes)
173 {
174 foreach (IScene scene in m_scenes.Values)
175 {
176 try
177 {
178 UploadMapTile(scene);
179 }
180 catch (Exception ex)
181 {
182 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message);
183 }
184 }
185 }
186  
187 m_lastrefresh = Util.EnvironmentTickCount();
188 }
189  
190 ///<summary>
191 ///
192 ///</summary>
193 private void UploadMapTile(IScene scene)
194 {
195 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
196  
197 // Create a JPG map tile and upload it to the AddMapTile API
198 byte[] jpgData = Utils.EmptyBytes;
199 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
200 if (tileGenerator == null)
201 {
202 m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
203 return;
204 }
205  
206 using (Image mapTile = tileGenerator.CreateMapTile())
207 {
208 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
209 // is no static map tile.
210 if (mapTile == null)
211 return;
212  
213 using (MemoryStream stream = new MemoryStream())
214 {
215 mapTile.Save(stream, ImageFormat.Jpeg);
216 jpgData = stream.ToArray();
217 }
218 }
219  
220 if (jpgData == Utils.EmptyBytes)
221 {
222 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
223 return;
224 }
225  
226 string reason = string.Empty;
227 if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason))
228 {
229 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
230 scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
231 }
232 }
233 }
234 }