aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups
diff options
context:
space:
mode:
authorJohn Hurliman2010-04-14 19:48:40 -0700
committerJohn Hurliman2010-04-14 19:48:40 -0700
commit8fa13e387110233e2a38ceb41906f65992f014e5 (patch)
treed5492b20b59d92ffd9a9f6d314efdd6bc0c4d183 /OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC-8fa13e387110233e2a38ceb41906f65992f014e5.zip
opensim-SC-8fa13e387110233e2a38ceb41906f65992f014e5.tar.gz
opensim-SC-8fa13e387110233e2a38ceb41906f65992f014e5.tar.bz2
opensim-SC-8fa13e387110233e2a38ceb41906f65992f014e5.tar.xz
Patch from mcortez to add basic caching to the groups module. This prevents database/network explosions when you have a significant number of group-owned prims in a scene
Diffstat (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups')
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs81
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs131
2 files changed, 160 insertions, 52 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 669373f..9363205 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -167,6 +167,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
167 167
168 private bool m_debugEnabled = false; 168 private bool m_debugEnabled = false;
169 169
170 private ExpiringCache<string, OSDMap> m_memoryCache;
171 private int m_cacheTimeout = 30;
172
170 // private IUserAccountService m_accountService = null; 173 // private IUserAccountService m_accountService = null;
171 174
172 175
@@ -203,7 +206,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
203 return; 206 return;
204 } 207 }
205 208
206 m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); 209 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
207 210
208 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 211 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
209 if ((m_groupsServerURI == null) || 212 if ((m_groupsServerURI == null) ||
@@ -214,6 +217,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
214 return; 217 return;
215 } 218 }
216 219
220
221 m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30);
222 if (m_cacheTimeout == 0)
223 {
224 m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled.");
225 }
226 else
227 {
228 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout);
229 }
230
231
232
233 m_memoryCache = new ExpiringCache<string,OSDMap>();
234
235
217 // If we got all the config options we need, lets start'er'up 236 // If we got all the config options we need, lets start'er'up
218 m_connectorEnabled = true; 237 m_connectorEnabled = true;
219 238
@@ -224,7 +243,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
224 243
225 public void Close() 244 public void Close()
226 { 245 {
227 m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); 246 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name);
228 } 247 }
229 248
230 public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) 249 public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene)
@@ -657,7 +676,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
657 }; 676 };
658 677
659 678
660 OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); 679 OSDMap response = CachedPostRequest(requestArgs);
661 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) 680 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
662 { 681 {
663 OSDArray entryArray = (OSDArray)response["Entries"]; 682 OSDArray entryArray = (OSDArray)response["Entries"];
@@ -1086,7 +1105,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1086 }; 1105 };
1087 1106
1088 1107
1089 OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); 1108 OSDMap Response = CachedPostRequest(RequestArgs);
1090 if (Response["Success"].AsBoolean()) 1109 if (Response["Success"].AsBoolean())
1091 { 1110 {
1092 return true; 1111 return true;
@@ -1113,7 +1132,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1113 }; 1132 };
1114 1133
1115 1134
1116 OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); 1135 OSDMap Response = CachedPostRequest(RequestArgs);
1117 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) 1136 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1118 { 1137 {
1119 OSDArray entryArray = (OSDArray)Response["Entries"]; 1138 OSDArray entryArray = (OSDArray)Response["Entries"];
@@ -1153,7 +1172,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1153 }; 1172 };
1154 1173
1155 1174
1156 OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); 1175 OSDMap Response = CachedPostRequest(RequestArgs);
1157 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) 1176 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1158 { 1177 {
1159 OSDArray entryArray = (OSDArray)Response["Entries"]; 1178 OSDArray entryArray = (OSDArray)Response["Entries"];
@@ -1194,7 +1213,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1194 }; 1213 };
1195 1214
1196 1215
1197 OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); 1216 OSDMap Response = CachedPostRequest(RequestArgs);
1198 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) 1217 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1199 { 1218 {
1200 OSDArray entryArray = (OSDArray)Response["Entries"]; 1219 OSDArray entryArray = (OSDArray)Response["Entries"];
@@ -1234,7 +1253,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1234 1253
1235 1254
1236 1255
1237 OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); 1256 OSDMap response = CachedPostRequest(requestArgs);
1238 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) 1257 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
1239 { 1258 {
1240 maps = new Dictionary<string, OSDMap>(); 1259 maps = new Dictionary<string, OSDMap>();
@@ -1272,7 +1291,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1272 1291
1273 1292
1274 1293
1275 OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); 1294 OSDMap response = CachedPostRequest(requestArgs);
1276 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) 1295 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
1277 { 1296 {
1278 maps = new Dictionary<UUID, OSDMap>(); 1297 maps = new Dictionary<UUID, OSDMap>();
@@ -1310,7 +1329,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1310 }; 1329 };
1311 1330
1312 1331
1313 OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); 1332 OSDMap response = CachedPostRequest(requestArgs);
1314 if (response["Success"].AsBoolean()) 1333 if (response["Success"].AsBoolean())
1315 { 1334 {
1316 return true; 1335 return true;
@@ -1323,6 +1342,48 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1323 } 1342 }
1324 #endregion 1343 #endregion
1325 1344
1345 #region CheesyCache
1346 OSDMap CachedPostRequest(NameValueCollection requestArgs)
1347 {
1348 // Immediately forward the request if the cache is disabled.
1349 if (m_cacheTimeout == 0)
1350 {
1351 return WebUtil.PostToService(m_groupsServerURI, requestArgs);
1352 }
1353
1354 // Check if this is an update or a request
1355 if ( requestArgs["RequestMethod"] == "RemoveGeneric"
1356 || requestArgs["RequestMethod"] == "AddGeneric"
1357 )
1358
1359 {
1360 // Any and all updates cause the cache to clear
1361 m_memoryCache.Clear();
1362
1363 // Send update to server, return the response without caching it
1364 return WebUtil.PostToService(m_groupsServerURI, requestArgs);
1365
1366 }
1367
1368 // If we're not doing an update, we must be requesting data
1369
1370 // Create the cache key for the request and see if we have it cached
1371 string CacheKey = WebUtil.BuildQueryString(requestArgs);
1372 OSDMap response = null;
1373 if (!m_memoryCache.TryGetValue(CacheKey, out response))
1374 {
1375 // if it wasn't in the cache, pass the request to the Simian Grid Services
1376 response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
1377
1378 // and cache the response
1379 m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout));
1380 }
1381
1382 // return cached response
1383 return response;
1384 }
1385 #endregion
1386
1326 } 1387 }
1327 1388
1328} 1389}
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index 523dfbe..e7967d1 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Text;
32 33
33using Nwc.XmlRpc; 34using Nwc.XmlRpc;
34 35
@@ -70,6 +71,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
70 71
71 private IUserAccountService m_accountService = null; 72 private IUserAccountService m_accountService = null;
72 73
74 private ExpiringCache<string, XmlRpcResponse> m_memoryCache;
75 private int m_cacheTimeout = 30;
76
73 // Used to track which agents are have dropped from a group chat session 77 // Used to track which agents are have dropped from a group chat session
74 // Should be reset per agent, on logon 78 // Should be reset per agent, on logon
75 // TODO: move this to Flotsam XmlRpc Service 79 // TODO: move this to Flotsam XmlRpc Service
@@ -111,7 +115,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
111 return; 115 return;
112 } 116 }
113 117
114 m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); 118 m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
115 119
116 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 120 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
117 if ((m_groupsServerURI == null) || 121 if ((m_groupsServerURI == null) ||
@@ -127,7 +131,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
127 m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); 131 m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty);
128 m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); 132 m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty);
129 133
130 134
135 m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30);
136 if (m_cacheTimeout == 0)
137 {
138 m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled.");
139 }
140 else
141 {
142 m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout);
143 }
131 144
132 145
133 // If we got all the config options we need, lets start'er'up 146 // If we got all the config options we need, lets start'er'up
@@ -137,7 +150,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
137 150
138 public void Close() 151 public void Close()
139 { 152 {
140 m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); 153 m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name);
141 } 154 }
142 155
143 public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) 156 public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene)
@@ -919,50 +932,84 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
919 /// </summary> 932 /// </summary>
920 private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) 933 private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param)
921 { 934 {
922 string UserService; 935 XmlRpcResponse resp = null;
923 UUID SessionID; 936 string CacheKey = null;
924 GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); 937
925 param.Add("requestingAgentID", requestingAgentID.ToString()); 938 // Only bother with the cache if it isn't disabled.
926 param.Add("RequestingAgentUserService", UserService); 939 if (m_cacheTimeout > 0)
927 param.Add("RequestingSessionID", SessionID.ToString()); 940 {
928 941 if (!function.StartsWith("groups.get"))
942 {
943 // Any and all updates cause the cache to clear
944 m_memoryCache.Clear();
945 }
946 else
947 {
948 StringBuilder sb = new StringBuilder(requestingAgentID + function);
949 foreach (object key in param.Keys)
950 {
951 if (param[key] != null)
952 {
953 sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString());
954 }
955 }
956
957 CacheKey = sb.ToString();
958 m_memoryCache.TryGetValue(CacheKey, out resp);
959 }
929 960
930 param.Add("ReadKey", m_groupReadKey); 961 }
931 param.Add("WriteKey", m_groupWriteKey); 962
963 if( resp == null )
964 {
965 string UserService;
966 UUID SessionID;
967 GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID);
968 param.Add("requestingAgentID", requestingAgentID.ToString());
969 param.Add("RequestingAgentUserService", UserService);
970 param.Add("RequestingSessionID", SessionID.ToString());
932 971
933 972
934 IList parameters = new ArrayList(); 973 param.Add("ReadKey", m_groupReadKey);
935 parameters.Add(param); 974 param.Add("WriteKey", m_groupWriteKey);
936 975
937 ConfigurableKeepAliveXmlRpcRequest req;
938 req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive);
939 976
940 XmlRpcResponse resp = null; 977 IList parameters = new ArrayList();
978 parameters.Add(param);
941 979
942 try 980 ConfigurableKeepAliveXmlRpcRequest req;
943 { 981 req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive);
944 resp = req.Send(m_groupsServerURI, 10000);
945 }
946 catch (Exception e)
947 {
948
949 982
950 m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function);
951 m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString());
952 983
953 foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine },StringSplitOptions.None)) 984 try
954 { 985 {
955 m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); 986 resp = req.Send(m_groupsServerURI, 10000);
956 } 987
988 if ((m_cacheTimeout > 0) && (CacheKey != null))
989 {
990 m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout));
991 }
957 992
958 foreach (string key in param.Keys) 993 }
994 catch (Exception e)
959 { 995 {
960 m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); 996 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function);
997 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", e.ToString());
998
999 foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None))
1000 {
1001 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine);
1002 }
1003
1004 foreach (string key in param.Keys)
1005 {
1006 m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString());
1007 }
1008
1009 Hashtable respData = new Hashtable();
1010 respData.Add("error", e.ToString());
1011 return respData;
961 } 1012 }
962
963 Hashtable respData = new Hashtable();
964 respData.Add("error", e.ToString());
965 return respData;
966 } 1013 }
967 1014
968 if (resp.Value is Hashtable) 1015 if (resp.Value is Hashtable)
@@ -976,21 +1023,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
976 return respData; 1023 return respData;
977 } 1024 }
978 1025
979 m_log.ErrorFormat("[XMLRPCGROUPDATA]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); 1026 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString());
980 1027
981 if (resp.Value is ArrayList) 1028 if (resp.Value is ArrayList)
982 { 1029 {
983 ArrayList al = (ArrayList)resp.Value; 1030 ArrayList al = (ArrayList)resp.Value;
984 m_log.ErrorFormat("[XMLRPCGROUPDATA]: Contains {0} elements", al.Count); 1031 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count);
985 1032
986 foreach (object o in al) 1033 foreach (object o in al)
987 { 1034 {
988 m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} :: {1}", o.GetType().ToString(), o.ToString()); 1035 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString());
989 } 1036 }
990 } 1037 }
991 else 1038 else
992 { 1039 {
993 m_log.ErrorFormat("[XMLRPCGROUPDATA]: Function returned: {0}", resp.Value.ToString()); 1040 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString());
994 } 1041 }
995 1042
996 Hashtable error = new Hashtable(); 1043 Hashtable error = new Hashtable();
@@ -1000,16 +1047,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1000 1047
1001 private void LogRespDataToConsoleError(Hashtable respData) 1048 private void LogRespDataToConsoleError(Hashtable respData)
1002 { 1049 {
1003 m_log.Error("[XMLRPCGROUPDATA]: Error:"); 1050 m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:");
1004 1051
1005 foreach (string key in respData.Keys) 1052 foreach (string key in respData.Keys)
1006 { 1053 {
1007 m_log.ErrorFormat("[XMLRPCGROUPDATA]: Key: {0}", key); 1054 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key);
1008 1055
1009 string[] lines = respData[key].ToString().Split(new char[] { '\n' }); 1056 string[] lines = respData[key].ToString().Split(new char[] { '\n' });
1010 foreach (string line in lines) 1057 foreach (string line in lines)
1011 { 1058 {
1012 m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); 1059 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line);
1013 } 1060 }
1014 1061
1015 } 1062 }