public override bool AddFolder(InventoryFolderBase folder) { //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder: folder {0} is not within Suitcase tree", folder.ParentID); return(false); } // OK, it's legit if (base.AddFolder(folder)) { List <XInventoryFolder> tree; if (m_SuitcaseTrees.TryGetValue(folder.Owner, out tree)) { tree.Add(ConvertFromOpenSim(folder)); } return(true); } return(false); }
public UserAccount Get(UUID userID, out bool inCache) { UserAccount account = null; inCache = false; if (m_UUIDCache.TryGetValue(userID, out account)) { //m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName); inCache = true; return(account); } return(null); }
public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) { inCache = false; GridRegion rinfo = null; ScopedRegionUUID id = new ScopedRegionUUID(scopeID, regionID); if (m_UUIDCache.TryGetValue(id, out rinfo)) { inCache = true; return(rinfo); } return(null); }
public UserAccount GetUserAccount(UUID scopeID, UUID userID) { // Cache check UserAccount account; if (m_accountCache.TryGetValue(userID, out account)) { return(account); } NameValueCollection requestArgs = new NameValueCollection { { "RequestMethod", "GetUser" }, { "UserID", userID.ToString() } }; account = GetUser(requestArgs); if (account == null) { // Store null responses too, to avoid repeated lookups for missing accounts m_accountCache.AddOrUpdate(userID, null, CACHE_EXPIRATION_SECONDS); } return(account); }
public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) { if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) { // Update the cache too GridUserInfo info = null; if (m_Infos.TryGetValue(userID, out info)) { info.HomeRegionID = regionID; info.HomePosition = position; info.HomeLookAt = lookAt; } return(true); } return(false); }
public void BeginDecode(UUID assetID, byte[] j2kData, DecodedCallback callback) { OpenJPEG.J2KLayerInfo[] result; // If it's cached, return the cached results if (m_decodedCache.TryGetValue(assetID, out result)) { // m_log.DebugFormat( // "[J2KDecoderModule]: Returning existing cached {0} layers j2k decode for {1}", // result.Length, assetID); callback(assetID, result); } else { // Not cached, we need to decode it. // Add to notify list and start decoding. // Next request for this asset while it's decoding will only be added to the notify list // once this is decoded, requests will be served from the cache and all clients in the notifylist will be updated bool decode = false; lock (m_notifyList) { if (m_notifyList.ContainsKey(assetID)) { m_notifyList[assetID].Add(callback); } else { List <DecodedCallback> notifylist = new List <DecodedCallback>(); notifylist.Add(callback); m_notifyList.Add(assetID, notifylist); decode = true; } } // Do Decode! if (decode) { Util.FireAndForget(delegate { Decode(assetID, j2kData); }); } } }
/// <summary> /// Try to get an asset from the in-memory cache. /// </summary> /// <param name="id"></param> /// <returns></returns> private AssetBase GetFromMemoryCache(string id) { AssetBase asset = null; if (m_MemoryCache.TryGetValue(GetAssetID(id), out asset)) { m_MemoryHits++; } return(asset); }
public InventoryFolderBase GetRootFolder(UUID userID) { InventoryFolderBase root = null; if (m_RootFolders.TryGetValue(userID, out root)) { return(root); } return(null); }
private AvatarAppearance GetAppearance(UUID principalID) { AvatarAppearance a = null; if (m_Appearances.TryGetValue(principalID, out a)) { return(a); } a = m_AvatarService.GetAppearance(principalID); m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes return(a); }
public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection inv = null; InventoryCollection c; if (m_Inventories.TryGetValue(userID, out inv)) { c = new InventoryCollection(); c.OwnerID = userID; c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) { return(f.ParentID == folderID); }); c.Items = inv.Items.FindAll(delegate(InventoryItemBase i) { return(i.Folder == folderID); }); return(c); } return(null); }
public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) { ThreadedClasses.RwLockedDictionary <AssetType, InventoryFolderBase> ff = null; if (m_FolderTypes.TryGetValue(userID, out ff)) { InventoryFolderBase f = null; if (ff.TryGetValue(type, out f)) { return(f); } } return(null); }
public GridRegion Get(UUID scopeID, ulong handle, out bool inCache) { inCache = false; GridRegion rinfo = null; ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, handle); if (m_PositionCache.TryGetValue(pos, out rinfo)) { inCache = true; return(rinfo); } return(null); }
public UserAccount Get(string name, out bool inCache) { inCache = false; UserAccount account = null; UUID uuid = UUID.Zero; if (m_NameCache.TryGetValue(name, out uuid)) { if (m_UUIDCache.TryGetValue(uuid, out account)) { inCache = true; return(account); } } return(null); }
public bool HasGroupAccess(UUID avatar) { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { ScenePresence sp; if (!m_scene.TryGetScenePresence(avatar, out sp)) { bool isMember; if (m_groupMemberCache.TryGetValue(avatar, out isMember)) { m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout); return(isMember); } IGroupsModule groupsModule = m_scene.RequestModuleInterface <IGroupsModule>(); if (groupsModule == null) { return(false); } GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); if (membership == null || membership.Length == 0) { m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); return(false); } foreach (GroupMembershipData d in membership) { if (d.GroupID == LandData.GroupID) { m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); return(true); } } m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); return(false); } return(sp.ControllingClient.IsGroupMember(LandData.GroupID)); } return(false); }
bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner) { bool imresult = false; GridRegion reginfo = null; if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo)) { reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID); if (reginfo != null) { m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS); } } if (reginfo != null) { imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); } else { m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI); return(false); } if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. m_UserLocationMap[toAgentID] = upd; return(true); } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! return(TrySendInstantMessage(im, upd, false, foreigner)); } }
public GridRegion Get(UUID scopeID, string name, out bool inCache) { inCache = false; ScopedRegionName sname = new ScopedRegionName(scopeID, name); ScopedRegionUUID id; if (m_NameCache.TryGetValue(sname, out id)) { GridRegion rinfo = null; if (m_UUIDCache.TryGetValue(id, out rinfo)) { inCache = true; return(rinfo); } } return(null); }
public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) { if (!(client.Scene is Scene)) { return; } // Scene scene = (Scene)(client.Scene); GridInstantMessage im = null; if (m_PendingLures.TryGetValue(lureID, out im)) { m_PendingLures.Remove(lureID); Lure(client, teleportFlags, im); } else { m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID); } }
public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func <GroupMembersData, bool> sendCondition) { UUID fromAgentID = new UUID(im.fromAgentID); // Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent // is not necessary. List <GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID); int groupMembersCount = groupMembers.Count; PresenceInfo[] onlineAgents = null; // In V2 we always only send to online members. // Sending to offline members is not an option. string[] t1 = groupMembers.ConvertAll <string>(gmd => gmd.AgentID.ToString()).ToArray(); // We cache in order not to overwhelm the presence service on large grids with many groups. This does // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. // (assuming this is the same across all grid simulators). if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) { onlineAgents = m_presenceService.GetAgents(t1); m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); } HashSet <string> onlineAgentsUuidSet = new HashSet <string>(); Array.ForEach <PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) // m_log.DebugFormat( // "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // groupID, groupMembersCount, groupMembers.Count()); int requestStartTick = Environment.TickCount; im.imSessionID = groupID.Guid; im.fromGroup = true; IClientAPI thisClient = GetActiveClient(fromAgentID); if (thisClient != null) { im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid; } if ((im.binaryBucket == null) || (im.binaryBucket.Length == 0) || ((im.binaryBucket.Length == 1 && im.binaryBucket[0] == 0))) { ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), groupID, null); if (groupInfo != null) { im.binaryBucket = Util.StringToBytes256(groupInfo.GroupName); } } // Send to self first of all im.toAgentID = im.fromAgentID; im.fromGroup = true; ProcessMessageFromGroupSession(im); List <UUID> regions = new List <UUID>(); List <UUID> clientsAlreadySent = new List <UUID>(); // Then send to everybody else foreach (GroupMembersData member in groupMembers) { if (member.AgentID.Guid == im.fromAgentID) { continue; } if (clientsAlreadySent.Contains(member.AgentID)) { continue; } clientsAlreadySent.Add(member.AgentID); if (sendCondition != null) { if (!sendCondition(member)) { if (m_debugEnabled) { m_log.DebugFormat( "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", member.AgentID); } continue; } } else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); } continue; } im.toAgentID = member.AgentID.Guid; IClientAPI client = GetActiveClient(member.AgentID); if (client == null) { // If they're not local, forward across the grid // BUT do it only once per region, please! Sim would be even better! if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID); } bool reallySend = true; if (onlineAgents != null) { PresenceInfo presence = onlineAgents.First(p => p.UserID == member.AgentID.ToString()); if (regions.Contains(presence.RegionID)) { reallySend = false; } else { regions.Add(presence.RegionID); } } if (reallySend) { // We have to create a new IM structure because the transfer module // uses async send GridInstantMessage msg = new GridInstantMessage(im, true); m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); } } else { // Deliver locally, directly if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); } ProcessMessageFromGroupSession(im); } } if (m_debugEnabled) { m_log.DebugFormat( "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } }
public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func <GroupMembersData, bool> sendCondition) { List <GroupMembersData> groupMembers = m_groupData.GetGroupMembers(sendingAgentForGroupCalls, groupID); int groupMembersCount = groupMembers.Count; if (m_messageOnlineAgentsOnly) { string[] t1 = groupMembers.ConvertAll <string>(gmd => gmd.AgentID.ToString()).ToArray(); // We cache in order not to overwhlem the presence service on large grids with many groups. This does // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. // (assuming this is the same across all grid simulators). PresenceInfo[] onlineAgents; if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) { onlineAgents = m_presenceService.GetAgents(t1); m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); } HashSet <string> onlineAgentsUuidSet = new HashSet <string>(); Array.ForEach <PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) // m_log.DebugFormat( // "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // groupID, groupMembersCount, groupMembers.Count()); } else { if (m_debugEnabled) { m_log.DebugFormat( "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", groupID, groupMembers.Count); } } int requestStartTick = Environment.TickCount; foreach (GroupMembersData member in groupMembers) { if (sendCondition != null) { if (!sendCondition(member)) { if (m_debugEnabled) { m_log.DebugFormat( "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition", member.AgentID); } continue; } } else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session if (m_debugEnabled) { m_log.DebugFormat( "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); } continue; } // Copy Message GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = im.imSessionID; msg.fromAgentName = im.fromAgentName; msg.message = im.message; msg.dialog = im.dialog; msg.offline = im.offline; msg.ParentEstateID = im.ParentEstateID; msg.Position = im.Position; msg.RegionID = im.RegionID; msg.binaryBucket = im.binaryBucket; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentID = im.fromAgentID; msg.fromGroup = true; msg.toAgentID = member.AgentID.Guid; IClientAPI client = GetActiveClient(member.AgentID); if (client == null) { // If they're not local, forward across the grid if (m_debugEnabled) { m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); } m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); } else { // Deliver locally, directly if (m_debugEnabled) { m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); } ProcessMessageFromGroupSession(msg, client); } } // Temporary for assessing how long it still takes to send messages to large online groups. if (m_messageOnlineAgentsOnly) { m_log.DebugFormat( "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } }
/// <summary> /// Encapsulate the XmlRpc call to standardize security and error handling. /// </summary> private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { XmlRpcResponse resp = null; string CacheKey = null; // Only bother with the cache if it isn't disabled. if (m_cacheTimeout > 0) { if (!function.StartsWith("groups.get")) { // Any and all updates cause the cache to clear m_memoryCache.Clear(); } else { StringBuilder sb = new StringBuilder(requestingAgentID + function); foreach (object key in param.Keys) { if (param[key] != null) { sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString()); } } CacheKey = sb.ToString(); m_memoryCache.TryGetValue(CacheKey, out resp); } } if (resp == null) { if (m_debugEnabled) { m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Cache miss for key {0}", CacheKey); } string UserService; UUID SessionID; GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); param.Add("RequestingAgentID", requestingAgentID.ToString()); param.Add("RequestingAgentUserService", UserService); param.Add("RequestingSessionID", SessionID.ToString()); param.Add("ReadKey", m_groupReadKey); param.Add("WriteKey", m_groupWriteKey); IList parameters = new ArrayList(); parameters.Add(param); ConfigurableKeepAliveXmlRpcRequest req; req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); try { resp = req.Send(m_groupsServerURI, 10000); if ((m_cacheTimeout > 0) && (CacheKey != null)) { m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); } } catch (Exception e) { m_log.ErrorFormat( "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}", function, m_groupsServerURI); m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}{1}", e.Message, e.StackTrace); foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) { m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); } foreach (string key in param.Keys) { m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); } Hashtable respData = new Hashtable(); respData.Add("error", e.ToString()); return(respData); } } if (resp.Value is Hashtable) { Hashtable respData = (Hashtable)resp.Value; if (respData.Contains("error") && !respData.Contains("succeed")) { LogRespDataToConsoleError(requestingAgentID, function, param, respData); } return(respData); } m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); if (resp.Value is ArrayList) { ArrayList al = (ArrayList)resp.Value; m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count); foreach (object o in al) { m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString()); } } else { m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString()); } Hashtable error = new Hashtable(); error.Add("error", "invalid return value"); return(error); }
/// <summary> /// Send updated position information about an agent in this region to a neighbor /// This operation may be called very frequently if an avatar is moving about in /// the region. /// </summary> public bool UpdateAgent(GridRegion destination, AgentPosition data) { bool v = true; if (_failedSims.TryGetValue(destination.ServerURI, out v)) { return(false); } // The basic idea of this code is that the first thread that needs to // send an update for a specific avatar becomes the worker for any subsequent // requests until there are no more outstanding requests. Further, only send the most // recent update; this *should* never be needed but some requests get // slowed down and once that happens the problem with service end point // limits kicks in and nothing proceeds string uri = destination.ServerURI + AgentPath() + data.AgentID + "/"; lock (m_updateAgentQueue) { if (m_updateAgentQueue.ContainsKey(uri)) { // Another thread is already handling // updates for this simulator, just update // the position and return, overwrites are // not a problem since we only care about the // last update anyway m_updateAgentQueue[uri] = data; return(true); } // Otherwise update the reference and start processing m_updateAgentQueue[uri] = data; } AgentPosition pos = null; bool success = true; while (success) { lock (m_updateAgentQueue) { // save the position AgentPosition lastpos = pos; pos = m_updateAgentQueue[uri]; // this is true if no one put a new // update in the map since the last // one we processed, if thats the // case then we are done if (pos == lastpos) { m_updateAgentQueue.Remove(uri); return(true); } } success = UpdateAgent(destination, (IAgentData)pos, 10000); } // we get here iff success == false // blacklist sim for 2 minutes lock (m_updateAgentQueue) { _failedSims.AddOrUpdate(destination.ServerURI, true, 120); m_updateAgentQueue.Remove(uri); } return(false); }