Make cache an option, for issue #25

This commit is contained in:
lickx
2024-11-20 10:19:27 +01:00
parent 68eb1595ac
commit b19f50904e
4 changed files with 214 additions and 42 deletions

View File

@@ -44,6 +44,10 @@ namespace OpenSim.Services.PresenceService
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected bool m_allowDuplicatePresences = false;
protected bool m_useCache = true;
const int EXPIREMS = 300000;
static ExpiringCacheOS<UUID, PresenceData> BySessionCache = new ExpiringCacheOS<UUID, PresenceData>(60000);
static ExpiringCacheOS<string, PresenceData> ByUserCache = new ExpiringCacheOS<string, PresenceData>(60000);
public PresenceService(IConfigSource config)
: base(config)
@@ -54,15 +58,37 @@ namespace OpenSim.Services.PresenceService
if (presenceConfig != null)
{
m_allowDuplicatePresences = presenceConfig.GetBoolean("AllowDuplicatePresences", m_allowDuplicatePresences);
m_useCache = presenceConfig.GetBoolean("UseCache", m_useCache);
}
}
public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
{
PresenceData prevUser = GetUser(userID);
bool inCache = false;
PresenceData prevUser;
if (m_useCache)
{
inCache = ByUserCache.TryGetValue(userID, out prevUser);
if (!inCache)
{
PresenceData[] dataprv = m_Database.Get("UserID", userID);
if (dataprv.Length > 0)
prevUser = dataprv[0];
}
}
else
prevUser = GetUser(userID);
if (!m_allowDuplicatePresences && (prevUser != null))
{
m_Database.Delete("UserID", userID.ToString());
if(m_useCache && inCache)
{
BySessionCache.Remove(prevUser.SessionID);
ByUserCache.Remove(userID);
}
}
PresenceData data = new PresenceData();
@@ -73,6 +99,11 @@ namespace OpenSim.Services.PresenceService
data.Data["SecureSessionID"] = secureSessionID.ToString();
m_Database.Store(data);
if (m_useCache)
{
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(userID, data, EXPIREMS);
}
string prevUserStr = "";
if (prevUser != null)
@@ -86,14 +117,31 @@ namespace OpenSim.Services.PresenceService
public bool LogoutAgent(UUID sessionID)
{
PresenceInfo presence = GetAgent(sessionID);
bool inCache = false;
PresenceData presence;
if (m_useCache)
{
inCache = BySessionCache.TryGetValue(sessionID, out presence);
if(!inCache)
presence = m_Database.Get(sessionID);
}
else
presence = m_Database.Get(sessionID);
m_log.DebugFormat("[PRESENCE SERVICE]: LogoutAgent: session {0}, user {1}, region {2}",
sessionID,
(presence == null) ? null : presence.UserID,
(presence == null) ? null : presence.RegionID.ToString());
return m_Database.Delete("SessionID", sessionID.ToString());
bool ret = m_Database.Delete("SessionID", sessionID.ToString());
if(m_useCache && inCache)
{
BySessionCache.Remove(sessionID);
if(presence is not null)
ByUserCache.Remove(presence.UserID);
}
return ret;
}
public bool LogoutRegionAgents(UUID regionID)
@@ -103,8 +151,16 @@ namespace OpenSim.Services.PresenceService
if ((prevSessions is null) || (prevSessions.Length == 0))
return true;
m_log.DebugFormat("[PRESENCE SERVICE]: Logout users in region {0}: {1}", regionID,
string.Join(", ", Array.ConvertAll(prevSessions, session => session.UserID)));
m_log.DebugFormat("[PRESENCE SERVICE]: Logout users in region {0}", regionID);
if (m_useCache)
{
for (int i = 0; i < prevSessions.Length; ++i)
{
PresenceData pd = prevSessions[i];
BySessionCache.Remove(pd.SessionID);
ByUserCache.Remove(pd.UserID);
}
}
// There's a small chance that LogoutRegionAgents() will logout different users than the
// list that was logged above, but it's unlikely and not worth dealing with.
@@ -118,7 +174,17 @@ namespace OpenSim.Services.PresenceService
{
try
{
PresenceData presence = m_Database.Get(sessionID);
bool inCache = false;
PresenceData presence;
if (m_useCache)
{
inCache = BySessionCache.TryGetValue(sessionID, out presence);
if(!inCache)
presence = m_Database.Get(sessionID);
}
else
presence = m_Database.Get(sessionID);
bool success;
if (presence == null)
@@ -131,6 +197,21 @@ namespace OpenSim.Services.PresenceService
sessionID, (presence == null) ? null : presence.UserID, regionID,
(presence == null) ? "not logged-in" : "region " + presence.RegionID);
if (m_useCache)
{
if (success)
{
presence.RegionID = regionID;
BySessionCache.Add(sessionID, presence, EXPIREMS); // lastseen seems unused
ByUserCache.Add(presence.UserID, presence, EXPIREMS); // lastseen seems unused
}
else if (inCache)
{
BySessionCache.Remove(sessionID);
ByUserCache.Remove(presence.UserID);
}
}
return success;
}
catch (Exception e)
@@ -142,37 +223,72 @@ namespace OpenSim.Services.PresenceService
public PresenceInfo GetAgent(UUID sessionID)
{
PresenceInfo ret = new PresenceInfo();
PresenceData data;
if (m_useCache)
{
if(!BySessionCache.TryGetValue(sessionID, out data))
data = m_Database.Get(sessionID);
}
else
data = m_Database.Get(sessionID);
PresenceData data = m_Database.Get(sessionID);
if (data == null)
return null;
ret.UserID = data.UserID;
ret.RegionID = data.RegionID;
if (m_useCache)
{
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(data.UserID, data, EXPIREMS);
}
var ret = new PresenceInfo()
{
UserID = data.UserID,
RegionID = data.RegionID
};
return ret;
}
public PresenceInfo[] GetAgents(string[] userIDs)
{
List<PresenceInfo> info = new List<PresenceInfo>();
var info = new List<PresenceInfo>(userIDs.Length);
PresenceInfo ret;
foreach (string userIDStr in userIDs)
{
PresenceData[] data = m_Database.Get("UserID", userIDStr);
foreach (PresenceData d in data)
if(m_useCache && ByUserCache.TryGetValue(userIDStr, out PresenceData pd))
{
PresenceInfo ret = new PresenceInfo();
ret.UserID = d.UserID;
ret.RegionID = d.RegionID;
// cache hit
ByUserCache.Add(pd.UserID, pd, EXPIREMS);
BySessionCache.Add(pd.SessionID, pd, EXPIREMS);
ret = new PresenceInfo()
{
UserID = pd.UserID,
RegionID = pd.RegionID
};
info.Add(ret);
}
// m_log.DebugFormat(
// "[PRESENCE SERVICE]: GetAgents for {0} found {1} presences", userIDStr, data.Length);
else
{
// no cache used or cache miss
PresenceData[] data = m_Database.Get("UserID", userIDStr);
if(data.Length == 0)
continue;
PresenceData d = data[0];
if (m_useCache)
{
ByUserCache.Add(d.UserID, d, EXPIREMS);
BySessionCache.Add(d.SessionID, d, EXPIREMS);
}
ret = new PresenceInfo()
{
UserID = d.UserID,
RegionID = d.RegionID
};
info.Add(ret);
}
//m_log.DebugFormat(
// "[PRESENCE SERVICE]: GetAgents for {0} found {1} presences", userIDStr, data.Length);
}
return info.ToArray();

View File

@@ -44,6 +44,7 @@ namespace OpenSim.Services.UserAccountService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static bool m_Initialized;
protected bool m_useCache = true;
public GridUserService(IConfigSource config) : base(config)
{
@@ -69,6 +70,13 @@ namespace OpenSim.Services.UserAccountService
"This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n."
+ "For this reason, users online for more than 5 days are not currently counted",
HandleShowGridUsersOnline);
IConfig griduserConfig = config.Configs["GridUserService"];
if (griduserConfig != null)
{
m_useCache = griduserConfig.GetBoolean("UseCache", m_useCache);
}
}
}
@@ -126,27 +134,49 @@ namespace OpenSim.Services.UserAccountService
MainConsole.Instance.Output("Users online: {0}", onlineRecentlyCount);
}
private static ExpiringCacheOS<string, GridUserData> cache = new ExpiringCacheOS<string, GridUserData>(100000);
private GridUserData GetGridUserData(string userID)
{
GridUserData d = null;
if (userID.Length > 36) // it's a UUI
{
d = m_Database.Get(userID);
}
else // it's a UUID
{
GridUserData[] ds = m_Database.GetAll(userID);
if (ds == null)
return null;
if (userID.Length > 36)
userID = userID.Substring(0, 36);
if (ds.Length > 0)
{
d = ds[0];
foreach (GridUserData dd in ds)
if (dd.UserID.Length > d.UserID.Length) // find the longest
d = dd;
}
if (m_useCache && cache.TryGetValue(userID, out GridUserData d))
return d;
GridUserData[] ds = m_Database.GetAll(userID);
if (ds == null || ds.Length == 0)
{
if (m_useCache) cache.Add(userID, null, 300000);
return null;
}
d = ds[0];
if (ds.Length > 1)
{
// try find most recent record
try
{
int tsta = int.Parse(d.Data["Login"]);
int tstb = int.Parse(d.Data["Logout"]);
int cur = tstb > tsta? tstb : tsta;
for (int i = 1; i < ds.Length; ++i)
{
GridUserData dd = ds[i];
tsta = int.Parse(dd.Data["Login"]);
tstb = int.Parse(dd.Data["Logout"]);
if(tsta > tstb)
tstb = tsta;
if (tstb > cur)
{
cur = tstb;
d = dd;
}
}
}
catch { }
}
if (m_useCache) cache.Add(userID, d, 300000);
return d;
}
@@ -227,6 +257,8 @@ namespace OpenSim.Services.UserAccountService
d.Data["Login"] = Util.UnixTimeSinceEpoch().ToString();
m_Database.Store(d);
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return ToInfo(d);
}
@@ -249,7 +281,13 @@ namespace OpenSim.Services.UserAccountService
d.Data["LastPosition"] = lastPosition.ToString();
d.Data["LastLookAt"] = lastLookAt.ToString();
return m_Database.Store(d);
if(m_Database.Store(d))
{
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}
return false;
}
public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt)
@@ -266,7 +304,13 @@ namespace OpenSim.Services.UserAccountService
d.Data["HomePosition"] = homePosition.ToString();
d.Data["HomeLookAt"] = homeLookAt.ToString();
return m_Database.Store(d);
if(m_Database.Store(d))
{
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}
return false;
}
public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
@@ -285,7 +329,13 @@ namespace OpenSim.Services.UserAccountService
d.Data["LastPosition"] = lastPosition.ToString();
d.Data["LastLookAt"] = lastLookAt.ToString();
return m_Database.Store(d);
if(m_Database.Store(d))
{
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}
return false;
}
}
}

View File

@@ -490,6 +490,7 @@
[GridUserService]
; for the server connector
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
;UseCache = true
[AgentPreferencesService]
@@ -500,6 +501,8 @@
[PresenceService]
; for the server connector
LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService"
;AllowDuplicatePresences = false
;UseCache = true
[AvatarService]
; for the server connector

View File

@@ -431,6 +431,7 @@
[GridUserService]
; for the server connector
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
;UseCache = true
[AgentPreferencesService]
@@ -441,6 +442,8 @@
[PresenceService]
; for the server connector
LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService"
;AllowDuplicatePresences = false
;UseCache = true
[AvatarService]
; for the server connector